Repository: google/oss-fuzz Branch: master Commit: f7e5bbb2fc46 Files: 6768 Total size: 25.1 MB Directory structure: gitextract_pywrjdt2/ ├── .allstar/ │ └── binary_artifacts.yaml ├── .clusterfuzzlite/ │ ├── Dockerfile │ ├── build.sh │ ├── coverage_atheris_fuzzer.py │ └── project.yaml ├── .dockerignore ├── .gitattributes ├── .github/ │ ├── header-checker-lint.yml │ └── workflows/ │ ├── cflite_pr.yml │ ├── check_base_os.yml │ ├── codeql-analysis.yml │ ├── index_build_tests.yml │ ├── indexer_build.yml │ ├── infra_tests.yml │ ├── pr_helper.yml │ ├── presubmit.yml │ ├── project_tests.yml │ └── ubuntu_version_sync.yml ├── .gitignore ├── .pylintrc ├── .style.yapf ├── AGENTS.md ├── CITATION.cff ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs/ │ ├── .gitignore │ ├── 404.html │ ├── Gemfile │ ├── README.md │ ├── _config.yml │ ├── _sass/ │ │ └── color_schemes/ │ │ └── wider.scss │ ├── advanced-topics/ │ │ ├── advanced_topics.md │ │ ├── bug_fixing_guidance.md │ │ ├── code_coverage.md │ │ ├── corpora.md │ │ ├── debugging.md │ │ ├── fuzz_introspector.md │ │ ├── ideal_integration.md │ │ └── reproducing.md │ ├── assets/ │ │ └── css/ │ │ └── just-the-docs-wider.scss │ ├── faq.md │ ├── further-reading/ │ │ ├── clusterfuzz.md │ │ ├── further_reading.md │ │ └── fuzzer_environment.md │ ├── getting-started/ │ │ ├── accepting_new_projects.md │ │ ├── bug_disclosure_guidelines.md │ │ ├── continuous_integration.md │ │ ├── getting_started.md │ │ ├── integration_rewards.md │ │ ├── new-project-guide/ │ │ │ ├── bazel.md │ │ │ ├── go_lang.md │ │ │ ├── javascript_lang.md │ │ │ ├── jvm_lang.md │ │ │ ├── lua_lang.md │ │ │ ├── python_lang.md │ │ │ ├── rust_lang.md │ │ │ └── swift_lang.md │ │ └── new_project_guide.md │ ├── glossary.md │ ├── ideal_integration.md │ ├── index.md │ ├── new_project_guide.md │ ├── oss-fuzz/ │ │ └── architecture.md │ ├── reference/ │ │ ├── glossary.md │ │ ├── reference.md │ │ └── useful_links.md │ ├── reproducing.md │ └── research/ │ └── target_generation.md ├── infra/ │ ├── .dockerignore │ ├── MAINTAINERS.csv │ ├── README.md │ ├── base-images/ │ │ ├── README.md │ │ ├── all.sh │ │ ├── base-builder/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── afl_llvm22_patch.diff │ │ │ ├── bazel.bazelrc │ │ │ ├── bazel_build_fuzz_tests │ │ │ ├── bisect_clang.py │ │ │ ├── bisect_clang_test.py │ │ │ ├── cargo │ │ │ ├── compile │ │ │ ├── compile_afl │ │ │ ├── compile_centipede │ │ │ ├── compile_fuzztests.sh │ │ │ ├── compile_go_fuzzer │ │ │ ├── compile_honggfuzz │ │ │ ├── compile_javascript_fuzzer │ │ │ ├── compile_libfuzzer │ │ │ ├── compile_native_go_fuzzer │ │ │ ├── compile_native_go_fuzzer_v2 │ │ │ ├── compile_python_fuzzer │ │ │ ├── debug_afl │ │ │ ├── detect_repo.py │ │ │ ├── detect_repo_test.py │ │ │ ├── go_utils.sh │ │ │ ├── indexer/ │ │ │ │ ├── README.md │ │ │ │ ├── clang_wrapper.py │ │ │ │ ├── clang_wrapper_test.py │ │ │ │ ├── coverage.cc │ │ │ │ ├── dwarf_info.py │ │ │ │ ├── dwarf_info_diff.py │ │ │ │ ├── fuzzing_engine.cc │ │ │ │ ├── ignored_deps.json │ │ │ │ ├── index_build.py │ │ │ │ ├── index_build_test.py │ │ │ │ ├── manifest_constants.py │ │ │ │ ├── manifest_types.py │ │ │ │ └── utils.py │ │ │ ├── install_deps.sh │ │ │ ├── install_deps_ubuntu-20-04.sh │ │ │ ├── install_deps_ubuntu-24-04.sh │ │ │ ├── install_go.sh │ │ │ ├── install_java.sh │ │ │ ├── install_javascript.sh │ │ │ ├── install_python.sh │ │ │ ├── install_ruby.sh │ │ │ ├── install_rust.sh │ │ │ ├── install_swift.sh │ │ │ ├── install_swift_ubuntu-20-04.sh │ │ │ ├── install_swift_ubuntu-24-04.sh │ │ │ ├── jcc/ │ │ │ │ ├── build_jcc.bash │ │ │ │ ├── go.mod │ │ │ │ ├── jcc.go │ │ │ │ ├── jcc2.go │ │ │ │ ├── jcc_test.go │ │ │ │ └── testdata/ │ │ │ │ ├── .gitignore │ │ │ │ ├── cfile.c │ │ │ │ ├── cpp.cc │ │ │ │ └── path/ │ │ │ │ └── to/ │ │ │ │ └── header.h │ │ │ ├── llvmsymbol.diff │ │ │ ├── make_build_replayable.py │ │ │ ├── ossfuzz_coverage_runner.go │ │ │ ├── precompile_afl │ │ │ ├── precompile_centipede │ │ │ ├── precompile_honggfuzz │ │ │ ├── precompile_honggfuzz_ubuntu_20_04 │ │ │ ├── precompile_honggfuzz_ubuntu_24_04 │ │ │ ├── python_coverage_helper.py │ │ │ ├── replay_build.sh │ │ │ ├── sanitizers/ │ │ │ │ └── pysecsan/ │ │ │ │ ├── .gitignore │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── pyproject.toml │ │ │ │ ├── pysecsan/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── command_injection.py │ │ │ │ │ ├── redos.py │ │ │ │ │ ├── sanlib.py │ │ │ │ │ └── yaml_deserialization.py │ │ │ │ ├── setup.py │ │ │ │ └── tests/ │ │ │ │ ├── README.md │ │ │ │ ├── eval_command_injection.py │ │ │ │ ├── os_command_injection.py │ │ │ │ ├── poe/ │ │ │ │ │ ├── ansible-runner-cve-2021-4041/ │ │ │ │ │ │ ├── build.sh │ │ │ │ │ │ └── fuzz_ansible_runner.py │ │ │ │ │ ├── libvcs-cve-2022-21187/ │ │ │ │ │ │ ├── build.sh │ │ │ │ │ │ └── fuzz_libvcs.py │ │ │ │ │ ├── python-ldap-GHSL-2021-117/ │ │ │ │ │ │ ├── build.sh │ │ │ │ │ │ └── fuzz_ldap.py │ │ │ │ │ └── pytorch-lightning-1.5.10/ │ │ │ │ │ ├── build.sh │ │ │ │ │ ├── fuzz_pytorch_lightning.dict │ │ │ │ │ └── fuzz_pytorch_lightning.py │ │ │ │ ├── subprocess_popen_injection.py │ │ │ │ ├── yaml_deserialization_general.py │ │ │ │ └── yaml_deserialization_simple.py │ │ │ ├── srcmap │ │ │ ├── test_data/ │ │ │ │ └── culprit-commit.txt │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ ├── ubuntu-24-04.Dockerfile │ │ │ ├── unshallow_repos.py │ │ │ └── write_labels.py │ │ ├── base-builder-fuzzbench/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── fuzzbench_build │ │ │ ├── fuzzbench_install_dependencies │ │ │ ├── fuzzbench_install_dependencies_ubuntu_20_04 │ │ │ ├── fuzzbench_install_dependencies_ubuntu_24_04 │ │ │ ├── fuzzbench_measure │ │ │ ├── fuzzbench_run_fuzzer │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-go/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── gosigfuzz.c │ │ │ ├── ossfuzz_coverage_runner.go │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-javascript/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-jvm/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-python/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-ruby/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ruzzy-build │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-rust/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-builder-swift/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── llvmsymbol.diff │ │ │ ├── precompile_swift │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-clang/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── checkout_build_install_llvm.sh │ │ │ ├── checkout_build_install_llvm_ubuntu_20_04.sh │ │ │ ├── checkout_build_install_llvm_ubuntu_24_04.sh │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-image/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-runner/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── bad_build_check │ │ │ ├── coverage │ │ │ ├── coverage_helper │ │ │ ├── download_corpus │ │ │ ├── generate_differential_cov_report.py │ │ │ ├── gocoverage/ │ │ │ │ ├── go.mod │ │ │ │ ├── go.sum │ │ │ │ ├── gocovmerge/ │ │ │ │ │ ├── LICENSE │ │ │ │ │ └── gocovmerge.go │ │ │ │ ├── gocovsum/ │ │ │ │ │ └── gocovsum.go │ │ │ │ └── pprof-merge/ │ │ │ │ ├── LICENSE │ │ │ │ └── main.go │ │ │ ├── install_deps.sh │ │ │ ├── install_deps_ubuntu_20_04.sh │ │ │ ├── install_deps_ubuntu_24_04.sh │ │ │ ├── install_go.sh │ │ │ ├── install_java.sh │ │ │ ├── install_javascript.sh │ │ │ ├── jacoco_report_converter.py │ │ │ ├── nyc_report_converter.py │ │ │ ├── parse_options.py │ │ │ ├── profraw_update.py │ │ │ ├── python_coverage_runner_help.py │ │ │ ├── rcfilt │ │ │ ├── reproduce │ │ │ ├── run_fuzzer │ │ │ ├── ruzzy │ │ │ ├── targets_list │ │ │ ├── test_all.py │ │ │ ├── test_all_test.py │ │ │ ├── test_one.py │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── base-runner-debug/ │ │ │ ├── CHANGELOG.md │ │ │ ├── Dockerfile │ │ │ ├── ubuntu-20-04.Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ └── list_images.py │ ├── bisector.py │ ├── bisector_test.py │ ├── build/ │ │ ├── blog/ │ │ │ ├── .gitignore │ │ │ ├── Dockerfile │ │ │ ├── build_blog.sh │ │ │ ├── content/ │ │ │ │ ├── about.md │ │ │ │ └── posts/ │ │ │ │ ├── introducing-java-auto-harnessing.md │ │ │ │ ├── introducing-llm-based-harness-synthesis-for-unfuzzed-projects.md │ │ │ │ ├── oss-fuzz-hello-world.md │ │ │ │ └── oss-fuzz-integrations-via-agent-based-build-generation.md │ │ │ └── hugo.toml │ │ ├── build_status/ │ │ │ ├── Dockerfile │ │ │ ├── cloudbuild.yaml │ │ │ ├── fuzz_introspector_page_gen.py │ │ │ ├── update_build_status.py │ │ │ └── update_build_status_test.py │ │ ├── functions/ │ │ │ ├── __init__.py │ │ │ ├── base_images.py │ │ │ ├── build_and_push_test_images.py │ │ │ ├── build_and_run_coverage.py │ │ │ ├── build_and_run_coverage_test.py │ │ │ ├── build_lib.py │ │ │ ├── build_project.py │ │ │ ├── build_project_test.py │ │ │ ├── datastore_entities.py │ │ │ ├── deploy.sh │ │ │ ├── fuzzbench.py │ │ │ ├── fuzzbench_local_run.py │ │ │ ├── fuzzbench_test.py │ │ │ ├── gcb.py │ │ │ ├── gcb_test.py │ │ │ ├── index.yaml │ │ │ ├── indexer_build_test.py │ │ │ ├── main.py │ │ │ ├── ood.Dockerfile │ │ │ ├── ood_upload_corpus.py │ │ │ ├── ood_upload_corpus_test.py │ │ │ ├── ood_upload_testcase.py │ │ │ ├── ood_upload_testcase_test.py │ │ │ ├── oss_fuzz_on_demand.py │ │ │ ├── project_experiment.py │ │ │ ├── project_sync.py │ │ │ ├── project_sync_test.py │ │ │ ├── report_generator.py │ │ │ ├── request_build.py │ │ │ ├── request_build_test.py │ │ │ ├── request_coverage_build.py │ │ │ ├── request_coverage_build_test.py │ │ │ ├── request_introspector_build.py │ │ │ ├── request_introspector_build_test.py │ │ │ ├── requirements.txt │ │ │ ├── target_experiment.py │ │ │ ├── test_data/ │ │ │ │ ├── expected_build_steps.json │ │ │ │ ├── expected_build_steps_ubuntu_24_04.json │ │ │ │ ├── expected_centipede_build_steps.json │ │ │ │ ├── expected_coverage_build_steps.json │ │ │ │ └── expected_trial_build_steps.json │ │ │ ├── test_utils.py │ │ │ ├── trial_build/ │ │ │ │ ├── Dockerfile │ │ │ │ └── cloudbuild.yaml │ │ │ ├── trial_build.py │ │ │ └── trial_build_test.py │ │ ├── fuzz-introspector-webapp/ │ │ │ ├── Dockerfile │ │ │ └── cloudbuild.yaml │ │ ├── request_all_builds.sh │ │ ├── request_build.sh │ │ └── status/ │ │ ├── bower.json │ │ ├── deploy.sh │ │ ├── index.html │ │ ├── manifest.json │ │ ├── polymer.json │ │ └── src/ │ │ └── build-status/ │ │ └── build-status.html │ ├── build_fuzzers.Dockerfile │ ├── build_fuzzers.ubuntu-24-04.Dockerfile │ ├── build_specified_commit.py │ ├── build_specified_commit_test.py │ ├── chronos/ │ │ ├── README.md │ │ ├── __init__.py │ │ ├── container_cache_build.sh │ │ ├── container_coverage_collection.sh │ │ ├── container_patch_replay_test.sh │ │ ├── container_patch_tests_test.sh │ │ ├── coverage_test_collection.py │ │ ├── integrity_validator_check_replay.py │ │ ├── integrity_validator_run_tests.py │ │ ├── manager.py │ │ └── requirements.txt │ ├── ci/ │ │ ├── build.py │ │ ├── build_test.py │ │ ├── check_base_os.py │ │ └── requirements.txt │ ├── cifuzz/ │ │ ├── CHANGELOG │ │ ├── actions/ │ │ │ ├── build_fuzzers/ │ │ │ │ └── action.yml │ │ │ └── run_fuzzers/ │ │ │ └── action.yml │ │ ├── affected_fuzz_targets.py │ │ ├── affected_fuzz_targets_test.py │ │ ├── base_runner_utils.py │ │ ├── build-images.sh │ │ ├── build_fuzzers.py │ │ ├── build_fuzzers_entrypoint.py │ │ ├── build_fuzzers_test.py │ │ ├── cifuzz-base/ │ │ │ ├── Dockerfile │ │ │ └── ubuntu-24-04.Dockerfile │ │ ├── cifuzz_combined_entrypoint.py │ │ ├── cifuzz_end_to_end_test.py │ │ ├── cloudbuild.yaml │ │ ├── clusterfuzz_deployment.py │ │ ├── clusterfuzz_deployment_test.py │ │ ├── config_utils.py │ │ ├── config_utils_test.py │ │ ├── continuous_integration.py │ │ ├── continuous_integration_test.py │ │ ├── docker.py │ │ ├── docker_test.py │ │ ├── environment.py │ │ ├── example_cifuzz.yml │ │ ├── external-actions/ │ │ │ ├── build_fuzzers/ │ │ │ │ └── action.yml │ │ │ └── run_fuzzers/ │ │ │ └── action.yml │ │ ├── filestore/ │ │ │ ├── __init__.py │ │ │ ├── filesystem/ │ │ │ │ └── __init__.py │ │ │ ├── git/ │ │ │ │ ├── __init__.py │ │ │ │ └── git_test.py │ │ │ ├── github_actions/ │ │ │ │ ├── __init__.py │ │ │ │ ├── github_actions_test.py │ │ │ │ ├── github_api.py │ │ │ │ ├── github_api_test.py │ │ │ │ └── upload.js │ │ │ ├── gitlab/ │ │ │ │ └── __init__.py │ │ │ ├── gsutil/ │ │ │ │ └── __init__.py │ │ │ └── no_filestore/ │ │ │ └── __init__.py │ │ ├── filestore_utils.py │ │ ├── filestore_utils_test.py │ │ ├── fuzz_target.py │ │ ├── fuzz_target_test.py │ │ ├── generate_coverage_report.py │ │ ├── generate_coverage_report_test.py │ │ ├── get_coverage.py │ │ ├── get_coverage_test.py │ │ ├── http_utils.py │ │ ├── http_utils_test.py │ │ ├── logs.py │ │ ├── package.json │ │ ├── platform_config/ │ │ │ ├── __init__.py │ │ │ ├── gcb.py │ │ │ ├── github.py │ │ │ ├── github_test.py │ │ │ ├── gitlab.py │ │ │ ├── platform_config_test.py │ │ │ ├── prow.py │ │ │ └── standalone.py │ │ ├── requirements.txt │ │ ├── run_cifuzz.py │ │ ├── run_fuzzers.py │ │ ├── run_fuzzers_entrypoint.py │ │ ├── run_fuzzers_test.py │ │ ├── sarif_utils.py │ │ ├── sarif_utils_test.py │ │ ├── test_data/ │ │ │ ├── TimeoutFuzzer.cpp │ │ │ ├── build-out/ │ │ │ │ ├── example_crash_fuzzer │ │ │ │ └── example_nocrash_fuzzer │ │ │ ├── example_coverage_report_summary.json │ │ │ ├── example_crash_fuzzer_bug_summary.txt │ │ │ ├── example_crash_fuzzer_output.txt │ │ │ ├── example_curl_cov.json │ │ │ ├── example_curl_file_list.json │ │ │ ├── example_curl_fuzzer_cov.json │ │ │ ├── external-project/ │ │ │ │ ├── .clusterfuzzlite/ │ │ │ │ │ ├── Dockerfile │ │ │ │ │ └── build.sh │ │ │ │ ├── Makefile │ │ │ │ ├── do_stuff_fuzzer.cpp │ │ │ │ ├── do_stuff_fuzzer.dict │ │ │ │ ├── my_api.cpp │ │ │ │ ├── my_api.h │ │ │ │ └── standalone_fuzz_target_runner.cpp │ │ │ ├── memory/ │ │ │ │ └── build-out/ │ │ │ │ └── curl_fuzzer_memory │ │ │ ├── msan_crash_fuzzer_bug_summary.txt │ │ │ ├── msan_crash_fuzzer_output.txt │ │ │ ├── sarif_utils_msan_stack.txt │ │ │ ├── sarif_utils_only_llvmfuzzer_stack.txt │ │ │ ├── sarif_utils_systemd_stack.txt │ │ │ ├── timeout_fuzzer │ │ │ └── undefined/ │ │ │ └── build-out/ │ │ │ └── curl_fuzzer_undefined │ │ ├── test_helpers.py │ │ └── workspace_utils.py │ ├── common_utils.py │ ├── constants.py │ ├── experimental/ │ │ ├── SystemSan/ │ │ │ ├── Makefile │ │ │ ├── PoEs/ │ │ │ │ ├── node-shell-quote-v1.7.3/ │ │ │ │ │ ├── Dockerfile │ │ │ │ │ ├── Makefile │ │ │ │ │ ├── build.sh │ │ │ │ │ └── target.js │ │ │ │ └── pytorch-lightning-1.5.10/ │ │ │ │ ├── Dockerfile │ │ │ │ ├── Makefile │ │ │ │ ├── build.sh │ │ │ │ ├── fuzz_pytorch_lightning.py │ │ │ │ └── vuln.dict │ │ │ ├── README.md │ │ │ ├── SystemSan.cpp │ │ │ ├── inspect_dns.cpp │ │ │ ├── inspect_dns.h │ │ │ ├── inspect_utils.cpp │ │ │ ├── inspect_utils.h │ │ │ ├── target.cpp │ │ │ ├── target_dns.cpp │ │ │ ├── target_file.cpp │ │ │ └── vuln.dict │ │ ├── chronos/ │ │ │ ├── Dockerfile │ │ │ ├── README.md │ │ │ ├── build_all.sh │ │ │ ├── build_cache_local.sh │ │ │ ├── build_on_cloudbuild.sh │ │ │ ├── check_tests.sh │ │ │ ├── chronos.sh │ │ │ ├── cloudbuild.yaml │ │ │ ├── cloudbuild_all.yaml │ │ │ ├── e2e-replay-build.sh │ │ │ ├── match_artifacts.sh │ │ │ ├── prepare-ccache │ │ │ ├── prepare-replay-rebuild │ │ │ └── requirements.txt │ │ ├── contrib/ │ │ │ └── arvo/ │ │ │ ├── LICENSE │ │ │ ├── __init__.py │ │ │ ├── arvo_data.py │ │ │ ├── arvo_reproducer.py │ │ │ ├── arvo_reproducer_test.py │ │ │ ├── arvo_utils.py │ │ │ ├── component_fixes.json │ │ │ ├── hacks/ │ │ │ │ ├── __init__.py │ │ │ │ ├── cryptofuzz.py │ │ │ │ ├── dlplibs.py │ │ │ │ ├── duckdb.py │ │ │ │ ├── ffmpeg.py │ │ │ │ ├── ghostscript.py │ │ │ │ ├── gnutls.py │ │ │ │ ├── graphicsmagick.py │ │ │ │ ├── imagemagick.py │ │ │ │ ├── jbig2dec.py │ │ │ │ ├── lcms.py │ │ │ │ ├── libheif.py │ │ │ │ ├── libredwg.py │ │ │ │ ├── libreoffice.py │ │ │ │ ├── libyang.py │ │ │ │ ├── lwan.py │ │ │ │ ├── openh264.py │ │ │ │ ├── quickjs.py │ │ │ │ ├── radare2.py │ │ │ │ ├── skia.py │ │ │ │ ├── uwebsockets.py │ │ │ │ ├── wireshark.py │ │ │ │ ├── wolfssl.py │ │ │ │ └── yara.py │ │ │ └── string_replacement.json │ │ ├── mcp/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── client.py │ │ │ ├── config.py │ │ │ ├── oss_fuzz_server.py │ │ │ └── requirements.txt │ │ └── sanitizers/ │ │ └── ExecSan/ │ │ └── README.md │ ├── helper.py │ ├── helper_test.py │ ├── indexer/ │ │ ├── CMakeLists.txt │ │ ├── Dockerfile │ │ ├── frontend/ │ │ │ ├── ast_visitor.cc │ │ │ ├── ast_visitor.h │ │ │ ├── common.cc │ │ │ ├── common.h │ │ │ ├── frontend.cc │ │ │ ├── frontend.h │ │ │ ├── frontend_test.cc │ │ │ ├── index_action.cc │ │ │ ├── index_action.h │ │ │ ├── pp_callbacks.cc │ │ │ └── pp_callbacks.h │ │ ├── index/ │ │ │ ├── file_copier.cc │ │ │ ├── file_copier.h │ │ │ ├── file_copier_unittest.cc │ │ │ ├── in_memory_index.cc │ │ │ ├── in_memory_index.h │ │ │ ├── in_memory_index_unittest.cc │ │ │ ├── sqlite.cc │ │ │ ├── sqlite.h │ │ │ ├── types.cc │ │ │ ├── types.h │ │ │ └── types_unittest.cc │ │ ├── init.h │ │ ├── main.cc │ │ ├── merge_queue.cc │ │ ├── merge_queue.h │ │ ├── queue_state.cc │ │ ├── queue_state.h │ │ ├── ubuntu-20-04.Dockerfile │ │ └── ubuntu-24-04.Dockerfile │ ├── manifest.py │ ├── pr_helper.py │ ├── presubmit.py │ ├── pytest.ini │ ├── repo_manager.py │ ├── repo_manager_test.py │ ├── retry.py │ ├── run_fuzzers.Dockerfile │ ├── run_fuzzers.ubuntu-24-04.Dockerfile │ ├── templates.py │ ├── test │ ├── test_repos.py │ ├── tools/ │ │ ├── hold_back_images.py │ │ └── wycheproof/ │ │ ├── .gitignore │ │ ├── generate_job.py │ │ ├── launcher.py │ │ ├── package.bash │ │ └── run.py │ ├── uploader/ │ │ └── Dockerfile │ ├── utils.py │ └── utils_test.py ├── projects/ │ ├── abseil-cpp/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── WORKSPACE │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── string_escape_fuzzer.cc │ │ └── string_utilities_fuzzer.cc │ ├── abseil-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_argparse.py │ │ └── project.yaml │ ├── ada-url/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── adal/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_util.py │ │ ├── fuzz_xmlutil.py │ │ └── project.yaml │ ├── aiohttp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_http_parser.py │ │ ├── fuzz_http_payload_parser.py │ │ ├── fuzz_multipart.py │ │ ├── fuzz_payload_url.py │ │ ├── fuzz_web_request.py │ │ └── project.yaml │ ├── airflow/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── dag_fuzz.py │ │ └── project.yaml │ ├── alembic/ │ │ ├── Dockerfile │ │ ├── alembic_dump_info_fuzzer.cc │ │ ├── build.sh │ │ ├── fuzzer_temp_file.h │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── ampproject/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_patch.diff │ │ └── project.yaml │ ├── angle/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_sha1.cc │ │ ├── fuzzer_profile │ │ └── project.yaml │ ├── angular/ │ │ ├── Dockerfile │ │ ├── babel.config.json │ │ ├── build.sh │ │ ├── compiler/ │ │ │ └── fuzz_tests/ │ │ │ ├── fuzz_parse_template.js │ │ │ └── fuzz_parser.js │ │ └── project.yaml │ ├── angus-mail/ │ │ ├── ASCIIUtilityFuzzer.java │ │ ├── BASE64EncoderStreamFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── anise/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── aniso8601/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_aniso8601.py │ │ └── project.yaml │ ├── ansible/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_encrypt.py │ │ ├── fuzz_encrypt.sh │ │ ├── fuzz_parse.py │ │ ├── fuzz_task.py │ │ └── project.yaml │ ├── antlr3-java/ │ │ ├── Dockerfile │ │ ├── GrammarFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── antlr4-java/ │ │ ├── Dockerfile │ │ ├── GrammarFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-axis2/ │ │ ├── Dockerfile │ │ ├── axis-axis2-java-core-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ ├── org/ │ │ │ │ └── apache/ │ │ │ │ └── axis2/ │ │ │ │ └── HttpInterfaceFuzzer.java │ │ │ └── samples/ │ │ │ └── quickstart/ │ │ │ └── service/ │ │ │ └── pojo/ │ │ │ └── StockQuoteService.java │ │ ├── build.sh │ │ ├── maven-settings.xml │ │ └── project.yaml │ ├── apache-commons-bcel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ ├── remove-rat.diff │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── BcelFuzzer.java │ ├── apache-commons-beanutils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── BeanutilsFuzzer.java │ ├── apache-commons-cli/ │ │ ├── Dockerfile │ │ ├── ParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-codec/ │ │ ├── BinaryEncodingFuzzer.java │ │ ├── ChecksumFuzzer.java │ │ ├── CryptFuzzer.java │ │ ├── DigestUtilsFuzzer.java │ │ ├── Dockerfile │ │ ├── HmacUtilsFuzzer.java │ │ ├── LanguageStringEncoderFuzzer.java │ │ ├── MurmurHashFuzzer.java │ │ ├── NetCodecFuzzer.java │ │ ├── PhoneticEngineFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-collections/ │ │ ├── CollectionsBidiMapFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-compress/ │ │ ├── ArchiverArFuzzer.java │ │ ├── ArchiverArjFuzzer.java │ │ ├── ArchiverCpioFuzzer.java │ │ ├── ArchiverDumpFuzzer.java │ │ ├── ArchiverTarStreamFuzzer.java │ │ ├── ArchiverZipStreamFuzzer.java │ │ ├── BaseTests.java │ │ ├── CompressSevenZFuzzer.java │ │ ├── CompressTarFuzzer.java │ │ ├── CompressZipFuzzer.java │ │ ├── CompressorBZip2Fuzzer.java │ │ ├── CompressorDeflate64Fuzzer.java │ │ ├── CompressorGzipFuzzer.java │ │ ├── CompressorLZ4Fuzzer.java │ │ ├── CompressorPack200Fuzzer.java │ │ ├── CompressorSnappyFuzzer.java │ │ ├── CompressorZFuzzer.java │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-configuration/ │ │ ├── Dockerfile │ │ ├── INIConfigurationReadFuzzer.java │ │ ├── INIConfigurationWriteFuzzer.java │ │ ├── JSONConfigurationReadFuzzer.java │ │ ├── JSONConfigurationWriteFuzzer.java │ │ ├── XMLConfigurationLoadFuzzer.java │ │ ├── XMLConfigurationWriteFuzzer.java │ │ ├── YAMLConfigurationReadFuzzer.java │ │ ├── YAMLConfigurationWriteFuzzer.java │ │ ├── build.sh │ │ ├── ini.dict │ │ └── project.yaml │ ├── apache-commons-csv/ │ │ ├── CSVParserFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-fileupload/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── Constants.java │ │ │ │ ├── FileUploadFuzzer.java │ │ │ │ ├── MockHttpServletRequest.java │ │ │ │ └── Util.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── apache-commons-geometry/ │ │ ├── Dockerfile │ │ ├── GeometryObjFuzzer.java │ │ ├── GeometryStlBinaryFuzzer.java │ │ ├── GeometryStlTextFuzzer.java │ │ ├── GeometryTextFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-imaging/ │ │ ├── Dockerfile │ │ ├── ImagingBmpFuzzer.java │ │ ├── ImagingGifFuzzer.java │ │ ├── ImagingJpegFuzzer.java │ │ ├── ImagingPngFuzzer.java │ │ ├── ImagingTiffFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-io/ │ │ ├── Dockerfile │ │ ├── FileComparatorFuzzer.java │ │ ├── FileFilterFuzzer.java │ │ ├── FileUtilsFuzzer.java │ │ ├── GeneralUtilsFuzzer.java │ │ ├── InputStreamFuzzer.java │ │ ├── InputXmlFuzzer.java │ │ ├── OutputStreamFuzzer.java │ │ ├── PathUtilsFuzzer.java │ │ ├── ReaderFuzzer.java │ │ ├── WriterFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-jxpath/ │ │ ├── Dockerfile │ │ ├── JXPathFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-lang/ │ │ ├── AnnotationUtilsFuzzer.java │ │ ├── ArrayUtilsFuzzer.java │ │ ├── BuilderFuzzer.java │ │ ├── CharUtilsFuzzer.java │ │ ├── ClassFuzzerBase.java │ │ ├── ConversionFuzzer.java │ │ ├── DateUtilsFuzzer.java │ │ ├── Dockerfile │ │ ├── EscapeHtmlFuzzer.java │ │ ├── FractionFuzzer.java │ │ ├── LocaleUtilsFuzzer.java │ │ ├── MathUtilsFuzzer.java │ │ ├── ReflectUtilsFuzzer.java │ │ ├── SerializationUtilsFuzzer.java │ │ ├── StringEscapeUtilsFuzzer.java │ │ ├── StringUtilsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-logging/ │ │ ├── Dockerfile │ │ ├── LoggingBasicFuzzer.java │ │ ├── Package/ │ │ │ └── MyAppender.java │ │ ├── build.sh │ │ ├── log4j2-test.xml │ │ └── project.yaml │ ├── apache-commons-math/ │ │ ├── Dockerfile │ │ ├── MathClusteringFuzzer.java │ │ ├── MathDistanceMeasureFuzzer.java │ │ ├── MathSimplexSolverFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-net/ │ │ ├── Base64Fuzzer.java │ │ ├── Dockerfile │ │ ├── MLSxEntryParserFuzzer.java │ │ ├── NTFTPEntryParserFuzzer.java │ │ ├── OS400FTPEntryParserFuzzer.java │ │ ├── TelnetOptionFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-commons-text/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── StringSubstitutorFuzzer.java │ │ │ │ └── StringSubstitutorInterpolatorFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── apache-commons-validator/ │ │ ├── CreditCardValidatorFuzzer.java │ │ ├── Dockerfile │ │ ├── IBANValidatorFuzzer.java │ │ ├── UrlValidator2Fuzzer.java │ │ ├── UrlValidatorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-cxf/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── AttachmentDeserializerFuzzer.java │ │ │ │ ├── AttachmentSerializerDeserializerFuzzer.java │ │ │ │ ├── JsonMapObjectReaderWriterFuzzer.java │ │ │ │ └── XMLStreamReadersFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── apache-doris/ │ │ └── project.yaml │ ├── apache-felix-dev/ │ │ ├── Dockerfile │ │ ├── JSONParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── apache-httpd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_addr_parse.c │ │ ├── fuzz_parse.c │ │ ├── fuzz_preq.c │ │ ├── fuzz_request.c │ │ ├── fuzz_tokenize.c │ │ ├── fuzz_uri.c │ │ ├── fuzz_utils.c │ │ └── project.yaml │ ├── apache-logging-log4cxx/ │ │ ├── Dockerfile │ │ ├── README.adoc │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── apache-poi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── resources/ │ │ └── log4j2.xml │ ├── apache-tika/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── build_seeds.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── main/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── example/ │ │ │ │ │ ├── AudioVideoParsersFuzzer.java │ │ │ │ │ ├── AutoDetectParserFuzzer.java │ │ │ │ │ ├── CompressorParserFuzzer.java │ │ │ │ │ ├── HtmlParserFuzzer.java │ │ │ │ │ ├── ImageParsersFuzzer.java │ │ │ │ │ ├── JackcessParserFuzzer.java │ │ │ │ │ ├── OOXMLParserFuzzer.java │ │ │ │ │ ├── OfficeParserFuzzer.java │ │ │ │ │ ├── OneNoteParserFuzzer.java │ │ │ │ │ ├── PDFParserFuzzer.java │ │ │ │ │ ├── PackageParserFuzzer.java │ │ │ │ │ ├── ParserFuzzer.java │ │ │ │ │ ├── RFC822ParserFuzzer.java │ │ │ │ │ ├── RTFParserFuzzer.java │ │ │ │ │ ├── TextAndCSVParserFuzzer.java │ │ │ │ │ └── XMLReaderUtilsFuzzer.java │ │ │ │ └── resources/ │ │ │ │ ├── log4j2.xml │ │ │ │ └── tika-config.xml │ │ │ └── pom.xml │ │ └── project.yaml │ ├── aptos-core/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── archaius-core/ │ │ ├── Dockerfile │ │ ├── DynamicPropertyFuzzer.java │ │ ├── build.sh │ │ ├── pom-core.xml │ │ └── project.yaml │ ├── arduinojson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── argcomplete/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_shlex.py │ │ └── project.yaml │ ├── argo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── args/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── args4j/ │ │ ├── CmdLineParserFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── arrow/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── arrow-java/ │ │ ├── Dockerfile │ │ ├── FuzzIpcFile.java │ │ ├── FuzzIpcStream.java │ │ ├── build.sh │ │ └── project.yaml │ ├── arrow-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_datetime.py │ │ ├── fuzz_tzinfo.py │ │ └── project.yaml │ ├── askama/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── asn1crypto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── aspectj/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── ASTFuzzer.java │ ├── aspell/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── assimp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── astc-encoder/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── asteval/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_eval.py │ │ └── project.yaml │ ├── astro-compiler/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── astroid/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── asttokens/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_asttokens.py │ │ └── project.yaml │ ├── async-http-client/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── AsyncHttpClientFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── atomic/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── attrs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_attrs.py │ │ └── project.yaml │ ├── augeas/ │ │ ├── Dockerfile │ │ ├── augeas_api_fuzzer.cc │ │ ├── augeas_escape_name_fuzzer.cc │ │ ├── augeas_fa_fuzzer.cc │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── autoflake/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fix_code.py │ │ └── project.yaml │ ├── autopep8/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fix_file.py │ │ └── project.yaml │ ├── avahi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── avro/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── AvroSerializationFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── azure-sdk-for-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_mgmt_serialization.py │ │ └── project.yaml │ ├── babel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_lexer.py │ │ ├── fuzz_profile.py │ │ └── project.yaml │ ├── bad_example/ │ │ ├── Dockerfile │ │ ├── bad_example_fuzzer.cc │ │ ├── build.sh │ │ └── project.yaml │ ├── bazel-rules-fuzzing-test/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bazel-rules-fuzzing-test-java/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bc-gh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bc-java/ │ │ ├── CMSEnvelopedDataParserFuzzer.java │ │ ├── Dockerfile │ │ ├── EncodingFuzzer.java │ │ ├── PEMParserFuzzer.java │ │ ├── X509CertPairParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── bearssl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── behaviortreecpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── bignum-fuzzer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bincode/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bind9/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── patch.diff │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── binutils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_addr2line.c │ │ ├── fuzz_as.c │ │ ├── fuzz_bfd.c │ │ ├── fuzz_bfd_ext.c │ │ ├── fuzz_disas_ext.c │ │ ├── fuzz_disassemble.c │ │ ├── fuzz_dlltool.c │ │ ├── fuzz_dwarf.c │ │ ├── fuzz_nm.c │ │ ├── fuzz_objcopy.c │ │ ├── fuzz_objdump.c │ │ ├── fuzz_ranlib_simulation.c │ │ ├── fuzz_readelf.c │ │ ├── fuzz_strings.c │ │ ├── fuzz_windres.c │ │ └── project.yaml │ ├── bios-bmc-smm-error-logger/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-patch.diff │ │ └── project.yaml │ ├── bitcoin-core/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── descriptor_parse.options │ │ ├── i2p.options │ │ ├── miniscript_string.options │ │ ├── process_messages.options │ │ └── project.yaml │ ├── black/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_format_filecontents.py │ │ ├── fuzz_lib2to3_parse.py │ │ ├── fuzz_raw_format_filecontents.py │ │ └── project.yaml │ ├── blackfriday/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── render_fuzzer.go │ ├── bleach/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── linkify_fuzzer.py │ │ ├── project.yaml │ │ └── sanitize_fuzzer.py │ ├── bloaty/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bls-signatures/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bluez/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_gobex.c │ │ ├── fuzz_hci.c │ │ ├── fuzz_sdp.c │ │ ├── fuzz_textfile.c │ │ ├── fuzz_xml.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── bmcweb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── content_type_fuzzer.cpp │ │ ├── filter_expr_fuzzer.cpp │ │ ├── json_html_serializer_fuzzer.cpp │ │ ├── json_parser_fuzzer.cpp │ │ ├── multipart_parser_fuzzer.cpp │ │ └── project.yaml │ ├── boost/ │ │ ├── Dockerfile │ │ ├── boost_datetime_fuzzer.cc │ │ ├── boost_filesystem_fuzzer.cc │ │ ├── boost_graph_graphml_fuzzer.cc │ │ ├── boost_graph_graphviz_fuzzer.cc │ │ ├── boost_programoptions_fuzzer.cc │ │ ├── boost_ptree_inforead_fuzzer.cc │ │ ├── boost_ptree_iniread_fuzzer.cc │ │ ├── boost_ptree_jsonread_fuzzer.cc │ │ ├── boost_ptree_xmlread_fuzzer.cc │ │ ├── boost_regex_fuzzer.cc │ │ ├── boost_regex_pattern_fuzzer.cc │ │ ├── boost_regex_replace_fuzzer.cc │ │ ├── boost_stralg_fuzzer.cc │ │ ├── boost_uuid_fuzzer.cc │ │ ├── build.sh │ │ └── project.yaml │ ├── boost-beast/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── boost-json/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── boringssl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_certs.cc │ │ ├── fuzz_pkcs12.cc │ │ ├── fuzz_pkcs8.cc │ │ └── project.yaml │ ├── botan/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── botocore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_serialization.py │ │ └── project.yaml │ ├── bottleneck/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_bn.py │ │ └── project.yaml │ ├── brotli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── brotli-java/ │ │ ├── Dockerfile │ │ ├── FuzzDecode.java │ │ ├── build.sh │ │ └── project.yaml │ ├── brpc/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── brunsli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── bs4/ │ │ ├── Dockerfile │ │ ├── bs4_fuzzer.py │ │ ├── build.sh │ │ └── project.yaml │ ├── bson-rust/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── burntsushi-toml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── bz2file/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_bz2file.py │ │ └── project.yaml │ ├── bzip2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── bzip2_compress_target.c │ │ ├── bzip2_decompress_target.c │ │ ├── bzip2_fd.c │ │ ├── bzip2_filename.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── c-ares/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── c-blosc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── c-blosc2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cachetools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cached.py │ │ └── project.yaml │ ├── caddy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── caffeine/ │ │ ├── CaffeineSpecFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cairo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── targets/ │ │ ├── fuzzer_temp_file.h │ │ ├── pdf_surface_fuzzer.c │ │ ├── raster_fuzzer.c │ │ ├── surface_write_png_fuzzer.c │ │ └── text_glyphs_fuzzer.c │ ├── calcite/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── CalciteFuzzer.java │ │ │ │ └── SqlParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── calcite-avatica/ │ │ ├── Base64Fuzzer.java │ │ ├── ConnectStringParserFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── canvg/ │ │ ├── Dockerfile │ │ ├── babel.config.json │ │ ├── build.sh │ │ ├── fuzz.js │ │ ├── package.patch │ │ └── project.yaml │ ├── capnproto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── capstone/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cascadia/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── casync/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── catapult/ │ │ └── project.yaml │ ├── cbor-java/ │ │ ├── Dockerfile │ │ ├── FuzzDec.java │ │ ├── build.sh │ │ └── project.yaml │ ├── cbor2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cctz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cctz.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cel-cpp/ │ │ ├── .bazelrc │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── MODULE.bazel │ │ ├── WORKSPACE │ │ ├── build.sh │ │ ├── fuzz_parse.cc │ │ └── project.yaml │ ├── cel-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── cel-go-lpm.proto │ │ ├── fuzz_compile.go │ │ ├── fuzz_env.go │ │ ├── fuzz_eval.go │ │ ├── go-lpm.cc │ │ └── project.yaml │ ├── cert-manager/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pki_fuzzer.go │ │ └── project.yaml │ ├── cfengine/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── string_fuzzer.c │ ├── cffi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_recompiler.py │ │ └── project.yaml │ ├── cgif/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cglib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── EnhancerFuzzer.java │ ├── chardet/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_detector.py │ │ └── project.yaml │ ├── charset_normalizer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_normalize.py │ │ └── project.yaml │ ├── checker-framework/ │ │ ├── Dockerfile │ │ ├── UtilCheckerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── checkstyle/ │ │ ├── CheckstyleFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── chrono/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cifuzz-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cilium/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── circl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cirq/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_circuit.py │ │ └── project.yaml │ ├── civetweb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cjson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── clamav/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── clamav-scanfile-fuzzer.options │ │ ├── project.yaml │ │ └── replay_build.sh │ ├── clib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── click/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── clickhouse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── clock/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── closure-compiler/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── ParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── closure-library/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── cloud-custodian/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_actions_parser.py │ │ ├── fuzz_actions_process.py │ │ ├── fuzz_actions_validate.py │ │ ├── fuzz_filters_parser.py │ │ ├── fuzz_filters_process.py │ │ ├── fuzz_filters_validate.py │ │ ├── fuzz_gcp_actions_validate_process.py │ │ ├── fuzz_gcp_filters_validate_process.py │ │ ├── fuzz_gcp_resources_process.py │ │ ├── fuzz_query_parser.py │ │ ├── fuzz_resources_parser.py │ │ ├── fuzz_resources_process.py │ │ ├── fuzz_resources_validate.py │ │ └── project.yaml │ ├── cloud-hypervisor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cmake/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cmark/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── cmark_fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cockroachdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── compress/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── config-validator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── configparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_dict.py │ │ ├── fuzz_read.py │ │ └── project.yaml │ ├── connectedhomeip/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── connexion/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_query_resolving.py │ │ └── project.yaml │ ├── containerd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── coreutils/ │ │ └── project.yaml │ ├── cosign/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cosmos-sdk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── coturn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── coveragepy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── cpp-httplib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cppcheck/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cppitertools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cppitertools.cpp │ │ └── project.yaml │ ├── cpuinfo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cpuinfo.c │ │ └── project.yaml │ ├── cpython3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cras/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cri-o/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── croaring/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cron-utils/ │ │ ├── CronParserFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── croniter/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_iter.py │ │ ├── fuzz_match.py │ │ ├── fuzz_range.py │ │ └── project.yaml │ ├── crossplane/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── crosvm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── crow/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cryptofuzz/ │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── build.sh │ │ ├── project.yaml │ │ └── xxd.c │ ├── cryptography/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_aead.py │ │ ├── fuzz_dh.py │ │ ├── fuzz_dsa.py │ │ ├── fuzz_rsa.py │ │ ├── fuzz_sym.py │ │ └── project.yaml │ ├── cryptsetup/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cssselect/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ ├── fuzz_xpath.py │ │ └── project.yaml │ ├── cubefs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── cups/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── test_patch.diff │ ├── cups-filters/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cura-engine/ │ │ └── project.yaml │ ├── curl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── curvesapi/ │ │ ├── Dockerfile │ │ ├── ParseFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── cxxopts/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── cyclonedds/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── d3/ │ │ ├── Dockerfile │ │ ├── babel.config.json │ │ ├── build.sh │ │ ├── fuzz_tests/ │ │ │ └── fuzz_csv_parse.js │ │ └── project.yaml │ ├── dapr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dart/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── patch.diff │ │ └── project.yaml │ ├── dask/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fuse.py │ │ ├── fuzz_serialize.py │ │ └── project.yaml │ ├── data-encoding/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── date/ │ │ └── project.yaml │ ├── dateparser/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── dav1d/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── linux32.meson │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── dbus-broker/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-message.c │ │ └── project.yaml │ ├── dcmtk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── dcmtk_dicom_fuzzer.cc │ │ ├── dcmtk_dicom_fuzzer.dict │ │ ├── dcmtk_meta_fuzzer.cc │ │ ├── make_seed_corpus.py │ │ └── project.yaml │ ├── decorator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decorator.py │ │ ├── fuzz_funcmarker.py │ │ └── project.yaml │ ├── defusedxml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_etree_parse.py │ │ ├── fuzz_parse_string.py │ │ └── project.yaml │ ├── demangle/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── deno/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dgraph/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser_test.go │ │ └── project.yaml │ ├── digest/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_digest.py │ │ └── project.yaml │ ├── dill/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_dumps.py │ │ └── project.yaml │ ├── distlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_marker.py │ │ ├── fuzz_metadata.py │ │ └── project.yaml │ ├── distribution/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── django/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dlplibs/ │ │ ├── Dockerfile │ │ ├── abwfuzzer.options │ │ ├── build.sh │ │ ├── fb2fuzzer.options │ │ ├── icu4c-ubsan.patch │ │ ├── ofz2894.patch │ │ ├── ofz3670.patch │ │ ├── ofz4303.patch │ │ ├── ofz4860.patch │ │ ├── project.yaml │ │ ├── vdxfuzzer.options │ │ └── vsdxfuzzer.options │ ├── dng_sdk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── dng_camera_profile_fuzzer.cpp │ │ ├── dng_fixed_validate_fuzzer.cpp │ │ ├── dng_stage_fuzzer.cpp │ │ ├── dng_validate_fuzzer.cpp │ │ └── project.yaml │ ├── dnsmasq/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_auth.c │ │ ├── fuzz_dhcp.c │ │ ├── fuzz_dhcp6.c │ │ ├── fuzz_header.h │ │ ├── fuzz_patch.patch │ │ ├── fuzz_rfc1035.c │ │ ├── fuzz_util.cc │ │ └── project.yaml │ ├── dnspython/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_message.py │ │ ├── fuzz_token.py │ │ └── project.yaml │ ├── docker-client/ │ │ ├── Dockerfile │ │ ├── RegistryAuthFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── docutils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_rst.py │ │ ├── fuzz_rst_parse.py │ │ ├── fuzz_table.py │ │ └── project.yaml │ ├── dom4j/ │ │ ├── DOMReaderFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── double-conversion/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── string_to_double_fuzzer.cc │ ├── dovecot/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dpp/ │ │ └── project.yaml │ ├── draco/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dragonfly/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dropbear/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dropwizard/ │ │ ├── DefaultServerFactoryFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── duckdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── dulwich/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── e2fsprogs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── ext2fs_check_directory_fuzzer.cc │ │ │ ├── ext2fs_image_read_write_fuzzer.cc │ │ │ └── ext2fs_read_bitmap_fuzzer.cc │ │ └── project.yaml │ ├── easywsclient/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── easyws_fuzzer.cpp │ │ └── project.yaml │ ├── ecc-diff-fuzzer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ecdsa-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_private_key.py │ │ └── project.yaml │ ├── eclipse-equinox/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── equinox-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── eclipse/ │ │ │ └── osgi/ │ │ │ └── ConditionInfoFuzzer.java │ │ ├── maven-settings.xml │ │ ├── maven-toolchains.xml │ │ └── project.yaml │ ├── edk2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── eigen/ │ │ ├── Dockerfile │ │ ├── basicstuff_fuzzer.cc │ │ ├── build.sh │ │ ├── project.yaml │ │ └── solver_fuzzer.cc │ ├── elfutils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-dwfl-core.c │ │ ├── fuzz-libdwfl.c │ │ ├── fuzz-libelf.c │ │ └── project.yaml │ ├── envoy/ │ │ ├── Dockerfile │ │ ├── WORKSPACE │ │ ├── build.sh │ │ └── project.yaml │ ├── esp-v2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── espeak-ng/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── et-xmlfile/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_write.py │ │ └── project.yaml │ ├── etcd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── evo-inflector/ │ │ ├── Dockerfile │ │ ├── EnglishFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── my-api-repo/ │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── do_stuff_fuzzer.cpp │ │ │ ├── do_stuff_fuzzer.dict │ │ │ ├── do_stuff_test_data/ │ │ │ │ ├── 410c23d234e7f97a2dd6265eb2909324deb8c13a │ │ │ │ ├── 7a74862169c3375f4149daff75187cbca7372a38 │ │ │ │ ├── a835d6f1c6b2ae4a35e8c0a4a0576715c8b27283 │ │ │ │ ├── e8fb273916196a5e29967af0b5826daffb9b3765 │ │ │ │ └── fc09d362f05ab97efdfcd873dacad6a9c29e57ff │ │ │ ├── do_stuff_unittest.cpp │ │ │ ├── my_api.cpp │ │ │ ├── my_api.h │ │ │ └── standalone_fuzz_target_runner.cpp │ │ └── project.yaml │ ├── exiv2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── exp4j/ │ │ ├── Dockerfile │ │ ├── ExpressionBuilderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── expat/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── xml.dict │ │ ├── xml_UTF_16.dict │ │ ├── xml_UTF_16BE.dict │ │ └── xml_UTF_16LE.dict │ ├── expr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── exprtk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── exprtk_fuzzer.cpp │ │ ├── exprtk_test_expressions.dict │ │ └── project.yaml │ ├── faad2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fabric/ │ │ ├── Dockerfile │ │ ├── FuzzExtractFileEntries.options │ │ ├── FuzzParseChaincodePackage.options │ │ ├── FuzzPersistence.options │ │ ├── build.sh │ │ ├── ccprovider_fuzzer.go │ │ ├── fabenc_fuzzer.go │ │ ├── msp_fuzzer.go │ │ ├── persistence_fuzzer.go │ │ ├── policydsl_fuzzer.go │ │ └── project.yaml │ ├── face/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_command.py │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── fast-dds/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fast-xml-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── fast_float/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── fastcsv/ │ │ ├── CsvReaderFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fasthttp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fastify/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fastjson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fastjson2/ │ │ ├── Dockerfile │ │ ├── JsonFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── feign/ │ │ ├── BodyTemplateFuzzer.java │ │ ├── Dockerfile │ │ ├── UriUtilsFuzzer.java │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── settings.xml │ │ └── toolchains.xml │ ├── ffmpeg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── group_seed_corpus.py │ │ ├── name_mappings.py │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── ffms2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── ffms2_fuzzer.cc │ │ └── project.yaml │ ├── fftw3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fftw3_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── file/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer_temp_file.h │ │ ├── magic_fuzzer.cc │ │ ├── magic_fuzzer_fd.cc │ │ ├── magic_fuzzer_loaddb.cc │ │ └── project.yaml │ ├── filelock/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_filelock.py │ │ └── project.yaml │ ├── filesystem_spec/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_http.py │ │ └── project.yaml │ ├── fio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── fips203/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── firefox/ │ │ ├── Dockerfile │ │ ├── ImageBMP.options │ │ ├── ImageGIF.options │ │ ├── SdpParser.options │ │ ├── build.sh │ │ ├── mozconfig.address │ │ ├── mozconfig.coverage │ │ ├── mozconfig.undefined │ │ ├── project.yaml │ │ └── target.c │ ├── firestore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── flac/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer_exo.cpp │ │ └── project.yaml │ ├── flask/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── cors_fuzz_flask.py │ │ ├── fuzz_json.py │ │ ├── fuzz_werkzeug_formparser.py │ │ ├── fuzz_werkzeug_http.py │ │ ├── fuzz_werkzeug_url.py │ │ └── project.yaml │ ├── flask-jwt-extended/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_jwt.py │ │ └── project.yaml │ ├── flask-restx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_reqparse.py │ │ └── project.yaml │ ├── flask-wtf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_flask_wtf.py │ │ └── project.yaml │ ├── flatbuffers/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── flate2-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── flex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── flex-patch.diff │ │ ├── fuzz-main.c │ │ ├── fuzz-main.options │ │ ├── fuzz-scanopt.c │ │ └── project.yaml │ ├── fluent-bit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fluxcd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── flyway/ │ │ ├── Dockerfile │ │ ├── LocationFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── fmt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── fontations/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── freeimage/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── load_from_memory_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── freeradius/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── freerdp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── freetype2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── fribidi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── frr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── fsnotify/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── ftfy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fix.py │ │ ├── fuzz_format.py │ │ └── project.yaml │ ├── fuzzing-puzzles/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── fuzztest-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzztest-enable-fuzzers.diff │ │ └── project.yaml │ ├── fuzztest-raksha/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── raksha-fuzztest.diff │ ├── fuzzywuzzy/ │ │ ├── DiffUtilsFuzzer.java │ │ ├── Dockerfile │ │ ├── FuzzySearchFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── fwupd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── g-api-auth-httplib2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_http.py │ │ └── project.yaml │ ├── g-api-auth-library-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_jwt.py │ │ ├── fuzz_jwt_roundtrip.py │ │ └── project.yaml │ ├── g-api-pubsub/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_msg.py │ │ └── project.yaml │ ├── g-api-py-api-common-protos/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_api.py │ │ └── project.yaml │ ├── g-api-py-oauthlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_config.py │ │ └── project.yaml │ ├── g-api-python-bigquery-storage/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_avroparser.py │ │ └── project.yaml │ ├── g-api-python-client/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_mimeparser.py │ │ └── project.yaml │ ├── g-api-python-cloud-core/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_helpers.py │ │ └── project.yaml │ ├── g-api-python-firestore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.py │ │ └── project.yaml │ ├── g-api-python-tasks/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cloudtask_client.py │ │ └── project.yaml │ ├── g-api-resource-manager/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_tag_values_client.py │ │ └── project.yaml │ ├── g-api-resumable-media-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_uploader.py │ │ └── project.yaml │ ├── g-api-secret-manager/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_client.py │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── g-apis-py-api-core/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_path_template.py │ │ └── project.yaml │ ├── g-auth-library-java/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── CredentialsFuzzer.java │ │ │ │ └── TokenVerifierFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── g-cloud-logging-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_entries.py │ │ ├── fuzz_handlers.py │ │ ├── fuzz_helpers.py │ │ ├── fuzz_resources.py │ │ └── project.yaml │ ├── g-http-java-client/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JsonObjectParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── g-oauth-java-client/ │ │ ├── Dockerfile │ │ ├── OauthSignerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── g-py-bigquery/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── g-py-crc32c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_checksum.py │ │ └── project.yaml │ ├── gast/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gateway/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── gc-iam/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_credentials.py │ │ └── project.yaml │ ├── gcloud-error-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_util.py │ │ └── project.yaml │ ├── gcloud-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gcp-python-cloud-storage/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fileio.py │ │ └── project.yaml │ ├── gdal/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── gdbm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── gdk-pixbuf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── targets/ │ │ ├── animation_fuzzer.c │ │ ├── fuzzer_temp_file.h │ │ ├── pixbuf_cons_fuzzer.c │ │ ├── pixbuf_file_fuzzer.c │ │ ├── pixbuf_scale_fuzzer.c │ │ └── stream_fuzzer.c │ ├── genshi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_html.py │ │ └── project.yaml │ ├── geos/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── patch.diff │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── gfwx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ghostscript/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── dicts/ │ │ │ ├── pdf.dict │ │ │ └── ps.dict │ │ ├── gs_device_bmpmono_fuzzer.cc │ │ ├── gs_device_eps2write_fuzzer.cc │ │ ├── gs_device_faxg3_fuzzer.cc │ │ ├── gs_device_pdfwrite_fuzzer.cc │ │ ├── gs_device_pdfwrite_opts_fuzzer.cc │ │ ├── gs_device_pgmraw_fuzzer.cc │ │ ├── gs_device_png16m_fuzzer.cc │ │ ├── gs_device_ps2write_fuzzer.cc │ │ ├── gs_device_psdcmyk_fuzzer.cc │ │ ├── gs_device_pxlcolor_fuzzer.cc │ │ ├── gs_device_pxlmono_fuzzer.cc │ │ ├── gs_device_tiffsep1_fuzzer.cc │ │ ├── gs_device_xpswrite_fuzzer.cc │ │ ├── gs_fuzzlib.h │ │ ├── gstoraster_fuzzer.cc │ │ ├── gstoraster_fuzzer_all_colors.cc │ │ ├── gstoraster_fuzzer_all_colors.options │ │ ├── gstoraster_pdf_fuzzer.cc │ │ ├── gstoraster_ps_fuzzer.cc │ │ ├── gstoraster_ps_fuzzer.options │ │ └── project.yaml │ ├── giflib/ │ │ ├── Dockerfile │ │ ├── ProtoToGif.cpp │ │ ├── ProtoToGif.h │ │ ├── build.sh │ │ ├── dgif_fuzz_common.cc │ │ ├── dgif_fuzz_common.h │ │ ├── dgif_protobuf_target.cc │ │ ├── dgif_target.cc │ │ ├── dgif_target.options │ │ ├── egif_fuzz_common.cc │ │ ├── egif_fuzz_common.h │ │ ├── egif_target.cc │ │ ├── gif_fuzz_proto.proto │ │ └── project.yaml │ ├── gimli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── git/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── gitdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_gitdb.py │ │ └── project.yaml │ ├── gitea/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── github_scarecrow/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fakelib.py │ │ ├── project.yaml │ │ └── shell_injection_poc_fuzzer.py │ ├── gitoxide/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gitpython/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── glaze/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── glib/ │ │ ├── 0001-deflate-Zero-initialise-the-prev-and-window-buffers.patch │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── globaleaks-whistleblowing-software/ │ │ └── project.yaml │ ├── glog/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── glom/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_core.py │ │ ├── fuzz_glom.py │ │ ├── fuzz_matching.py │ │ ├── fuzz_mutation.py │ │ ├── fuzz_reduction.py │ │ └── project.yaml │ ├── glslang/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── compile_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── gluon/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gnucobol/ │ │ └── project.yaml │ ├── gnupg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decrypt.c │ │ ├── fuzz_decrypt.options │ │ ├── fuzz_import.c │ │ ├── fuzz_list.c │ │ ├── fuzz_list.options │ │ ├── fuzz_verify.c │ │ ├── fuzzer_stubs.c │ │ ├── fuzzgnupg.diff │ │ └── project.yaml │ ├── gnutls/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-attestation/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-cmp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-coap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-containerregistry/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.go │ │ └── project.yaml │ ├── go-coredns/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-dhcp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-dns/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-ethereum/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── go-git/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-humanize/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-json-iterator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_json.go │ │ └── project.yaml │ ├── go-ldap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-ole/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-pprof/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-readline/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-redis/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-sftp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-shlex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── go-snappy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.go │ │ └── project.yaml │ ├── go-sqlite3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-toml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── go-yaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── gobgp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gogo-protobuf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── goipp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── golang/ │ │ ├── Dockerfile │ │ ├── aes_fuzzer.go │ │ ├── build.sh │ │ ├── dsa_fuzzer.go │ │ ├── ecdsa_fuzzer.go │ │ ├── elf_fuzzer.go │ │ ├── encoding_fuzzer.go │ │ ├── filepath_fuzzer.go │ │ ├── fuzz_tar_reader.go │ │ ├── fuzz_tar_reader.options │ │ ├── fuzz_tiff_decode.options │ │ ├── fuzz_webp_decode.options │ │ ├── fuzz_x_h2c.options │ │ ├── glob_fuzzer.options │ │ ├── h2c_fuzzer.go │ │ ├── language_fuzzer.go │ │ ├── math_big_fuzzer.go │ │ ├── multipart_fuzzer.go │ │ ├── openpgp_fuzzer.go │ │ ├── project.yaml │ │ ├── regexp_fuzzer.go │ │ ├── strings_fuzzer.go │ │ ├── text_fuzzer.go │ │ ├── tiff_fuzzer.go │ │ ├── unicode_fuzzer.go │ │ ├── webp_fuzzer.go │ │ └── x509_fuzzer.go │ ├── golang-appengine/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── golang-protobuf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gonids/ │ │ ├── 372f9bd.diff │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gopacket/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gopsutil/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── gosnmp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gpac/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gprof2dot/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_profile.py │ │ └── project.yaml │ ├── gpsd/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── graphicsmagick/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── graphql-java/ │ │ ├── Dockerfile │ │ ├── GraphqlFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── greenmail/ │ │ ├── Dockerfile │ │ ├── UserManagerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── grok/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── groovy/ │ │ ├── Dockerfile │ │ ├── DurationFuzzer.java │ │ ├── TestFuzzer.java │ │ ├── add-shadow-to-test.diff │ │ ├── build.sh │ │ └── project.yaml │ ├── grpc-gateway/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── grpc-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_hello.go │ │ └── project.yaml │ ├── grpc-httpjson-transcoding/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── grpc-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_server.py │ │ └── project.yaml │ ├── grpc-swift/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── gson/ │ │ ├── Dockerfile │ │ ├── FuzzParse.java │ │ ├── FuzzReader.java │ │ ├── FuzzStreamParser.java │ │ ├── build.sh │ │ └── project.yaml │ ├── gss-ntlmssp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzing/ │ │ │ ├── Makefile │ │ │ ├── fuzz-accept-sec-context.c │ │ │ └── fuzz-accept-sec-context.dict │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── gstreamer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── guava/ │ │ ├── Dockerfile │ │ ├── HashingFuzzer.java │ │ ├── HostAndPortFuzzer.java │ │ ├── HostSpecifierFuzzer.java │ │ ├── InetAddressesFuzzer.java │ │ ├── InternetDomainNameFuzzer.java │ │ ├── MediaTypeFuzzer.java │ │ ├── UrlEscapersFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── guetzli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── guice/ │ │ ├── Dockerfile │ │ ├── InjectorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── gunicorn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_util.py │ │ └── project.yaml │ ├── gwt/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── JsParserFuzzer.java │ │ │ │ └── JsonFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── h11/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_h11.py │ │ └── project.yaml │ ├── h2database/ │ │ ├── CsvReadBackFuzzer.java │ │ ├── CsvReadFuzzer.java │ │ ├── Dockerfile │ │ ├── ServerLoginFuzzer.java │ │ ├── ShellFuzzer.java │ │ ├── SqlPreparedStatementFuzzer.java │ │ ├── SqlStatementFuzzer.java │ │ ├── TestServer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── h2o/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── h2o-fuzzer-http1.options │ │ ├── h2o-fuzzer-http2.options │ │ ├── h2o-fuzzer-http3.options │ │ ├── h2o-fuzzer-url.options │ │ └── project.yaml │ ├── h3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── h5py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_h5f.py │ │ └── project.yaml │ ├── hadoop/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── FileUtilFuzzer.java │ │ │ │ └── JavaSerializationFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── halide/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hamcrest/ │ │ ├── Dockerfile │ │ ├── HamcrestFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── haproxy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cfg_parser.c │ │ ├── fuzz_hpack_decode.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── harfbuzz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── hb-raster-fuzzer.options │ │ ├── hb-repacker-fuzzer.options │ │ ├── hb-shape-fuzzer.options │ │ ├── hb-subset-fuzzer.options │ │ ├── hb-vector-fuzzer.options │ │ └── project.yaml │ ├── hcl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hdf5/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── h5_extended_fuzzer.c │ │ ├── h5_read_fuzzer.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── hdrhistogram/ │ │ ├── Dockerfile │ │ ├── LogReaderWriterFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── helm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hermes/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── preprocess-corpus.py │ │ └── project.yaml │ ├── hibernate-orm/ │ │ ├── Dockerfile │ │ ├── PersistentClass.java │ │ ├── PersistentClassFuzzer.java │ │ ├── SerializableClass.java │ │ ├── SessionFactoryBuilder.java │ │ ├── TestServer.java │ │ ├── add-shadow.diff │ │ ├── build.sh │ │ ├── hibernate.xml │ │ ├── persistentClass.xml │ │ └── project.yaml │ ├── hibernate-validator/ │ │ ├── Dockerfile │ │ ├── MappingParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── highwayhash/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── hikaricp/ │ │ ├── ClockFuzzer.java │ │ ├── Dockerfile │ │ ├── DriverDataSourceFuzzer.java │ │ ├── PropertyElfFuzzer.java │ │ ├── TestObject.java │ │ ├── UtilityElfFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── hiredis/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hiredis-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_reader.py │ │ └── project.yaml │ ├── hive/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── DeserializeFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── hoextdown/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── hoextdown.dict │ │ ├── hoextdown_fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── hostap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hpn-ssh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── hsqldb/ │ │ ├── ConnectionOptionsFuzzer.java │ │ ├── Dockerfile │ │ ├── SqlPreparedStatementFuzzer.java │ │ ├── SqlStatementFuzzer.java │ │ ├── TestServer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── html2text/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_html2text.py │ │ └── project.yaml │ ├── html5lib-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── htmlunit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── htmlunit-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── ossfuzz/ │ │ │ └── HtmlParserFuzzer.java │ │ ├── maven-settings.xml │ │ └── project.yaml │ ├── htslib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── http-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── http-pattern-matcher/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── httparse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── httpcomponents-client/ │ │ ├── ByteArrayBodyWriteToFuzzer.java │ │ ├── Dockerfile │ │ ├── FileBodyWriteToFuzzer.java │ │ ├── FormBodyPartBuilderBuildFuzzer.java │ │ ├── HttpFuzzer.java │ │ ├── InputStreamBodyWriteToFuzzer.java │ │ ├── StringBodyWriteToFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── httpcomponents-core/ │ │ ├── ClassicHttpRequestFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── httpcore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_http11.py │ │ └── project.yaml │ ├── httplib2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── httpretty/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_httpretty_e2e.py │ │ └── project.yaml │ ├── httpx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_api.py │ │ ├── fuzz_decoders.py │ │ ├── fuzz_url.py │ │ └── project.yaml │ ├── hugo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_pageparser.go │ │ └── project.yaml │ ├── hunspell/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── hwloc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── hwloc_fuzzer.c │ │ ├── hwloc_fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── hyperium/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ibmswtpm2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer.cc │ │ ├── no_writes.patch │ │ └── project.yaml │ ├── ical4j/ │ │ └── project.yaml │ ├── icalendar/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── icu/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── idna/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_encode_decode.py │ │ └── project.yaml │ ├── igraph/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── ijson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_all.py │ │ ├── fuzz_native_parser.py │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── image-png/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── image-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── imageio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── imagemagick/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── immer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── importlib_metadata/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_importlib.py │ │ └── project.yaml │ ├── inchi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── inchi_input_fuzzer.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── influxdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── iniconfig/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── inih/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── inihfuzz.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── ion-java/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── IonReaderFuzzer.java │ │ │ │ └── IonWriterFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── ipaddress/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_ip_address.py │ │ ├── fuzz_ip_interface.py │ │ ├── fuzz_ip_network.py │ │ └── project.yaml │ ├── iperf/ │ │ ├── Dockerfile │ │ ├── auth_fuzzer.c │ │ ├── build.sh │ │ ├── cjson_fuzzer.c │ │ └── project.yaml │ ├── ipfs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ipp-usb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ipykernel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_serialization_roundtrip.py │ │ ├── fuzz_unpack_roundtrip.py │ │ └── project.yaml │ ├── ipython/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_inputsplitter.py │ │ └── project.yaml │ ├── iroha/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── irssi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── irssi-fuzz.options │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── theme-load-fuzz.dict │ ├── isodate/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── istio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── istio-ztunnel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── itext7/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── example/ │ │ │ │ │ └── PdfFuzzer.java │ │ │ │ └── resources/ │ │ │ │ └── junit-platform.properties │ │ │ └── pom.xml │ │ └── project.yaml │ ├── itoa/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── itsdangerous/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_itsdangerous.py │ │ └── project.yaml │ ├── iverilog/ │ │ └── project.yaml │ ├── ja3/ │ │ └── project.yaml │ ├── jackson-core/ │ │ ├── DataInputFuzzer.java │ │ ├── Dockerfile │ │ ├── JsonFuzzer.java │ │ ├── ParseNextTokenFuzzer.java │ │ ├── UTF8GeneratorFuzzer.java │ │ ├── WriterBasedJsonGeneratorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-databind/ │ │ ├── AdaLObjectReader3Fuzzer.java │ │ ├── AdaLObjectReader3Fuzzer.options │ │ ├── ConvertValueFuzzer.java │ │ ├── Dockerfile │ │ ├── ObjectReader2Fuzzer.java │ │ ├── ObjectReaderFuzzer.java │ │ ├── ObjectWriterFuzzer.java │ │ ├── ReadTreeFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-dataformat-xml/ │ │ ├── Dockerfile │ │ ├── FromXmlParserFuzzer.java │ │ ├── ToXmlGeneratorFuzzer.java │ │ ├── XmlDeserializerFuzzer.java │ │ ├── XmlFuzzer.java │ │ ├── XmlSerializerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-dataformats-binary/ │ │ ├── AvroGeneratorFuzzer.java │ │ ├── AvroParserFuzzer.java │ │ ├── CborFuzzer.java │ │ ├── CborGeneratorFuzzer.java │ │ ├── CborParserFuzzer.java │ │ ├── DeserializerFuzzer.java │ │ ├── Dockerfile │ │ ├── IonGeneratorFuzzer.java │ │ ├── IonParserFuzzer.java │ │ ├── ProtobufParserFuzzer.java │ │ ├── SerializerFuzzer.java │ │ ├── SmileFuzzer.java │ │ ├── SmileGeneratorFuzzer.java │ │ ├── SmileParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-dataformats-text/ │ │ ├── CSVFuzzer.java │ │ ├── DeserializerFuzzer.java │ │ ├── Dockerfile │ │ ├── PropertiesFuzzer.java │ │ ├── SerializerFuzzer.java │ │ ├── TOMLFuzzer.java │ │ ├── YAMLFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-datatype-joda/ │ │ ├── Dockerfile │ │ ├── JodaDeserializerFuzzer.java │ │ ├── JodaMapperFuzzer.java │ │ ├── JodaSerializerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-datatypes-collections/ │ │ ├── Dockerfile │ │ ├── EclipseCollectionsDeserializerFuzzer.java │ │ ├── EclipseCollectionsSerializerFuzzer.java │ │ ├── GuavaDeserializerFuzzer.java │ │ ├── GuavaSerializerFuzzer.java │ │ ├── HppcDeserializerFuzzer.java │ │ ├── HppcSerializerFuzzer.java │ │ ├── PCollectionsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jackson-modules-java8/ │ │ ├── DatatypeFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jakarta-mail-api/ │ │ ├── Dockerfile │ │ ├── HeaderTokenizerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── janet/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── janino/ │ │ ├── Dockerfile │ │ ├── ExpressionEvaluatorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jansi/ │ │ ├── Dockerfile │ │ ├── JansiFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jansson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── janus-gateway/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── java-diff-utils/ │ │ ├── DiffUtilsFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── java-example/ │ │ ├── Dockerfile │ │ ├── ExampleFuzzTest.java │ │ ├── ExampleFuzzer.java │ │ ├── ExampleFuzzerNative.cpp │ │ ├── ExampleFuzzerNative.h │ │ ├── ExampleFuzzerNative.java │ │ ├── ExampleValueProfileFuzzer.java │ │ ├── MutatorFuzzTest.java │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── java-jwt/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JWTFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── java-uuid-generator/ │ │ ├── Dockerfile │ │ ├── GeneratorsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── java-xmlbuilder/ │ │ ├── Dockerfile │ │ ├── XmlBuilderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── javacpp/ │ │ ├── Dockerfile │ │ ├── JavacppFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── javaparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parseFuzzer.java │ │ └── project.yaml │ ├── javapoet/ │ │ ├── Dockerfile │ │ ├── TypeSpecFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── javascript-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_promise.js │ │ ├── fuzz_string_compare.js │ │ ├── fuzz_value_profiling.js │ │ ├── package.json │ │ └── project.yaml │ ├── javassist/ │ │ ├── ClassFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml.diff │ │ └── project.yaml │ ├── javy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jaxb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── DataTypeConverterFuzzer.java │ ├── jbig2dec/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── jbig2_fuzzer.cc │ │ ├── jbig2_fuzzer.dict │ │ ├── jbig2_fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── jboss-logging/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── LoggingFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── jc/ │ │ └── project.yaml │ ├── jdom/ │ │ ├── Dockerfile │ │ ├── SAXBuilderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jedi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_script.py │ │ └── project.yaml │ ├── jedis/ │ │ ├── Dockerfile │ │ ├── JedisURIFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jerryscript/ │ │ └── project.yaml │ ├── jersey/ │ │ ├── Dockerfile │ │ ├── HttpHeaderReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jettison/ │ │ ├── Dockerfile │ │ ├── JsonFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jetty/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── AbstractHttpClientServerTest.java │ │ │ │ ├── AbstractServerTest.java │ │ │ │ ├── HTTP2CServer.java │ │ │ │ ├── HTTP2CServerFuzzer.java │ │ │ │ ├── HttpClientFuzzer.java │ │ │ │ ├── HttpParserFuzzer.java │ │ │ │ ├── ServerHandlersFuzzer.java │ │ │ │ ├── SslConnectionFuzzer.java │ │ │ │ ├── URIUtilDecodePathFuzzer.java │ │ │ │ ├── WebAppDefaultServletFuzzer.java │ │ │ │ └── XmlParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── jflex/ │ │ ├── Dockerfile │ │ ├── JflexFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jfreechart/ │ │ ├── DefaultCategoryDatasetChartFuzzer.java │ │ ├── Dockerfile │ │ ├── PieDatasetChartFuzzer.java │ │ ├── TimeSeriesChartFuzzer.java │ │ ├── build.sh │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── TestUtils.java │ ├── jimfs/ │ │ ├── Dockerfile │ │ ├── FileSystemFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jimp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── jinja2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_env_jinja_lexer.py │ │ ├── fuzz_jinja_compile_expr.py │ │ ├── fuzz_jinja_compile_templates.py │ │ └── project.yaml │ ├── jline3/ │ │ ├── Dockerfile │ │ ├── LineReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jmespathpy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── jmh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── OptionsBuilderFuzzer.java │ ├── joblib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_serialization_roundtrip.py │ │ └── project.yaml │ ├── joda-convert/ │ │ ├── Dockerfile │ │ ├── FromStringFuzzer.java │ │ ├── StringConvertFuzzer.java │ │ ├── ToStringFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── joda-time/ │ │ ├── Dockerfile │ │ ├── TimeFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jolt/ │ │ ├── Dockerfile │ │ ├── JsonUtilsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── joni/ │ │ ├── AddrListFixFuzzer.java │ │ ├── Dockerfile │ │ ├── RegexMatcherFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jooq/ │ │ ├── Dockerfile │ │ ├── GenerationToolFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jopt-simple/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── OptionParserFuzzer.java │ ├── jose4j/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JsonUtilFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── jpeg-js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.js │ │ ├── fuzz_encode.js │ │ └── project.yaml │ ├── jpegoptim/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── jq/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── jq.dict │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── js-yaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── jsc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsch/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── jsch-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── jcraft/ │ │ │ └── jsch/ │ │ │ └── OpenSSHConfigFuzzer.java │ │ ├── maven-settings.xml │ │ └── project.yaml │ ├── jsemver/ │ │ ├── Dockerfile │ │ ├── VersionFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jsign/ │ │ ├── AuthenticodeAppxSignerFuzzer.java │ │ ├── AuthenticodeCabSignerFuzzer.java │ │ ├── AuthenticodeExeSignerFuzzer.java │ │ ├── AuthenticodeMsiSignerFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsmin/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_minimize.py │ │ └── project.yaml │ ├── json/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer-parse.options │ │ ├── parse_afl_fuzzer.dict │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── json-c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── json-flattener/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── FlattenFuzzer.java │ │ │ │ └── UnflattenFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── json-java/ │ │ ├── Dockerfile │ │ ├── JsonJavaFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── json-patch/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_create_merge.go │ │ ├── fuzz_decode_apply.go │ │ └── project.yaml │ ├── json-sanitizer/ │ │ ├── DenylistFuzzer.java │ │ ├── Dockerfile │ │ ├── IdempotenceFuzzer.java │ │ ├── ValidJsonFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── json-simple/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── JsonEncodeDecodeFuzzer.java │ │ │ │ └── JsonParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── json-smart-v2/ │ │ ├── Dockerfile │ │ ├── JSONParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── json2avro/ │ │ ├── ConverterFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── json5format/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsoncons/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsoncpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── json.proto │ │ ├── json_proto_converter.cc │ │ ├── json_proto_converter.h │ │ ├── jsoncpp_fuzz_proto.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── jsonnet/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── convert_jsonnet_fuzzer_multi.cc │ │ ├── convert_jsonnet_fuzzer_regular.cc │ │ ├── convert_jsonnet_fuzzer_stream.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── jsonp-api/ │ │ ├── CreateJsonFuzzer.java │ │ ├── Dockerfile │ │ ├── GeneratorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jsonparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsonpath/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── ossfuzz/ │ │ │ └── PathParserFuzzer.java │ │ └── resources/ │ │ └── test.json │ ├── jsonpickle/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsonschema/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jsoup/ │ │ ├── CssHtmlFuzzer.java │ │ ├── CssHtmlFuzzer.options │ │ ├── Dockerfile │ │ ├── FragmentHtmlFuzzer.java │ │ ├── FragmentHtmlFuzzer.options │ │ ├── HtmlFuzzer.java │ │ ├── HtmlFuzzer.options │ │ ├── XmlFuzzer.java │ │ ├── XmlFuzzer.options │ │ ├── build.sh │ │ └── project.yaml │ ├── jsqlparser/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JSqlParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── jstl-api/ │ │ ├── 0001-support-new-jdk.patch │ │ ├── 0002-avoid-ConcurrentModificationException.patch │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── jstl-api-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── jakarta/ │ │ │ └── servlet/ │ │ │ └── jsp/ │ │ │ └── ParserFuzzer.java │ │ ├── maven-settings.xml │ │ └── project.yaml │ ├── jts/ │ │ ├── Dockerfile │ │ ├── JtsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── juju/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── devices_fuzzer.go │ │ └── project.yaml │ ├── jul-to-slf4j/ │ │ ├── BridgeFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── junrar/ │ │ ├── Dockerfile │ │ ├── JunrarFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── jupyter-nbconvert/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_markdown_converter.py │ │ └── project.yaml │ ├── jupyter_server/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_serialization.py │ │ └── project.yaml │ ├── jupytext/ │ │ └── project.yaml │ ├── jwt-verify-lib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── jxls/ │ │ ├── Dockerfile │ │ ├── ProcessTemplateFuzzer.dict │ │ ├── ProcessTemplateFuzzer.java │ │ ├── build.patch │ │ ├── build.sh │ │ └── project.yaml │ ├── kafka/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_consumer.py │ │ ├── fuzz_producer.py │ │ └── project.yaml │ ├── kamailio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── karchive/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── kcodecs/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── kde-thumbnailers/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kea/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── keras/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_model.py │ │ ├── fuzz_serialization.py │ │ └── project.yaml │ ├── keycloak/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── keystone/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── kie-soup/ │ │ ├── CronExpressionFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kimageformats/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── kiwisolver/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_solver.py │ │ └── project.yaml │ ├── kmime/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── knative/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── knot-dns/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── krb5/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── kryo/ │ │ ├── DeserializeCollectionsFuzzer.java │ │ ├── DeserializeNumbersFuzzer.java │ │ ├── DeserializeStringFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kubearmor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kubeedge/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kubeflow-katib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── generateNNImage_fuzzer.go │ │ └── project.yaml │ ├── kubeflow-model-registry/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── filter_fuzzer.go │ │ └── project.yaml │ ├── kubeflow-pipelines/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── expr_fuzzer.go │ │ └── project.yaml │ ├── kubeflow-spark-operator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parseSecret_fuzzer.go │ │ └── project.yaml │ ├── kubernetes/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kubernetes-cluster-api/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kubevirt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── kyverno/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lame/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lark-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── lcms/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── cmsIT8_load_fuzzer.c │ │ ├── cmsIT8_load_fuzzer.options │ │ ├── cms_cgats_fuzzer.c │ │ ├── cms_cie_cam02_fuzzer.c │ │ ├── cms_devicelink_fuzzer.c │ │ ├── cms_dict_fuzzer.c │ │ ├── cms_gdb_fuzzer.c │ │ ├── cms_md5_fuzzer.c │ │ ├── cms_overwrite_transform_fuzzer.c │ │ ├── cms_overwrite_transform_fuzzer.options │ │ ├── cms_postscript_fuzzer.c │ │ ├── cms_profile_fuzzer.c │ │ ├── cms_transform_all_fuzzer.c │ │ ├── cms_transform_extended_fuzzer.c │ │ ├── cms_transform_fuzzer.c │ │ ├── cms_transform_fuzzer.options │ │ ├── cms_universal_transform_fuzzer.c │ │ ├── cms_virtual_profile_fuzzer.c │ │ ├── icc.dict │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── leptonica/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── leveldb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_db.cc │ │ ├── fuzz_db.options │ │ └── project.yaml │ ├── libaom/ │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── build.sh │ │ └── project.yaml │ ├── libarchive/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libarchive_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libass/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libass_fuzzer.options │ │ └── project.yaml │ ├── libavc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libavif/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libbpf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libcacard/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libcbor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libcoap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libconfig/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libcst/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_transformer.py │ │ └── project.yaml │ ├── libcue/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libcups/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libdwarf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libecc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libevent/ │ │ ├── Dockerfile │ │ ├── buffer_add_file_fuzzer.cc │ │ ├── buffer_fuzzer.cc │ │ ├── bufferevent_fuzzer.cc │ │ ├── build.sh │ │ ├── dns_config_fuzzer.cc │ │ ├── fuzz_request_cb.c │ │ ├── http_fuzzer.cc │ │ ├── parse_query_fuzzer.cc │ │ ├── project.yaml │ │ └── utils_fuzzer.cc │ ├── libexif/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── exif_from_data_fuzzer.cc │ │ ├── exif_loader_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libfdk-aac/ │ │ ├── Dockerfile │ │ ├── aacDecoder_ConfigRaw.cpp │ │ ├── aacDecoder_DecodeFrame.cpp │ │ ├── aacDecoder_Open.cpp │ │ ├── build.sh │ │ └── project.yaml │ ├── libfido2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libfuse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_optparse.c │ │ └── project.yaml │ ├── libgd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── gd_image_string_fuzzer.cc │ │ ├── parser_target.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libgit2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libheif/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libhevc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libhtp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libical/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libical_extended_fuzzer.cc │ │ ├── libical_fuzzer.cc │ │ ├── libicalvcard_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libidn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libidn2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── replay_build.sh │ ├── libiec61850/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.options │ │ └── project.yaml │ ├── libigl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── igl_fuzzer.cpp │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libjpeg-turbo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libjxl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libldac/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libldac_encode_fuzzer.cc │ │ └── project.yaml │ ├── liblouis/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libmicrohttpd/ │ │ └── project.yaml │ ├── libmicrohttpd2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── connection_helper.cpp │ │ ├── connection_helper.h │ │ ├── default.options │ │ ├── fuzz_connection.cpp │ │ ├── fuzz_crypto_ext.cpp │ │ ├── fuzz_crypto_int.cpp │ │ ├── fuzz_daemon.cpp │ │ ├── fuzz_daemon.dict │ │ ├── fuzz_daemon_connection.cpp │ │ ├── fuzz_libinfo.cpp │ │ ├── fuzz_mhd2.cpp │ │ ├── fuzz_response.cpp │ │ ├── fuzz_str.cpp │ │ ├── mhd_helper.cpp │ │ ├── mhd_helper.h │ │ └── project.yaml │ ├── libmodbus/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── FuzzClient.c │ │ │ ├── FuzzServer.c │ │ │ └── Makefile │ │ └── project.yaml │ ├── libmpeg2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── liboqs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libpcap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libpg_query/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libphonenumber/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libplist/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libpng/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── libpng-proto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libpng_transforms_fuzzer.cc │ │ ├── png_fuzz_proto.proto │ │ ├── png_proto_fuzzer_example.cc │ │ ├── png_proto_mutator.cc │ │ └── project.yaml │ ├── libprotobuf-mutator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── expat_example.options │ │ ├── libxml2_example.options │ │ ├── project.yaml │ │ └── xml.dict │ ├── libproxy/ │ │ └── project.yaml │ ├── libpsl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── config.site │ │ ├── md5sum │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libra/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libraw/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libraw_fuzzer.cc │ │ └── project.yaml │ ├── librawspeed/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── librdkafka/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libredwg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── llvmfuzz.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libreoffice/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libressl/ │ │ ├── Dockerfile │ │ ├── bignum.options │ │ ├── build.sh │ │ └── project.yaml │ ├── librosa/ │ │ └── project.yaml │ ├── librsvg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── render_document.options │ ├── libsass/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── data_context_fuzzer.cc │ │ └── project.yaml │ ├── libsndfile/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libsodium/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fake_random.h │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── secret_key_auth_fuzzer.cc │ │ └── secretbox_easy_fuzzer.cc │ ├── libsoup/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libspdm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libspectre/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libspng/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libsrtp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libssh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libssh2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libstdcpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libtasn1/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libteken/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libteken_fuzzer.c │ │ └── project.yaml │ ├── libtheora/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libtiff/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libtorrent/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libtpms/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libtsm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libtsm_fuzzer.c │ │ └── project.yaml │ ├── libucl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── ucl_add_string_fuzzer.options │ ├── libultrahdr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libunwind/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_libunwind.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libusb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libusb_fuzzer.cc │ │ └── project.yaml │ ├── libvips/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libvnc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libvpx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── vpx_dec_fuzzer.dict │ ├── libwebp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libwebsockets/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── lws_upng_inflate_fuzzer.cpp │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libxaac/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libxls/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libxlsxwriter/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libxml2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libxslt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libyal/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libyaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libyaml_deconstructor_alt_fuzzer.c │ │ ├── libyaml_deconstructor_fuzzer.c │ │ ├── libyaml_dumper_fuzzer.c │ │ ├── libyaml_emitter_fuzzer.c │ │ ├── libyaml_fuzzer.options │ │ ├── libyaml_loader_fuzzer.c │ │ ├── libyaml_parser_fuzzer.c │ │ ├── libyaml_reformatter_alt_fuzzer.c │ │ ├── libyaml_reformatter_fuzzer.c │ │ ├── libyaml_scanner_fuzzer.c │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── yaml.dict │ │ └── yaml_write_handler.h │ ├── libyang/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── libyuv/ │ │ └── project.yaml │ ├── libzip/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── libzmq/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── lighttpd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_burl.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── lima/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── linkerd2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── linkerd2-proxy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── rustc.py │ ├── lit/ │ │ ├── Dockerfile │ │ ├── babel.config.json │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── litmuschaos/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── llamacpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzers/ │ │ │ ├── fuzz_apply_template.cpp │ │ │ ├── fuzz_grammar.cpp │ │ │ ├── fuzz_inference.cpp │ │ │ ├── fuzz_json_to_grammar.cpp │ │ │ ├── fuzz_load_model.cpp │ │ │ ├── fuzz_structurally_created.cpp │ │ │ ├── fuzz_structured.cpp │ │ │ ├── fuzz_tokenizer.cpp │ │ │ └── llama.dict │ │ └── project.yaml │ ├── lldb-eval/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── lldb_vs_lldb_eval_libfuzzer_test.options │ │ └── project.yaml │ ├── lldpd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── llhttp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── llvm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── coverage_patcher.py │ │ └── project.yaml │ ├── llvm_libcxx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── llvm_libcxxabi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lodash/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── lodepng/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── log4j2/ │ │ ├── Dockerfile │ │ ├── README.adoc │ │ ├── build.sh │ │ └── project.yaml │ ├── logback/ │ │ ├── Dockerfile │ │ ├── JoranFuzzer.java │ │ ├── build.sh │ │ ├── logback.xml │ │ └── project.yaml │ ├── loki/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── looker-sdk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_looker.py │ │ └── project.yaml │ ├── lotus/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lua/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_lua.c │ │ └── project.yaml │ ├── lua-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── compile_lua_fuzzer │ │ ├── example_basic.lua │ │ └── project.yaml │ ├── lucene/ │ │ ├── CustomAnalyzerFuzzer.java │ │ ├── Dockerfile │ │ ├── IndexSearchFuzzer.java │ │ ├── QueryParserFuzzer.java │ │ ├── build.patch │ │ ├── build.sh │ │ └── project.yaml │ ├── lwan/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lxc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lxml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_html_parse.py │ │ ├── fuzz_sax.py │ │ ├── fuzz_schematron.py │ │ ├── fuzz_xml_parse.py │ │ ├── fuzz_xmlschema.py │ │ ├── fuzz_xslt.py │ │ ├── project.yaml │ │ └── test_utils.py │ ├── lz4/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── lz4_flex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lzma/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── lzo/ │ │ ├── Dockerfile │ │ ├── all_lzo_compress.cc │ │ ├── build.sh │ │ ├── lzo_compress_target.c │ │ ├── lzo_compress_target.options │ │ ├── lzo_decompress_target.c │ │ ├── lzo_decompress_target.options │ │ ├── lzo_decompress_target_seeds/ │ │ │ └── seed.lzo │ │ └── project.yaml │ ├── magic-enum/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── magic_enum_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── magic-modules/ │ │ └── project.yaml │ ├── mako/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_lexer.py │ │ └── project.yaml │ ├── mandelbulber/ │ │ └── project.yaml │ ├── mapserver/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── mariadb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_json.c │ │ └── project.yaml │ ├── mariadb-connector-j/ │ │ ├── Dockerfile │ │ ├── MariaDbPoolDataSourceFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── markdown-it-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── markupsafe/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_encoding.py │ │ └── project.yaml │ ├── matio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── matplotlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_plt.py │ │ └── project.yaml │ ├── maven/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ ├── MojoDescriptorFuzzer.java │ │ └── ProjectArtifactMetadataFuzzer.java │ ├── maven-model/ │ │ ├── Dockerfile │ │ ├── Xpp3ReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── mbedtls/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── mccabe/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_get_code_complexity.py │ │ └── project.yaml │ ├── md4c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── mdbook-i18n-helpers/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mdbtools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mdit-py-plugins/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_containers.py │ │ ├── fuzz_plugins_individually.py │ │ └── project.yaml │ ├── mdurl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_mdurl.py │ │ └── project.yaml │ ├── memcached/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer_proxy.c │ │ ├── fuzzer_proxy.options │ │ ├── generate_corpus.py │ │ ├── patch.diff │ │ └── project.yaml │ ├── mercurial/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── meshoptimizer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── metadata-extractor/ │ │ ├── Dockerfile │ │ ├── ImageMetadataReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── metallb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mfcmapi/ │ │ └── project.yaml │ ├── micronaut/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── migtd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── minify/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── miniz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── miniz_oxide/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── minizip/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── moby/ │ │ ├── Dockerfile │ │ ├── FuzzAdd.options │ │ ├── backend_build_fuzzer.go │ │ ├── build.sh │ │ ├── containerstream_fuzzer.go │ │ ├── daemon_fuzzer.go │ │ ├── jsonmessage_fuzzer.go │ │ ├── project.yaml │ │ └── remotecontext_fuzzer.go │ ├── model-transparency/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── monero/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_rpc.options │ │ ├── fuzz_rpc_full.options │ │ ├── fuzz_rpc_full_no_exceptions.options │ │ ├── fuzz_zmq.options │ │ └── project.yaml │ ├── mongo-go-driver/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mongoose/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_netdriver_http.c │ │ └── project.yaml │ ├── more-itertools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_mi.py │ │ └── project.yaml │ ├── mosh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── mosquitto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mp4parse-rust/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── mp4san/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mpg123/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── decode_fuzzer.cc │ │ ├── project.yaml │ │ └── read_fuzzer.c │ ├── mpv/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mrab-regex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_match.py │ │ ├── fuzz_regex.py │ │ ├── fuzz_search.py │ │ └── project.yaml │ ├── mruby/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── ms-tpm-20-ref/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── libfuzzer.patch │ │ ├── project.yaml │ │ └── tpm_cmd.options │ ├── msal/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_auth.py │ │ ├── fuzz_tokencache.py │ │ └── project.yaml │ ├── msgpack-c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── msgpack-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_unpack.py │ │ └── project.yaml │ ├── msquic/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mtail/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── muduo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── muduo_http_fuzzer.cpp │ │ └── project.yaml │ ├── multidict/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_md.py │ │ └── project.yaml │ ├── multierr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── muparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── set_eval_fuzzer.cc │ ├── mupdf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pdf_fuzzer.cc │ │ ├── pdf_fuzzer.options │ │ └── project.yaml │ ├── mutagen/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── mvel/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── MvelFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── mxj/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.go │ │ └── project.yaml │ ├── myanmar-tools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── mybatis-3/ │ │ ├── Dockerfile │ │ ├── PooledDataSourceFuzzer.java │ │ ├── ResolverUtilFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── mysql-connector-j/ │ │ ├── Dockerfile │ │ ├── ServerLoginFuzzer.java │ │ ├── SqlPreparedStatementFuzzer.java │ │ ├── SqlStatementFuzzer.java │ │ ├── TestServer.java │ │ ├── build.sh │ │ ├── entrypoint.sh │ │ └── project.yaml │ ├── mysql-server/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fix.diff │ │ ├── project.yaml │ │ └── targets/ │ │ ├── CMakeLists.txt │ │ ├── README │ │ ├── fuzz_docommand.cc │ │ ├── fuzz_docommand.dict │ │ ├── fuzz_docommand.options │ │ ├── fuzz_initfile.cc │ │ ├── fuzz_initfile.dict │ │ ├── fuzz_initfile.options │ │ ├── fuzz_mysqld.cc │ │ ├── fuzz_mysqld.dict │ │ ├── fuzz_mysqld.options │ │ ├── fuzz_real_query.cc │ │ ├── fuzz_stmt_fetch.cc │ │ ├── init.sql │ │ ├── initnopw.sql │ │ ├── onefile.cc │ │ ├── util_fuzz.cc │ │ └── util_fuzz.h │ ├── naga/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nanopb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nats/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nbclassic/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_cell.py │ │ └── project.yaml │ ├── nbformat/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_read.py │ │ └── project.yaml │ ├── nccl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_xml.cpp │ │ └── project.yaml │ ├── ndpi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── neomutt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── neqo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nestegg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── net-snmp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── mib.dict │ │ └── project.yaml │ ├── netaddr-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parsing.py │ │ └── project.yaml │ ├── netcdf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── netdata/ │ │ └── project.yaml │ ├── nettle/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_dsa_openssl_private_key_from_der.c │ │ ├── fuzz_dsa_sha1_keypair_from_sexp.c │ │ ├── fuzz_dsa_sha256_keypair_from_sexp.c │ │ ├── fuzz_dsa_signature_from_sexp.c │ │ ├── fuzz_rsa_keypair_from_der.c │ │ ├── fuzz_rsa_keypair_from_sexp.c │ │ ├── fuzz_rsa_public_key_from_der.c │ │ └── project.yaml │ ├── netty/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── io/ │ │ └── netty/ │ │ ├── buffer/ │ │ │ ├── ByteBufUtilFuzzer.java │ │ │ └── LongLongHashMapFuzzer.java │ │ └── handler/ │ │ ├── HandlerFuzzerBase.java │ │ └── codec/ │ │ └── http/ │ │ ├── HttpRequestDecoderFuzzer.java │ │ └── cookie/ │ │ └── ServerCookieDecoderFuzzer.java │ ├── netty-tcnative/ │ │ ├── Dockerfile │ │ ├── NettyTcnativeFuzzer.java │ │ ├── build.sh │ │ ├── netty-patch.diff │ │ └── project.yaml │ ├── networkmanager/ │ │ └── project.yaml │ ├── networkx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_graph6.py │ │ ├── fuzz_graphml.py │ │ ├── fuzz_sparse6.py │ │ └── project.yaml │ ├── nfstream/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pcap_fuzzer.py │ │ └── project.yaml │ ├── nghttp2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── nghttp2_fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── nginx/ │ │ ├── Dockerfile │ │ ├── add_fuzzers.diff │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── http_request_fuzzer.cc │ │ │ ├── http_request_fuzzer.dict │ │ │ ├── http_request_proto.proto │ │ │ └── wrappers.c │ │ ├── make_fuzzers │ │ └── project.yaml │ ├── ngolo-fuzzing/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ngolo-fuzzing-x/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nimbus-jwt/ │ │ ├── 0001-disable-jar-signing.patch │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── maven-settings.xml │ │ ├── nimbus-jwt-fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── nimbusds/ │ │ │ └── jwt/ │ │ │ └── JWTParserFuzzer.java │ │ └── project.yaml │ ├── ninja/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── njs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── node-xml2js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parseString.js │ │ └── project.yaml │ ├── nodejs/ │ │ ├── Dockerfile │ │ ├── add_fuzzers_to_node_gyp.go │ │ ├── build.sh │ │ ├── fuzz_sources/ │ │ │ ├── fuzz_ClientHelloParser.cc │ │ │ ├── fuzz_blob.cc │ │ │ ├── fuzz_buffer_compare.cc │ │ │ ├── fuzz_buffer_equals.cc │ │ │ ├── fuzz_buffer_includes.cc │ │ │ ├── fuzz_cipheriv.cc │ │ │ ├── fuzz_common.cc │ │ │ ├── fuzz_common.h │ │ │ ├── fuzz_createPrivateKeyDER.cc │ │ │ ├── fuzz_createPrivateKeyJWK.cc │ │ │ ├── fuzz_createPrivateKeyPEM.cc │ │ │ ├── fuzz_diffieHellmanDER.cc │ │ │ ├── fuzz_diffieHellmanJWK.cc │ │ │ ├── fuzz_diffieHellmanPEM.cc │ │ │ ├── fuzz_fs_write_open_read.cc │ │ │ ├── fuzz_fs_write_read_append.cc │ │ │ ├── fuzz_httpparser1.cc │ │ │ ├── fuzz_js_format.h │ │ │ ├── fuzz_js_precompiled.h │ │ │ ├── fuzz_path_basename.cc │ │ │ ├── fuzz_path_dirname.cc │ │ │ ├── fuzz_path_extname.cc │ │ │ ├── fuzz_path_format.cc │ │ │ ├── fuzz_path_isAbsolute.cc │ │ │ ├── fuzz_path_join.cc │ │ │ ├── fuzz_path_normalize.cc │ │ │ ├── fuzz_path_parse.cc │ │ │ ├── fuzz_path_relative.cc │ │ │ ├── fuzz_path_resolve.cc │ │ │ ├── fuzz_path_toNamespacedPath.cc │ │ │ ├── fuzz_querystring_parse.cc │ │ │ ├── fuzz_quic_token.cc │ │ │ ├── fuzz_sign_verify.cc │ │ │ ├── fuzz_stream1.cc │ │ │ ├── fuzz_string_decoder.cc │ │ │ ├── fuzz_strings.cc │ │ │ ├── fuzz_tls_socket_request.cc │ │ │ ├── fuzz_v8_deserialize.cc │ │ │ ├── fuzz_x509.cc │ │ │ ├── fuzz_zlib_brotliCompress.cc │ │ │ ├── fuzz_zlib_brotliDecompress.cc │ │ │ ├── fuzz_zlib_createBrotliDecompress.cc │ │ │ └── fuzz_zlib_gzip_createUnzip.cc │ │ └── project.yaml │ ├── nokogiri/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nom/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── notary/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── nss/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── ntlm-auth/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_ntlm_auth.py │ │ └── project.yaml │ ├── ntlm2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_auth.py │ │ ├── fuzz_core.py │ │ └── project.yaml │ ├── ntopng/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ntp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── patch.diff │ │ └── project.yaml │ ├── ntpsec/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── FuzzClient.c │ │ │ ├── FuzzExtens.c │ │ │ ├── FuzzServer.c │ │ │ ├── Makefile │ │ │ └── setup.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── num-bigint/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── numactl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── numexpr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_numexpr.py │ │ └── project.yaml │ ├── numpy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_binary_loader.options │ │ ├── fuzz_binary_loader.py │ │ ├── fuzz_datetime.py │ │ ├── fuzz_dtype.py │ │ ├── fuzz_fromfile_loader.py │ │ ├── fuzz_fromregex_loader.py │ │ ├── fuzz_loader.py │ │ └── project.yaml │ ├── oak/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── oatpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── oauth2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_helpers.py │ │ └── project.yaml │ ├── oauthlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_oauth1_sig.py │ │ └── project.yaml │ ├── ogre/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── image_fuzz.cpp │ │ ├── project.yaml │ │ └── stream_fuzz.cpp │ ├── ohc/ │ │ ├── Dockerfile │ │ ├── OhcFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── okhttp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ ├── LoggingInterceptorFuzzer.java │ │ ├── NullLogger.java │ │ └── RequestFuzzer.java │ ├── olefile/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_reader.py │ │ └── project.yaml │ ├── onednn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_json.cpp │ │ └── project.yaml │ ├── open-json/ │ │ ├── Dockerfile │ │ ├── JsonTokenerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── open5gs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── open62541/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openapi-schema-validator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_general.py │ │ ├── fuzz_structured.py │ │ └── project.yaml │ ├── openbabel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── opencensus-cpp/ │ │ ├── .bazelrc │ │ ├── Dockerfile │ │ ├── WORKSPACE │ │ ├── build.sh │ │ └── project.yaml │ ├── opencensus-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── opencensus-java/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JsonConversionFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── opencensus-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_trace.py │ │ └── project.yaml │ ├── opencsv/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── CSVReaderFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── opencv/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── core_fuzzer.cc │ │ ├── filestorage_read_file_fuzzer.cc │ │ ├── filestorage_read_filename_fuzzer.cc │ │ ├── filestorage_read_string_fuzzer.cc │ │ ├── fuzzer_temp_file.h │ │ ├── generateusergallerycollage_fuzzer.cc │ │ ├── imdecode_fuzzer.cc │ │ ├── imencode_fuzzer.cc │ │ ├── imread_fuzzer.cc │ │ ├── project.yaml │ │ └── readnetfromtensorflow_fuzzer.cc │ ├── opendal/ │ │ ├── .fs.env │ │ ├── .memory.env │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── opendds/ │ │ └── project.yaml │ ├── opendnp3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openexr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── openfga/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openh264/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── decoder_fuzzer.cpp │ │ └── project.yaml │ ├── openjpeg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── openjph/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openkruise/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── opennavsurf-bag/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── openpyxl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_basic.py │ │ ├── fuzz_cellutil.py │ │ ├── fuzz_chart.py │ │ ├── fuzz_comment.py │ │ ├── fuzz_formulae.py │ │ ├── fuzz_load.py │ │ ├── fuzz_sheet.py │ │ ├── fuzz_sort.py │ │ └── project.yaml │ ├── opensc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── opensips/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── opensk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openslide/ │ │ └── project.yaml │ ├── openssh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openssl/ │ │ ├── Dockerfile │ │ ├── bignum.options │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── quic-srtm.options │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── opentelemetry/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── dict │ │ └── project.yaml │ ├── opentelemetry-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── opentelemetry-go-contrib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── openthread/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── openvpn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── crypto_patch.txt │ │ ├── fuzz.h │ │ ├── fuzz_base64.c │ │ ├── fuzz_buffer.c │ │ ├── fuzz_crypto.c │ │ ├── fuzz_dhcp.c │ │ ├── fuzz_forward.c │ │ ├── fuzz_header.h │ │ ├── fuzz_list.c │ │ ├── fuzz_misc.c │ │ ├── fuzz_mroute.c │ │ ├── fuzz_packet_id.c │ │ ├── fuzz_proxy.c │ │ ├── fuzz_randomizer.cpp │ │ ├── fuzz_randomizer.h │ │ ├── fuzz_route.c │ │ ├── fuzz_verify_cert.c │ │ ├── fuzz_verify_cert.h │ │ └── project.yaml │ ├── openvswitch/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── openweave/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── patch.diff │ │ └── project.yaml │ ├── openyurt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── opt_einsum/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── opus/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── opus_encode_fuzzer.cc │ │ ├── opus_multistream_decode_fuzzer.cc │ │ ├── opus_multistream_encode_fuzzer.cc │ │ ├── opus_ossfuzz_utils.h │ │ ├── opus_projection_decoder_fuzzer.cc │ │ ├── opus_projection_encoder_fuzzer.cc │ │ ├── opus_repacketizer_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── opusfile/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── opusfile_fuzzer.c │ │ └── project.yaml │ ├── oracle-py-cx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_basic.py │ │ └── project.yaml │ ├── orjson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_orjson.py │ │ └── project.yaml │ ├── oscrypto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_asymmetric_load.py │ │ ├── fuzz_keys.py │ │ └── project.yaml │ ├── osgi/ │ │ ├── CoreFilterFuzzer.java │ │ ├── CoreVersionFuzzer.java │ │ ├── CoreVersionRangeFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── osquery/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── oss-fuzz-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ossf-scorecard/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── probes_fuzzer.go │ │ ├── project.yaml │ │ └── yaml_fuzzer.go │ ├── ostree/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-bsdiff.c │ │ ├── fuzz-repo.c │ │ └── project.yaml │ ├── ots/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── ots-fuzzer.options │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── ox-ruby/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.rb │ │ ├── fuzz_sax_parse.rb │ │ └── project.yaml │ ├── oxia/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── p11-kit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── p9/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pacemaker/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── packaging/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_packaging.py │ │ └── project.yaml │ ├── pako/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── pandas/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_crosstab.py │ │ ├── fuzz_interpolate.py │ │ ├── fuzz_json_parser.py │ │ ├── fuzz_melt_map.py │ │ ├── fuzz_python_parser.py │ │ ├── fuzz_replace.py │ │ ├── fuzz_textreader_parser.py │ │ ├── fuzz_to_datetime.py │ │ ├── fuzz_to_latex.py │ │ └── project.yaml │ ├── paramiko/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_packetizer.py │ │ └── project.yaml │ ├── parse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── parsimonious/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_grammar_match.py │ │ └── project.yaml │ ├── parso/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parso_diff_fuzz.py │ │ ├── parso_extended_fuzz.py │ │ ├── parso_fuzz.py │ │ ├── parso_pep8_fuzz.py │ │ └── project.yaml │ ├── pasta/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── pathlib2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_match.py │ │ ├── fuzz_posix_compile.py │ │ ├── fuzz_windows_compile.py │ │ └── project.yaml │ ├── pborman-uuid/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── pcapplusplus/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pcapplusplus_enable_tests.diff │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── pcl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pcre2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── pdf-js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pdfbox/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── extract-fonts.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ ├── java/ │ │ │ │ │ └── com/ │ │ │ │ │ └── example/ │ │ │ │ │ ├── CFFParserFuzzer.java │ │ │ │ │ ├── CMapParserFuzzer.java │ │ │ │ │ ├── OTFParserFuzzer.java │ │ │ │ │ ├── PDFExtractTextFuzzer.java │ │ │ │ │ ├── PDFStreamParserFuzzer.java │ │ │ │ │ ├── PDFWriteReadFuzzer.java │ │ │ │ │ ├── PFAParserFuzzer.java │ │ │ │ │ └── TTFParserFuzzer.java │ │ │ │ └── resources/ │ │ │ │ └── log4j2.xml │ │ │ └── pom.xml │ │ └── project.yaml │ ├── pdfminersix/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── pdfplumber/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── pdoc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_html_helpers.py │ │ └── project.yaml │ ├── pem/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── data.pem │ │ ├── fuzz_pem.py │ │ └── project.yaml │ ├── pendulum/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── perfetto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pest/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pffft/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── generate_seed_corpus.py │ │ ├── pffft_fuzzer.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── phmap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── phashmap_fuzz.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── phosphor-host-ipmid/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-patch.diff │ │ ├── fuzz_fru_area.cpp │ │ ├── fuzz_payload_unpack.cpp │ │ ├── fuzz_sensor_utils.cpp │ │ ├── lg2_stub.cpp │ │ └── project.yaml │ ├── php/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── replay_build.sh │ ├── picotls/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pidgin/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pidgin_utils_fuzzer.c │ │ ├── pidgin_xml_fuzzer.c │ │ └── project.yaml │ ├── piex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── piex_fuzzer.cc │ │ └── project.yaml │ ├── pigweed/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pikepdf/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── pillow/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── build_depends.sh │ │ └── project.yaml │ ├── pip/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_requirements.py │ │ ├── project.yaml │ │ └── requirement_seeds/ │ │ └── seed1 │ ├── pistache/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pjsip/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── plan9port/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_libsec.c │ │ ├── fuzz_libsec.options │ │ ├── fuzz_patch.diff │ │ └── project.yaml │ ├── plexus-utils/ │ │ ├── Dockerfile │ │ ├── MXParserFuzzer.java │ │ ├── MXParserFuzzer.options │ │ ├── XmlStreamReaderFuzzer.java │ │ ├── XmlStreamReaderFuzzer.options │ │ ├── build.sh │ │ └── project.yaml │ ├── ply/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_lex_yacc.py │ │ └── project.yaml │ ├── pngquant/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── poco/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── poppler/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── postfix/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_mime.c │ │ ├── fuzz_tok822.c │ │ └── project.yaml │ ├── postgis/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── postgresql/ │ │ ├── Dockerfile │ │ ├── add_fuzzers.diff │ │ ├── build.sh │ │ ├── fuzzer/ │ │ │ ├── Makefile │ │ │ ├── dbfuzz.c │ │ │ ├── fuzzer_initialize.c │ │ │ ├── json_parser_fuzzer.c │ │ │ ├── protocol_fuzzer.c │ │ │ └── simple_query_fuzzer.c │ │ ├── main.diff │ │ └── project.yaml │ ├── powerdns/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── powsybl-java/ │ │ ├── DeserializeFuzzer.java │ │ ├── Dockerfile │ │ ├── LoadFlowFuzzer.java │ │ ├── MatrixFuzzer.java │ │ ├── MetrixFuzzer.java │ │ ├── OpenRaoFuzzer.java │ │ ├── ParseFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── presidio/ │ │ └── project.yaml │ ├── presto/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── SqlParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── proftpd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── proj4/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── prometheus/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── promise-polyfill/ │ │ ├── Dockerfile │ │ ├── babel.config.json │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── prost/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── proto-plus-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_json_serialization.py │ │ └── project.yaml │ ├── protobuf-c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── unpack_fuzzer.c │ ├── protobuf-java/ │ │ ├── Dockerfile │ │ ├── ProtobufFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── protobuf-js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── protobuf-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_protobuf.py │ │ └── project.yaml │ ├── protoc-gen-validate/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── protocompile/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_protocompile.go │ │ └── project.yaml │ ├── proton-bridge/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── proxygen/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── psqlparse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── psutil/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_native.py │ │ └── project.yaml │ ├── psycopg2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_sql.py │ │ └── project.yaml │ ├── publicsuffix-list/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_test.go │ │ └── project.yaml │ ├── pugixml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pulldown-cmark/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pulumi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── config_fuzzer.go │ │ ├── project.yaml │ │ └── schema_fuzzer.go │ ├── pupnp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── py-serde/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_model.py │ │ └── project.yaml │ ├── pyasn1/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.py │ │ └── project.yaml │ ├── pyasn1-modules/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.py │ │ └── project.yaml │ ├── pybind11/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── pybind_fuzzer.cc │ ├── pycparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_c_parser.py │ │ └── project.yaml │ ├── pycrypto/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_aes.py │ │ ├── fuzz_all_or_nothing.py │ │ ├── fuzz_hash.py │ │ ├── fuzz_number.py │ │ └── project.yaml │ ├── pycryptodome/ │ │ ├── Dockerfile │ │ ├── block_common.patch │ │ ├── build.sh │ │ ├── pcd_aes_fuzzer.cc │ │ ├── pcd_hash_fuzzer.cc │ │ └── project.yaml │ ├── pycups/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── pydantic/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_date.py │ │ ├── fuzz_network.py │ │ └── project.yaml │ ├── pydateutil/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parser.py │ │ ├── fuzz_prop_isoparse.py │ │ ├── fuzz_tzstr.py │ │ └── project.yaml │ ├── pygments/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_guesser.py │ │ ├── fuzz_lexers.py │ │ └── project.yaml │ ├── pyjson5/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_json.py │ │ └── project.yaml │ ├── pyjwt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_jwt.py │ │ └── project.yaml │ ├── pymysql/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_connection.py │ │ └── project.yaml │ ├── pynacl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_hash.py │ │ ├── fuzz_signing.py │ │ └── project.yaml │ ├── pyodbc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fake_odbc_driver.c │ │ ├── fuzz_curs_exec.py │ │ └── project.yaml │ ├── pyparsing/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── pyrsistent/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_vector.py │ │ └── project.yaml │ ├── pytables/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_file.py │ │ ├── fuzz_file_extended.py │ │ └── project.yaml │ ├── pytest-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_source.py │ │ └── project.yaml │ ├── python-ecdsa/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_ecdsa.py │ │ ├── fuzz_eddsa.py │ │ ├── fuzz_keys.py │ │ └── project.yaml │ ├── python-email-validator/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_validator.py │ │ └── project.yaml │ ├── python-fastjsonschema/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_compile.py │ │ └── project.yaml │ ├── python-future/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_future_email.py │ │ ├── fuzz_future_htmlparser.py │ │ ├── fuzz_future_urllib.py │ │ ├── fuzz_past.py │ │ └── project.yaml │ ├── python-graphviz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_graph.py │ │ └── project.yaml │ ├── python-hyperlink/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_host.py │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── python-jose/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_jwe.py │ │ ├── fuzz_jws.py │ │ └── project.yaml │ ├── python-lz4/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_lz4.py │ │ └── project.yaml │ ├── python-markdown/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_convert.py │ │ └── project.yaml │ ├── python-markdownify/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_convert.py │ │ └── project.yaml │ ├── python-multipart/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_form.options │ │ ├── fuzz_form.patch │ │ ├── helpers.patch │ │ └── project.yaml │ ├── python-nameparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_fullname.py │ │ └── project.yaml │ ├── python-nvd3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_linechart.py │ │ └── project.yaml │ ├── python-pathspec/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_pathspec.py │ │ └── project.yaml │ ├── python-phonenumbers/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── python-prompt-toolkit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_contrib.py │ │ ├── fuzz_formatted_text.py │ │ └── project.yaml │ ├── python-pypdf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_encryption.py │ │ └── project.yaml │ ├── python-rison/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.py │ │ ├── fuzz_roundtrip.py │ │ └── project.yaml │ ├── python-rsa/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_roundtrip.py │ │ └── project.yaml │ ├── python-tabulate/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_tabulate.py │ │ └── project.yaml │ ├── python3-libraries/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── python3-openid/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_html_parse.py │ │ └── project.yaml │ ├── pytz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_pytz.py │ │ └── project.yaml │ ├── pyvex/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── pyxdg/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_desktop_entry.py │ │ ├── fuzz_icon.py │ │ ├── fuzz_menu.dict │ │ ├── fuzz_menu.py │ │ ├── fuzz_mime.py │ │ ├── project.yaml │ │ └── seeds/ │ │ └── menu.xdg │ ├── pyyaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_emitter.py │ │ ├── fuzz_loader.py │ │ ├── fuzz_reader.py │ │ └── project.yaml │ ├── pyzmq/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_frame.py │ │ └── project.yaml │ ├── qcms/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── qdox/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── JavaProjectBuilderFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── qemu/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── qpdf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── qpid-proton/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── qs/ │ │ └── project.yaml │ ├── qt/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── quantlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── quartz/ │ │ ├── CronScheduleBuilderFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── qubes-os/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── quic-go/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ └── project.yaml │ ├── quiche/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── quiche-patch.diff │ ├── quiche-cloudflare/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── quick-xml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── quickjs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── run_tests_patch.diff │ ├── rabbitmq-c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── racket/ │ │ └── project.yaml │ ├── radare2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── radon/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── radvd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_config.c │ │ ├── fuzz_process.c │ │ └── project.yaml │ ├── rapidjson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer.cpp │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── rauc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── rdf4j/ │ │ ├── Dockerfile │ │ ├── ParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── rdkit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── re2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── readstat/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_format_sas_commands.dict │ │ ├── fuzz_format_spss_commands.dict │ │ ├── fuzz_format_stata_commands.dict │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── realm-core/ │ │ └── project.yaml │ ├── redis-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_backoff.py │ │ ├── fuzz_encoder.py │ │ ├── fuzz_func.py │ │ ├── fuzz_helper.py │ │ ├── fuzz_util.py │ │ └── project.yaml │ ├── redis-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ └── parser.rs │ │ └── project.yaml │ ├── redux/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── reflections/ │ │ ├── ConfigurationBuilderFuzzer.java │ │ ├── Dockerfile │ │ ├── FilterBuilderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── rekor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── relic/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── reload4j/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ ├── remove-jdk8-cap.diff │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ ├── LoggerFuzzer.java │ │ └── MyAppender.java │ ├── requests/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_requests.py │ │ └── project.yaml │ ├── resiprocate/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── retrofit/ │ │ ├── Dockerfile │ │ ├── PathTraversalFuzzer.java │ │ ├── RequestFuzzer.java │ │ ├── build.patch │ │ ├── build.sh │ │ └── project.yaml │ ├── retry/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_retry.py │ │ └── project.yaml │ ├── rfc3967/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_rfc3986.py │ │ └── project.yaml │ ├── rhai/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rhino/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── ParserFuzzer.java │ ├── rich/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_markdown.py │ │ └── project.yaml │ ├── ring/ │ │ └── project.yaml │ ├── rnp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── roaring-bitmap/ │ │ ├── Dockerfile │ │ ├── RoaringBitmapFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── rocksdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rome/ │ │ ├── Dockerfile │ │ ├── XmlReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── ron/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── roughtime/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rtpproxy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ruby/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_array.cpp │ │ ├── fuzz_bignum.cpp │ │ ├── fuzz_hash.cpp │ │ ├── fuzz_iseq.cpp │ │ ├── fuzz_json.c │ │ ├── fuzz_pack.cpp │ │ ├── fuzz_prism.cpp │ │ ├── fuzz_regex.cpp │ │ ├── fuzz_ruby_parser.cpp │ │ ├── fuzz_string.cpp │ │ ├── project.yaml │ │ └── ruby.options │ ├── runc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rust-brotli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ ├── decompress.rs │ │ │ └── roundtrip.rs │ │ └── project.yaml │ ├── rust-coreutils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rust-lexical/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rust-regex/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── rust-semver-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rustls/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── rxjava/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ ├── IntegerObserver.java │ │ └── ObservableFuzzer.java │ ├── ryu/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── s2geometry/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.patch │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── s2_fuzzer.cc │ ├── s2opc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sacremoses/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_detokenize.py │ │ ├── fuzz_normalizer.py │ │ ├── fuzz_split_xml.py │ │ ├── fuzz_tokenizer.py │ │ └── project.yaml │ ├── samba/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── scapy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pcap_fuzzer.py │ │ └── project.yaml │ ├── scikit-learn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_preprocessing_encoders.py │ │ └── project.yaml │ ├── scipy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_io_mio5.py │ │ ├── fuzz_io_wavfile.py │ │ └── project.yaml │ ├── scorecard-web/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── scrypt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── selinux/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sentencepiece/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── sample_encode_fuzzer.cc │ ├── serde-yaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── serde_json/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── serde_urlencoded/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ ├── reverse_roundtrip.rs │ │ │ └── roundtrip.rs │ │ └── project.yaml │ ├── serenity/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── servo/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── servo-core/ │ │ ├── Dockerfile │ │ ├── MonitorConfigFuzzer.java │ │ ├── build.sh │ │ ├── pom-core.xml │ │ └── project.yaml │ ├── setuptools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_config_pyprojecttoml.py │ │ └── project.yaml │ ├── shaderc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── glslc_fuzzer.cc │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── run_tests_patch.diff │ │ ├── shaderc_fdp_fuzzer.cc │ │ ├── shaderc_fuzzer.cc │ │ └── shaderc_general_fuzzer.cc │ ├── sharp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── sigstore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sigstore-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sigstore-java/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sigstore-python/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_verify_artifact.dict │ │ ├── fuzz_verify_artifact.py │ │ └── project.yaml │ ├── simd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── simd_load_fuzzer.cpp │ ├── simdjson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── simdutf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── simplejson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_decode.py │ │ ├── fuzz_encode.py │ │ └── project.yaml │ ├── six/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_six.py │ │ └── project.yaml │ ├── skcms/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── iccprofile.dict │ │ ├── iccprofile.options │ │ └── project.yaml │ ├── sketches-core/ │ │ ├── Dockerfile │ │ ├── FdtSketchFuzzer.java │ │ ├── MurmurHash3AdaptorFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── skia/ │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── build.sh │ │ ├── image_filter_deserialize_width.options │ │ ├── json.dict │ │ ├── project.yaml │ │ └── sksl.dict │ ├── skipper/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sleuthkit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── replay_build.sh │ │ └── run_tests.sh │ ├── slf4j-api/ │ │ ├── Dockerfile │ │ ├── LoggingFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── smart_open/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_bytebuffer.py │ │ ├── fuzz_func.py │ │ ├── fuzz_util.py │ │ ├── fuzz_zip.py │ │ └── project.yaml │ ├── smt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── snakeyaml/ │ │ ├── DefaultYamlFuzzer.java │ │ ├── Dockerfile │ │ ├── SecureYamlFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── snappy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── snappy-java/ │ │ ├── BitShuffleFuzzer.java │ │ ├── Dockerfile │ │ ├── SnappyStreamFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── snort3/ │ │ └── project.yaml │ ├── solidity/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── sonic/ │ │ └── project.yaml │ ├── sound-open-firmware/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fetch-sdk.sh │ │ └── project.yaml │ ├── soupsieve/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_closest.py │ │ ├── fuzz_filter.py │ │ ├── fuzz_match.py │ │ ├── fuzz_select.py │ │ └── project.yaml │ ├── spatial4j/ │ │ ├── Dockerfile │ │ ├── SpatialContextFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spdk/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parse_json_fuzzer.cc │ │ └── project.yaml │ ├── spdlog/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── backtrace_fuzzer.cc │ │ │ ├── format_fuzzer.cc │ │ │ ├── format_fuzzer.options │ │ │ ├── levels_fuzzer.cc │ │ │ ├── levels_fuzzer.options │ │ │ ├── log_fuzzer.cc │ │ │ ├── log_fuzzer.options │ │ │ ├── pattern_fuzzer.cc │ │ │ └── pattern_fuzzer.options │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── spdlog_fuzzer.dict │ ├── spdm-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── speex/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── spice-usbredir/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── spicy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── spidermonkey/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── spidermonkey-ufi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── target.c │ ├── spirv-cross/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parser_fuzzer.cpp │ │ ├── patch.diff │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── spirv-tools/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── generate_spirv_corpus.py │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── spotify-json/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── spring-amqp/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── AllowedListDeserializingMessageConverterFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── spring-boot/ │ │ ├── BasicJsonParserFuzzer.java │ │ ├── ConfigurationMetadataRepositoryJsonBuilderFuzzer.java │ │ ├── Dockerfile │ │ ├── JsonMarshallerFuzzer.java │ │ ├── TokenFuzzer.java │ │ ├── add-shadow-spring-boot-configuration-metadata.diff │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-cloud-commons/ │ │ ├── Dockerfile │ │ ├── EncryptionIntegrationFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-cloud-config/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ ├── ConfigServerPropertiesFuzzer.java │ │ └── EnvironmentFuzzer.java │ ├── spring-cloud-netflix/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── pom.xml │ │ ├── project.yaml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── org/ │ │ └── springframework/ │ │ └── cloud/ │ │ └── netflix/ │ │ └── eureka/ │ │ └── config/ │ │ └── HostnameBasedUrlRandomizerFuzzer.java │ ├── spring-cloud-sleuth-brave/ │ │ ├── Dockerfile │ │ ├── W3CPropagationFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-cloud-stream/ │ │ ├── Dockerfile │ │ ├── RabbitExchangeQueueProvisionerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-data-jpa/ │ │ ├── Dockerfile │ │ ├── QueryUtilsFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-data-keyvalue/ │ │ ├── Dockerfile │ │ ├── KeyValueTemplateFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-data-mongodb/ │ │ ├── Dockerfile │ │ ├── ParameterBindingJsonReaderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-data-redis/ │ │ ├── Dockerfile │ │ ├── GenericJackson2JsonRedisSerializerFuzzer.java │ │ ├── RedisStringDeserializationFuzzer.java │ │ ├── RedisStringSerializationFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-framework/ │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── add-shadow-context.diff │ │ ├── add-shadow-core.diff │ │ ├── add-shadow-jdbc.diff │ │ ├── add-shadow-jms.diff │ │ ├── add-shadow-messaging.diff │ │ ├── add-shadow-orm.diff │ │ ├── add-shadow-oxm.diff │ │ ├── add-shadow-test.diff │ │ ├── add-shadow-tx.diff │ │ ├── add-shadow-web.diff │ │ ├── add-shadow-webmvc.diff │ │ ├── add-shadow-websocket.diff │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── spring-aop/ │ │ │ └── AspectJExpressionPointcutFuzzer.java │ │ ├── spring-beans/ │ │ │ └── BeanWrapperFuzzer.java │ │ ├── spring-context/ │ │ │ └── XmlApplicationContextFuzzer.java │ │ ├── spring-expression/ │ │ │ └── SpelExpressionFuzzer.java │ │ ├── spring-jdbc/ │ │ │ ├── DataAccessObject.java │ │ │ ├── JdbcCoreMapperFuzzer.java │ │ │ ├── JdbcCoreMapperFuzzerBeans.xml │ │ │ ├── Mapper.java │ │ │ ├── MapperFuzzerServer.java │ │ │ ├── PersistentClass.java │ │ │ ├── Server.java │ │ │ └── Template.java │ │ ├── spring-jms/ │ │ │ └── SimpleJmsHeaderMapperFuzzer.java │ │ ├── spring-messaging/ │ │ │ └── PayloadMethodArgumentResolverFuzzer.java │ │ ├── spring-oxm/ │ │ │ └── XStreamMarshallerFuzzer.java │ │ ├── spring-tx/ │ │ │ ├── TransactionAttributeSourceEditorFuzzer.dict │ │ │ └── TransactionAttributeSourceEditorFuzzer.java │ │ ├── spring-web/ │ │ │ ├── ContentDispositionFuzzer.java │ │ │ └── CookieLocaleResolverFuzzer.java │ │ ├── spring-webflux/ │ │ │ └── BindStatusFuzzer.java │ │ └── spring-websocket/ │ │ └── StompSubProtocolHandlerFuzzer.java │ ├── spring-integration/ │ │ ├── Dockerfile │ │ ├── SimpleJsonSerializerFuzzer.java │ │ ├── add-shadow.patch │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-ldap/ │ │ ├── Dockerfile │ │ ├── LdapQueryBuilderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-retry/ │ │ ├── Dockerfile │ │ ├── PatternMatcher_match_Fuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── spring-security/ │ │ ├── BCryptPasswordEncoderFuzzer.java │ │ ├── BindAuthenticatorFuzzer.java │ │ ├── Dockerfile │ │ ├── EncodingUtilsConcatenateFuzzer.java │ │ ├── HexFuzzer.java │ │ ├── InMemoryUserDetailsManagerChangePasswordFuzzer.java │ │ ├── StrictHttpFirewallFuzzer.java │ │ ├── Utf8Fuzzer.java │ │ ├── acl/ │ │ │ └── AclFormattingUtilsFuzzer.java │ │ ├── build.sh │ │ ├── diff.patch │ │ ├── oauth2-client/ │ │ │ └── ClientRegistrationFuzzer.java │ │ ├── oauth2-core/ │ │ │ └── OAuth2AccessTokenFuzzer.java │ │ ├── oauth2-jose/ │ │ │ └── NimbusJwtEncoderFuzzer.java │ │ └── project.yaml │ ├── spring-shell/ │ │ ├── Dockerfile │ │ ├── add-shadow-core.patch │ │ ├── add-shadow-standard.patch │ │ ├── add-shadow-table.patch │ │ ├── build.sh │ │ ├── core/ │ │ │ └── CommandParserFuzzer.java │ │ ├── project.yaml │ │ ├── standard/ │ │ │ └── BashCompletionsFuzzer.java │ │ └── table/ │ │ └── TableFuzzer.java │ ├── spring-webflow/ │ │ ├── DefaultConversionServiceFuzzer.java │ │ ├── Dockerfile │ │ ├── build.patch │ │ ├── build.sh │ │ └── project.yaml │ ├── sql-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_sql_parse.cpp │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── sqlalchemy/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── sqlalchemy_fuzzer.py │ ├── sqlalchemy-utils/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_db.py │ │ ├── fuzz_orm.py │ │ ├── fuzz_type.py │ │ └── project.yaml │ ├── sqlalchemy_jsonfield/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_basic.py │ │ └── project.yaml │ ├── sqlite-jdbc/ │ │ ├── Dockerfile │ │ ├── SqliteConnectionFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── sqlite3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── ossfuzz.options │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ └── sql.dict │ ├── sqlparse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_format.py │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── stack_data/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_source.py │ │ └── project.yaml │ ├── starlark-rust/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── starnix-netlink/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── cargo.toml/ │ │ │ ├── core │ │ │ ├── generic │ │ │ ├── parent │ │ │ ├── route │ │ │ ├── sock_diag │ │ │ └── utils │ │ ├── fuzz/ │ │ │ ├── .gitignore │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ ├── core_fuzzer.rs │ │ │ └── utils_fuzzer.rs │ │ └── project.yaml │ ├── stax/ │ │ ├── Dockerfile │ │ ├── build-jdk.sh │ │ ├── build.sh │ │ ├── enable-jdk.sh │ │ ├── maven-settings.xml │ │ ├── project.yaml │ │ └── stax-fuzzer/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── ossfuzz/ │ │ └── XMLStreamReaderFuzzer.java │ ├── stb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── stringtemplate4/ │ │ ├── Dockerfile │ │ ├── StringFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── strongswan/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── struts/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── maven-settings.xml │ │ ├── project.yaml │ │ └── struts2-fuzzer/ │ │ ├── .gitignore │ │ ├── fuzzer/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── apache/ │ │ │ └── struts/ │ │ │ └── test/ │ │ │ └── StrutsSimpleRequestFuzzer.java │ │ ├── pom.xml │ │ └── webapp/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── apache/ │ │ │ └── struts/ │ │ │ └── test/ │ │ │ └── TestAction.java │ │ ├── resources/ │ │ │ └── struts.xml │ │ └── webapp/ │ │ ├── HelloWorld.jsp │ │ ├── WEB-INF/ │ │ │ └── web.xml │ │ └── index.jsp │ ├── sudoers/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── suricata/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── surrealdb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── swagger-core/ │ │ ├── Dockerfile │ │ ├── YamlFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── swc/ │ │ └── project.yaml │ ├── swift-nio/ │ │ ├── Dockerfile │ │ ├── Package.swift │ │ ├── build.sh │ │ ├── fuzz_http1.swift │ │ └── project.yaml │ ├── swift-protobuf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── symphonia/ │ │ └── project.yaml │ ├── systemd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── syzkaller/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tablesaw/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── ReaderFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── tailscale/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tar-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tarantool/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── compile_lua_fuzzer │ │ └── project.yaml │ ├── tcmalloc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── td-shim/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tdengine/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── sql-fuzzer.options │ ├── teleport/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tendermint/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tensorflow/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_patch.patch │ │ └── project.yaml │ ├── tensorflow-addons/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_text_ops.py │ │ └── project.yaml │ ├── tensorflow-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tensorflow-serving/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── tensorflow-serving.diff │ ├── tesseract-ocr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── textdistance/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── textwrap/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── threetenbp/ │ │ ├── Dockerfile │ │ ├── ThreetenbpFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-c_glib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── thrift-cpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-go/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-java/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-py/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── thrift-rust/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tidb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzMarshalJSON.go │ │ ├── fuzzNewBitLiteral.go │ │ ├── fuzzNewHexLiteral.go │ │ └── project.yaml │ ├── tidy-html5/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzer_temp_file.h │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── tidy_config_fuzzer.c │ │ ├── tidy_config_fuzzer.options │ │ ├── tidy_fuzzer.c │ │ ├── tidy_general_fuzzer.c │ │ ├── tidy_parse_file_fuzzer.c │ │ ├── tidy_parse_string_fuzzer.c │ │ └── tidy_xml_fuzzer.c │ ├── time/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── timestamp-authority/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tink-cc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzing_CMake │ │ ├── project.yaml │ │ └── tink_encrypt_decrypt_fuzzer.cc │ ├── tinycss2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_components.py │ │ ├── fuzz_parse.py │ │ └── project.yaml │ ├── tinygltf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── tinyobjloader/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── tinysparql/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tinyusb/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tinyxml2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── xml.dict │ │ ├── xmltest.cpp │ │ ├── xmltest.options │ │ ├── xmltest2.cpp │ │ └── xmltest2.options │ ├── tmux/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tokio/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tomcat/ │ │ ├── DecodeFuzzer.java │ │ ├── Dockerfile │ │ ├── EnDecodeFuzzer.java │ │ ├── FileHandlerFuzzer.java │ │ ├── HttpParserFuzzer.java │ │ ├── WsPingPongFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── toml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_dump.py │ │ ├── fuzz_load.py │ │ └── project.yaml │ ├── toml_edit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tomli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tomlkit/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_dumps.py │ │ ├── fuzz_parser.py │ │ └── project.yaml │ ├── tomlplusplus/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── toolbelt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_multipart.py │ │ └── project.yaml │ ├── toolz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_itertoolz.py │ │ └── project.yaml │ ├── tor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tpm2/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── tpm2-tss/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── tqdm/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_tqdm.py │ │ └── project.yaml │ ├── trafficserver/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── tremor/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── decode_fuzzer.cc │ │ └── project.yaml │ ├── trust-dns/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tslib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ └── project.yaml │ ├── ttf-parser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── .gitignore │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ ├── fuzz-aat.rs │ │ │ ├── fuzz-base.rs │ │ │ ├── fuzz-cpal.rs │ │ │ ├── fuzz-glyph-index.rs │ │ │ ├── fuzz-outline.rs │ │ │ ├── fuzz-table-with-builder.rs │ │ │ ├── fuzz-table.rs │ │ │ └── fuzz-variable-outline.rs │ │ └── project.yaml │ ├── tungstenite-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── turf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.js │ │ ├── package.json │ │ └── project.yaml │ ├── twelve-monkeys/ │ │ ├── Dockerfile │ │ ├── WildcardStringParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── twitter4j/ │ │ ├── Dockerfile │ │ ├── TwitterObjectFactoryFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── typescript/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_ast.js │ │ ├── fuzz_compiler.js │ │ ├── fuzz_json_parser.js │ │ ├── fuzz_scanner.js │ │ ├── fuzz_transpile_module.js │ │ ├── fuzz_util.js │ │ └── project.yaml │ ├── typescript-example/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_explore_me.ts │ │ ├── package.json │ │ ├── project.yaml │ │ ├── target.ts │ │ └── tsconfig.json │ ├── typing_extensions/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_typing_extensions.py │ │ └── project.yaml │ ├── typst/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── tyrus/ │ │ ├── Dockerfile │ │ ├── UriTemplateParserFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── u-boot/ │ │ ├── Dockerfile │ │ ├── btrfs.c │ │ ├── build.sh │ │ ├── efi_load_image.c │ │ ├── fit_image_load.c │ │ ├── image_decomp.c │ │ ├── oss-fuzz.patch │ │ └── project.yaml │ ├── u-root/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── ua-parser-js/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── uint256/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── ujson/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── hypothesis_structured_fuzzer.py │ │ ├── json_differential_fuzzer.py │ │ ├── project.yaml │ │ └── ujson_fuzzer.py │ ├── unblob/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── unbound/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_1.c │ │ ├── fuzz_2.c │ │ ├── fuzz_3.c │ │ ├── fuzz_4.c │ │ ├── parse_packet_fuzzer.c │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── underscore/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_compile.py │ │ └── project.yaml │ ├── undertow/ │ │ ├── Dockerfile │ │ ├── RedirectHandlerFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── unicode-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── unicorn/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── unirest-java/ │ │ ├── Dockerfile │ │ ├── JacksonEngineFuzzer.java │ │ ├── JsonArrayFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── unit/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── univocity-parsers/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── CsvParserFuzzer.java │ │ │ │ └── TsvParserFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── unsafe-libyaml/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── upx/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzers/ │ │ │ ├── build.patch │ │ │ ├── decompress_packed_file_fuzzer.cpp │ │ │ ├── list_packed_file_fuzzer.cpp │ │ │ └── test_packed_file_fuzzer.cpp │ │ └── project.yaml │ ├── uriparser/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── uritemplate/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_expand.py │ │ └── project.yaml │ ├── urlextract/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_find_urls.py │ │ └── project.yaml │ ├── urllib3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_requests.py │ │ ├── fuzz_urlparse.py │ │ └── project.yaml │ ├── usbguard/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── userver/ │ │ ├── CMakeLists.txt │ │ ├── CMakePresets.json │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── main.cpp │ │ ├── project.yaml │ │ └── static_config.yaml │ ├── usrsctp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── utf8parse/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── .gitignore │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ └── parse.rs │ │ └── project.yaml │ ├── utf8proc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── util-linux/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── uwebsockets/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── v8/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── validators/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_validators.py │ │ └── project.yaml │ ├── valijson/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── varnish/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── vitess/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── vlc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzzing-modules.patch │ │ └── project.yaml │ ├── volcano/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── vorbis/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── vtpm-td/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── vulkan-loader/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz-patch.diff │ │ ├── fuzzers/ │ │ │ ├── fuzz_header.h │ │ │ ├── instance_create_advanced_fuzzer.c │ │ │ ├── instance_create_fuzzer.c │ │ │ ├── instance_enumerate_fuzzer.c │ │ │ ├── json_load_fuzzer.c │ │ │ └── settings_fuzzer.c │ │ ├── project.yaml │ │ └── vulkan-keywords.dict │ ├── vulnerable-project/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── solution.seed │ │ └── vulnerable.cc │ ├── w3lib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_parse_data_uri.py │ │ ├── fuzz_safe_download_url.py │ │ ├── fuzz_url_safe.py │ │ └── project.yaml │ ├── w3m/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wabt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── read_binary_interp_fuzzer.cc │ │ ├── read_binary_ir_fuzzer.cc │ │ ├── run_tests.sh │ │ ├── wasm2wat_fuzzer.cc │ │ ├── wasm_objdump_fuzzer.cc │ │ └── wat2wasm_fuzzer.cc │ ├── wamr/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wasm3/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wasmedge/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wasmer/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── wasmi/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wasmtime/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── default.options │ │ └── project.yaml │ ├── wavpack/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── wazuh/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_xml.c │ │ ├── fuzz_xml.options │ │ └── project.yaml │ ├── websocket-client/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_http.py │ │ ├── fuzz_url.py │ │ └── project.yaml │ ├── websockets/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── weechat/ │ │ └── project.yaml │ ├── wget/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wget2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── wheel/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_wheel.py │ │ └── project.yaml │ ├── wireshark/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── woff2/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── convert_woff2ttf_fuzzer.options │ │ ├── convert_woff2ttf_fuzzer_new_entry.options │ │ └── project.yaml │ ├── wolfmqtt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wolfssl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── woodstox/ │ │ ├── Dockerfile │ │ ├── XmlFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── wpantund/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── wt/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wtforms/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_validators.py │ │ └── project.yaml │ ├── wuffs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── wxwidgets/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xbps/ │ │ └── project.yaml │ ├── xen/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xerces/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parserFuzzer.java │ │ └── project.yaml │ ├── xerces-c/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── parse_target.cpp │ │ ├── parse_target_proto.cpp │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── xerces_fuzz_common.cpp │ │ ├── xerces_fuzz_common.h │ │ ├── xml.proto │ │ ├── xmlProtoConverter.cpp │ │ └── xmlProtoConverter.h │ ├── xlrd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_open_workbook.py │ │ └── project.yaml │ ├── xlsxwriter/ │ │ ├── Dockerfile │ │ └── project.yaml │ ├── xmlbeans/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── regExFuzzer.java │ ├── xmldom/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xmlpull/ │ │ ├── Dockerfile │ │ ├── PullParserFactoryFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── xmlsec/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── xmltodict/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── unparse_parse_fuzzer.py │ ├── xmlunit/ │ │ ├── DOMDifferenceEngineCompareFuzzer.java │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xnio-api/ │ │ ├── 0001-avoid-ConcurrentModificationException.patch │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── maven-settings.xml │ │ ├── project.yaml │ │ └── xnio-fuzzer/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── org/ │ │ └── xnio/ │ │ └── http/ │ │ └── HttpParserFuzzer.java │ ├── xnnpack/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_model.cc │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── xnu/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xpdf/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_JBIG2.cc │ │ ├── fuzz_JBIG2.options │ │ ├── fuzz_pdfload.cc │ │ ├── fuzz_pdfload.options │ │ ├── fuzz_zxdoc.cc │ │ └── project.yaml │ ├── xs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── xst.options │ ├── xstream/ │ │ ├── Dockerfile │ │ ├── XmlFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── xvid/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xz/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── xz-java/ │ │ ├── Dockerfile │ │ ├── XZEncoderFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── yajl-ruby/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── json_fuzzer.c │ │ ├── json_fuzzer.dict │ │ └── project.yaml │ ├── yaml-cpp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── yamlbeans/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ ├── YamlReaderFuzzer.java │ │ │ │ └── YamlWriterFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── yara/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── yarl/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_url.py │ │ └── project.yaml │ ├── ygot/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz.go │ │ └── project.yaml │ ├── yoga/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── zeek/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── zip/ │ │ ├── Dockerfile │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── zip-rs/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz/ │ │ │ ├── Cargo.toml │ │ │ └── fuzz_targets/ │ │ │ ├── fuzz_zip.rs │ │ │ ├── roundtrip.rs │ │ │ └── structured_fuzz_reader.rs │ │ └── project.yaml │ ├── zip4j/ │ │ ├── Dockerfile │ │ ├── Zip4jFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── zipp/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── fuzz_zipp.py │ │ └── project.yaml │ ├── zlib/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── checksum_fuzzer.c │ │ ├── compress_fuzzer.c │ │ ├── example_dict_fuzzer.c │ │ ├── example_flush_fuzzer.c │ │ ├── example_large_fuzzer.c │ │ ├── example_small_fuzzer.c │ │ ├── gzio_fuzzer.c │ │ ├── minigzip_fuzzer.c │ │ ├── project.yaml │ │ ├── run_tests.sh │ │ ├── zlib_uncompress2_fuzzer.cc │ │ ├── zlib_uncompress3_fuzzer.cc │ │ └── zlib_uncompress_fuzzer.cc │ ├── zlib-ng/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── znc/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── msg_parse_fuzzer.cpp │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── zookeeper/ │ │ ├── DataTreeFuzzer.java │ │ ├── Dockerfile │ │ ├── MessageTrackerPeekReceivedFuzzer.java │ │ ├── ProcessTxnFuzzer.java │ │ ├── SerializeFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ ├── zopfli/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ ├── zopfli_compress_fuzzer.cc │ │ └── zopfli_deflate_fuzzer.cc │ ├── zstd/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project.yaml │ │ └── run_tests.sh │ ├── zstd-safe/ │ │ ├── Dockerfile │ │ ├── build.sh │ │ └── project.yaml │ ├── zt-zip/ │ │ ├── .gitignore │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── project-parent/ │ │ │ ├── fuzz-targets/ │ │ │ │ ├── pom.xml │ │ │ │ └── src/ │ │ │ │ └── test/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── example/ │ │ │ │ └── UnpackFuzzer.java │ │ │ └── pom.xml │ │ └── project.yaml │ ├── zxing/ │ │ ├── Dockerfile │ │ ├── MultiFormatDecodeFuzzer.java │ │ ├── MultiFormatEncodeFuzzer.java │ │ ├── build.sh │ │ └── project.yaml │ └── zydis/ │ ├── Dockerfile │ ├── build.sh │ ├── project.yaml │ └── run_tests.sh └── tools/ └── vscode-extension/ ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .prettierrc.js ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .vscodeignore ├── LICENSE ├── README.md ├── package.json ├── src/ │ ├── cifuzz.ts │ ├── commandUtils.ts │ ├── commands/ │ │ ├── cmdBuildFuzzerFromWorkspace.ts │ │ ├── cmdBuildFuzzerFromWorkspaceCFLite.ts │ │ ├── cmdCreateOSSFuzzSetup.ts │ │ ├── cmdDispatcherGenerateClusterfuzzLite.ts │ │ ├── cmdDisplayCoverage.ts │ │ ├── cmdEndToEndCoverage.ts │ │ ├── cmdFIGetOptimalTargets.ts │ │ ├── cmdListFuzzers.ts │ │ ├── cmdRedo.ts │ │ ├── cmdReproduceTestcase.ts │ │ ├── cmdRunFI.ts │ │ ├── cmdRunFuzzer.ts │ │ ├── cmdSetOSSFuzzPath.ts │ │ ├── cmdSetupCIFuzz.ts │ │ ├── cmdSetupFI.ts │ │ ├── cmdSetupOSSFuzz.ts │ │ ├── cmdTemplate.ts │ │ ├── cmdTestFuzzer.ts │ │ └── cmdTestFuzzerCFLite.ts │ ├── config.ts │ ├── coverageHelper.ts │ ├── extension.ts │ ├── fuzzIntrospectorHelper.ts │ ├── logger.ts │ ├── ossfuzzWrappers.ts │ ├── projectIntegrationHelper.ts │ └── utils.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .allstar/binary_artifacts.yaml ================================================ # Exemption reason: This repo uses binary artifacts for integration tests. optConfig: optOut: true ================================================ FILE: .clusterfuzzlite/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:v1 COPY . $SRC/oss-fuzz WORKDIR oss-fuzz COPY .clusterfuzzlite/build.sh $SRC/ RUN cp .clusterfuzzlite/coverage_atheris_fuzzer.py infra WORKDIR infra/ RUN pip3 install --upgrade pip RUN pip3 install -r cifuzz/requirements.txt RUN cp -r cifuzz/* . ================================================ FILE: .clusterfuzzlite/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. fuzzer=coverage_atheris_fuzzer.py fuzzer_basename=$(basename -s .py $fuzzer) fuzzer_package=${fuzzer_basename}.pkg # To avoid issues with Python version conflicts, or changes in environment # over time on the OSS-Fuzz bots, we use pyinstaller to create a standalone # package. Though not necessarily required for reproducing issues, this is # required to keep fuzzers working properly in OSS-Fuzz. pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer # Create execution wrapper. Atheris requires that certain libraries are # preloaded, so this is also done here to ensure compatibility and simplify # test case reproduction. Since this helper script is what OSS-Fuzz will # actually execute, it is also always required. # NOTE: If you are fuzzing python-only code and do not have native C/C++ # extensions, then remove the LD_PRELOAD line below as preloading sanitizer # library is not required and can lead to unexpected startup crashes. echo "#!/bin/sh # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \ ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \ \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename ================================================ FILE: .clusterfuzzlite/coverage_atheris_fuzzer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import json import os from unittest import mock import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cifuzz')) with atheris.instrument_imports(): import get_coverage REPO_PATH = '/src/curl' PROJECT_NAME = 'curl' with mock.patch('get_coverage._get_oss_fuzz_fuzzer_stats_dir_url', return_value="randomurl"): oss_fuzz_coverage = get_coverage.OSSFuzzCoverage(REPO_PATH, PROJECT_NAME) def TestOneInput(data): try: decoded_json = json.loads(data) except (json.decoder.JSONDecodeError, UnicodeDecodeError): # Wart return oss_fuzz_coverage.get_files_covered_by_target('fuzz-target') with mock.patch('get_coverage.OSSFuzzCoverage.get_target_coverage', return_value=decoded_json): oss_fuzz_coverage.get_files_covered_by_target('fuzz-target') return 0 def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: .clusterfuzzlite/project.yaml ================================================ language: python ================================================ FILE: .dockerignore ================================================ .git .venv infra/cifuzz/test_data/* docs/* # Copied from .gitignore. .vscode/ *.pyc build *~ .DS_Store *.swp .pytest_cache *__pycache__/* ================================================ FILE: .gitattributes ================================================ # Check out Linux shell scripts with LF (necessary when using Docker setup on Windows) *.sh text eol=lf ================================================ FILE: .github/header-checker-lint.yml ================================================ allowedCopyrightHolders: - 'Google LLC' allowedLicenses: - 'Apache-2.0' sourceFileExtensions: - 'ts' - 'js' - 'java' - 'Dockerfile' - 'java' - 'c' - 'h' - 'cc' - 'cpp' - 'css' - 'html' - 'htm' - 'go' - 'sh' - 'bash' - 'rs' - 'proto' - 'swift' ================================================ FILE: .github/workflows/cflite_pr.yml ================================================ name: ClusterFuzzLite PR fuzzing on: pull_request: paths: - 'infra/**' permissions: read-all jobs: PR: runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} cancel-in-progress: true strategy: fail-fast: false matrix: sanitizer: - address # Override this with the sanitizers you want. # - undefined # - memory steps: - name: Build Fuzzers (${{ matrix.sanitizer }}) id: build uses: google/clusterfuzzlite/actions/build_fuzzers@v1 with: language: python github-token: ${{ secrets.GITHUB_TOKEN }} sanitizer: ${{ matrix.sanitizer }} # Optional but recommended: used to only run fuzzers that are affected # by the PR. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". - name: Run Fuzzers (${{ matrix.sanitizer }}) id: run uses: google/clusterfuzzlite/actions/run_fuzzers@v1 with: github-token: ${{ secrets.GITHUB_TOKEN }} fuzz-seconds: 600 mode: 'code-change' sanitizer: ${{ matrix.sanitizer }} # Optional but recommended: used to download the corpus produced by # batch fuzzing. # See later section on "Git repo for storage". # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git # storage-repo-branch: main # Optional. Defaults to "main" # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". ================================================ FILE: .github/workflows/check_base_os.yml ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ name: 'Check Base OS Consistency' on: pull_request: paths: - 'projects/**' jobs: check-consistency: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 # Fetch all history to compare with main - name: Get changed project directories id: changed-projects run: | # Get the list of changed files compared to the target branch # and filter for unique directories under 'projects/'. CHANGED_DIRS=$(git diff --name-only ${GITHUB_BASE_REF} ${GITHUB_HEAD_REF} | \ grep '^projects/' | \ xargs -n 1 dirname | \ sort -u) echo "changed_dirs=${CHANGED_DIRS}" >> $GITHUB_OUTPUT - name: Set up Python uses: actions/setup-python@v6 with: python-version: '3.x' - name: Install dependencies run: pip install PyYAML - name: Check each modified project if: steps.changed-projects.outputs.changed_dirs != '' run: | EXIT_CODE=0 for project_dir in ${STEPS_CHANGED_PROJECTS_OUTPUTS_CHANGED_DIRS}; do echo "--- Checking ${project_dir} ---" python3 infra/ci/check_base_os.py "${project_dir}" || EXIT_CODE=$? done exit $EXIT_CODE env: STEPS_CHANGED_PROJECTS_OUTPUTS_CHANGED_DIRS: ${{ steps.changed-projects.outputs.changed_dirs }} ================================================ FILE: .github/workflows/codeql-analysis.yml ================================================ name: "CodeQL" on: push: branches: [ master ] paths: [infra/**, .github/**] pull_request: # The branches below must be a subset of the branches above branches: [ master ] paths: [infra/**, .github/**] jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false steps: - name: Checkout repository uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: python # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines # and modify them (or add more) to build your code if your project # uses a compiled language #- run: | # make bootstrap # make release - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 ================================================ FILE: .github/workflows/index_build_tests.yml ================================================ name: indexer tests permissions: contents: read on: pull_request: paths: - 'infra/base-images/base-builder/indexer/**' - '.github/workflows/index_build_tests.yml' jobs: 'indexer': runs-on: ubuntu-latest permissions: actions: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true steps: - uses: actions/checkout@v6 with: # Needed for git diff to work. (get_changed_files) fetch-depth: 0 - run: | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master - name: Setup python environment uses: actions/setup-python@v6 with: python-version: 3.11 - name: Get latest indexer binary run: curl -O https://clusterfuzz-builds.storage.googleapis.com/oss-fuzz-artifacts/indexer && chmod +x indexer working-directory: 'infra/base-images/base-builder/indexer' - name: Run indexer tests run: sudo env "PATH=$PATH" INDEX_BUILD_TESTS=1 python -m unittest index_build_test working-directory: 'infra/base-images/base-builder/indexer' ================================================ FILE: .github/workflows/indexer_build.yml ================================================ name: indexer build tests permissions: contents: read on: pull_request: paths: - 'infra/indexer/**' - '.github/workflows/indexer_build.yml' jobs: indexer: runs-on: ubuntu-latest permissions: actions: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true steps: - uses: actions/checkout@v6 with: # Needed for git diff to work. (get_changed_files) fetch-depth: 0 - run: | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master - name: Build indexer run: docker build -t indexer . working-directory: 'infra/indexer' ================================================ FILE: .github/workflows/infra_tests.yml ================================================ name: Infra tests permissions: contents: read on: pull_request: paths: - 'infra/**' - '.github/workflows/**' jobs: build: runs-on: ubuntu-latest permissions: actions: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true steps: - uses: actions/checkout@v6 with: # Needed for git diff to work. (get_changed_files) fetch-depth: 0 - run: | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master - name: Setup python environment uses: actions/setup-python@v6 with: python-version: 3.11 # For gcloud emulators. - name: Setup Java environment uses: actions/setup-java@v5 with: java-version: '21' distribution: 'temurin' - name: Install dependencies run: | sudo env "PATH=$PATH" python -m pip install --upgrade pip sudo env "PATH=$PATH" pip install -r infra/ci/requirements.txt sudo env "PATH=$PATH" pip install -r infra/build/functions/requirements.txt sudo env "PATH=$PATH" pip install -r infra/cifuzz/requirements.txt - uses: google-github-actions/setup-gcloud@v3 with: version: '523.0.0' - run: | sudo env "PATH=$PATH" gcloud components install beta cloud-datastore-emulator - name: Run infra tests run: sudo env "PATH=$PATH" END_TO_END_TESTS=1 INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p ================================================ FILE: .github/workflows/pr_helper.yml ================================================ name: PR helper on: pull_request_target: types: [opened] branches: - master paths: - 'projects/**' jobs: build: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v6 - name: Setup python environment uses: actions/setup-python@v6 with: python-version: 3.11 cache: pip cache-dependency-path: | infra/ci/requirements.txt - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r infra/ci/requirements.txt - name: setup go environment uses: actions/setup-go@v6 with: go-version: 'stable' - run: go install github.com/ossf/criticality_score/cmd/criticality_score@latest - name: Check if authors are authorized to modify. id: checkAuthor env: GITHUBTOKEN: ${{secrets.GITHUB_TOKEN}} PRAUTHOR: ${{ github.event.pull_request.user.login }} PRNUMBER: ${{ github.event.pull_request.number }} run: python infra/pr_helper.py - name: Leave comments if: env.IS_INTERNAL == 'FALSE' uses: actions/github-script@v8 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: process.env.MESSAGE }) - name: Add labels for valid PR if: env.IS_READY_FOR_MERGE == 'True' uses: actions/github-script@v8 with: script: | github.rest.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: ['Ready to merge'] }) ================================================ FILE: .github/workflows/presubmit.yml ================================================ name: Presubmit checks permissions: contents: read on: pull_request: branches: - master jobs: build: runs-on: ubuntu-latest permissions: actions: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true steps: - uses: actions/checkout@v6 with: # Needed for git diff to work. (get_changed_files) fetch-depth: 0 - run: | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master - name: Setup python environment uses: actions/setup-python@v6 with: python-version: 3.11 cache: pip cache-dependency-path: | infra/ci/requirements.txt infra/build/functions/requirements.txt - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r infra/ci/requirements.txt pip install -r infra/build/functions/requirements.txt - name: Run presubmit checks run: python infra/presubmit.py ================================================ FILE: .github/workflows/project_tests.yml ================================================ name: Project tests permissions: contents: read on: pull_request: branches: - master jobs: build: runs-on: ubuntu-latest concurrency: group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ matrix.engine }}-${{ matrix.architecture }}-${{ github.ref }} cancel-in-progress: true permissions: actions: write strategy: fail-fast: false matrix: engine: - libfuzzer sanitizer: - address - memory - undefined - coverage architecture: - x86_64 include: - engine: afl sanitizer: address architecture: x86_64 - engine: honggfuzz sanitizer: address architecture: x86_64 - engine: libfuzzer sanitizer: address architecture: i386 - engine: none sanitizer: address architecture: x86_64 - engine: centipede sanitizer: address architecture: x86_64 - engine: centipede sanitizer: none architecture: x86_64 env: ENGINE: ${{ matrix.engine }} SANITIZER: ${{ matrix.sanitizer }} ARCHITECTURE: ${{ matrix.architecture }} steps: - uses: actions/checkout@v6 with: # Needed for git diff to work. (get_changed_files) fetch-depth: 0 - run: | git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/master - name: Clear unnecessary files run: | df -h sudo swapoff -a sudo rm -f /swapfile sudo apt clean docker rmi $(docker images -a -q) || true df -h echo "Remove large unused folders, inspired by https://github.com/apache/flink/blame/master/tools/azure-pipelines/free_disk_space.sh" sudo bash -c '(ionice -c 3 nice -n 19 rm -rf /usr/share/dotnet/ /usr/local/graalvm/ /usr/local/.ghcup/ /usr/local/share/powershell /usr/local/share/chromium /usr/local/lib/android /usr/local/lib/node_modules)&' - name: Setup python environment uses: actions/setup-python@v6 with: python-version: 3.11 cache: pip cache-dependency-path: | infra/ci/requirements.txt - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r infra/ci/requirements.txt - name: Run project tests run: python infra/ci/build.py ================================================ FILE: .github/workflows/ubuntu_version_sync.yml ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ name: 'Ubuntu Version Sync Check' on: pull_request: types: [opened, synchronize, reopened] jobs: check-sync: name: Ubuntu File Synchronization Check runs-on: ubuntu-latest env: BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} steps: - name: 'Checkout code' uses: actions/checkout@v6 with: # Fetch all history so we can diff against the base branch. fetch-depth: 0 - name: 'Run sync check' run: | set -e MODIFIED_FILES=$(git diff --name-only $BASE_SHA...$HEAD_SHA) echo "Checking for synchronized file changes..." echo "Modified files in this PR:" echo "$MODIFIED_FILES" ERRORS="" # Define the mapping of legacy files to their versioned counterparts. # Format: "legacy_file;versioned_file_pattern" # The pattern uses {version} which will be replaced with "ubuntu-20-04" and "ubuntu-24-04". # For Dockerfiles, the pattern is different from scripts. declare -A LEGACY_DOCKERFILES LEGACY_DOCKERFILES["infra/base-images/base-builder-fuzzbench/Dockerfile"]="infra/base-images/base-builder-fuzzbench/{version}.Dockerfile" LEGACY_DOCKERFILES["infra/base-images/base-builder-swift/Dockerfile"]="infra/base-images/base-builder-swift/{version}.Dockerfile" LEGACY_DOCKERFILES["infra/base-images/base-builder/Dockerfile"]="infra/base-images/base-builder/{version}.Dockerfile" LEGACY_DOCKERFILES["infra/base-images/base-clang/Dockerfile"]="infra/base-images/base-clang/{version}.Dockerfile" LEGACY_DOCKERFILES["infra/base-images/base-runner/Dockerfile"]="infra/base-images/base-runner/{version}.Dockerfile" declare -A LEGACY_SCRIPTS LEGACY_SCRIPTS["infra/base-images/base-builder-fuzzbench/fuzzbench_install_dependencies"]="infra/base-images/base-builder-fuzzbench/fuzzbench_install_dependencies_{version}" LEGACY_SCRIPTS["infra/base-images/base-builder/install_deps.sh"]="infra/base-images/base-builder/install_deps_{version}.sh" LEGACY_SCRIPTS["infra/base-images/base-builder/install_swift.sh"]="infra/base-images/base-builder/install_swift_{version}.sh" LEGACY_SCRIPTS["infra/base-images/base-builder/precompile_honggfuzz"]="infra/base-images/base-builder/precompile_honggfuzz_{version}" LEGACY_SCRIPTS["infra/base-images/base-clang/checkout_build_install_llvm.sh"]="infra/base-images/base-clang/checkout_build_install_llvm_{version}.sh" LEGACY_SCRIPTS["infra/base-images/base-runner/install_deps.sh"]="infra/base-images/base-runner/install_deps_{version}.sh" VERSIONS=("ubuntu-20-04" "ubuntu-24-04") # Check Dockerfiles for legacy_file in "${!LEGACY_DOCKERFILES[@]}"; do if [[ "${legacy_file}" == infra/* ]] && echo "$MODIFIED_FILES" | grep -q "^${legacy_file}$"; then echo "Legacy file changed: $legacy_file. Verifying counterparts..." for version in "${VERSIONS[@]}"; do pattern="${LEGACY_DOCKERFILES[$legacy_file]}" versioned_file="${pattern/\{version\}/$version}" if ! echo "$MODIFIED_FILES" | grep -q "^${versioned_file}$"; then ERRORS+="\n- Legacy file '${legacy_file}' was changed, but its counterpart '${versioned_file}' was not." fi done fi done # Check Scripts for legacy_file in "${!LEGACY_SCRIPTS[@]}"; do if echo "$MODIFIED_FILES" | grep -q "^${legacy_file}$"; then echo "Legacy script changed: $legacy_file. Verifying counterparts..." for version in "${VERSIONS[@]}"; do pattern="${LEGACY_SCRIPTS[$legacy_file]}" versioned_file="${pattern/\{version\}/$version}" if ! echo "$MODIFIED_FILES" | grep -q "^${versioned_file}$"; then ERRORS+="\n- Legacy script '${legacy_file}' was changed, but its counterpart '${versioned_file}' was not." fi done fi done if [ -n "$ERRORS" ]; then echo -e "\n\e[31mError: Found synchronization issues between legacy and versioned files.\e[0m" echo -e "Please update the following files to match their legacy counterparts or ensure they are included in this PR:$ERRORS" exit 1 else echo -e "\n\e[32mSuccess: All modified legacy files are synchronized with their versioned counterparts.\e[0m" fi ================================================ FILE: .gitignore ================================================ /.vscode/ *.pyc /build/ *~ .DS_Store *.swp .venv .gdb_history infra/base-images/base-builder/indexer/indexer infra/base-images/base-builder/indexer/fuzzing_engine.a # IntelliJ IDEA /.idea **/*.iml # Chronos ccaches/ ================================================ FILE: .pylintrc ================================================ [MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. extension-pkg-whitelist= # Add files or directories to the blocklist. They should be base names, not # paths. ignore=CVS,base-clang,base-sanitizer-libs-builder # Add files or directories matching the regex patterns to the blocklist. The # regex matches against base names, not paths. ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the # number of processors available to use. jobs=1 # Control the amount of potential inferred values when inferring a single # object. This can help the performance when dealing with large functions or # complex, nested conditions. limit-inference-results=100 # List of plugins (as comma separated values of python module names) to load, # usually to register additional checkers. load-plugins= # Pickle collected data for later comparisons. persistent=yes # Specify a configuration file. #rcfile= # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. suggestion-mode=yes # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. confidence= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once). You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use "--disable=all --enable=classes # --disable=W". disable=print-statement, parameter-unpacking, unpacking-in-except, old-raise-syntax, backtick, long-suffix, old-ne-operator, old-octal-literal, import-star-module-level, non-ascii-bytes-literal, raw-checker-failed, bad-inline-option, locally-disabled, file-ignored, suppressed-message, useless-suppression, deprecated-pragma, use-symbolic-message-instead, apply-builtin, basestring-builtin, buffer-builtin, cmp-builtin, coerce-builtin, execfile-builtin, file-builtin, long-builtin, raw_input-builtin, reduce-builtin, standarderror-builtin, unicode-builtin, xrange-builtin, coerce-method, delslice-method, getslice-method, setslice-method, no-absolute-import, old-division, dict-iter-method, dict-view-method, next-method-called, metaclass-assignment, indexing-exception, raising-string, reload-builtin, oct-method, hex-method, nonzero-method, cmp-method, input-builtin, round-builtin, intern-builtin, unichr-builtin, map-builtin-not-iterating, zip-builtin-not-iterating, range-builtin-not-iterating, filter-builtin-not-iterating, using-cmp-argument, eq-without-hash, div-method, idiv-method, rdiv-method, exception-message-attribute, invalid-str-codec, sys-max-int, bad-python3-import, deprecated-string-function, deprecated-str-translate-call, deprecated-itertools-function, deprecated-types-field, next-method-defined, dict-items-not-iterating, dict-keys-not-iterating, dict-values-not-iterating, deprecated-operator-function, deprecated-urllib-function, xreadlines-attribute, deprecated-sys-function, exception-escape, comprehension-escape, fixme, import-error, logging-fstring-interpolation, # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. enable=c-extension-no-member [REPORTS] # Python expression which should return a score less than or equal to 10. You # have access to the variables 'error', 'warning', 'refactor', and 'convention' # which contain the number of messages in each category, as well as 'statement' # which is the total number of statements analyzed. This score is used by the # global evaluation report (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details. #msg-template= # Set the output format. Available formats are text, parseable, colorized, json # and msvs (visual studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages. reports=no # Activate the evaluation score. score=yes [REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 # Complete name of functions that never returns. When checking for # inconsistent-return-statements if a never returning function is called then # it will be considered as an explicit return statement and no message will be # printed. never-returning-functions=sys.exit [BASIC] # Naming style matching correct argument names. argument-naming-style=snake_case # Regular expression matching correct argument names. Overrides argument- # naming-style. #argument-rgx= # Naming style matching correct attribute names. attr-naming-style=snake_case # Regular expression matching correct attribute names. Overrides attr-naming- # style. #attr-rgx= # Bad variable names which should always be refused, separated by a comma. bad-names=foo, bar, baz, toto, tutu, tata # Naming style matching correct class attribute names. class-attribute-naming-style=any # Regular expression matching correct class attribute names. Overrides class- # attribute-naming-style. #class-attribute-rgx= # Naming style matching correct class names. class-naming-style=PascalCase # Regular expression matching correct class names. Overrides class-naming- # style. #class-rgx= # Naming style matching correct constant names. const-naming-style=UPPER_CASE # Regular expression matching correct constant names. Overrides const-naming- # style. #const-rgx= # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 # Naming style matching correct function names. function-naming-style=snake_case # Regular expression matching correct function names. Overrides function- # naming-style. #function-rgx= # Good variable names which should always be accepted, separated by a comma. good-names=i, j, k, fp, ex, Run, _ # Include a hint for the correct naming format with invalid-name. include-naming-hint=no # Naming style matching correct inline iteration names. inlinevar-naming-style=any # Regular expression matching correct inline iteration names. Overrides # inlinevar-naming-style. #inlinevar-rgx= # Naming style matching correct method names. method-naming-style=snake_case # Regular expression matching correct method names. Overrides method-naming- # style. #method-rgx= # Naming style matching correct module names. module-naming-style=snake_case # Regular expression matching correct module names. Overrides module-naming- # style. #module-rgx= # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. # These decorators are taken in consideration only for invalid-name. property-classes=abc.abstractproperty # Naming style matching correct variable names. variable-naming-style=snake_case # Regular expression matching correct variable names. Overrides variable- # naming-style. #variable-rgx= [SIMILARITIES] # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no # Minimum lines number of a similarity. min-similarity-lines=4 [FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' # Maximum number of characters on a single line. max-line-length=100 # Maximum number of lines in a module. max-module-lines=1000 # List of optional constructs for which whitespace checking is disabled. `dict- # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. # `trailing-comma` allows a space between comma and closing bracket: (a, ). # `empty-line` allows space-only lines. no-space-check=trailing-comma, dict-separator # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME, XXX, TODO [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # Tells whether to warn about missing members when the owner of the attribute # is inferred to be None. ignore-none=yes # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference # can return multiple potential results while evaluating a Python object, but # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. ignore-on-opaque-inference=yes # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis). It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. missing-member-hint=yes # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. missing-member-hint-distance=1 # The total number of similar names that should be taken in consideration when # showing a hint for a missing member. missing-member-max-choices=1 # List of decorators that change the signature of a decorated function. signature-mutators= [SPELLING] # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 # Spelling dictionary name. Available dictionaries: none. To make it work, # install the python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains the private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to the private dictionary (see the # --spelling-private-dict-file option) instead of raising a message. spelling-store-unknown-words=no [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid defining new builtins when possible. additional-builtins= # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=no # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_, _cb # A regular expression matching the name of placeholder variables (i.e. expected # to not be used). dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ # Argument names that match this expression will be ignored. Default to name # with leading underscore. ignored-argument-names=_.*|^ignored_|^unused_ # Tells whether we should check for unused import in __init__ files. init-import=no # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io [LOGGING] # Format style used to check logging format string. `old` means using % # formatting, `new` is for `{}` formatting,and `fstr` is for f-strings. logging-format-style=old # Logging modules to check that the string format arguments are in logging # function parameter format. logging-modules=logging [STRING] # This flag controls whether the implicit-str-concat-in-sequence should # generate a warning on implicit string concatenation in sequences defined over # several lines. check-str-concat-over-line-jumps=no [IMPORTS] # List of modules that can be imported at any level, not just the top level # one. allow-any-import-level= # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no # Deprecated modules which should not be used, separated by a comma. deprecated-modules=optparse,tkinter.tix # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled). ext-import-graph= # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled). import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled). int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant # Couples of modules and preferred modules, separated by a comma. preferred-modules= [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__, __new__, setUp, __post_init__ # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict, _fields, _replace, _source, _make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=cls [DESIGN] # Maximum number of arguments for function / method. max-args=5 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Maximum number of boolean expressions in an if statement (see R0916). max-bool-expr=5 # Maximum number of branch for function / method body. max-branches=12 # Maximum number of locals for function / method body. max-locals=15 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of return / yield for function / method body. max-returns=6 # Maximum number of statements in function / method body. max-statements=50 # Minimum number of public methods for a class (see R0903). min-public-methods=2 [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "BaseException, Exception". overgeneral-exceptions=BaseException, Exception # Maximum number of characters on a single line. max-line-length=80 ================================================ FILE: .style.yapf ================================================ [style] based_on_style = google column_limit = 80 indent_width = 2 split_before_named_assigns = true ================================================ FILE: AGENTS.md ================================================ * Use python3 infra/helper.py to build projects and run fuzzers. * If doing development on infra/ you should use a venv and if it doesn't already exist, install deps from infra/ci/requirements.txt build/functions/requirements.txt with pip. * If doing development on infra/ run python infra/presubmit.py to format, lint and run tests. ================================================ FILE: CITATION.cff ================================================ cff-version: 1.2.0 title: OSS-Fuzz message: >- If you use this software, please cite it using the metadata from this file. type: software authors: - given-names: Abhishek family-names: Arya affiliation: Google LLC email: aarya@google.com orcid: 'https://orcid.org/0009-0009-4558-4314' - given-names: Oliver family-names: Chang email: ochang@google.com affiliation: Google LLC orcid: 'https://orcid.org/0009-0006-3181-4551' - given-names: Jonathan family-names: Metzman email: metzman@google.com affiliation: Google LLC orcid: 'https://orcid.org/0000-0002-7042-0444' - given-names: Kostya family-names: Serebryany email: kcc@google.com affiliation: Google LLC orcid: 'https://orcid.org/0009-0009-2379-3641' - given-names: Dongge family-names: Liu email: donggeliu@google.com affiliation: Google LLC orcid: 'https://orcid.org/0000-0003-4821-7033' repository-code: 'https://github.com/google/oss-fuzz' abstract: >- OSS-Fuzz is an open-source project by Google that provides continuous fuzzing for open-source software. It aims to make common open-source software more secure and stable by combining modern fuzzing techniques with scalable, distributed execution. As of August 2023, OSS-Fuzz has helped identify and fix over 10,000 vulnerabilities and 36,000 bugs across 1,000 projects. keywords: - open-source - fuzzing license: Apache-2.0 ================================================ FILE: CONTRIBUTING.md ================================================ Want to contribute? Great! First, read this page (including the small print at the end). ### Before you contribute Before we can use your code, you must sign the [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) (CLA), which you can do online. The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things: for instance that you'll tell us if you know that your code infringes on other people's patents. You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase. Before you start working on a larger contribution, you should get in touch with us first through the issue tracker with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on. ### Code reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. ### The small print Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate). ### Requesting a review PRs should be reviewed within a few days by the OSS-Fuzz oncall. There is no need to add anyone to review your code. If for some reason this does not happen for a few days, feel free to add a team member or email oss-fuzz-team@google.com about your PR. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # OSS-Fuzz: Continuous Fuzzing for Open Source Software [Fuzz testing] is a well-known technique for uncovering programming errors in software. Many of these detectable errors, like [buffer overflow], can have serious security implications. Google has found [thousands] of security vulnerabilities and stability bugs by deploying [guided in-process fuzzing of Chrome components], and we now want to share that service with the open source community. [Fuzz testing]: https://en.wikipedia.org/wiki/Fuzz_testing [buffer overflow]: https://en.wikipedia.org/wiki/Buffer_overflow [thousands]: https://issues.chromium.org/issues?q=label:Stability-LibFuzzer%20-status:Duplicate,WontFix [guided in-process fuzzing of Chrome components]: https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html In cooperation with the [Core Infrastructure Initiative] and the [OpenSSF], OSS-Fuzz aims to make common open source software more secure and stable by combining modern fuzzing techniques with scalable, distributed execution. Projects that do not qualify for OSS-Fuzz (e.g. closed source) can run their own instances of [ClusterFuzz] or [ClusterFuzzLite]. [Core Infrastructure Initiative]: https://www.coreinfrastructure.org/ [OpenSSF]: https://www.openssf.org/ We support the [libFuzzer], [AFL++], and [Honggfuzz] fuzzing engines in combination with [Sanitizers], as well as [ClusterFuzz], a distributed fuzzer execution environment and reporting tool. [libFuzzer]: https://llvm.org/docs/LibFuzzer.html [AFL++]: https://github.com/AFLplusplus/AFLplusplus [Honggfuzz]: https://github.com/google/honggfuzz [Sanitizers]: https://github.com/google/sanitizers [ClusterFuzz]: https://github.com/google/clusterfuzz [ClusterFuzzLite]: https://google.github.io/clusterfuzzlite/ Currently, OSS-Fuzz supports C/C++, Rust, Go, Python, Java/JVM, JavaScript and Lua code. Other languages supported by [LLVM] may work too. OSS-Fuzz supports fuzzing x86_64 and i386 builds. [LLVM]: https://llvm.org ## Overview ![OSS-Fuzz process diagram](docs/images/process.png) ## Documentation Read our [detailed documentation] to learn how to use OSS-Fuzz. [detailed documentation]: https://google.github.io/oss-fuzz ## Trophies As of May 2025, OSS-Fuzz has helped identify and fix over 13,000 vulnerabilities and 50,000 bugs across [1,000] projects. [1,000]: https://github.com/google/oss-fuzz/tree/master/projects ## Blog posts * 2024-11-20 - [Leveling Up Fuzzing: Finding more vulnerabilities with AI] * 2023-08-16 - [AI-Powered Fuzzing: Breaking the Bug Hunting Barrier] * 2023-02-01 - [Taking the next step: OSS-Fuzz in 2023] * 2022-09-08 - [Fuzzing beyond memory corruption: Finding broader classes of vulnerabilities automatically] * 2021-12-16 - [Improving OSS-Fuzz and Jazzer to catch Log4Shell] * 2021-03-10 - [Fuzzing Java in OSS-Fuzz] * 2020-12-07 - [Improving open source security during the Google summer internship program] * 2020-10-09 - [Fuzzing internships for Open Source Software] * 2018-11-06 - [A New Chapter for OSS-Fuzz] * 2017-05-08 - [OSS-Fuzz: Five months later, and rewarding projects] * 2016-12-01 - [Announcing OSS-Fuzz: Continuous fuzzing for open source software] [Leveling Up Fuzzing: Finding more vulnerabilities with AI]: https://security.googleblog.com/2024/11/leveling-up-fuzzing-finding-more.html [AI-Powered Fuzzing: Breaking the Bug Hunting Barrier]: https://security.googleblog.com/2023/08/ai-powered-fuzzing-breaking-bug-hunting.html [Announcing OSS-Fuzz: Continuous fuzzing for open source software]: https://opensource.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html [OSS-Fuzz: Five months later, and rewarding projects]: https://opensource.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html [A New Chapter for OSS-Fuzz]: https://security.googleblog.com/2018/11/a-new-chapter-for-oss-fuzz.html [Fuzzing internships for Open Source Software]: https://security.googleblog.com/2020/10/fuzzing-internships-for-open-source.html [Improving open source security during the Google summer internship program]: https://security.googleblog.com/2020/12/improving-open-source-security-during.html [Fuzzing Java in OSS-Fuzz]: https://security.googleblog.com/2021/03/fuzzing-java-in-oss-fuzz.html [Improving OSS-Fuzz and Jazzer to catch Log4Shell]: https://security.googleblog.com/2021/12/improving-oss-fuzz-and-jazzer-to-catch.html [Fuzzing beyond memory corruption: Finding broader classes of vulnerabilities automatically]: https://security.googleblog.com/2022/09/fuzzing-beyond-memory-corruption.html [Taking the next step: OSS-Fuzz in 2023]: https://security.googleblog.com/2023/02/taking-next-step-oss-fuzz-in-2023.html ================================================ FILE: docs/.gitignore ================================================ _site .bundle .sass-cache .jekyll-metadata vendor ================================================ FILE: docs/404.html ================================================ --- layout: default ---

404

Page not found :(

================================================ FILE: docs/Gemfile ================================================ source "https://rubygems.org" gem 'github-pages', group: :jekyll_plugins gem "webrick", "~> 1.8" ================================================ FILE: docs/README.md ================================================ # Readme Use the following instructions to make documentation changes locally. ## Prerequisites ```bash $ sudo apt install ruby bundler $ bundle config set path 'vendor/bundle' $ bundle install ``` ## Serving locally ```bash $ bundle exec jekyll serve ``` ## Theme documentation We are using the [just the docs](https://just-the-docs.github.io/just-the-docs/) theme. ================================================ FILE: docs/_config.yml ================================================ # Welcome to Jekyll! # # This config file is meant for settings that affect your whole blog, values # which you are expected to set up once and rarely edit after that. If you find # yourself editing this file very often, consider using Jekyll's data files # feature for the data you need to update frequently. # # For technical reasons, this file is *NOT* reloaded automatically when you use # 'bundle exec jekyll serve'. If you change this file, please restart the server process. # Site settings # These are used to personalize your new site. If you look in the HTML files, # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. # You can create any custom variable you would like, and they will be accessible # in the templates via {{ site.myvariable }}. title: OSS-Fuzz description: Documentation for OSS-Fuzz baseurl: "/oss-fuzz" # the subpath of your site, e.g. /blog url: "" # the base hostname & protocol for your site, e.g. http://example.com # Build settings markdown: kramdown remote_theme: pmarsceill/just-the-docs search_enabled: true ga_tracking: G-LRX1V3S5P aux_links: "OSS-Fuzz on GitHub": - https://github.com/google/oss-fuzz # Exclude from processing. exclude: - Gemfile - Gemfile.lock - node_modules - vendor/bundle/ - vendor/cache/ - vendor/gems/ - vendor/ruby/ ================================================ FILE: docs/_sass/color_schemes/wider.scss ================================================ @import "./color_schemes/light"; $content-width: 70rem; ================================================ FILE: docs/advanced-topics/advanced_topics.md ================================================ --- layout: default title: Advanced topics has_children: true nav_order: 3 permalink: /advanced-topics/ --- # Advanced topics ================================================ FILE: docs/advanced-topics/bug_fixing_guidance.md ================================================ --- layout: default title: Bug fixing guidance nav_order: 6 permalink: /advanced-topics/bug-fixing-guidance --- # Bug fixing guidance {: .no_toc} This page provides brief guidance on how to prioritise and fix bugs reported by OSS-Fuzz. - TOC {:toc} ## Threat modelling In general the severity of an issue reported by OSS-Fuzz must be determined relative to the threat model of the project under analysis. Therefore, although the fuzzers OSS-Fuzz makes an effort into determining the severity of the bug the true severity of the bug depends on the threat model of the project. ## Bug prioritisation ### Security issues These are the top priority of solving. A label is attached to these on the OSS-Fuzz testcase page and you can also search up all of these on monorail using the search pattern `-Bug=security`. Issues of this kind include issues reported by Address Sanitizer, e.g. heap-based buffer overflows, stack-based buffer overflows and use-after-frees. ### Functional issues and memory leaks These are issues that in general can tamper with the functionality of the application. The bugs that have highest priority in this case are those that can be easily triggered by an untrusted user of the project. ### Timeouts and out-of-memory These are in general the least prioritised issues to solve. ### Bug prioritisation of non C/C++ projects Currently there is no prioritisation of bugs in non C/C++ projects. As such, in this scenario it is crucial you do the analysis yourself relative to the threat model of your project. ## Non-reproducible bugs OSS-Fuzz will report some bugs that are labeled `Reliably reproduces: NO` and these can be tricky to deal with. A non-reproducible bug is an issue that OSS-Fuzz did indeed discover, however, OSS-Fuzz is unable to reproduce the bug with `python3 infra/helper.py reproduce`. In general, our suggestion is to do analysis of the bug and determine whether there in fact is an issue. The non-reproducible bugs can be of varying nature. Some of these bugs will be due to some internal state of the target application being manipulated over the cause of several executions of the fuzzer function. This could be several hundreds or even thousands of executions and the bug may not be reproducible by a single fuzzer test-case, however, there is indeed a bug in the application. There are other reasons why bugs may be non-reproducible and in general any non-determinism introduced into the application can have an effect on this. In the case of non-reproducible bugs our advice is to put effort into analysing the potential bug and also assess whether this is due to some internal state that persists between each fuzz run. If that is indeed the case then we also suggest investigating whether the fuzzer can be written such that the internal state in the code will be reset between each fuzz run. ## Should all reported issues be solved? It is reported by some project maintainers that fixing timeout issues reported by OSS-Fuzz can increase the complexity of the project’s source code. The result of this is that maintainers put effort into solving a timeout issue and the fix results in additional complexity of the project. The question is whether in a scenario like this if the overall result actually improves the state of the application. In order to answer this question we must assess the issue relative to the threat model. Following the timeout anecdote then some timing issues can have severe security implications. For example, if the timeout issue can cause manipulation of control-flow then the timing issue may be of high security severity. As such, it is difficult to say in the general case whether or not some bugs should not be solved, as it should be analysed and determined on a project-by-project basis. In the event that a bug is reported by OSS-Fuzz that is not relevant to security or reliability of the application then there may still be a point to fixing the bug. For example, if the issue is often run into by the fuzzer then the fuzzer may have difficulty exploring further code in the target, and thus fixing the bug will allow the fuzzer to explore further code. In this case some suggested examples of resolving the issue could be: * Perform a hot-patch that is only applied during fuzzer executions and does not overcomplicate the project’s code. * Patch the code of the fuzzer to avoid the timeout. For example, some fuzzers restrict the size of the input to avoid certain deep recursions or time-intensive loops. * Patch the code in the target despite complicating things. ================================================ FILE: docs/advanced-topics/code_coverage.md ================================================ --- layout: default title: Code coverage parent: Advanced topics nav_order: 2 permalink: /advanced-topics/code-coverage/ --- # Code Coverage {: .no_toc} For projects written in C/C++, Rust, Go, Swift or Java and other JVM-based languages, you can generate code coverage reports using Clang source-based code coverage. This page walks you through the basic steps. For more details on C/C++ coverage, see [Clang's documentation]. Code coverage reports generation for other languages is not supported yet. - TOC {:toc} --- ## Pull the latest Docker images Docker images get regularly updated with a newer version of build tools, build configurations, scripts, and other changes. We recommend you pull the most recent images by running the following command: ```bash $ python3 infra/helper.py pull_images ``` ## Build fuzz targets Code coverage report generation requires a special build configuration to be used. To create a code coverage build for your project, run these commands: ```bash $ python3 infra/helper.py build_image $PROJECT_NAME $ python3 infra/helper.py build_fuzzers --sanitizer=coverage $PROJECT_NAME ``` ## Establish access to GCS To get a good understanding of fuzz testing quality, you should generate code coverage reports by running fuzz targets against the corpus aggregated by OSS-Fuzz. Set up `gsutil` and ensure that you have access to the corpora by doing the following: * Install the [gsutil tool]. * Check whether you have access to the corpus for your project: ```bash $ gsutil ls gs://${PROJECT_NAME}-corpus.clusterfuzz-external.appspot.com/ ``` If you see an authorization error from the command above, run this: ```bash $ gcloud auth login ``` and try again. Once `gsutil` works, you can run the report generation. ## Generate code coverage reports ### Full project report If you want to generate a code coverage report using the corpus aggregated on OSS-Fuzz, run this command: ```bash $ python3 infra/helper.py coverage $PROJECT_NAME ``` If you want to generate a code coverage report using the corpus you have locally, copy the corpus into the `build/corpus/$PROJECT_NAME//` directories for each fuzz target, then run this command: ```bash $ python3 infra/helper.py coverage --no-corpus-download $PROJECT_NAME ``` ### Single fuzz target You can generate a code coverage report for a particular fuzz target by using the `--fuzz-target` argument: ```bash $ python3 infra/helper.py coverage --fuzz-target= $PROJECT_NAME ``` In this mode, you can specify an arbitrary corpus location for the fuzz target (instead of the corpus downloaded from OSS-Fuzz) by using `--corpus-dir`: ```bash $ python3 infra/helper.py coverage --fuzz-target= \ --corpus-dir= $PROJECT_NAME ``` ### Additional arguments for `llvm-cov` (C/C++/Rust only) You may want to use some of the options provided by the [llvm-cov tool], like `-ignore-filename-regex=`. You can pass these to the helper script after `--`: ```bash $ python3 infra/helper.py coverage $PROJECT_NAME -- \ -ignore-filename-regex=.*code/to/be/ignored/.* ``` If you want to specify particular source files or directories to show in the report, list their paths at the end of the extra arguments sequence: ```bash $ python3 infra/helper.py coverage zlib -- \ /src/zlib/inftrees.c /src/zlib_uncompress_fuzzer.cc /src/zlib/zutil.c ``` If you want OSS-Fuzz to use extra arguments when generating code coverage reports for your project, add the arguments into your `project.yaml` file as follows: ```yaml coverage_extra_args: -ignore-filename-regex=.*crc.* -ignore-filename-regex=.*adler.* ``` [Clang's documentation]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html [gsutil tool]: https://cloud.google.com/storage/docs/gsutil_install [llvm-cov tool]: https://llvm.org/docs/CommandGuide/llvm-cov.html ================================================ FILE: docs/advanced-topics/corpora.md ================================================ --- layout: default title: Corpora parent: Advanced topics nav_order: 3 permalink: /advanced-topics/corpora/ --- # Accessing Corpora {: .no_toc} If you want to access the corpora that we are using for your fuzz targets (synthesized by the fuzzing engines), follow these steps. - TOC {:toc} --- ## Obtain access To get access to a project's corpora, you must be listed as the primary contact or as an auto cc in the project's `project.yaml` file, as described in the [New Project Guide]({{ site.baseurl }}/getting-started/new-project-guide/#projectyaml). If you don't do this, most of the links below won't work. ## Install Google Cloud SDK The corpora for fuzz targets are stored on [Google Cloud Storage](https://cloud.google.com/storage/). To access them, you need to [install the gsutil tool](https://cloud.google.com/storage/docs/gsutil_install), which is part of the Google Cloud SDK. Follow the instructions on the installation page to login with the Google account listed in your project's `project.yaml` file. ## Viewing the corpus for a fuzz target The fuzzer statistics page for your project on [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) contains a link to the Google Cloud console for your corpus under the **corpus_size** column. Click the link to browse and download individual test inputs in the corpus. ![viewing_corpus](https://raw.githubusercontent.com/google/oss-fuzz/master/docs/images/viewing_corpus.png) ## Downloading the corpus If you want to download the entire corpus, click the link in the **corpus_size** column, then copy the **Buckets** path at the top of the page: ![corpus_path](https://raw.githubusercontent.com/google/oss-fuzz/master/docs/images/corpus_path.png) Copy the corpus to a directory on your machine by running the following command: ```bash $ gsutil -m cp -r gs:// ``` Using the expat example above, this would be: ```bash $ gsutil -m cp -r \ gs://expat-corpus.clusterfuzz-external.appspot.com/libFuzzer/expat_parse_fuzzer \ ``` ## Corpus backups We keep daily zipped backups of your corpora. These can be accessed from the **corpus_backup** column of the fuzzer statistics page. Downloading these can be significantly faster than running `gsutil -m cp -r` on the corpus bucket. ================================================ FILE: docs/advanced-topics/debugging.md ================================================ --- layout: default title: Debugging parent: Advanced topics nav_order: 4 permalink: /advanced-topics/debugging/ --- # Debugging issues {: .no_toc} - TOC {:toc} --- ## Debugging build scripts While developing your build script, it may be useful to run bash within the container: ```bash $ python3 infra/helper.py shell $PROJECT_NAME # runs /bin/bash within container $ compile # runs compilation manually ``` ## Debugging fuzzers with GDB If you wish to debug a fuzz target with gdb, you can use the base-runner-debug image: ```bash # Copy input testcase into host output directory so it can be accessed # within the Docker image. $ cp /path/to/testcase build/out/$PROJECT_NAME # Run the Docker image containing GDB. $ python3 infra/helper.py shell base-runner-debug $ gdb --args /out/$PROJECT_NAME/$FUZZ_TARGET_NAME /out/$PROJECT_NAME/testcase ``` **Note:** The `base-runner-debug` image does not have access to your sources, so you will not be able to do source code level debugging. We recommend integrating your fuzz target upstream as part of [ideal integration]({{ site.baseurl }}/advanced-topics/ideal-integration/) for debugging purposes. ================================================ FILE: docs/advanced-topics/fuzz_introspector.md ================================================ --- layout: default title: Fuzz Introspector parent: Advanced topics nav_order: 2 permalink: /advanced-topics/fuzz-introspector/ --- # Fuzz Introspector {: .no_toc} For projects written in C/C++, Python and Java you can generate Fuzz Introspector reports to help guide the development of your fuzzing suite. These reports help to extract details about the fuzzing setup of your project with the goal of making it easier to improve the fuzzing set up. The Fuzz Introspector reports are generated automatically and uploaded to the cloud like code coverage reports, and you can also generate them locally using the OSS-Fuzz helper script. - TOC {:toc} --- ## Fuzz Introspector overview As soon as your project is run with ClusterFuzz (<1 day), you can view the Fuzz Introspector report for your project. [Fuzz Introspector](https://github.com/ossf/fuzz-introspector) helps you understand your fuzzers' performance and identify any potential blockers. It provides individual and aggregated fuzzer reachability and coverage reports. You can monitor each fuzzer's static reachability potential and compare it against dynamic coverage and identify any potential bottlenecks. Fuzz Introspector can offer suggestions on increasing coverage by adding new fuzz targets or modify existing ones. Fuzz Introspector reports can be viewed from the [OSS-Fuzz homepage](https://oss-fuzz.com/) or through this [index](http://oss-fuzz-introspector.storage.googleapis.com/index.html). - [Fuzz Introspector documentation](https://fuzz-introspector.readthedocs.io/en/latest/) - [Fuzz Introspector source code](https://github.com/ossf/fuzz-introspector) - [OSS-Fuzz Fuzz Introspector reports](http://oss-fuzz-introspector.storage.googleapis.com/index.html) ## Tutorials and guides The reports generated can be a lot to digest when first viewing them. The [Fuzz Introspector documentation](https://fuzz-introspector.readthedocs.io/en/latest/) provides various user guides and tutorials rooted in OSS-Fuzz projects, which is a useful reference on how to make use of the reports. For ideas on how to use Fuzz Introspector, see [user guides](https://fuzz-introspector.readthedocs.io/en/latest/user-guides/index.html) which includes sections e.g. - [Quickly extract overview of a given project](https://fuzz-introspector.readthedocs.io/en/latest/user-guides/quick-overview.html) - [Get ideas for new fuzz targets](https://fuzz-introspector.readthedocs.io/en/latest/user-guides/get-ideas-for-new-targets.html) - [Comparing introspector reports](https://fuzz-introspector.readthedocs.io/en/latest/user-guides/comparing-introspector-reports.html) ## Run Fuzz Introspector locally To generate a Fuzz Introspector report locally use `infra/helper.py` and the `introspector` command. Fuzz Introspector relies on code coverage to analyze a given project, and this means we need to extract code coverage in the Fuzz Introspector process. We can do this in two ways. First, by running the fuzzers for a given amount of time, and, second, by generating code coverage using the public corpus available from OSS-Fuzz. ### Generate reports by running fuzzers for X seconds The following command will generate a Fuzz Introspector report for the `libdwarf` project and will extract code coverage based on a corpus created from running the fuzzers for 30 seconds. ```bash $ python3 infra/helper.py introspector libdwarf --seconds=30 ``` If the above command was succesful, you should see output along the lines of: ```bash INFO:root:To browse the report, run: python3 -m http.server 8008 --directory /home/my_user/oss-fuzz/build/out/libdwarf/introspector-report/inspector and navigate to localhost:8008/fuzz_report.html in your browser ``` The above output gives you directions on how to start a simple webserver using `python3 -m http.server`, which you can use to view the Fuzz Introspector report. ### Generate reports by using public corpora The following command will generate a Fuzz Introspector report for the `libdwarf` project and will extract code coverage based on the publicly available corpora. ```bash $ python3 infra/helper.py introspector libdwarf --public-corpora ``` Assuming the above command is succesful you can view the report using `python3 -m http.server` following the example described above. ## Differences in build tooling There are some differences in build environment for Fuzz Introspector builds in comparison to e.g. ASAN or code coverage builds. The reason is that Fuzz Introspector relies on certain compile-time tools to do its analysis. This compile time tooling differs between languages, namely: - For C/C++, Fuzz Introspector relies on [LLVM LTO](https://llvm.org/docs/LinkTimeOptimization.html) and [LLVM Gold](https://llvm.org/docs/GoldPlugin.html) - For Python, Fuzz Introspector relies on a modified [PyCG](https://github.com/vitsalis/PyCG) - For Java, Fuzz Introspector relies on [Soot](https://soot-oss.github.io/soot/) The consequence of this is your project must be compatible with these projects. PyCG and Soot have not shown to be a blocker for many projects, however, experience has shown that sometimes a project's build needs modification in order to compile with LLVM LTO. The easiest way to test if your project works with LLVM is checking whether your project can compile with the flags `-flto -fuse-ld=gold` and using the gold linker. OSS-Fuzz automatically sets these flags and linker options when using `infra/helper.py` to build your project with `--sanitizer=introspector`, e.g. ```bash python3 infra/helper.py build_fuzzers --sanitizer=introspector PROJ_NAME ``` ================================================ FILE: docs/advanced-topics/ideal_integration.md ================================================ --- layout: default title: Ideal integration parent: Advanced topics nav_order: 1 permalink: /advanced-topics/ideal-integration/ --- # Ideal integration with OSS-Fuzz {: .no_toc} OSS projects have different build and test systems. We can't expect them all to implement and maintain fuzz targets or integrate them with OSS-Fuzz in the same way. However, we do have recommendations. This page documents several features (starting from the easiest) that will make automated fuzzing simple and efficient, and will help you catch regressions early in the development cycle. This simple [example](https://github.com/google/oss-fuzz/tree/master/projects/example/my-api-repo) covers most of the items. - TOC {:toc} --- ## Summary Every [fuzz target](https://llvm.org/docs/LibFuzzer.html#fuzz-target): * Is [maintained by code owners](#fuzz-target) in their RCS (Git, SVN, etc). * Is [built with the rest of the tests](#build-support) - no bit rot! * Has a [seed corpus](#seed-corpus) with good [code coverage](#coverage). * Has a [dictionary](#dictionary), if applicable. * Is [continuously tested on the seed corpus](#regression-testing) with [ASan/UBSan/MSan](https://github.com/google/sanitizers). * Is [fast and has no OOMs](#performance). ## Fuzz Target The code of the [fuzz target(s)](https://llvm.org/docs/LibFuzzer.html#fuzz-target) should be part of the project's source code repository. All fuzz targets should be easily discoverable (reside in the same directory, follow the same naming pattern, etc.). This makes it easy to maintain the fuzzers and minimizes breakages that can arise as source code changes over time. Make sure to fuzz the target locally for a small period of time to ensure that it does not crash, hang, or run out of memory instantly. Also make sure that the fuzzer can make at least some progress. If you're having trouble, read about [what makes a good fuzz target](https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md). The interface between the [fuzz target](https://llvm.org/docs/LibFuzzer.html#fuzz-target) and the fuzzing engines is C, so you can use either C or C++ to implement the fuzz target. Make sure to not return values other than **zero** [^1]. Examples: [boringssl](https://github.com/google/boringssl/tree/master/fuzz), [SQLite](https://www.sqlite.org/src/artifact/ad79e867fb504338), [s2n](https://github.com/awslabs/s2n/tree/master/tests/fuzz), [openssl](https://github.com/openssl/openssl/tree/master/fuzz), [FreeType](http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/src/tools/ftfuzzer), [re2](https://github.com/google/re2/tree/master/re2/fuzzing), [harfbuzz](https://github.com/behdad/harfbuzz/tree/master/test/fuzzing), [pcre2](https://vcs.pcre.org/pcre2/code/trunk/src/pcre2_fuzzsupport.c?view=markup), [ffmpeg](https://github.com/FFmpeg/FFmpeg/blob/master/tools/target_dec_fuzzer.c). [^1]: While LibFuzzer uses a non-zero value as a signal to discard inputs other fuzzers in use by OSS-Fuzz do not necessarily support this behavior. (Discarding inputs can be used to stop a fuzzer from exploring further, which should only be used with good reason.) ## Build support Many different build systems exist in the open-source world. The less OSS-Fuzz knows about them, the better it can scale. An ideal build integration for OSS-Fuzz looks like this: * For every fuzz target `foo` in the project, there is a build rule that builds `foo_fuzzer`, a binary that: * Contains the fuzzing entry point. * Contains (`LLVMFuzzerTestOneInput`) and all the code it depends on. * Uses the `main()` function from `$LIB_FUZZING_ENGINE` (env var [provided]({{ site.baseurl }}/getting-started/new-project-guide/) by OSS-Fuzz environment). * Since the build system supports changing the compiler and passing extra compiler flags, the build command for `foo_fuzzer` looks similar to this: ```bash # Assume the following env vars are set: # CC, CXX, CFLAGS, CXXFLAGS, LIB_FUZZING_ENGINE $ make_or_whatever_other_command foo_fuzzer ``` This minimizes OSS-Fuzz-specific configuration, making your fuzzing more robust. There is no point in hardcoding the exact compiler flags in the build system because they a) may change and b) depend on the fuzzing engine and sanitizer being used. ## Seed Corpus The *seed corpus* is a set of test inputs, stored as individual files, provided to the fuzz target as a starting point (to "seed" the mutations). The quality of the seed corpus has a huge impact on fuzzing efficiency; the higher the quality, the easier it is for the fuzzer to discover new code paths. The ideal corpus is a minimal set of inputs that provides maximal code coverage. For better OSS-Fuzz integration, the seed corpus should be available in revision control (it can be the same as or different from the source code). It should be regularly extended with the inputs that (used to) trigger bugs and/or touch new parts of the code. Examples: [boringssl](https://github.com/google/boringssl/tree/master/fuzz), [openssl](https://github.com/openssl/openssl/tree/master/fuzz), [nss](https://github.com/mozilla/nss-fuzzing-corpus) (corpus in a separate repo). ## Dictionary For some input types, a simple dictionary of tokens used by the input language can have a dramatic impact on fuzzing efficiency. For example, when fuzzing an XML parser, a dictionary of XML tokens is helpful. AFL++ has a [collection](https://github.com/AFLplusplus/AFLplusplus/tree/master/dictionaries) of dictionaries for popular data formats. Ideally, a dictionary should be maintained alongside the fuzz target, and it must use [correct syntax](https://llvm.org/docs/LibFuzzer.html#dictionaries). ## Coverage For a fuzz target to be useful, it must have good coverage in the code that it is testing. You can view the coverage for your fuzz targets by looking at the [fuzzer stats]({{ site.baseurl }}/further-reading/clusterfuzz#fuzzer-stats) dashboard on ClusterFuzz, as well as [coverage reports]({{ site.baseurl }}/further-reading/clusterfuzz#coverage-reports). To generate an aggregated code coverage report for your project, please see the [code coverage]({{ site.baseurl }}/advanced-topics/code-coverage) page. Coverage can often be improved by adding dictionaries, more inputs for seed corpora, and fixing timeouts/out-of-memory bugs in your targets. ## Regression Testing Fuzz targets should be regularly tested (not necessarily fuzzed!) as a part of the project's regression testing process. One way to do so is to link the fuzz target with a simple standalone driver ([example](https://github.com/llvm-mirror/compiler-rt/tree/master/lib/fuzzer/standalone)) that runs the provided inputs, then use this driver with the seed corpus created in previous step. We recommend you use [sanitizers](https://github.com/google/sanitizers) during regression testing. Examples: [SQLite](https://www.sqlite.org/src/artifact/d9f1a6f43e7bab45), [openssl](https://github.com/openssl/openssl/blob/master/fuzz/test-corpus.c). ## Performance Fuzz targets should perform well, because high memory usage and/or slow execution speed can slow the down the growth of coverage and finding of new bugs. ClusterFuzz provides a [performance analyzer]({{ site.baseurl }}/further-reading/clusterfuzz/#performance-analyzer) for each fuzz target that shows problems that are impacting performance. ## Not a project member? If you are a member of the project you want to fuzz, most of the steps above are simple. However in some cases, someone outside the project team may want to fuzz the code, and the project maintainers are not interested in helping. In such cases, we can host the fuzz targets, dictionaries, etc. in OSS-Fuzz's repository and mention them in the Dockerfile. It's not ideal, because the fuzz targets will not be continuously tested, so may quickly bitrot. Examples: [libxml2](https://github.com/google/oss-fuzz/tree/master/projects/libxml2), [c-ares](https://github.com/google/oss-fuzz/tree/master/projects/c-ares), [expat](https://github.com/google/oss-fuzz/tree/master/projects/expat). If you are not a project maintainer, we may not be able to CC you to security bugs found by OSS-Fuzz. ================================================ FILE: docs/advanced-topics/reproducing.md ================================================ --- layout: default title: Reproducing parent: Advanced topics nav_order: 5 permalink: /advanced-topics/reproducing/ --- # Reproducing OSS-Fuzz issues {: .no_toc} You've been CCed on an OSS-Fuzz issue ([examples](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=Type%3ABug%2CBug-Security)). Now what? Before attempting to fix the bug, you should be able to reliably reproduce it. - TOC {:toc} --- ## Fuzz target bugs Every issue has a [reproducer file]({{ site.baseurl }}/reference/glossary/#reproducer) (also know as a "testcase" file) attached. Download it. This file contains the bytes that were fed to the [fuzz target](https://llvm.org/docs/LibFuzzer.html#fuzz-target). **Note:** If the issue is not public, you will need to login using a [Google account](https://support.google.com/accounts/answer/176347?hl=en) ([why?]({{ site.baseurl }}/faq/#why-do-you-require-a-google-account-for-authentication)) that the bug report CCs. If you have already [integrated]({{ site.baseurl }}/advanced-topics/ideal-integration/) the fuzz target with your build and test system, all you have to do is run this command: ```bash $ ./fuzz_target_binary ``` For timeout bugs, add the `-timeout=65` argument. For OOM bugs, add the `-rss_limit_mb=2560` argument. Read more on [how timeouts and OOMs are handled]({{ site.baseurl }}/faq/#how-do-you-handle-timeouts-and-ooms). Depending on the nature of the bug, the fuzz target binary needs to be built with the appropriate [sanitizer](https://github.com/google/sanitizers) (for example, if it's a buffer overflow, build with [AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html)). If you're not sure how to build the fuzzer using the project's build system, you can also use Docker commands to replicate the exact build steps used by OSS-Fuzz, then feed the reproducer input to the fuzz target ([how?]({{ site.baseurl }}/getting-started/new-project-guide/#prerequisites), [why?]({{ site.baseurl }}/faq/#why-do-you-use-docker)). ## Building using Docker ### Cloning OSS-Fuzz To use the following `infra/helper.py` commands, you need a checkout of OSS-Fuzz: ```bash $ git clone --depth=1 https://github.com/google/oss-fuzz.git $ cd oss-fuzz ``` ### Pull the latest Docker images Docker images get regularly updated with a newer version of build tools, build configurations, scripts, and other changes. In some cases, a particular issue can be reproduced only with a fresh image being used. Pull the latest images by running the following command: ```bash $ python3 infra/helper.py pull_images ``` ### Build the image and the fuzzers Run the following commands: ```bash $ python3 infra/helper.py build_image $PROJECT_NAME $ python3 infra/helper.py build_fuzzers --sanitizer
\ --architecture $PROJECT_NAME ``` The `sanitizer` used in the report is the value in the **Sanitizer** column. It's one of the following: * **address** for AddressSanitizer. * **memory** for MemorySanitizer. * **undefined** for UndefinedBehaviorSanitizer. **Notes**: * The `architecture` argument is only necessary if you want to specify `i386` configuration. * Some bugs (specially ones related to pointer and integer overflows) are reproducible only in 32 bit mode or only in 64 bit mode. If you can't reproduce a particular bug building for x86_64, try building for i386. ## Reproducing bugs After you build an image and a fuzzer, you can reproduce a bug by running the following command: ```bash $ python3 infra/helper.py reproduce $PROJECT_NAME ``` For example, to build the [libxml2](https://github.com/google/oss-fuzz/tree/master/projects/libxml2) project with UndefinedBehaviorSanitizer (`undefined`) instrumentation and reproduce a crash testcase for a fuzzer named `libxml2_xml_read_memory_fuzzer`, you would run: ```bash $ python3 infra/helper.py build_image libxml2 $ python3 infra/helper.py build_fuzzers --sanitizer undefined libxml2 $ python3 infra/helper.py reproduce libxml2 libxml2_xml_read_memory_fuzzer ~/Downloads/testcase ``` ## Reproduce using local source checkout You can also mount local sources into the running container by using these commands: ```bash $ python3 infra/helper.py build_fuzzers \ --sanitizer
$PROJECT_NAME $ python3 infra/helper.py reproduce $PROJECT_NAME ``` Once you reproduce the bug, you can do the following: - **Fix issue:** Write a patch to fix the issue in your local checkout, then use the previous command to verify the fix (i.e. no crash occurred). [Use gdb]({{ site.baseurl }}/advanced-topics/debugging/#debugging-fuzzers-with-gdb) if needed. - **Submit fix:** Submit the fix in the project's repository. ClusterFuzz will automatically pick up the changes, recheck the testcase, and close the issue (in < 1 day). - **Improve fuzzing support:** Consider [improving your integration with OSS-Fuzz]({{ site.baseurl }}/advanced-topics/ideal-integration/). ## Reproducing build failures Our infrastructure runs some sanity tests to make sure that your build was correctly configured, even if it succeeded. To reproduce these locally, run these commands: ```bash $ python3 infra/helper.py build_image $PROJECT_NAME $ python3 infra/helper.py build_fuzzers --sanitizer
\ --engine --architecture $PROJECT_NAME $ python3 infra/helper.py check_build --sanitizer
\ --engine --architecture $PROJECT_NAME \ ``` **Note:** Unless you have a reason to think the build is an `i386` build, the build is probably an `x86_64` build and the `architecture` argument can be omitted. If you need to reproduce a `coverage` build failure, follow the [Code Coverage page]({{ site.baseurl }}/advanced-topics/code-coverage) to build your project and generate a code coverage report. ================================================ FILE: docs/assets/css/just-the-docs-wider.scss ================================================ --- --- {% include css/just-the-docs.scss.liquid color_scheme="wider" %} ================================================ FILE: docs/faq.md ================================================ --- layout: default title: FAQ nav_order: 7 permalink: /faq/ --- # Frequently Asked Questions - TOC {:toc} --- ## Where can I learn more about fuzzing? We recommend reading [libFuzzer tutorial] and the other docs in [google/fuzzing] repository. These and some other resources are listed on the [useful links]({{ site.baseurl }}/reference/useful-links/#tutorials) page. [google/fuzzing]: https://github.com/google/fuzzing/tree/master/docs [libFuzzer tutorial]: https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md ## What kind of projects are you accepting? We accept established projects that have a critical impact on infrastructure and user security. We will consider each request on a case-by-case basis, but some things we keep in mind are: - Exposure to remote attacks (e.g. libraries that are used to process untrusted input). - Number of users/other projects depending on this project. We hope to relax this requirement in the future though, so keep an eye out even if we are not able to accept your project at this time! ## How can I find potential fuzz targets in my open source project? You should look for places in your code that: - consume un-trusted data from users or from the network. - consume complex input data even if it's 'trusted'. - use an algorithm that has two or more implementations (to verify their equivalence). - look for existing fuzz target [examples](https://github.com/google/oss-fuzz/tree/master/projects) and find similarities. ## Where can I store fuzz target sources and the build script if it's not yet accepted upstream? Fuzz target sources as well as the build script may temporarily live inside the `projects/` directory in the OSS-Fuzz repository. Note that we do not accept integrations that rely on forked repositories. Refer to the [ideal integration guide] for the preferred long term solution. ## My project is not open source. Can I use OSS-Fuzz? You cannot use OSS-Fuzz, but you can use [ClusterFuzz] which OSS-Fuzz is based on. ClusterFuzz is an open-source fuzzing infrastructure that you can deploy in your own environment and run continuously at scale. OSS-Fuzz is a production instance of ClusterFuzz, plus the code living in [OSS-Fuzz repository]: build scripts, `project.yaml` files with contacts, etc. [OSS-Fuzz repository]: https://github.com/google/oss-fuzz ## Why do you use a [different issue tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list) for reporting bugs in OSS projects? Security access control is important for the kind of issues that OSS-Fuzz detects, hence why by default issues are only opened on the OSS-Fuzz tracker. You can opt-in to have them on Github as well by adding the `file_github_issue` attribute to your `project.yaml` file. Note that this is only for visibility's purpose, and that the actual details can be found by following the link to the OSS-Fuzz tracker. ## Why do you require a Google account for authentication? Our [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) fuzzing infrastructure and [issue tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list) require a Google account for authentication. Note that an alternate email address associated with a Google account does not work due to appengine api limitations. ## Why do you use Docker? Building fuzzers requires building your project with a fresh Clang compiler and special compiler flags. An easy-to-use Docker image is provided to simplify toolchain distribution. This also simplifies our support for a variety of Linux distributions and provides a reproducible environment for fuzzer building and execution. ## How do you handle timeouts and OOMs? If a single input to a [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target) requires more than **~25 seconds** or more than **2.5GB RAM** to process, we report this as a timeout or an OOM (out-of-memory) bug (examples: [timeouts](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=%22Crash+Type%3A+Timeout%22), [OOMs](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q="Crash+Type%3A+Out-of-memory")). This may or may not be considered as a real bug by the project owners, but nevertheless we treat all timeouts and OOMs as bugs since they significantly reduce the efficiency of fuzzing. Remember that fuzzing is executed with AddressSanitizer or other sanitizers which introduces a certain overhead in RAM and CPU. We currently do not have a good way to deduplicate timeout or OOM bugs. So, we report only one timeout and only one OOM bug per fuzz target. Once that bug is fixed, we will file another one, and so on. ## Can I change the default timeout and OOM for a fuzz target? Yes, you can. For this, create a fuzz target options file named `.options`, where `` is the executable file name of the fuzz target, in the same directory as your `project.yaml`. The options file can contain fuzzer-specific configuration values, such as: ``` [libfuzzer] rss_limit_mb = 6000 timeout = 30 ``` ## My library gracefully handles allocation failures, why are OOMs reported? OOM detection is done *not* by instrumenting memory allocation routines such as `malloc` to have them return NULL, but using a separate watchdog thread that measures the resident set size (RSS) on a periodic basis. Therefore, your fuzz target might successfully allocate more than the configured max RSS, and yet get killed shortly afterwards. The only reliable way to avoid this is for your fuzz target to use a custom allocator that will prevent allocating more memory than a given limit. You can find a more detailed discussion of this topic, as well as links to the solution implemented by a specific project, in [this issue](https://github.com/google/oss-fuzz/issues/1830). ## Can I launch an additional process (e.g. a daemon) from my fuzz target? No. In order to get all the benefits of in-process, coverage-guided fuzz testing, it is required to run everything inside a single process. Any child processes created outside the main process introduces heavy launch overhead and is not monitored for code coverage. Another rule of thumb is: "the smaller fuzz target is, the better it is". It is expected that your project will have many fuzz targets to test different components, instead of a single fuzz target trying to cover everything. Think of fuzz target as a unit test, though it is much more powerful since it helps to test millions of data permutations rather than just one. ## What if my fuzz target finds a bug in another project (dependency) ? Every bug report has a crash stack-trace that shows where the crash happened. Using that, you can debug the root cause and see which category the bug falls in: - If this is a bug is due to an incorrect usage of the dependent project's API in your project, then you need to fix your usage to call the API correctly. - If this is a real bug in the dependent project, then you should CC the maintainers of that project on the bug. Once CCed, they will get automatic access to all the information necessary to reproduce the issue. If this project is maintained in OSS-Fuzz, you can search for contacts in the respective project.yaml file. ## What if my fuzzer does not find anything? If your fuzz target is running for many days and does not find bugs or new coverage, it may mean several things: - We've covered all reachable code. In order to cover more code we need more fuzz targets. - The [seed corpus]({{ site.baseurl }}/getting-started/new-project-guide#seed-corpus) is not good enough and the fuzzing engine(s) are not able to go deeper based on the existing seeds. Need to add more seeds. - There is some crypto/crc stuff in the code that will prevent any fuzzing engine from going deeper, in which case the crypto should be disabled in [fuzzing mode](https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode). Examples: [openssl](https://github.com/openssl/openssl/tree/master/fuzz#reproducing-issues), [boringssl](https://boringssl.googlesource.com/boringssl/+/HEAD/FUZZING.md#Fuzzer-mode) - It is also possible that the fuzzer is running too slow (you may check the speed of your targets at https://oss-fuzz.com/) In either case, look at the [coverage reports]({{ site.baseurl }}/further-reading/clusterfuzz#coverage-reports) for your target(s) and figure out why some parts of the code are not covered. ## What if my fuzzer does not find new coverage or bugs after a while? It is common for fuzzers to plateau and stop finding new coverage or bugs. [Fuzz Introspector](https://github.com/ossf/fuzz-introspector) helps you evaluate your fuzzers' performance. It can help you identify bottlenecks causing your fuzzers to plateau. It provides aggregated and individual fuzzer reachability and coverage reports. Developers can either introduce a new fuzz target or modify an existing one to reach previously unreachable code. Here are [case studies](https://github.com/ossf/fuzz-introspector/blob/main/doc/CaseStudies.md) where Fuzz Introspector helped developers improve fuzzing of a project. Fuzz Introspector reports are available on the [OSS-Fuzz homepage](https://oss-fuzz.com/) or through this [index](http://oss-fuzz-introspector.storage.googleapis.com/index.html). Developers can also use Fuzz Introspector on their local machines. Detailed instructions are available [here](https://github.com/ossf/fuzz-introspector/tree/main/oss_fuzz_integration#build-fuzz-introspector-with-oss-fuzz). ## Why are code coverage reports public? We work with open source projects and try to keep as much information public as possible. We believe that public code coverage reports do not put users at risk, as they do not indicate the presence of bugs or lack thereof. ## Why is the coverage command complaining about format compatibility issues? This may happen if the Docker images fetched locally become out of sync. Make sure you run the following command to pull the most recent images: ```bash $ python3 infra/helper.py pull_images ``` Please refer to [code coverage]({{ site.baseurl }}/advanced-topics/code-coverage/) for detailed information on code coverage generation. ## What happens when I rename a fuzz target ? If you rename your fuzz targets, the existing bugs for those targets will get closed and fuzzing will start from scratch from a fresh corpora (seed corpus only). Similar corpora will get accumulated over time depending on the number of cpu cycles that original fuzz target has run. If this is not desirable, make sure to copy the accumulated corpora from the original fuzz target (instructions to download [here]({{ site.baseurl }}/advanced-topics/corpora/#downloading-the-corpus)) and restore it to the new GCS location later (instruction to find the new location [here]({{ site.baseurl }}/advanced-topics/corpora/#viewing-the-corpus-for-a-fuzz-target)). ## Does OSS-Fuzz support AFL or honggfuzz or Centipede? OSS-Fuzz *uses* the following [fuzzing engines]({{ site.baseurl }}/reference/glossary/#fuzzing-engine): 1. [libFuzzer](https://llvm.org/docs/LibFuzzer.html). 1. [AFL++](https://github.com/AFLplusplus/AFLplusplus), an improved and well-maintained version of [AFL](https://lcamtuf.coredump.cx/afl/). 1. [Honggfuzz](https://github.com/google/honggfuzz). 1. [Centipede (Experimental)](https://github.com/google/centipede). Follow the [new project guide] and OSS-Fuzz will use all its fuzzing engines on your code. ## What are the specs on your machines? OSS-Fuzz builders have 32CPU/28.8GB RAM. Fuzzing machines only have a single core and fuzz targets should not use more than 2.5GB of RAM. ## Are there any restrictions on using test cases / corpora generated by OSS-Fuzz? No, you can freely use (i.e. share, add to your repo, etc.) the test cases and corpora generated by OSS-Fuzz. OSS-Fuzz infrastructure is fully open source (including [ClusterFuzz], various fuzzing engines, and other dependencies). We have no intent to restrict the use of the artifacts produced by OSS-Fuzz. [ClusterFuzz]: https://github.com/google/clusterfuzz [new project guide]: {{ site.baseurl }}/getting-started/new-project-guide/ [ideal integration guide]: {{ site.baseurl }}/getting-started/new-project-guide/ ================================================ FILE: docs/further-reading/clusterfuzz.md ================================================ --- layout: default title: ClusterFuzz parent: Further reading nav_order: 1 permalink: /further-reading/clusterfuzz/ --- # ClusterFuzz [ClusterFuzz](https://github.com/google/clusterfuzz) is the distributed fuzzing infrastructure behind OSS-Fuzz. It was initially built for fuzzing Chrome at scale. - TOC {:toc} --- ## Web interface ClusterFuzz provides a [web interface](https://oss-fuzz.com) to view statistics about your fuzz targets, as well as current crashes. *Note*: Access is restricted to project developers who we auto CC on new bug reports. ## Testcase reports ClusterFuzz will automatically de-duplicate and file reproducible crashes into our [bug tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list). We provide a crash report page that gives you the stack trace, a link to the crashing testcase, and regression ranges where the bug was most likely introduced. ![report]({{ site.baseurl }}/images/pcre2_testcase.png?raw=true) ## Fuzzer stats You can view statistics about your fuzz targets (e.g. speed, coverage information, memory usage) on our fuzzer statistics dashboard. ![stats]({{ site.baseurl }}/images/freetype_stats_graphs.png?raw=true) ![stats]({{ site.baseurl }}/images/freetype_stats_table.png?raw=true) ## Coverage reports We provide coverage reports, where we highlight the parts of source code that are being reached by your fuzz target. Make sure to look at the uncovered code marked in red and add appropriate fuzz targets to cover those use cases. ![coverage_1]({{ site.baseurl }}/images/freetype_coverage_1.png?raw=true) ![coverage_2]({{ site.baseurl }}/images/freetype_coverage_2.png?raw=true) ## Performance analyzer You can view performance issues that your fuzz target is running into (e.g. leaks, timeouts, etc) by clicking on `Performance` link on our fuzzer statistics dashboard. Make sure to fix all cited issues, so as to keep your fuzz target running efficiently and finding new bugs. ![performance_analyzer]({{ site.baseurl }}/images/expat_performance_analyzer.png?raw=true) ## Crash stats You can view statistics of crashes over time on our crash statistics dashboard. ![crash_stats]({{ site.baseurl }}/images/crash_stats.png?raw=true) ================================================ FILE: docs/further-reading/further_reading.md ================================================ --- layout: default title: Further reading has_children: true nav_order: 4 permalink: /further-reading/ --- # Further reading ================================================ FILE: docs/further-reading/fuzzer_environment.md ================================================ --- layout: default title: Fuzzer environment parent: Further reading nav_order: 2 permalink: /further-reading/fuzzer-environment/ --- # Fuzzer environment on ClusterFuzz Your fuzz targets will be run on a [Google Compute Engine](https://cloud.google.com/compute/) VM (Linux). - TOC {:toc} --- ## Runtime Dependencies You should not make any assumptions on the availability of dependent packages in the execution environment. Packages that are installed via [Dockerfile]({{ site.baseurl }}/getting-started/new-project-guide/#dockerfile) or built as part of [build.sh]({{ site.baseurl }}/getting-started/new-project-guide/#buildsh) are not available on the bot runtime environment (where the fuzz targets run). If you need these dependencies in the runtime environment, you can either: - (recommended) Build the dependencies statically in [build.sh]({{ site.baseurl }}/getting-started/new-project-guide/#buildsh) ([example](https://github.com/google/oss-fuzz/blob/64f8b6593da141b97c98c7bc6f07df92c42ee010/projects/ffmpeg/build.sh#L26)). Their source code should be inside the `$SRC` directory so that coverage can find it. - Or install the packages via Dockerfile ([example](https://github.com/google/oss-fuzz/blob/2d5e2ef84f281e6ab789055aa735606d3122fda9/projects/tor/Dockerfile#L19)) and then link statically against them ([example](https://github.com/google/oss-fuzz/blob/2d5e2ef84f281e6ab789055aa735606d3122fda9/projects/tor/build.sh#L40)). **Dependencies built in this way will not be instrumented** and may prevent the fuzzer from finding bugs if they are involved in the execution of a fuzz target. All build artifacts needed during fuzz target execution should be inside the `$OUT` directory. Only those artifacts are archived and used on the bots. Everything else is ignored (e.g. artifacts in `$WORK`, `$SRC`, etc) and hence is not available in the execution environment. We strongly recommend static linking because it just works. However dynamic linking can work if shared objects are included in the `$OUT` directory and are loaded relative to `'$ORIGIN'`, the path of the binary (see the discussion of `'$ORIGIN'` [here](http://man7.org/linux/man-pages/man8/ld.so.8.html)). A fuzzer can be instructed to load libraries relative to `'$ORIGIN'` during compilation (i.e. `-Wl,-rpath,'$ORIGIN/lib'` ) or afterwards using `chrpath -r '$ORIGIN/lib' $OUT/$fuzzerName` ([example](https://github.com/google/oss-fuzz/blob/09aa9ac556f97bd4e31928747eca0c8fed42509f/projects/php/build.sh#L40)). Note that `'$ORIGIN'` should be surrounded by single quotes because it is not an environment variable like `$OUT` that can be retrieved during execution of `build.sh`. Its value is retrieved during execution of the binary. You can verify that you did this correctly using `ldd ` and the `check_build` command in `infra/helper.py`. You should ensure that the fuzz target works correctly by using `run_fuzzer` command (see instructions [here]({{ site.baseurl }}/getting-started/new-project-guide/#testing-locally)). This command uses a clean base-runner docker container and not the base-builder docker container created during build-time. ## argv[0] You must not modify `argv[0]`. It is required for certain things to work correctly. ## Current working directory You should not make any assumptions about the current working directory of your fuzz target. If you need to load data files, please use `argv[0]` to get the directory where your fuzz target executable is located. ## File system Everything except `/tmp` is read-only, including the directory that your fuzz target executable lives in. `/dev` is also unavailable. ## Hardware Your project should not be compiled with `-march=native` or `-mtune=native` flags, as the build infrastructure and fuzzing machines may have different CPUs as well as other hardware differences. You may however use `-mtune=generic`. ================================================ FILE: docs/getting-started/accepting_new_projects.md ================================================ --- layout: default title: Accepting new projects parent: Getting started nav_order: 1 permalink: /getting-started/accepting-new-projects/ --- # Accepting New Projects To be accepted to OSS-Fuzz, an open-source project must have a significant user base and/or be critical to the global IT infrastructure. To submit a new project, do the following: 1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) with a new `projects//project.yaml` file ([example](https://github.com/google/oss-fuzz/tree/master/projects/libarchive/project.yaml)). **Note:** `project_name` can only contain alphanumeric characters, underscores(_) or dashes(-). 2. In the file, provide the following information: * Your project's homepage. ([`homepage`]({{ site.baseurl }}/getting-started/new-project-guide/#homepage)) * Your project's main repository URL. ([`main_repo`]({{ site.baseurl }}/getting-started/new-project-guide/#main_repo)) * Your project's primary language. ([`language`]({{ site.baseurl }}/getting-started/new-project-guide/#language)) * An email address for the engineering contact to be CCed on new issues ([`primary_contact`]({{ site.baseurl }}/getting-started/new-project-guide/#primary)), satisfying the following: * The address belongs to an established project committer (according to VCS logs). If the address isn't you, or if the address differs from VCS, we'll require an informal email verification. * The address is associated with a Google account ([why?]({{ site.baseurl }}/faq/#why-do-you-require-a-google-account-for-authentication)). If you use an alternate email address [linked to a Google Account](https://support.google.com/accounts/answer/176347?hl=en), you'll only get access to [filed bugs in the issue tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list), not to the [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) dashboard. This is due to appengine API limitations. 3. Once your project is accepted, configure it by following the [New Project Guide]({{ site.baseurl }}/getting-started/new-project-guide/). ================================================ FILE: docs/getting-started/bug_disclosure_guidelines.md ================================================ --- layout: default title: Bug disclosure guidelines parent: Getting started nav_order: 4 permalink: /getting-started/bug-disclosure-guidelines/ --- ## Bug Disclosure Guidelines Following [Google's standard disclosure policy](https://googleprojectzero.blogspot.com/2015/02/feedback-and-data-driven-updates-to.html), OSS-Fuzz will adhere to following disclosure principles: - **Deadline**. After notifying project authors, we will open reported issues to the public in 90 days, or after the fix is released (whichever comes earlier). - **Weekends and holidays**. If a deadline is due to expire on a weekend, the deadline will be moved to the next normal work day. - **Grace period**. We have a 14-day grace period. If a 90-day deadline expires but the upstream engineers let us know before the deadline that a patch is scheduled for release on a specific day within 14 days following the deadline, the public disclosure will be delayed until the availability of the patch. ================================================ FILE: docs/getting-started/continuous_integration.md ================================================ --- layout: default title: Continuous Integration parent: Getting started nav_order: 5 permalink: /getting-started/continuous-integration/ --- # Continuous Integration OSS-Fuzz offers **CIFuzz**, a GitHub action/CI job that runs your fuzz targets on pull requests. This works similarly to running unit tests in CI. CIFuzz helps you find and fix bugs before they make it into your codebase. Currently, CIFuzz primarily supports projects hosted on GitHub. Non-OSS-Fuzz users can use CIFuzz with additional features through [ClusterFuzzLite](https://google.github.io/clusterfuzzlite/). ## How it works CIFuzz builds your project's fuzzers from the source at a particular pull request or commit. Then CIFuzz runs the fuzzers for a short amount of time. If CIFuzz finds a crash, CIFuzz reports the stacktrace, makes the crashing input available for download and the CI test fails (red X). If CIFuzz doesn't find a crash during the allotted time, the CI test passes (green check). If CIFuzz finds a crash, it reports the crash only if both of following are true: * The crash is reproducible (on the PR/commit build). * The crash does not occur on older OSS-Fuzz builds. (If the crash does occur on older builds, then it was not introduced by the PR/commit being tested.) If your project supports [OSS-Fuzz's code coverage]({{ site.baseurl }}/advanced-topics/code-coverage), CIFuzz only runs the fuzzers affected by a pull request/commit. Otherwise it will divide up the allotted fuzzing time (10 minutes by default) among all fuzzers in the project. CIFuzz uses 30 day old/public regressions and corpora from OSS-Fuzz. This makes fuzzing more effective and gives you regression testing for free. ## Requirements 1. Your project must be integrated with OSS-Fuzz. 1. Your project is hosted on GitHub. 1. Your repository needs to be cloned with `git` in oss-fuzz Dockerfile (do not use `go get` or other methods) ## Integrating into your repository You can integrate CIFuzz into your project using the following steps: 1. Create a `.github` directory in the root of your project. 1. Create a `workflows` directory inside of your `.github` directory. 1. Copy the example [`cifuzz.yml`](https://github.com/google/oss-fuzz/blob/master/infra/cifuzz/example_cifuzz.yml) file over from the OSS-Fuzz repository to the `workflows` directory. 1. Change the `oss-fuzz-project-name` value in `cifuzz.yml` from `example` to the name of your OSS-Fuzz project. It is **very important** that you use your OSS-Fuzz project name which is case sensitive. This name is the name of your project's subdirectory in the [`projects`](https://github.com/google/oss-fuzz/tree/master/projects) directory of OSS-Fuzz. 1. Set the value of `fuzz-seconds`. The longest time that the project maintainers are acceptable with should be used. This value should be at minimum 600 seconds and scale with project size. Your directory structure should look like the following: ``` project |___ .github | |____ workflows | |____ cifuzz.yml |___ other-files ``` cifuzz.yml for an example project: ```yaml name: CIFuzz on: [pull_request] permissions: {} jobs: Fuzzing: runs-on: ubuntu-latest permissions: security-events: write steps: - name: Build Fuzzers id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ fuzz-seconds: 600 output-sarif: true - name: Upload Crash uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts path: ./out/artifacts - name: Upload Sarif if: always() && steps.build.outcome == 'success' uses: github/codeql-action/upload-sarif@v2 with: # Path to SARIF file relative to the root of the repository sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif ``` ### Optional configuration #### Configurable Variables `language`: (optional) The language your target program is written in. Defaults to `c++`. This should be the same as the value you set in `project.yaml`. See [this explanation]({{ site.baseurl }}//getting-started/new-project-guide/#language) for more details. `fuzz-seconds`: Determines how long CIFuzz spends fuzzing your project in seconds. The default is 600 seconds. The GitHub Actions max run time is 21600 seconds (6 hours). This variable is only meaningful when supplied to the `run_fuzzers` action, not the `build_fuzzers` action. `dry-run`: Determines if CIFuzz surfaces errors. The default value is `false`. When set to `true`, CIFuzz will never report a failure even if it finds a crash in your project. This requires the user to manually check the logs for detected bugs. If dry run mode is desired, make sure to set the dry-run parameters in both the `Build Fuzzers` and `Run Fuzzers` action step. `allowed-broken-targets-percentage`: Can be set if you want to set a stricter limit for broken fuzz targets than OSS-Fuzz's check_build. Most users should not set this. This value is only meaningful when supplied to the `run_fuzzers` action, not the `build_fuzzers` action. `sanitizer`: Determines a sanitizer to build and run fuzz targets with. The choices are `'address'`, `'memory'` and `'undefined'`. The default is `'address'`. It is important to note that the `Build Fuzzers` and the `Run Fuzzers` sanitizer field needs to be the same. To specify a list of sanitizers a [matrix](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) can be used. To use a sanitizer add it to the list of sanitizers in the matrix field below: `report-timeouts`: Determines whether to report fails due to timeouts. `report-ooms`: Determines whether to report fails due to OOM. ```yaml {% raw %} name: CIFuzz on: [pull_request] permissions: {} jobs: Fuzzing: runs-on: ubuntu-latest permissions: security-events: write strategy: fail-fast: false matrix: sanitizer: [address, undefined, memory] steps: - name: Build Fuzzers (${{ matrix.sanitizer }}) id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ sanitizer: ${{ matrix.sanitizer }} - name: Run Fuzzers (${{ matrix.sanitizer }}) uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ fuzz-seconds: 600 sanitizer: ${{ matrix.sanitizer }} output-sarif: true - name: Upload Crash uses: actions/upload-artifact@v4 if: steps.build.outcome == 'success' with: name: ${{ matrix.sanitizer }}-artifacts path: ./out/artifacts - name: Upload Sarif if: always() && steps.build.outcome == 'success' uses: github/codeql-action/upload-sarif@v2 with: # Path to SARIF file relative to the root of the repository sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif {% endraw %} ``` #### Branches and paths You can make CIFuzz trigger only on certain branches or paths by following the instructions [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions). For example, the following code can used to trigger CIFuzz only on changes to C/C++ code residing on master and release branches: ```yaml name: CIFuzz on: pull_request: branches: - master - 'releases/**' paths: - '**.c' - '**.cc' - '**.cpp' - '**.cxx' - '**.h' permissions: {} jobs: Fuzzing: runs-on: ubuntu-latest steps: - name: Build Fuzzers id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'example' language: c++ fuzz-seconds: 600 - name: Upload Crash uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts path: ./out/artifacts ``` You can checkout CIFuzz configs for OSS-Fuzz projects. Example - [systemd](https://github.com/systemd/systemd/blob/main/.github/workflows/cifuzz.yml), [curl](https://github.com/curl/curl/blob/master/.github/workflows/fuzz.yml). ## Ubuntu 24.04 Support CIFuzz supports building and running fuzzers in an Ubuntu 24.04 environment. Existing projects will continue to use the legacy environment (Ubuntu 20.04) by default, preserving current behavior. To migrate your project to Ubuntu 24.04, add the following line to your `project.yaml`: ```yaml base_os_version: ubuntu-24-04 ``` For OSS-Fuzz projects, this file is located at `projects//project.yaml`. For external projects (ClusterFuzzLite), this file is typically located at `.clusterfuzzlite/project.yaml`. ## Understanding results The results of CIFuzz can be found in two different places. * Run fuzzers log: 1. This log can be accessed in the `actions` tab of a CIFuzz integrated repo. 1. Click on the `CIFuzz` button in the workflow selector on the left hand side. 1. Click on the event triggered by your desired pull request. 1. Click the `Fuzzing` workflow. 1. Select the `Run Fuzzer` drop down. It should show the timestamps and results from each of the fuzz targets. ![Finding fuzzer output](../images/run_fuzzers.png) * Artifacts: When the fuzzer crashes the input file that causes the crash is uploaded as an artifact. To download the artifact, do the following steps: 1. Click on the summary from the run, as illustrated in the screenshot below: ![github-actions-summary] 2. Click on the artifact you wish to download from the summary page, as illustrated in the screenshot below: ![github-actions-download-crash] [github-actions-summary]: (https://raw.githubusercontent.com/google/clusterfuzzlite/refs/heads/bucket/images/github-actions-summary.png) [github-actions-download-crash]: (https://raw.githubusercontent.com/google/clusterfuzzlite/refs/heads/bucket/images/github-actions-download-crash.png) ## Feedback/Questions/Issues Create an issue in [OSS-Fuzz](https://github.com/google/oss-fuzz/issues/new) if you have questions or any other feedback on CIFuzz. ================================================ FILE: docs/getting-started/getting_started.md ================================================ --- layout: default title: Getting started has_children: true nav_order: 2 permalink: /getting-started/ --- # Getting started These pages walk you through the process of integrating your open source project with OSS-Fuzz. ================================================ FILE: docs/getting-started/integration_rewards.md ================================================ --- layout: default title: Integration rewards parent: Getting started nav_order: 3 permalink: /getting-started/integration-rewards/ --- # Integration rewards We encourage you to apply for integration rewards (up to **$30,000**) once your project is successfully integrated with OSS-Fuzz. Please see the full details [here](https://bughunters.google.com/about/rules/5097259337383936/oss-fuzz-reward-program-rules). To submit your application for a reward, please fill out [this form](https://goo.gle/oss-fuzz-submission). ================================================ FILE: docs/getting-started/new-project-guide/bazel.md ================================================ --- layout: default title: Integrating a Bazel project parent: Setting up a new project grand_parent: Getting started nav_order: 5 permalink: /getting-started/new-project-guide/bazel/ --- # Integrating a Bazel project {: .no_toc} - TOC {:toc} --- ## Bazel projects The process of integrating a project using the [Bazel](https://bazel.build/) build system with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Bazel project are outlined below. ## Fuzzing support in Bazel For Bazel-based projects, we recommend using the [`rules_fuzzing`](https://github.com/bazelbuild/rules_fuzzing) extension library for defining fuzz tests. `rules_fuzzing` provides support for building and running fuzz tests under [multiple sanitizer and fuzzing engine configurations][rules-fuzzing-usage]. It also supports specifying corpora and dictionaries as part of the fuzz test definition. The fuzzing rules provide out-of-the-box support for building and packaging fuzz test artifacts in the OSS-Fuzz format. Each `//path/to:fuzz_test` fuzz test target automatically has a `//path/to:fuzz_test_oss_fuzz` packaging target that (a) builds the fuzz test using the instrumentation and engine library specified in the OSS-Fuzz environment variables, and (b) generates an archive containing the binary and its associated artifacts (corpus, dictionary, etc.). Moreover, OSS-Fuzz provides a standard tool to automatically process these targets, substantially simplifying the `build.sh` script (see below). [rules-fuzzing-usage]: https://github.com/bazelbuild/rules_fuzzing#using-the-rules-in-your-project ## Project files This section explains how to integrate the fuzz tests written using the `rules_fuzzing` library with OSS-Fuzz. You can also see a complete example in the [`bazel-rules-fuzzing-test`](https://github.com/google/oss-fuzz/tree/master/projects/bazel-rules-fuzzing-test) project. The structure of the project directory in the OSS-Fuzz repository does not differ for Bazel-based projects. The project files have the following specific aspects. ### project.yaml Only C++ projects are currently supported. Since the OSS-Fuzz target builds the fuzz test using the instrumentation and engine specified in the OSS-Fuzz environment variables, all the engine and sanitizer configurations supported in the `project.yaml` file are automatically supported by the fuzzing rules. ### Dockerfile There is no need to install Bazel in your Docker image. The OSS-Fuzz builder image provides the `bazel` executable through the [Bazelisk](https://github.com/bazelbuild/bazelisk) launcher, which will fetch and use the latest Bazel release. If your project requires a particular Bazel version, create a [`.bazelversion`](https://docs.bazel.build/versions/master/updating-bazel.html) file in your repository root with the desired version string. ### build.sh Your `build.sh` script essentially needs to perform three steps: (1) selecting which fuzz tests to build, (2) building their OSS-Fuzz package targets in the right configuration, and (3) copying the build artifacts to the `${OUT}/` destination. OSS-Fuzz provides a [`bazel_build_fuzz_tests`](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/bazel_build_fuzz_tests) tool that implements these steps in a standard way, so in most cases your build script only needs to invoke this command with no arguments. If necessary, the behavior of the tool can be customized through a set of environment variables. The most common are: * `BAZEL_EXTRA_BUILD_FLAGS` are extra build flags passed on the Bazel command line. * `BAZEL_FUZZ_TEST_TAG` and `BAZEL_FUZZ_TEST_EXCLUDE_TAG` can be overridden to specify which target tags to use when determining what fuzz tests to include. By default, the tool selects all the fuzz tests except for those tagged as `"no-oss-fuzz"`. * `BAZEL_FUZZ_TEST_QUERY` overrides the Bazel query the tool uses to identify the fuzz tests to build, if the tag-based approach is not sufficient. ================================================ FILE: docs/getting-started/new-project-guide/go_lang.md ================================================ --- layout: default title: Integrating a Go project parent: Setting up a new project grand_parent: Getting started nav_order: 1 permalink: /getting-started/new-project-guide/go-lang/ --- # Integrating a Go project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Go with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Go project are outlined below. ## Go-fuzz support OSS-Fuzz supports **go-fuzz** in the [libFuzzer compatible mode](https://github.com/mdempsky/go114-fuzz-build) only. In that mode, fuzz targets for Go use the libFuzzer engine with native Go coverage instrumentation. Binaries compiled in this mode provide the same libFuzzer command line interface as non-Go fuzz targets. ## Native Go Fuzzing support OSS-fuzz supports [fuzzers written for the native Go 1.18 engine](https://go.dev/doc/fuzz/). These fuzzers are built as libFuzzer binaries in a similar fashion as fuzzers written for the go-fuzz engine. Because of that, dictionaries and seed corpora should be handled in accordance with [the OSS-fuzz documentation](https://google.github.io/oss-fuzz/getting-started/new-project-guide/#seed-corpus). Unlike libFuzzer/go-fuzz targets which must accept one data buffer, fuzz targets written for the Native Go engine can accept any number of arguments of any type. Here is an example of a valid fuzzer with multiple arguments: ```go package demofuzzing import ( "fmt" "testing" ) func FuzzDemo(f *testing.F) { f.Fuzz(func(t *testing.T, data1 string, data2 uint32, data3 float64) { fmt.Println(data1) fmt.Println(data2) fmt.Println(data3) }) } ``` Some requirements for native Go 1.18 fuzzers are: * The only `testing.F` method supported is currently `F.Fuzz()`. * `F.Add()` will not add seeds when fuzzing. To provide OSS-fuzz with a seed corpus, follow the documentation [here](https://google.github.io/oss-fuzz/getting-started/new-project-guide/#seed-corpus). ## Project files First, you need to write a Go fuzz target. This fuzz target should reside in your project repository ([example](https://github.com/golang/go/blob/4ad13555184eb0697c2e92c64c1b0bdb287ccc10/src/html/fuzz.go#L13)). The structure of the project directory in OSS-Fuzz repository doesn't differ for projects written in Go. The project files have the following Go specific aspects. ### project.yaml The `language` attribute must be specified. ```yaml language: go ``` The only supported fuzzing engine and sanitizer are `libfuzzer` and `address`, respectively. [Example](https://github.com/google/oss-fuzz/blob/356f2b947670b7eb33a1f535c71bc5c87a60b0d1/projects/syzkaller/project.yaml#L7): ```yaml fuzzing_engines: - libfuzzer sanitizers: - address ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-go` The OSS-Fuzz builder image has the latest stable release of Golang installed. In order to install dependencies of your project, add `RUN git clone ...` command to your Dockerfile. [Example](https://github.com/google/oss-fuzz/blob/356f2b947670b7eb33a1f535c71bc5c87a60b0d1/projects/syzkaller/Dockerfile#L23): ```dockerfile # Dependency for one of the fuzz targets. RUN git clone --depth 1 https://github.com/ianlancetaylor/demangle ``` go-fuzz will then automatically download the dependencies based on the go.mod file ### build.sh In order to build a Go fuzz target, you need to call `go-fuzz` command first, and then link the resulting `.a` file against `$LIB_FUZZING_ENGINE` using the `$CXX $CXXFLAGS ...` command. For go-fuzz fuzzers, the best way to do this is by using the [`compile_go_fuzzer` script](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_go_fuzzer), and for native Go 1.18 fuzzers it is recommended to use the [`compile_native_go_fuzzer` script](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_native_go_fuzzer). Both of these also support coverage builds. `compile_native_go_fuzzer` requires two dependencies which can be installed with: ```bash go install github.com/AdamKorcz/go-118-fuzz-build@latest go get github.com/AdamKorcz/go-118-fuzz-build/testing ``` A usage example from go-dns project is ```sh compile_go_fuzzer github.com/miekg/dns FuzzNewRR fuzz_newrr fuzz ``` Arguments are : * path of the package with the fuzz target * name of the fuzz function * name of the fuzzer to be built * optional tag to be used by `go build` and such ================================================ FILE: docs/getting-started/new-project-guide/javascript_lang.md ================================================ --- layout: default title: Integrating a JavaScript project parent: Setting up a new project grand_parent: Getting started nav_order: 4 permalink: /getting-started/new-project-guide/javascript-lang/ --- # Integrating a JavaScript project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in JavaScript for Node.js with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a JavaScript project are outlined below. ## Jazzer.js JavaScript fuzzing in OSS-Fuzz is powered by [Jazzer.js](https://github.com/CodeIntelligenceTesting/jazzer.js), which is installed during the build step. As Jazzer.js operates directly on the JavaScript source code level, it can be applied to any project written in a language that can be transpiled into JavaScript such as TypeScript. More information on how Jazzer.js fuzz targets look like can be found in its [README's Usage section](https://github.com/CodeIntelligenceTesting/jazzer.js#usage). ## Project files ### Example project We recommend viewing [javascript-example](https://github.com/google/oss-fuzz/tree/master/projects/javascript-example) as an example of a simple JavaScript fuzzing project. We also recommend having a look at [typescript-example](https://github.com/google/oss-fuzz/tree/master/projects/typescript-example) as an example of how to fuzz TypeScript projects. This example also demonstrates how to use Jazzer.js fuzzed data provider. ### project.yaml The `language` attribute must be specified as follows: ```yaml language: javascript ``` The only supported fuzzing engine is libFuzzer (`libfuzzer`). So far, native sanitizers such as AddressSanitizer (`address`) and UndefinedBehaviorSanitizer (`undefined`) are not supported. They would only be needed for projects that have native addons, which is a rather infrequent use case for JavaScript projects. If you have a project where you need ASan or UBSan, please create open an issue on [Jazzer.js GitHub repo](https://github.com/CodeIntelligenceTesting/jazzer.js). None (`none`) is the default sanitizer for JavaScript projects, so setting it up in `project.yaml` is optional. ```yaml fuzzing_engines: - libfuzzer sanitizers: - none ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-javascript` The OSS-Fuzz base Docker images already come with Node.js 19 and `npm` pre-installed. Apart from that, you should usually not need to do more than to clone the project, set a `WORKDIR`, and copy any necessary files, or install any project-specific dependencies here as you normally would. ### Fuzzers In the simplest case, every fuzzer consists of a single JavaScript file that exports a function named `fuzz` taking a single argument of type [Buffer](https://nodejs.org/api/buffer.html). An example fuzz target could thus be a file `fuzz_string_compare.js` with contents: ```javascript /** * @param { Buffer } data */ module.exports.fuzz = function (data) { const s = data.toString(); if (s.length !== 16) { return; } if ( s.slice(0, 8) === "Awesome " && s.slice(8, 15) === "Fuzzing" && s[15] === "!" ) { throw Error("Welcome to Awesome Fuzzing!"); } }; ``` ### build.sh The OSS-Fuzz base docker image for JavaScript comes with the [`compile_javascript_fuzzer` script](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_javascript_fuzzer) preinstalled. In `build.sh`, you should install dependencies for your project, and if necessary compile the code into JavaScript. Then, you can use the script to build the fuzzers. The script ensures that [@Jazzer.js/core](https://www.npmjs.com/package/@jazzer.js/core) is installed so that its CLI can be used to execute your fuzz tests. It also generates a wrapper script that can be used as a drop-in replacement for libFuzzer. This means that the generated script accepts the same command line flags for libFuzzer. Under the hood these flags are simply forwarded to the libFuzzer native addon used by Jazzer.js. A usage example from the javascript-example project is ```shell compile_javascript_fuzzer example fuzz_string_compare.js --sync ``` Arguments are: * relative path of the project in the $SRC directory * relative path to the fuzz test inside the project * remaining arguments are forwarded to the [Jazzer.js CLI](https://github.com/CodeIntelligenceTesting/jazzer.js/blob/main/docs/fuzz-targets.md#running-the-fuzz-target) The [javascript-example](https://github.com/google/oss-fuzz/blob/master/projects/javascript-example/build.sh) project contains an example of a `build.sh` for JavaScript projects. ## FuzzedDataProvider Jazzer.js provides a `FuzzedDataProvider` that can simplify the task of creating a fuzz target by translating the raw input bytes received from the fuzzer into useful primitive JavaScript types. Its functionality is similar to `FuzzedDataProviders` available in other languages, such as [Java](https://codeintelligencetesting.github.io/jazzer-docs/jazzer-api/com/code_intelligence/jazzer/api/FuzzedDataProvider.html) and [C++](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md). A fuzz target using the `FuzzedDataProvider` would look as follows: ```javascript const { FuzzedDataProvider } = require("@jazzer.js/core"); /** * @param { Buffer } fuzzerInputData */ module.exports.fuzz = function (fuzzerInputData) { const data = new FuzzedDataProvider(fuzzerInputData); const i = data.consumeIntegral(4); const s = data.consumeRemainingAsString(); exploreMe(i, s); }; ``` ================================================ FILE: docs/getting-started/new-project-guide/jvm_lang.md ================================================ --- layout: default title: Integrating a Java/JVM project parent: Setting up a new project grand_parent: Getting started nav_order: 4 permalink: /getting-started/new-project-guide/jvm-lang/ --- # Integrating a Java/JVM project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Java or any other language running on the Java Virtual Machine (JVM) with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a JVM project are outlined below. ## Jazzer Java fuzzing in OSS-Fuzz depends on [Jazzer](https://github.com/CodeIntelligenceTesting/jazzer), which is pre-installed on the OSS-Fuzz base docker images. As Jazzer operates directly on the bytecode level, it can be applied to any project written in a JVM-based language. More information on how Jazzer fuzz targets look like can be found in its [README's Usage section](https://github.com/CodeIntelligenceTesting/jazzer#usage). ## Project files ### Example project We recommend viewing [json-sanitizer](https://github.com/google/oss-fuzz/tree/master/projects/json-sanitizer) as an example of a simple Java-only fuzzing project. Additional examples, including one for a Java project with native dependencies, are part of the [java-example](https://github.com/google/oss-fuzz/tree/master/projects/java-example) project. ### project.yaml The `language` attribute must be specified as follows: ```yaml language: jvm ``` The only supported fuzzing engine is libFuzzer (`libfuzzer`). So far the only supported sanitizers are AddressSanitizer (`address`) and UndefinedBehaviorSanitizer (`undefined`). For pure Java projects, specify just `address`: ```yaml fuzzing_engines: - libfuzzer sanitizers: - address ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-jvm` The OSS-Fuzz base Docker images already come with OpenJDK 15 pre-installed. If you need Maven to build your project, you can install it by adding the following line to your Dockerfile: ```docker RUN apt-get update && apt-get install -y maven ``` Apart from this, you should usually not need to do more than to clone the project, set a `WORKDIR`, and copy any necessary files, or install any project-specific dependencies here as you normally would. ### Fuzzers In the simplest case, every fuzzer consists of a single Java file with a filename matching `*Fuzzer.java` and no `package` directive. An example fuzz target could thus be a file `ExampleFuzzer.java` with contents: ```java public class ExampleFuzzer { public static void fuzzerTestOneInput(byte[] input) { ... // Call a function of the project under test with arguments derived from // input and throw an exception if something unwanted happens. ... } } ``` ### build.sh For JVM projects, `build.sh` does need some more significant modifications over C/C++ projects. Below is an annotated example build script for a Java-only project with single-file fuzz targets as described above: ```sh # Step 1: Build the project # Build the project .jar as usual, e.g. using Maven. mvn package # In this example, the project is built with Maven, which typically includes the # project version into the name of the packaged .jar file. The version can be # obtained as follows: CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) # Copy the project .jar into $OUT under a fixed name. cp "target/sample-project-$CURRENT_VERSION.jar" $OUT/sample-project.jar # Specify the projects .jar file(s), separated by spaces if there are multiple. PROJECT_JARS="sample-project.jar" # Step 2: Build the fuzzers (should not require any changes) # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings:-Djava.awt.headless=true\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ``` The [java-example](https://github.com/google/oss-fuzz/blob/master/projects/java-example/build.sh) project contains an example of a `build.sh` for Java projects with native libraries. ## FuzzedDataProvider Jazzer provides a `FuzzedDataProvider` that can simplify the task of creating a fuzz target by translating the raw input bytes received from the fuzzer into useful primitive Java types. Its functionality is similar to `FuzzedDataProviders` available in other languages, such as [Python](https://github.com/google/atheris#fuzzeddataprovider) and [C++](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md). On OSS-Fuzz, the required library is available in the base docker images under the path `$JAZZER_API_PATH`, which is added to the classpath by the example build script shown above. Locally, the library can be obtained from [Maven Central](https://search.maven.org/search?q=g:com.code-intelligence%20a:jazzer-api). A fuzz target using the `FuzzedDataProvider` would look as follows: ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ExampleFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { int number = data.consumeInt(); String string = data.consumeRemainingAsString(); // ... } } ``` For a list of convenience methods offered by `FuzzedDataProvider`, consult its [javadocs](https://codeintelligencetesting.github.io/jazzer-docs/jazzer-api/com/code_intelligence/jazzer/api/FuzzedDataProvider.html). ================================================ FILE: docs/getting-started/new-project-guide/lua_lang.md ================================================ --- layout: default title: Integrating a Lua project parent: Setting up a new project grand_parent: Getting started nav_order: 4 permalink: /getting-started/new-project-guide/lua-lang/ --- # Integrating a Lua project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Lua with OSS-Fuzz is similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Lua project are outlined below. ## luzer Lua fuzzing in OSS-Fuzz is powered by [luzer](https://github.com/ligurio/luzer). As luzer operates directly on the Lua source code level, it can be applied to any project written in a language that can be transpiled into Lua, such as [MoonScript](https://moonscript.org/), [TypeScriptToLua](https://typescripttolua.github.io/), [Fennel](https://fennel-lang.org/), and [Urn](https://urn-lang.com/). Also, it supports fuzzing C/C++ extensions written for Lua. When fuzzing native code, luzer can be used in combination with Address Sanitizer or Undefined Behavior Sanitizer to catch extra bugs. ## Project files ### Example project We recommend viewing [lua-example](https://github.com/google/oss-fuzz/tree/master/projects/lua-example) as an example of a simple Lua fuzzing project. This example also demonstrates how to use luzer's Fuzzed Data Provider. ### project.yaml The `language` attribute must be specified as follows: ```yaml language: c ``` The only supported fuzzing engine is libFuzzer (`libfuzzer`). ```yaml fuzzing_engines: - libfuzzer sanitizers: - none ``` There is nothing special for sanitizer support in OSS-Fuzz infrastructure. luzer builds its own DSO with libFuzzer and sanitizer and `compile_lua_fuzzer` (also managed by project) sets it to `LD_PRELOAD` if required. ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder`. The OSS-Fuzz base Docker images come without any pre-installed components required for Lua fuzzing. Apart from that, you should usually need to build or install a Lua runtime, luzer module, clone the project, set a `WORKDIR`, and copy any necessary files, or install any project-specific dependencies here as you normally would. ### Fuzzers In the simplest case, every fuzzer consists of a single Lua file that defines a function `TestOneInput` and executes a function named `luzer.Fuzz()`. An example fuzz target could thus be a file `fuzz_basic.lua` with contents: ```lua local parser = require("src.luacheck.parser") local decoder = require("luacheck.decoder") local luzer = require("luzer") local function TestOneInput(buf) parser.parse(decoder.decode(buf)) end local args = { print_final_stats = 1, } luzer.Fuzz(TestOneInput, nil, args) ``` ### compile_lua_fuzzer Unlike projects for other languages, the base image does not include a script that generates a wrapper script that can be used as a drop-in replacement for libFuzzer. Therefore, you need to add such a script yourself. This script sets a relative path to Lua runtime that will be used for running tests and the necessary environment variables (for example, `LUA_PATH`, `LUA_CPATH` and `LD_PRELOAD`) and specifies the path directly to the `.lua` file containing the test implementation. The script `compile_lua_fuzzer` must accept the same command line flags as libFuzzer-based tests. Note, the resulting wrapper scripts must contain the word "luarocks" to pass checks by `bad_build_check` in continuous integration. Then, you can use the script `compile_lua_fuzzer` to build the fuzzers. A usage example from the `lua-example` project is ```shell compile_lua_fuzzer lua fuzz_basic.lua ``` Arguments are: * a relative path to a Lua runtime name * a relative path to the fuzzing test inside the OSS Fuzz project directory The `lua-example` projects includes an [example](https://github.com/google/oss-fuzz/blob/master/projects/lua-example/compile_lua_fuzzer) of such script. ### build.sh The script is executed within the image built from your [Dockerfile](#Dockerfile). In general, this script should do the following: - Set up or build a Lua runtime. - Set up or build required dependencies for your tests. - Generate wrapper scripts for your tests using [compile_lua_fuzzer](#compile_lua_fuzzer). Resulting binaries, tests and their wrapper scripts, and a directory with Luarocks dependencies should be placed in `$OUT`. Beware, when installing the luzer module, you need to set the environment variable `OSS_FUZZ` to non-empty value, otherwise the build may fail. The [lua-example](https://github.com/google/oss-fuzz/blob/master/projects/lua-example/build.sh) project contains an example of a `build.sh` for a Lua projects. ## FuzzedDataProvider luzer provides a Fuzzed Data Provider that is helpful for splitting a fuzz input into multiple parts of various Lua types. Its functionality is similar to [Fuzzed Data Provider](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider) available in LLVM. Learn about methods, provided by FDP in luzer, in [documentation](https://github.com/ligurio/luzer/blob/master/docs/api.md#structure-aware-fuzzing). A fuzz target using the `FuzzedDataProvider` would look as follows: ```lua local luzer = require("luzer") local function TestOneInput(buf) local fdp = luzer.FuzzedDataProvider(buf) local str = fdp:consume_string(4) local b = {} str:gsub(".", function(c) table.insert(b, c) end) local count = 0 if b[1] == "o" then count = count + 1 end if b[2] == "o" then count = count + 1 end if b[3] == "p" then count = count + 1 end if b[4] == "s" then count = count + 1 end if count == 4 then assert(nil) end end local args = { only_ascii = 1, print_pcs = 1, } luzer.Fuzz(TestOneInput, nil, args) ``` ================================================ FILE: docs/getting-started/new-project-guide/python_lang.md ================================================ --- layout: default title: Integrating a Python project parent: Setting up a new project grand_parent: Getting started nav_order: 3 permalink: /getting-started/new-project-guide/python-lang/ --- # Integrating a Python project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Python with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Python project are outlined below. ## Atheris Python fuzzing in OSS-Fuzz depends on [Atheris](https://github.com/google/atheris). Fuzzers will depend on the `atheris` package, and dependencies are pre-installed on the OSS-Fuzz base docker images. ## Project files ### Example project We recommend viewing [ujson](https://github.com/google/oss-fuzz/tree/master/projects/ujson) as an example of a simple Python fuzzing project, with both plain-Atheris and Atheris + Hypothesis harnesses. ### project.yaml The `language` attribute must be specified. ```yaml language: python3 ``` The only supported fuzzing engine is libFuzzer (`libfuzzer`). The supported sanitizers are AddressSanitizer (`address`) and UndefinedBehaviorSanitizer (`undefined`). These must be explicitly specified. ```yaml fuzzing_engines: - libfuzzer sanitizers: - address - undefined ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-python` Because most dependencies are already pre-installed on the images, no significant changes are needed in the Dockerfile for Python fuzzing projects. You should simply clone the project, set a `WORKDIR`, and copy any necessary files, or install any project-specific dependencies here as you normally would. ### build.sh For Python projects, `build.sh` does need some more significant modifications over normal projects. The following is an annotated example build script, explaining why each step is necessary and when they can be omitted. ```sh # Build and install project (using current CFLAGS, CXXFLAGS). This is required # for projects with C extensions so that they're built with the proper flags. pip3 install . # Build fuzzers into $OUT. These could be detected in other ways. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do fuzzer_basename=$(basename -s .py $fuzzer) fuzzer_package=${fuzzer_basename}.pkg # To avoid issues with Python version conflicts, or changes in environment # over time on the OSS-Fuzz bots, we use pyinstaller to create a standalone # package. Though not necessarily required for reproducing issues, this is # required to keep fuzzers working properly in OSS-Fuzz. pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer # Create execution wrapper. Atheris requires that certain libraries are # preloaded, so this is also done here to ensure compatibility and simplify # test case reproduction. Since this helper script is what OSS-Fuzz will # actually execute, it is also always required. # NOTE: If you are fuzzing python-only code and do not have native C/C++ # extensions, then remove the LD_PRELOAD line below as preloading sanitizer # library is not required and can lead to unexpected startup crashes. echo "#!/bin/sh # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \ ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \ \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ``` ## Hypothesis Using [Hypothesis](https://hypothesis.readthedocs.io/), the Python library for [property-based testing](https://hypothesis.works/articles/what-is-property-based-testing/), makes it really easy to generate complex inputs - whether in traditional test suites or [by using test functions as fuzz harnesses](https://hypothesis.readthedocs.io/en/latest/details.html#use-with-external-fuzzers). > Property based testing is the construction of tests such that, when these tests are fuzzed, failures in the test reveal problems with the system under test that could not have been revealed by direct fuzzing of that system. We recommend using the [`hypothesis write`](https://hypothesis.readthedocs.io/en/latest/ghostwriter.html) command to generate a starter fuzz harness. This "ghostwritten" code may be usable as-is, or provide a useful template for writing more specific tests. See [here for the core "strategies"](https://hypothesis.readthedocs.io/en/latest/data.html), for arbitrary data, [here for Numpy + Pandas support](https://hypothesis.readthedocs.io/en/latest/numpy.html), or [here for a variety of third-party extensions](https://hypothesis.readthedocs.io/en/latest/strategies.html) supporting everything from protobufs, to jsonschemas, to networkx graphs or geojson or valid Python source code. Hypothesis' integrated test-case reduction also makes it trivial to report a canonical minimal example for each distinct failure discovered while fuzzing - just run the test function! To use Hypothesis in OSS-Fuzz, install it in your Dockerfile with ```shell RUN pip3 install hypothesis ``` See [the `ujson` structured fuzzer](https://github.com/google/oss-fuzz/blob/master/projects/ujson/hypothesis_structured_fuzzer.py) for an example "polyglot" which can either be run with `pytest` as a standard test function, or run with OSS-Fuzz as a fuzz harness. ================================================ FILE: docs/getting-started/new-project-guide/rust_lang.md ================================================ --- layout: default title: Integrating a Rust project parent: Setting up a new project grand_parent: Getting started nav_order: 2 permalink: /getting-started/new-project-guide/rust-lang/ --- # Integrating a Rust project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Rust with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Rust project are outlined below. ## cargo-fuzz support Rust integration with OSS-Fuzz is expected to use [`cargo fuzz`](https://github.com/rust-fuzz/cargo-fuzz) to build fuzzers. The `cargo fuzz` tool will build code with required compiler flags as well as link to the correct libFuzzer on OSS-Fuzz itself. Note that using `cargo fuzz` also makes it quite easy to run the fuzzers locally yourself if you get a failing test case! ## Project files First you'll want to follow the [setup instructions for `cargo fuzz` itself](https://rust-fuzz.github.io/book/). Afterwards your project should have: * A top-level `fuzz` directory. * A `fuzz/Cargo.toml` manifest which pulls in necessary dependencies to fuzz. * Some `fuzz/fuzz_targets/*.rs` files which are the fuzz targets that will be compiled and run on OSS-Fuzz. Note that you can customize this layout as well, but you'll need to edit some the scripts below to integrate into OSS-Fuzz. ### project.yaml The `language` attribute must be specified. ```yaml language: rust ``` The only supported fuzzing engine and sanitizer are `libfuzzer` and `address`, respectively. [Example](https://github.com/google/oss-fuzz/blob/12ef3654b3e9adfd20b5a6afdde54819ba71493d/projects/serde_json/project.yaml#L3-L6) ```yaml sanitizers: - address fuzzing_engines: - libfuzzer ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-rust` The OSS-Fuzz builder image has the latest nightly release of Rust as well as `cargo fuzz` pre-installed and in `PATH`. In the `Dockerfile` for your project all you'll need to do is fetch the latest copy of your code and install any system dependencies necessary to build your project. [Example](https://github.com/google/oss-fuzz/blob/12ef3654b3e9adfd20b5a6afdde54819ba71493d/projects/serde_json/Dockerfile#L18-L20) ```dockerfile RUN git clone --depth 1 https://github.com/serde-rs/json json ``` ### build.sh Here it's expected that you'll build the fuzz targets for your project and then copy the final binaries into the output directory. [Example](https://github.com/google/oss-fuzz/blob/12ef3654b3e9adfd20b5a6afdde54819ba71493d/projects/serde_json/build.sh#L20): ```sh cd $SRC/json cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/from_slice $OUT/ ``` Note that you likely want to pass the `-O` flag to `cargo fuzz build` which builds fuzzers in release mode. You may also want to pass the `--debug-assertions` flag to enable more checks while fuzzing. In this example the `from_slice` binary is the fuzz target. With some bash-fu you can also automatically copy over all fuzz targets into the output directory so when you add a fuzz target to your project it's automatically integrated into OSS-Fuzz: ```sh FUZZ_TARGET_OUTPUT_DIR=target/x86_64-unknown-linux-gnu/release for f in fuzz/fuzz_targets/*.rs do FUZZ_TARGET_NAME=$(basename ${f%.*}) cp $FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT/ done ``` ## Writing fuzzers using a test-style strategy In Rust you will often have tests written in a way so they are only compiled into the final binary when build in test-mode. This is, achieved by wrapping your test code in `cfg(test)`, e.g. ```rust #[cfg(test)] mod tests { use super::*; ... ``` Cargo-fuzz automatically enables the `fuzzing` feature, which means you can follow a similar strategy to writing fuzzers as you do when writing tests. Specifically, you can create modules wrapped in the `fuzzing` feature: ```rust #[cfg(fuzzing)] pub mod fuzz_logic { use super::*; ... ``` and then call the logic within `fuzz_logic` from your fuzzer. Furthermore, within your `.toml` files, you can then specify fuzzing-specific dependencies by wrapping them as follows: ``` [target.'cfg(fuzzing)'.dependencies] ``` similar to how you wrap test-dependencies as follows: ``` [dev-dependencies] ``` Finally, you can also combine the testing logic you have and the fuzz logic. This can be achieved simply by using ```rust #[cfg(any(test, fuzzing))] ``` A project that follows this structure is Linkerd2-proxy and the project files can be seen [here](https://github.com/google/oss-fuzz/tree/master/projects/linkerd2-proxy). ================================================ FILE: docs/getting-started/new-project-guide/swift_lang.md ================================================ --- layout: default title: Integrating a Swift project parent: Setting up a new project grand_parent: Getting started nav_order: 1 permalink: /getting-started/new-project-guide/swift-lang/ --- # Integrating a Swift project {: .no_toc} - TOC {:toc} --- The process of integrating a project written in Swift with OSS-Fuzz is very similar to the general [Setting up a new project]({{ site.baseurl }}/getting-started/new-project-guide/) process. The key specifics of integrating a Swift project are outlined below. ## Project files First, you need to write a Swift fuzz target that accepts a stream of bytes and calls the program API with that. This fuzz target should reside in your project repository. The structure of the project directory in OSS-Fuzz repository doesn't differ for projects written in Swift. The project files have the following Swift specific aspects. ### project.yaml The `language` attribute must be specified. ```yaml language: swift ``` The only supported fuzzing engine is `libfuzzer` The supported sanitizers are and `address`, `thread` [Example](https://github.com/google/oss-fuzz/blob/2a15c3c88b21f4f1be2a7ff115f72bd7a08e34ac/projects/swift-nio/project.yaml#L9): ```yaml fuzzing_engines: - libfuzzer sanitizers: - address - thread ``` ### Dockerfile The Dockerfile should start by `FROM gcr.io/oss-fuzz-base/base-builder-swift` instead of using the simple base-builder ### build.sh A `precompile_swift` generates an environment variable `SWIFTFLAGS` This can then be used in the building command such as `swift build -c release $SWIFTFLAGS` A usage example from swift-protobuf project is ```sh . precompile_swift # build project cd FuzzTesting swift build -c debug $SWIFTFLAGS ( cd .build/debug/ find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-debug; done ) ``` ================================================ FILE: docs/getting-started/new_project_guide.md ================================================ --- layout: default title: Setting up a new project parent: Getting started has_children: true nav_order: 2 permalink: /getting-started/new-project-guide/ --- # Setting up a new project {: .no_toc} - TOC {:toc} --- ## Prerequisites Before you can start setting up your new project for fuzzing, you must do the following: - [Integrate]({{ site.baseurl }}/advanced-topics/ideal-integration/) one or more [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) with the project you want to fuzz. For examples, see [boringssl](https://github.com/google/boringssl/tree/master/fuzz) or [SQLite](https://www.sqlite.org/src/artifact/ad79e867fb504338) (C/C++), [go-fuzz](https://github.com/dvyukov/go-fuzz-corpus/tree/86a5af9d6842f80b205a082538ea28f61bbb8ccb) or [syzkaller](https://github.com/google/syzkaller/tree/7c7ded697e6322b0975f061b7e268fe44f585dab/prog/test) (Go). - [Install Docker](https://docs.docker.com/engine/installation) (Googlers can visit [go/installdocker](https://goto.google.com/installdocker)). [Why Docker?]({{ site.baseurl }}/faq/#why-do-you-use-docker) If you want to run `docker` without `sudo`, you can [create a docker group](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/create-a-docker-group). **Note:** Docker images can consume significant disk space. Run [docker-cleanup](https://gist.github.com/mikea/d23a839cba68778d94e0302e8a2c200f) periodically to garbage-collect unused images. - (optional) [Install gsutil](https://cloud.google.com/storage/docs/gsutil_install) for local code coverage testing. For Google internal (gLinux) machines, please refer [here](https://cloud.google.com/storage/docs/gsutil_install#deb) instead. ## Creating the file structure Each OSS-Fuzz project has a subdirectory inside the [`projects/`](https://github.com/google/oss-fuzz/tree/master/projects) directory in the [OSS-Fuzz repository](https://github.com/google/oss-fuzz). For example, the [boringssl](https://github.com/google/boringssl) project is located in [`projects/boringssl`](https://github.com/google/oss-fuzz/tree/master/projects/boringssl). Each project directory also contains the following three configuration files: * [project.yaml](#projectyaml) - provides metadata about the project. * [Dockerfile](#dockerfile) - defines the container environment with information on dependencies needed to build the project and its [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target). * [build.sh](#buildsh) - defines the build script that executes inside the Docker container and generates the project build. You can automatically create a new directory for your project in OSS-Fuzz and generate templated versions of the configuration files by running the following commands: ```bash $ cd /path/to/oss-fuzz $ export PROJECT_NAME= $ export LANGUAGE= $ python3 infra/helper.py generate $PROJECT_NAME --language=$LANGUAGE ``` Once the template configuration files are created, you can modify them to fit your project. **Note:** We prefer that you keep and maintain [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your own source code repository. If this isn't possible, you can store them inside the OSS-Fuzz project directory you created. ## project.yaml {#projectyaml} This configuration file stores project metadata. The following attributes are supported: - [homepage](#homepage) - [language](#language) - [primary_contact](#primary) - [auto_ccs](#auto_ccs) - [main_repo](#main_repo) - [vendor_ccs](#vendor) (optional) - [sanitizers](#sanitizers) (optional) - [architectures](#architectures) (optional) - [help_url](#help_url) (optional) - [builds_per_day](#build_frequency) (optional) - [file_github_issue](#file_github_issue) (optional) - [disable_remediation](#disable_remediation) (optional) ### homepage You project's homepage. ### language Programming language the project is written in. Values you can specify include: * `c` * `c++` * [`go`]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/) * [`rust`]({{ site.baseurl }}//getting-started/new-project-guide/rust-lang/) * [`python`]({{ site.baseurl }}//getting-started/new-project-guide/python-lang/) * [`jvm` (Java, Kotlin, Scala and other JVM-based languages)]({{ site.baseurl }}//getting-started/new-project-guide/jvm-lang/) * [`swift`]({{ site.baseurl }}//getting-started/new-project-guide/swift-lang/) * [`javascript`]({{ site.baseurl }}//getting-started/new-project-guide/javascript-lang/) * [`lua`]({{ site.baseurl }}//getting-started/new-project-guide/lua-lang/) ### primary_contact, auto_ccs {#primary} The primary contact and list of other contacts to be CCed. Each person listed gets access to ClusterFuzz, including crash reports and fuzzer statistics, and are auto-cced on new bugs filed in the OSS-Fuzz tracker. If you're a primary or a CC, you'll need to use a [Google account](https://support.google.com/accounts/answer/176347?hl=en) to get full access. ([why?]({{ site.baseurl }}/faq/#why-do-you-require-a-google-account-for-authentication)). ### main_repo {#main_repo} Path to source code repository hosting the code, e.g. `https://path/to/main/repo.git`. ### vendor_ccs (optional) {#vendor} The list of vendor email addresses that are downstream consumers of the project and want access to the bug reports as they are filed. Any changes to this list must follow these rules: - Approved by the project maintainer (e.g. comment on pull request, reply on project mailing list). - An organization email address is used. ### sanitizers (optional) {#sanitizers} The list of sanitizers to use. Possible values are: `address`, `memory` and `undefined`. If you don't specify a list, `sanitizers` uses a default list of supported sanitizers (currently ["address"](https://clang.llvm.org/docs/AddressSanitizer.html) and ["undefined"](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html)). [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) ("memory") is also supported and recommended, but is not enabled by default due to the likelihood of false positives from un-instrumented system dependencies. If you want to use "memory," please build all libraries your project needs using MemorySanitizer. This can be done by building them with the compiler flags provided during MemorySanitizer builds. Then, you can opt in by adding "memory" to your list of sanitizers. If your project does not build with a particular sanitizer configuration and you need some time to fix it, you can use `sanitizers` to override the defaults temporarily. For example, to disable the UndefinedBehaviourSanitizer build, just specify all supported sanitizers except "undefined". If you want to test a particular sanitizer to see what crashes it generates without filing them in the issue tracker, you can set an `experimental` flag. For example, if you want to test "memory", set `experimental: True` like this: ``` sanitizers: - address - memory: experimental: True - undefined ``` Crashes can be accessed on the [ClusterFuzz homepage]({{ site.baseurl }}/further-reading/clusterfuzz#web-interface). `sanitizers` example: [boringssl](https://github.com/google/oss-fuzz/blob/master/projects/boringssl/project.yaml). ### architectures (optional) {#architectures} The list of architectures to fuzz on. ClusterFuzz supports fuzzing on x86_64 (aka x64) by default. Some projects can benefit from i386 fuzzing. OSS-Fuzz will build and run AddressSanitizer with libFuzzer on i386 by doing the following: ```yaml architectures: - x86_64 - i386 ``` By fuzzing on i386 you might find bugs that: * Only occur in architecture-specific source code (e.g. code that contains i386 assembly). * Exist in architecture-independent source code and which only affects i386 users. * Exist in architecture-independent source code and which affects users on other 32-bit platforms such as AArch32 (aka 32-bit ARM). Note that some bugs which affect x86_64 may be discovered on i386 and filed as such. On the testcase page of each oss-fuzz issue is a list of other jobs where the crash reproduces, this can let you know if the crash exists on x86_64 as well. Fuzzing on i386 is not enabled by default because many projects won't build for i386 without some modification to their OSS-Fuzz build process. For example, you will need to link against `$LIB_FUZZING_ENGINE` and possibly install i386 dependencies within the x86_64 docker image ([for example](https://github.com/google/oss-fuzz/blob/5b8dcb5d942b3b8bc173b823fb9ddbdca7ec6c99/projects/gdal/build.sh#L18)) to get things working. There are [known bugs](https://github.com/google/oss-fuzz/issues/2746) in ASAN on i386 that cause ClusterFuzz to report unreproducible crashes for 0 length testcases. There are no plans to fix these bugs so be ready for slightly more false positives if you use i386. These false positives should be somewhat easy to identify since they will manifest as crashes in ASAN rather than your code. ### fuzzing_engines (optional) {#fuzzing_engines} The list of fuzzing engines to use. By default, `libfuzzer`, `afl`, `honggfuzz`, and `centipede` are used. It is recommended to use all of them if possible. `libfuzzer` is required by OSS-Fuzz. ### help_url (optional) {#help_url} A link to a custom help URL that appears in bug reports instead of the default [OSS-Fuzz guide to reproducing crashes]({{ site.baseurl }}/advanced-topics/reproducing/). This can be useful if you assign bugs to members of your project unfamiliar with OSS-Fuzz, or if they should follow a different workflow for reproducing and fixing bugs than the standard one outlined in the reproducing guide. `help_url` example: [skia](https://github.com/google/oss-fuzz/blob/master/projects/skia/project.yaml). ### builds_per_day (optional) {#build_frequency} The number of times the project should be built per day. OSS-Fuzz allows upto 4 builds per day, and builds once per day by default. Example: ```yaml builds_per_day: 2 ``` Will build the project twice per day. ### file_github_issue (optional) {#file_github_issue} Whether to mirror issues on github instead of having them only in the OSS-Fuzz tracker. ### disable_remediation (optional) {#disable_remediation} Opt out of receiving remediation for all new and existing bugs. If remediation is disabled, all disclosure notifications will not include any proposed code changes. If enabled (default), proposed code changes and comments to remediate bugs may be automatically included in disclosure that is private during the embargo of each issue on a case-by-case basis basis. ## Dockerfile {#dockerfile} This configuration file defines the Docker image for your project. Your [build.sh](#buildsh) script will be executed in inside the container you define. For most projects, the image is simple: ```docker FROM gcr.io/oss-fuzz-base/base-builder # base image with clang toolchain RUN apt-get update && apt-get install -y ... # install required packages to build your project RUN git clone # checkout all sources needed to build your project WORKDIR # current directory for the build script COPY build.sh fuzzer.cc $SRC/ # copy build script and other fuzzer files in src dir ``` In the above example, the git clone will check out the source to `$SRC/`. Depending on your project's language, you will use a different base image, for instance `FROM gcr.io/oss-fuzz-base/base-builder-go` for golang. For an example, see [expat/Dockerfile](https://github.com/google/oss-fuzz/tree/master/projects/expat/Dockerfile) or [syzkaller/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/syzkaller/Dockerfile). In the case of a project with multiple languages/toolchains needed, you can run installation scripts `install_lang.sh` where lang is the language needed. You also need to setup environment variables needed by this toolchain, for example `GOPATH` is needed by golang. For an example, see [ecc-diff-fuzzer/Dockerfile](https://github.com/google/oss-fuzz/blob/master/projects/ecc-diff-fuzzer/Dockerfile). where we use `base-builder-rust`and install golang Runtime dependencies of your project, such as third-party static libraries, will not be instrumented if you build them in the Dockerfile. In most cases, you will want to build them in `build.sh` instead. ## build.sh {#buildsh} This file defines how to build binaries for [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) in your project. The script is executed within the image built from your [Dockerfile](#Dockerfile). In general, this script should do the following: - Build the project using your build system with the correct compiler. - Provide compiler flags as [environment variables](#Requirements). - Build your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) and link your project's build with libFuzzer. Resulting binaries should be placed in `$OUT`. Here's an example from Expat ([source](https://github.com/google/oss-fuzz/blob/master/projects/expat/build.sh)): ```bash #!/bin/bash -eu ./buildconf.sh # configure scripts usually use correct environment variables. ./configure make clean make -j$(nproc) all $CXX $CXXFLAGS -std=c++11 -Ilib/ \ $SRC/parse_fuzzer.cc -o $OUT/parse_fuzzer \ $LIB_FUZZING_ENGINE .libs/libexpat.a cp $SRC/*.dict $SRC/*.options $OUT/ ``` If your project is written in Go, check out the [Integrating a Go project]({{ site.baseurl }}//getting-started/new-project-guide/go-lang/) page. **Note:** 1. Don't assume the fuzzing engine is libFuzzer by default, because we generate builds for libFuzzer, AFL++, Honggfuzz, and Centipede fuzzing engine configurations. Instead, link the fuzzing engine using $LIB_FUZZING_ENGINE. 2. Make sure that the binary names for your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) contain only alphanumeric characters, underscore(_) or dash(-). Otherwise, they won't run on our infrastructure. 3. Don't remove source code files. They are needed for code coverage. ### Temporarily disabling code instrumentation during builds In some cases, it's not necessary to instrument every 3rd party library or tool that supports the build target. Use the following snippet to build tools or libraries without instrumentation: ``` CFLAGS_SAVE="$CFLAGS" CXXFLAGS_SAVE="$CXXFLAGS" unset CFLAGS unset CXXFLAGS export AFL_NOOPT=1 # # build commands here that should not result in instrumented code. # export CFLAGS="${CFLAGS_SAVE}" export CXXFLAGS="${CXXFLAGS_SAVE}" unset AFL_NOOPT ``` ### build.sh script environment When your build.sh script is executed, the following locations are available within the image: | Location| Env Variable | Description | |---------| ------------ | ---------- | | `/out/` | `$OUT` | Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives). | | `/src/` | `$SRC` | Directory to checkout source files. | | `/work/`| `$WORK` | Directory to store intermediate files. | Although the files layout is fixed within a container, environment variables are provided so you can write retargetable scripts. In case your fuzz target uses the [FuzzedDataProvider] class, make sure it is included via `#include ` directive. [FuzzedDataProvider]: https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider ### build.sh requirements {#Requirements} Only binaries without an extension are accepted as targets. Extensions are reserved for other artifacts, like .dict. You *must* use the special compiler flags needed to build your project and fuzz targets. These flags are provided in the following environment variables: | Env Variable | Description | ------------- | -------- | `$CC`, `$CXX`, `$CCC` | The C and C++ compiler binaries. | `$CFLAGS`, `$CXXFLAGS` | C and C++ compiler flags. | `$LIB_FUZZING_ENGINE` | C++ compiler argument to link fuzz target against the prebuilt engine library (e.g. libFuzzer). You *must* use `$CXX` as a linker, even if your project is written in pure C. Most well-crafted build scripts will automatically use these variables. If not, pass them manually to the build tool. See the [Provided Environment Variables](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/README.md#provided-environment-variables) section in `base-builder` image documentation for more details. ### Static and dynamic linking of libraries The `build.sh` should produce fuzzers that are statically linked. This is because the fuzzer build environment is different to the fuzzer runtime environment and if your project depends on third party libraries then it is likely they will not be present in the execution environment. Thus, any shared libraries you may install or compile in `build.sh` or `Dockerfile` will not be present in the fuzzer runtime environment. There are exceptions to this rule, and for further information on this please see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page. ## Disk space restrictions Our builders have a disk size of 250GB (this includes space taken up by the OS). Builds must keep peak disk usage below this. In addition, please keep the size of the build (everything copied to `$OUT`) small (<10GB uncompressed). The build is repeatedly transferred and unzipped during fuzzing and runs on VMs with limited disk space. ## Fuzzer execution environment For more on the environment that your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) run in, and the assumptions you can make, see the [fuzzer environment]({{ site.baseurl }}/further-reading/fuzzer-environment/) page. ## Testing locally You can build your docker image and fuzz targets locally, so you can test them before you push them to the OSS-Fuzz repository. 1. Run the same helper script you used to create your directory structure, this time using it to build your docker image and [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target): ```bash $ cd /path/to/oss-fuzz $ python3 infra/helper.py build_image $PROJECT_NAME $ python3 infra/helper.py build_fuzzers --sanitizer
$PROJECT_NAME ``` The built binaries appear in the `/path/to/oss-fuzz/build/out/$PROJECT_NAME` directory on your machine (and `$OUT` in the container). **Note:** You *must* run your fuzz target binaries inside the base-runner docker container to make sure that they work properly. 2. Find failures to fix by running the `check_build` command: ```bash $ python3 infra/helper.py check_build $PROJECT_NAME ``` 3. If you want to test changes against a particular fuzz target, run the following command: ```bash $ python3 infra/helper.py run_fuzzer --corpus-dir= $PROJECT_NAME ``` 4. We recommend taking a look at your code coverage as a test to ensure that your fuzz targets get to the code you expect. This would use the corpus generated from the previous `run_fuzzer` step in your local corpus directory. ```bash $ python3 infra/helper.py build_fuzzers --sanitizer coverage $PROJECT_NAME $ python3 infra/helper.py coverage $PROJECT_NAME --fuzz-target= --corpus-dir= ``` You may need to run `python3 infra/helper.py pull_images` to use the latest coverage tools. Please refer to [code coverage]({{ site.baseurl }}/advanced-topics/code-coverage/) for detailed information on code coverage generation. **Note:** Currently, we only support AddressSanitizer (address) and UndefinedBehaviorSanitizer (undefined) configurations by default. MemorySanitizer is recommended, but needs to be enabled manually since you must build all runtime dependencies with MemorySanitizer. Make sure to test each of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage). If everything works locally, it should also work on our automated builders and ClusterFuzz. If you check in your files and experience failures, review your [dependencies]({{ site.baseurl }}/further-reading/fuzzer-environment/#dependencies). ## Debugging Problems If you run into problems, our [Debugging page]({{ site.baseurl }}/advanced-topics/debugging/) lists ways to debug your build scripts and [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target). ## Efficient fuzzing To improve your fuzz target ability to find bugs faster, you should consider the following ways: ### Seed Corpus Most fuzzing engines use evolutionary fuzzing algorithms. Supplying a seed corpus consisting of good sample inputs is one of the best ways to improve [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s coverage. To provide a corpus for `my_fuzzer`, put `my_fuzzer_seed_corpus.zip` file next to the [fuzz target]({{ site.baseurl }}/reference/glossary/#fuzz-target)'s binary in `$OUT` during the build. Individual files in this archive will be used as starting inputs for mutations. You can store the corpus next to source files, generate during build or fetch it using curl or any other tool of your choice. (example: [boringssl](https://github.com/google/oss-fuzz/blob/master/projects/boringssl/build.sh#L41)). Seed corpus files will be used for cross-mutations and portions of them might appear in bug reports or be used for further security research. It is important that corpus has an appropriate and consistent license. OSS-Fuzz only: See also [Accessing Corpora]({{ site.baseurl }}/advanced-topics/corpora/) for information about getting access to the corpus we are currently using for your fuzz targets. ### Dictionaries Dictionaries hugely improve fuzzing efficiency for inputs with lots of similar sequences of bytes. [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html#dictionaries) Put your dict file in `$OUT`. If the dict filename is the same as your target binary name (i.e. `%fuzz_target%.dict`), it will be automatically used. If the name is different (e.g. because it is shared by several targets), specify this in .options file: ``` [libfuzzer] dict = dictionary_name.dict ``` It is common for several [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) to reuse the same dictionary if they are fuzzing very similar inputs. (example: [expat](https://github.com/google/oss-fuzz/blob/ad88a2e5295d91251d15f8a612758cd9e5ad92db/projects/expat/parse_fuzzer.options)). ### Input Size By default, the fuzzing engine will generate input of any arbitrary length. This might be useful to try corner cases that could lead to a security vulnerability. However, if large inputs are not necessary to increase the coverage of your target API, it is important to add a limit here to significantly improve performance. ```cpp if (size < kMinInputLength || size > kMaxInputLength) return 0; ``` ## Checking in to the OSS-Fuzz repository Once you've tested your fuzzing files locally, fork OSS-Fuzz, commit, and push to the fork. Then create a pull request with your change. Follow the [Forking Project](https://guides.github.com/activities/forking/) guide if you're new to contributing via GitHub. ### Copyright headers Please include copyright headers for all files checked in to oss-fuzz: ``` # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ``` **Exception:** If you're porting a fuzz target from Chromium, keep the original Chromium license header. ## Reviewing results Once your change is merged, your project and fuzz targets should be automatically built and run on ClusterFuzz after a short while (< 1 day). If you think there's a problem, you can check your project's [build status](https://oss-fuzz-build-logs.storage.googleapis.com/index.html). Use the [ClusterFuzz web interface](https://oss-fuzz.com/) to review the following: * Crashes generated * Code coverage statistics * Fuzzer statistics * Fuzzer performance analyzer (linked from fuzzer statistics) **Note:** Your Google Account must be listed in [project.yaml](#projectyaml) for you to have access to the ClusterFuzz web interface. ### Status Badge ![Example Badge](https://oss-fuzz-build-logs.storage.googleapis.com/badges/curl.svg) Once your project has started [building](https://oss-fuzz-build-logs.storage.googleapis.com/index.html), we'd love it if you added our badge in your project's README. This allows you to see bugs found by your OSS-Fuzz integration at a glance. See [brotli](https://github.com/google/brotli#introduction)'s README for an example. Adding it is super easy, just follow this template: ```markdown [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:) ``` ## Monitoring performance via Fuzz Introspector As soon as your project is run with ClusterFuzz (< 1 day), you can view the Fuzz Introspector report for your project. [Fuzz Introspector](https://github.com/ossf/fuzz-introspector) helps you understand your fuzzers' performance and identify any potential blockers. It provides individual and aggregated fuzzer reachability and coverage reports. You can monitor each fuzzer's static reachability potential and compare it against dynamic coverage and identify any potential bottlenecks. Fuzz Introspector can offer suggestions on increasing coverage by adding new fuzz targets or modify existing ones. Fuzz Introspector reports can be viewed from the [OSS-Fuzz homepage](https://oss-fuzz.com/) or through this [index](http://oss-fuzz-introspector.storage.googleapis.com/index.html). Fuzz Introspector support C and C++ projects. Support for Java and Python projects is in the progress. You can view the [Fuzz Introspector report for bzip2](https://storage.googleapis.com/oss-fuzz-introspector/bzip2/inspector-report/20221017/fuzz_report.html) as an example. ================================================ FILE: docs/glossary.md ================================================ This page has moved [here](https://google.github.io/oss-fuzz/reference/glossary/) ================================================ FILE: docs/ideal_integration.md ================================================ This page has moved [here](https://google.github.io/oss-fuzz/advanced-topics/ideal-integration) ================================================ FILE: docs/index.md ================================================ --- layout: default title: OSS-Fuzz permalink: / nav_order: 1 has_children: true has_toc: false --- # OSS-Fuzz [Fuzz testing] is a well-known technique for uncovering programming errors in software. Many of these detectable errors, like [buffer overflow], can have serious security implications. Google has found [thousands] of security vulnerabilities and stability bugs by deploying [guided in-process fuzzing of Chrome components], and we now want to share that service with the open source community. [Fuzz testing]: https://en.wikipedia.org/wiki/Fuzz_testing [buffer overflow]: https://en.wikipedia.org/wiki/Buffer_overflow [thousands]: https://bugs.chromium.org/p/chromium/issues/list?q=label%3AStability-LibFuzzer%2CStability-AFL%20-status%3ADuplicate%2CWontFix&can=1 [guided in-process fuzzing of Chrome components]: https://security.googleblog.com/2016/08/guided-in-process-fuzzing-of-chrome.html In cooperation with the [Core Infrastructure Initiative] and the [OpenSSF], OSS-Fuzz aims to make common open source software more secure and stable by combining modern fuzzing techniques with scalable, distributed execution. Projects that do not qualify for OSS-Fuzz (e.g. closed source) can run their own instances of [ClusterFuzz] or [ClusterFuzzLite]. [Core Infrastructure Initiative]: https://www.coreinfrastructure.org/ [OpenSSF]: https://www.openssf.org/ We support the [libFuzzer], [AFL++], [Honggfuzz], and [Centipede] fuzzing engines in combination with [Sanitizers], as well as [ClusterFuzz], a distributed fuzzer execution environment and reporting tool. [libFuzzer]: https://llvm.org/docs/LibFuzzer.html [AFL++]: https://github.com/AFLplusplus/AFLplusplus [Honggfuzz]: https://github.com/google/honggfuzz [Centipede]: https://github.com/google/centipede [Sanitizers]: https://github.com/google/sanitizers [ClusterFuzz]: https://github.com/google/clusterfuzz [ClusterFuzzLite]: https://google.github.io/clusterfuzzlite/ Currently, OSS-Fuzz supports C/C++, Rust, Go, Python, Java/JVM code, JavaScript and Lua. Other languages supported by [LLVM] may work too. OSS-Fuzz supports fuzzing x86_64 and i386 builds. [LLVM]: https://llvm.org ## Project history OSS-Fuzz was launched in 2016 in response to the [Heartbleed] vulnerability, discovered in [OpenSSL], one of the most popular open source projects for encrypting web traffic. The vulnerability had the potential to affect almost every internet user, yet was caused by a relatively simple memory buffer overflow bug that could have been detected by fuzzing—that is, by running the code on randomized inputs to intentionally cause unexpected behaviors or crashes. At the time, though, fuzzing was not widely used and was cumbersome for developers, requiring extensive manual effort. Google created OSS-Fuzz to fill this gap: it's a free service that runs fuzzers for open source projects and privately alerts developers to the bugs detected. Since its launch, OSS-Fuzz has become a critical service for the open source community, growing beyond C/C++ to detect problems in memory-safe languages such as Go, Rust, and Python. [Heartbleed]: https://heartbleed.com/ [OpenSSL]: https://www.openssl.org/ ## Learn more about fuzzing This documentation describes how to use OSS-Fuzz service for your open source project. To learn more about fuzzing in general, we recommend reading [libFuzzer tutorial] and the other docs in [google/fuzzing] repository. These and some other resources are listed on the [useful links] page. [google/fuzzing]: https://github.com/google/fuzzing/tree/master/docs [libFuzzer tutorial]: https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md [useful links]: {{ site.baseurl }}/reference/useful-links/#tutorials ## Trophies As of August 2023, OSS-Fuzz has helped identify and fix over [10,000] vulnerabilities and [36,000] bugs across [1,000] projects. [10,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=Type%3DBug-Security%20label%3Aclusterfuzz%20-status%3ADuplicate%2CWontFix&can=1 [36,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=Type%3DBug%20label%3Aclusterfuzz%20-status%3ADuplicate%2CWontFix&can=1 [1,000]: https://github.com/google/oss-fuzz/tree/master/projects ================================================ FILE: docs/new_project_guide.md ================================================ This page has moved [here](https://google.github.io/oss-fuzz/getting-started/new-project-guide/) ================================================ FILE: docs/oss-fuzz/architecture.md ================================================ --- layout: default title: Architecture permalink: /architecture/ nav_order: 1 parent: OSS-Fuzz --- # Architecture ![OSS-Fuzz architecture diagram]({{ site.baseurl }}/images/process.png?raw=true) The process works like this: 1. A maintainer of an open source project (or an outside volunteer) creates one or more [fuzz targets](https://llvm.org/docs/LibFuzzer.html#fuzz-target) and [integrates]({{ site.baseurl }}/advanced-topics/ideal-integration/) them with the project's build and test system. 1. The project is [accepted to OSS-Fuzz]({{ site.baseurl }}/getting-started/accepting-new-projects/) and the developer commits their build configurations. 1. The OSS-Fuzz [builder](https://github.com/google/oss-fuzz/tree/master/infra/build) builds the project from the committed configs. 1. The builder uploads the fuzz targets to the OSS-Fuzz GCS bucket. 1. [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) downloads the fuzz targets and begins to fuzz the projects. 1. When Clusterfuzz finds a bug, it reports the issue automatically to the OSS-Fuzz [issue tracker](https://bugs.chromium.org/p/oss-fuzz/issues/list) ([example](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9)). ([Why use a different tracker?]({{ site.baseurl }}/faq/#why-do-you-use-a-different-issue-tracker-for-reporting-bugs-in-oss-projects)) 1. Project owners are CCed on the bug report. 1. The project developer fixes the bug upstream and credits OSS-Fuzz for the discovery (the commit message should contain the string **'Credit to OSS-Fuzz'**). Once the developer fixes the bug, [ClusterFuzz]({{ site.baseurl }}/further-reading/clusterfuzz) automatically verifies the fix, adds a comment, and closes the issue ([example](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53#c3)). After the fix is verified or 90 days after reporting (whichever is earlier), the issue becomes [public]({{ site.baseurl }}/getting-started/bug-disclosure-guidelines/). ================================================ FILE: docs/reference/glossary.md ================================================ --- layout: default title: Glossary nav_order: 1 permalink: /reference/glossary/ parent: Reference --- # Glossary For general fuzzing terms, see the [glossary] from [google/fuzzing] project. [glossary]: https://github.com/google/fuzzing/blob/master/docs/glossary.md [google/fuzzing]: https://github.com/google/fuzzing - TOC {:toc} --- ## OSS-Fuzz specific terms ### ClusterFuzz A scalable fuzzing infrastructure that is used for OSS-Fuzz backend. [ClusterFuzz] is also used to fuzz Chrome and many other projects. A quick overview of ClusterFuzz user interface is available on this [page]. [page]: {{ site.baseurl }}/further-reading/clusterfuzz [ClusterFuzz]: https://github.com/google/clusterfuzz ### Fuzz Target In addition to its [general definition](https://github.com/google/fuzzing/blob/master/docs/glossary.md#fuzz-target), in OSS-Fuzz a fuzz target can be used to [reproduce bug reports]({{ site.baseurl }}/advanced-topics/reproducing/). It is recommended to use it for regression testing as well (see [ideal integration]({{ site.baseurl }}/advanced-topics/ideal-integration/)). ### Job type Or **Fuzzer Build**. This refers to a build that contains all the [fuzz targets] for a given [project](#project), is run with a specific [fuzzing engine], in a specific build mode (e.g. with enabled/disabled assertions), and optionally combined with a [sanitizer]. For example, we have a "libfuzzer_asan_sqlite" job type, indicating a build of all sqlite3 [fuzz targets] using [libFuzzer](http://libfuzzer.info) and [ASan](http://clang.llvm.org/docs/AddressSanitizer.html). ### Project A project is an open source software project that is integrated with OSS-Fuzz. Each project has a single set of configuration files (example: [expat](https://github.com/google/oss-fuzz/tree/master/projects/expat)) and may have one or more [fuzz targets] (example: [openssl](https://github.com/openssl/openssl/blob/master/fuzz/)). ### Reproducer Or a **testcase**. A [test input] that causes a specific bug to reproduce. [fuzz targets]: https://github.com/google/fuzzing/blob/master/docs/glossary.md#fuzz-target [fuzzing engine]: https://github.com/google/fuzzing/blob/master/docs/glossary.md#fuzzing-engine [sanitizer]: https://github.com/google/fuzzing/blob/master/docs/glossary.md#sanitizer [test input]: https://github.com/google/fuzzing/blob/master/docs/glossary.md#test-input ### Sanitizers Fuzzers are usually built with one or more [sanitizer](https://github.com/google/sanitizers) enabled. ```bash $ python3 infra/helper.py build_fuzzers --sanitizer undefined json ``` Supported sanitizers: | Sanitizer | Description | ------------ | ---------- | `address` *(default)* | [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) with [Leak Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer). | `undefined` | [Undefined Behavior Sanitizer](http://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html). | `memory` | [Memory Sanitizer](https://github.com/google/sanitizers/wiki/MemorySanitizer).
*NOTE: It is critical that you build __all__ the code in your program (including libraries it uses) with Memory Sanitizer. Otherwise, you will see false positive crashes due to an inability to see initializations in uninstrumented code.* | `coverage` | Used for generating code coverage reports. See [Code Coverage doc]({{ site.baseurl }}/advanced-topics/code-coverage/). Compiler flag values for predefined configurations are specified in the [Dockerfile](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/Dockerfile). These flags can be overridden by specifying `$SANITIZER_FLAGS` directly. You can choose which configurations to automatically run your fuzzers with in `project.yaml` file (e.g. [sqlite3](https://github.com/google/oss-fuzz/tree/master/projects/sqlite3/project.yaml)). ### Architectures ClusterFuzz supports fuzzing on x86_64 (aka x64) by default. However you can also fuzz using AddressSanitizer and libFuzzer on i386 (aka x86, or 32 bit) by specifying the `$ARCHITECTURE` build environment variable using the `--architecture` option: ```bash python3 infra/helper.py build_fuzzers --architecture i386 json ``` ================================================ FILE: docs/reference/reference.md ================================================ --- layout: default title: Reference has_children: true nav_order: 6 permalink: /reference/ --- # Reference ================================================ FILE: docs/reference/useful_links.md ================================================ --- layout: default title: Useful links nav_order: 2 permalink: /reference/useful-links/ parent: Reference --- # Useful links - TOC {:toc} --- ## Web Interface * The main page: [oss-fuzz.com](https://oss-fuzz.com) ## Build Status * [This page](https://oss-fuzz-build-logs.storage.googleapis.com/index.html) gives the latest build logs for each project. ## Blog posts * 2016-12-01 - Announcing OSS-Fuzz: Continuous fuzzing for open source software ([Open Source](https://opensource.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html), [Testing](https://testing.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html), [Security](https://security.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html)) * 2017-05-08 - OSS-Fuzz: Five months later, and rewarding projects ([Open Source](https://opensource.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html), [Testing](https://testing.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html), [Security](https://security.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html)) * 2018-11-06 - A New Chapter for OSS-Fuzz ([Security](https://security.googleblog.com/2018/11/a-new-chapter-for-oss-fuzz.html)) * 2020-10-09 - [Fuzzing internships for Open Source Software](https://security.googleblog.com/2020/10/fuzzing-internships-for-open-source.html) * 2020-12-07 - [Improving open source security during the Google summer internship program](https://security.googleblog.com/2020/12/improving-open-source-security-during.html) * 2021-03-10 - [Fuzzing Java in OSS-Fuzz](https://security.googleblog.com/2021/03/fuzzing-java-in-oss-fuzz.html) * 2021-12-16 - [Improving OSS-Fuzz and Jazzer to catch Log4Shell](https://security.googleblog.com/2021/12/improving-oss-fuzz-and-jazzer-to-catch.html) * 2022-09-08 - [Fuzzing beyond memory corruption: Finding broader classes of vulnerabilities automatically](https://security.googleblog.com/2022/09/fuzzing-beyond-memory-corruption.html) * 2023-02-01 - [Taking the next step: OSS-Fuzz in 2023](https://security.googleblog.com/2023/02/taking-next-step-oss-fuzz-in-2023.html) ## Tutorials * [libFuzzer documentation](https://llvm.org/docs/LibFuzzer.html) * [libFuzzer tutorial](https://github.com/google/fuzzing/blob/master/tutorial/libFuzzerTutorial.md) * [libFuzzer workshop](https://github.com/Dor1s/libfuzzer-workshop) * [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md) * [Chromium Fuzzing Page](https://chromium.googlesource.com/chromium/src/testing/libfuzzer/) * [Chromium Efficient Fuzzing Guide](https://chromium.googlesource.com/chromium/src/testing/libfuzzer/+/HEAD/efficient_fuzzing.md) * [ClusterFuzz documentation](https://google.github.io/clusterfuzz/) ================================================ FILE: docs/reproducing.md ================================================ This page has moved [here](https://google.github.io/oss-fuzz/advanced-topics/reproducing) ================================================ FILE: docs/research/target_generation.md ================================================ --- layout: default nav_exclude: true permalink: /research/llms/target_generation/ --- # Fuzz target generation using LLMs [Read our announcement blog.](https://security.googleblog.com/2023/08/ai-powered-fuzzing-breaking-bug-hunting.html) # Background [OSS-Fuzz](http://github.com/google/oss-fuzz) performs continuous fuzzing of [1000+](https://github.com/google/oss-fuzz/tree/master/projects) open source projects across most major languages. To integrate a new project, a human typically analyzes the attack surface of a library and writes [fuzz targets](https://github.com/google/fuzzing/blob/master/docs/glossary.md#fuzz-target) (also called fuzzing harnesses) to exercise the relevant code. Linked with a [fuzzing engine](https://github.com/google/fuzzing/blob/master/docs/glossary.md#fuzzing-engine) (e.g. libFuzzer, AFL, Centipede), this enables coverage-guided fuzzing for all OSS-Fuzz projects. Depending on the complexity of the project, writing fuzz targets typically requires several hours of manual work and sufficient background knowledge of the project. Additionally, the main challenge for most integrated OSS-Fuzz projects is ensuring high code coverage. Most OSS-Fuzz projects have fairly low runtime coverage ([~30%](http://introspector.oss-fuzz.com/)) despite millions of hours of CPU time. This means we are not finding vulnerabilities in approximately 70% of each project that we’re fuzzing. Our [preliminary research](https://dl.acm.org/doi/abs/10.1145/3605157.3605177) found that many[ fuzz blockers](https://github.com/ossf/fuzz-introspector/blob/main/doc/Glossary.md#fuzz-blockers) (as determined by [FuzzIntrospector](https://introspector.oss-fuzz.com/)) are because of deficiencies in existing targets, rather than deficiencies in fuzzing engines. Generating fuzz targets via LLMs can reduce the manual effort required to more thoroughly fuzz existing projects in OSS-Fuzz as well as integrating new projects into OSS-Fuzz. # Goals Our ideal end state of this research is to use LLMs for two use cases: 1. Completely automatic fuzz target generation (or modification of existing targets) for existing OSS-Fuzz projects to unblock fuzz blockers and increase project code coverage (and bugs found) for free. 2. Completely automatic fuzz target generation for completely new OSS-Fuzz projects. This is much more challenging than 1, and is an extension of it. Our current experiments focus on the first use case for C/C++ projects. This report serves as a preliminary investigation into how effective LLMs are for this use case. More detailed results and the experimentation framework for our research will be published at a later date. # Experiment framework To discover whether an LLM could successfully write new fuzz targets, we built an evaluation framework that connects OSS-Fuzz to Google’s LLMs, conducts the experiment, and evaluates the results. The steps look like this: ![experiment framework]({{ site.baseurl }}/images/llm_framework.png "image_tooltip") 1. OSS-Fuzz’s [Fuzz Introspector tool](http://introspector.oss-fuzz.com/) identifies an under-fuzzed, high-potential, portion of the target project’s code and passes the code to the evaluation framework. 2. The evaluation framework creates a prompt that the LLM will use to write the new fuzz target. The prompt includes project specific information. 3. The evaluation framework takes the fuzz target generated by the LLM and runs the new target. 4. The evaluation framework observes the run for any change in code coverage or crashes. 5. In the event that the fuzz target fails to compile, the evaluation framework prompts the LLM to write a revised fuzz target that addresses the compilation errors. ## 1. Identifying high potential portions of the project’s code We leverage [Fuzz Introspector](https://introspector.oss-fuzz.com/) ([example JSON endpoint](https://introspector.oss-fuzz.com/api/far-reach-but-low-coverage?project=tinyxml2)) to provide us with a list of functions with low runtime coverage (but high potential to reach more code coverage). These are turned into benchmark YAML files, which consist of an OSS-Fuzz project, and a list of function signatures to generate new targets for. We have started with a small set of benchmarks, and will gradually scale this to larger, automated sets of benchmarks taken from all of OSS-Fuzz as we improve the function selection and prompt generation process. Example benchmark (YAML): ```yaml functions: - XML_Parser XMLCALL XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context, const XML_Char *encodingName) - XML_Parser XMLCALL XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) - XML_Bool XMLCALL XML_ParserReset(XML_Parser parser, const XML_Char *encodingName) - static enum XML_Error PTRCALL externalParEntInitProcessor(XML_Parser parser, const char *s, const char *end, const char **nextPtr) project: expat target_path: /src/expat/expat/fuzz/xml_parse_fuzzer.c target_name: xml_parse_fuzzer_UTF-8 ``` ## 2. Prompt generation We dynamically generate a prompt based on a template ([example](https://storage.googleapis.com/oss-fuzz-llm-targets-public/jsoncpp-json-value-removeindex/prompts.txt)). As part of our experimentation, we tried various different prompt approaches. So far, the best results have come from including: * One example of an existing function signature and fuzz target from the project under test, formatted into problem and solution structure. Too many examples yields worse results. * Two examples from other projects in OSS-Fuzz, formatted in the same way. * Examples of how to leverage [FuzzedDataProvider](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider) to generate inputs for function arguments. * A priming that gives the task context. * Examples of code anti-patterns to avoid. The dynamically generated sections today include examples of existing fuzz targets from both other projects on OSS-Fuzz as well as one example from the project under test. We have other unexplored ideas including more structured information about the function under test, such as: * Relevant data structure definitions * Function implementations of the function under test and related functions * Usages of the function under test and related functions ## 3. Build and run We leverage the OSS-Fuzz build infrastructure to build new targets by replacing an existing target’s source code with the newly generated target source code. OSS-Fuzz projects often have strict compiler flags on by default. To make compilation easier, we also implemented a [compiler wrapper](https://github.com/google/oss-fuzz/blob/d78275b4e2e17d3d8f12b99db2b51de4b114edb3/infra/base-images/base-builder/jcc.go) that: * Turns off compiler warnings to prevent trivial issues such as missing pointer casts from blocking compilation. * Re-compiles targets as C++ (to leverage [FuzzedDataProvider](https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-provider)). ## 4. Measuring quality of generated targets An important part of our research is to define metrics to measure the quality of generated targets. These metrics are: * Syntax correctness and project consistency. This is measured by its compilation result. For example: whether it compiles successfully, does it call functions in the project correctly without hallucination. * Whether it crashes instantly or within the fuzz target. This often means that there is some miscalled API and the crashes are likely to be false positives. * **New code coverage**. This is measured by the new lines it covered compared to all existing targets in OSS-Fuzz for the same project. All of these metrics can be automatically computed for a given generated target. ## 5. LLM Code Fixer The fuzz targets generated by LLM often contain various trivial defects, which can be fixed by a separate LLM query. The prompt of the code fixing query is structured as follows, where the raw code and error are respectively replaced with the fuzz target source code generated by the LLM and the build error messages extracted from pages of build logs: ```` Given the following code and its build error message, fix the code without affecting its functionality. First explain the reason, then output the whole fixed code. If a function is missing, fix it by including the related libraries. Code: ``` {raw_code} ``` Build error message: ``` {error} ``` Fixed code: ```` Several rounds of code fixing queries are required for some cases. For example, when multiple defects incurs several error messages, sometimes LLM tends to only fix one of them at a time. Similarly, new defects may be introduced during code fixing. In these cases, we found iteratively querying LLM with the same prompt structure will gradually fix all errors. LLM often proposes several responses for each query, we prefer the one with the longest code. This is an implementation decision to avoid a quadratically increasing number of targets to build (e.g. the LLMs could propose 4 new targets across N iterations) and to avoid the LLM deleting the function code to fix build failures. Additionally, we also check that the generated target includes a call to the requested function to test. If it does not, this is surfaced as an error to the LLM. ### Example [Prompt](https://storage.googleapis.com/oss-fuzz-llm-targets-public/tinyxml2-tinyxml2-xmldocument-print/fixes/04-F4/prompt.txt): Incorrect target with missing arguments passed to target function. [After fix](https://storage.googleapis.com/oss-fuzz-llm-targets-public/tinyxml2-tinyxml2-xmldocument-print/fixes/04-F4/01.cpp): Correct function argument added. # Results Initially, getting any compilable output was a challenge. We were able to improve this via prompt engineering and our compiler wrapper to having [14/31 tested OSS-Fuzz projects](https://storage.googleapis.com/oss-fuzz-llm-targets-public/index.html?prefix=benchmarks/) successfully compile new targets and increase coverage. The successful examples and prompts are published [here](https://storage.googleapis.com/oss-fuzz-llm-targets-public/index.html). We see a wide range of coverage improvements from 0-31% code coverage increases. The top coverage increases, aggregated across all benchmarks per OSS-Fuzz project are:
tinyxml2 31%
cjson 6%
expat 4%
libplist 4%
libxml2 1%
elfutils 1%
The best result we’ve had is with the TinyXML2 project, where we managed to increase fuzz coverage from [38%](https://storage.googleapis.com/oss-fuzz-coverage/tinyxml2/reports/20230801/linux/report.html) line coverage to [69%](https://storage.googleapis.com/oss-fuzz-coverage/llm-results/tinyxml2/linux/report.html) line coverage without any interventions. ![alt_text]({{ site.baseurl }}/images/tinyxml2_examples.png "image_tooltip") Additionally, we targeted OpenSSL from the perspective of discovering past vulnerabilities that were not found due to lack of fuzzing coverage. We were able to replicate [a similar fuzz target](https://storage.googleapis.com/oss-fuzz-llm-targets-public/openssl-ossl_punycode_decode/targets/15.c) that rediscovered [CVE-2022-3602](https://nvd.nist.gov/vuln/detail/CVE-2022-3602). ![alt_text]({{ site.baseurl }}/images/punycode.png "Stacktrace from LLM-generated target finding CVE-2022-3602") # Future work We’ve seen very promising early results in this space and will continue our research. ## 1. Continue research There are a number of areas we’d like to further research on: * Expand benchmarks to all of OSS-Fuzz. We’d like to expand the set of benchmarks to cover all of OSS-Fuzz. * Continued prompt engineering and experimentation with project-specific context, such as more structured context (e.g. structure definitions, implementations) around the relevant function to test. * Model fine-tuning * Expand to other languages beyond C/C++ * Expand research to completely new projects with no existing OSS-Fuzz integration. ## 2. Open source evaluation framework We plan to open source the evaluation framework we’ve built to help test arbitrary auto-fuzz target generation capabilities. We hope that OSS-Fuzz can serve as a valuable benchmarking platform for researchers in this space. ## 3. OSS-Fuzz integration Ultimately, the goal is to integrate the results of this research into OSS-Fuzz, to provide: * Free coverage increases for existing projects * Automated onboarding of new projects, and tools to help maintainers write manual fuzz targets. # Appendix ## Successful benchmark results
Project Function Output Build rate Max Coverage Max Line coverage diff Reports
tinyxml2 tinyxml2-xmldocument-print Prompt;
Fixes;
Targets.

50

29.74

11.16

Reports
tinyxml2 tinyxml2-xmldocument-deepcopy Prompt;
Fixes;
Targets.

25

26.8

4.45

Reports
tinyxml2 tinyxml2-xmlelement-setattribute Prompt;
Fixes;
Targets.

75

26.08

3.77

Reports
libplist plist_print Prompt;
Fixes;
Targets.

25

12.88

3.42

Reports
tinyxml2 tinyxml2-xmlelement-doubletext Prompt;
Fixes;
Targets.

62.5

25.61

3.28

Reports
tinyxml2 tinyxml2-xmlelement-booltext Prompt;
Fixes;
Targets.

87.5

26.18

2.9

Reports
tinyxml2 tinyxml2-xmlelement-insertnewunknown Prompt;
Fixes;
Targets.

25

25.67

2.64

Reports
tinyxml2 tinyxml2-xmlelement-int64text Prompt;
Fixes;
Targets.

87.5

25.91

2.64

Reports
cjson cjson_compare Prompt;
Fixes;
Targets.

75

29.68

2.47

Reports
tinyxml2 tinyxml2-xmlelement-floattext Prompt;
Fixes;
Targets.

62.5

25.09

2.45

Reports
tinyxml2 tinyxml2-xmlelement-inttext Prompt;
Fixes;
Targets.

75

26.2

2.41

Reports
tinyxml2 tinyxml2-xmlelement-unsigned64text Prompt;
Fixes;
Targets.

37.5

25.74

2.22

Reports
tinyobjloader tinyobj-objreader-parsefromfile Prompt;
Fixes;
Targets.

37.5

5.7

2.16

Reports
tinyxml2 tinyxml2-xmlelement-unsignedtext Prompt;
Fixes;
Targets.

50

25.53

2.15

Reports
tinyxml2 tinyxml2-xmlelement-shallowclone Prompt;
Fixes;
Targets.

50

25.03

2.07

Reports
cjson cjson_replaceiteminobject Prompt;
Fixes;
Targets.

37.5

27.56

1.98

Reports
tinyxml2 tinyxml2-xmlelement-gettext Prompt;
Fixes;
Targets.

37.5

25.42

1.96

Reports
tinyxml2 tinyxml2-xmlelement-shallowequal Prompt;
Fixes;
Targets.

62.5

25.58

1.96

Reports
cjson cjson_duplicate Prompt;
Fixes;
Targets.

62.5

27.4

1.89

Reports
expat xml_externalentityparsercreate Prompt;
Fixes;
Targets.

12.5

1.25

1.88

Reports
cjson cjson_replaceiteminobjectcasesensitive Prompt;
Fixes;
Targets.

87.5

25.54

1.85

Reports
tinyxml2 tinyxml2-xmlelement-insertnewcomment Prompt;
Fixes;
Targets.

62.5

25.61

1.85

Reports
expat xml_parsercreatens Prompt;
Fixes;
Targets.

12.5

45.6

1.84

Reports
tinyxml2 tinyxml2-xmlelement-deleteattribute Prompt;
Fixes;
Targets.

50

25.73

1.7

Reports
tinyxml2 tinyxml2-xmlelement-insertnewdeclaration Prompt;
Fixes;
Targets.

50

25

1.7

Reports
tinyxml2 tinyxml2-xmlelement-insertnewchildelement Prompt;
Fixes;
Targets.

50

24.88

1.51

Reports
tinyxml2 tinyxml2-xmlnode-previoussiblingelement Prompt;
Fixes;
Targets.

87.5

26.08

1.43

Reports
tinyobjloader tinyobj-loadobj Prompt;
Fixes;
Targets.

25

4.33

1.35

Reports
tinyobjloader tinyobj-material_t-material_t Prompt;
Fixes;
Targets.

25

23.91

1.35

Reports
tinyxml2 tinyxml2-xmlelement-insertnewtext Prompt;
Fixes;
Targets.

62.5

24.42

1.32

Reports
elfutils dwfl_module_relocate_address Prompt;
Fixes;
Targets.

87.5

7.81

1.1

Reports
libxml2 xmlschemavalidatefile Prompt;
Fixes;
Targets.

50

4.18

0.93

Reports
tinyxml2 tinyxml2-xmldocument-loadfile Prompt;
Fixes;
Targets.

25

2.17

0.9

Reports
speex ogg_stream_packetin Prompt;
Fixes;
Targets.

25

8.06

0.55

Reports
libxml2 xmltextreadersetschema Prompt;
Fixes;
Targets.

37.5

1.44

0.48

Reports
libxml2 xmltextreaderschemavalidate Prompt;
Fixes;
Targets.

37.5

4.03

0.36

Reports
libplist plist_dict_merge Prompt;
Fixes;
Targets.

12.5

0.8

0.35

Reports
libxml2 xmltextreaderschemavalidatectxt Prompt;
Fixes;
Targets.

25

1.19

0.33

Reports
cjson cjson_printpreallocated Prompt;
Fixes;
Targets.

75

26.44

0.22

Reports
libucl ucl_parser_insert_chunk Prompt;
Fixes;
Targets.

25

10.5

0.22

Reports
libucl ucl_object_compare Prompt;
Fixes;
Targets.

12.5

1.35

0.21

Reports
elfutils dwarf_getlocations Prompt;
Fixes;
Targets.

62.5

7.22

0.2

Reports
libucl ucl_parser_add_fd_priority Prompt;
Fixes;
Targets.

71.43

19.61

0.18

Reports
jsoncpp json-value-resize Prompt;
Fixes;
Targets.

37.5

2.23

0.17

Reports
mosquitto mosquitto_topic_matches_sub2 Prompt;
Fixes;
Targets.

87.5

28.28

0.16

Reports
xvid xvid_encore Prompt;
Fixes;
Targets.

31.25

0.22

0.16

Reports
cjson cjson_parse Prompt;
Fixes;
Targets.

75

25.72

0.13

Reports
cjson cjson_parsewithlength Prompt;
Fixes;
Targets.

62.5

25.72

0.13

Reports
jsoncpp json-value-removeindex Prompt;
Fixes;
Targets.

25

5.11

0.13

Reports
libucl ucl_object_merge Prompt;
Fixes;
Targets.

25

0.65

0.12

Reports
speex ogg_stream_pageout_fill Prompt;
Fixes;
Targets.

6.25

0

0.07

Reports
libsndfile sf_command Prompt;
Fixes;
Targets.

25

3.41

0.06

Reports
mosquitto mosquitto_topic_matches_sub Prompt;
Fixes;
Targets.

62.5

4.03

0.05

Reports
libsndfile sf_format_check Prompt;
Fixes;
Targets.

12.5

0.1

0.04

Reports
libucl ucl_object_replace_key Prompt;
Fixes;
Targets.

50

7.14

0.04

Reports
libdwarf dwarf_find_die_given_sig8 Prompt;
Fixes;
Targets.

37.5

11.62

0.01

Reports
================================================ FILE: infra/.dockerignore ================================================ cifuzz/test_data/* # Copied from .gitignore. .vscode/ *.pyc build *~ .DS_Store *.swp ================================================ FILE: infra/MAINTAINERS.csv ================================================ Name,Email,Github Username Adam Korcz,adam@adalogics.com,AdamKorcz David Korczynski,david@adalogics.com,DavidKorczynski Dongge Liu,donggeliu@google.com,Alan32Liu Holly Gong,gongh@google.com,hogo6002 Jonathan Metzman,metzman@google.com,jonathanmetzman Oliver Chang,ochang@google.com,oliverchang ================================================ FILE: infra/README.md ================================================ # infra > OSS-Fuzz project infrastructure Core infrastructure: * [`base-images`](base-images/) - docker images for building fuzz targets & corresponding jenkins pipeline. Continuous Integration infrastructure: * [`ci`](ci/) - script to build projects in CI. ## helper.py > script to automate common docker operations | Command | Description | |---------|------------- | `generate` | Generates skeleton files for a new project | | `build_image` | Builds a docker image for a given project | | `build_fuzzers` | Builds fuzz targets for a given project | | `run_fuzzer` | Runs a fuzz target in a docker container | | `coverage` | Runs fuzz target(s) in a docker container and generates a code coverage report. See [Code Coverage doc](https://google.github.io/oss-fuzz/advanced-topics/code-coverage/) | | `reproduce` | Runs a testcase to reproduce a crash | | `shell` | Starts a shell inside the docker image for a project | ================================================ FILE: infra/base-images/README.md ================================================ # Base Images This directory contains the base images used by OSS-Fuzz. ## Building To build all images, run: ```bash # run from project root infra/base-images/all.sh ``` ## Trial Builds for Testing Changes When making changes to any of the base images, it's crucial to test them using the trial build system. This system is designed to build test versions of the images, identified by a `-testing` suffix, and use them to build a subset of OSS-Fuzz projects to ensure the changes don't cause regressions. ### Architecture Overview The trial build system now supports building multiple Ubuntu base variants in parallel to accelerate testing. The supported variants are: - `latest` (based on the default `Dockerfile`) - `ubuntu-20-04` (based on `ubuntu-20-04.Dockerfile`) - `ubuntu-24-04` (based on `ubuntu-24-04.Dockerfile`) When a trial build is triggered on a Pull Request that modifies files in `infra/base-images/`, the system initiates three separate, parallel builds in Google Cloud Build (GCB). Each of these builds is responsible for building all base images for a single Ubuntu variant. This parallel architecture allows for faster feedback on changes across different base OS versions. ### How to Trigger a Trial Build 1. Create a Pull Request with your changes to the base images. 2. Once the PR is open, add a comment with the following command: ``` /gcbrun trial_build.py all ``` 3. This command will be picked up by our CI system. It will first trigger a "coordinator" build, which then spawns the three parallel builds for the different Ubuntu variants. You can monitor the progress of these builds directly in the Google Cloud Build interface linked in your PR. ## Dependency Tree The following diagram shows the dependency tree of the base images. ```mermaid graph TD A[base-image] --> B(base-clang); B --> C(base-builder); C --> D(base-builder-go); C --> E(base-builder-javascript); C --> F(base-builder-jvm); C --> G(base-builder-python); C --> H(base-builder-ruby); C --> I(base-builder-rust); C --> J(base-builder-swift); C --> K(base-builder-fuzzbench); A --> L(base-runner); B --> L; C --> L; H --> L; L --> M(base-runner-debug); ``` ================================================ FILE: infra/base-images/all.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # # A script to build base images locally. # # This script is a wrapper around `docker build` that dynamically fetches the # official list of images from the Python source of truth, ensuring it never # goes out of date. # # Usage: # # Build the 'latest' version of all images. # ./all.sh # # # Build the 'ubuntu-24-04' version of all images. # ./all.sh ubuntu-24-04 # ################################################################################ # The first argument is the version tag, e.g., 'latest', 'ubuntu-20-04'. VERSION_TAG=${1:-latest} # Get the directory where this script is located to find the helper script. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" # Fetch the official list of images from the Python source of truth. # This avoids duplicating the image list and ensures this script is always # up-to-date. IMAGE_LIST=$(python3 "${SCRIPT_DIR}/list_images.py") echo "Building version: ${VERSION_TAG}" echo "Images to build: ${IMAGE_LIST}" # Loop through the official list of images and build each one. for image_name in ${IMAGE_LIST}; do image_dir="infra/base-images/${image_name}" if [ "${VERSION_TAG}" == "latest" ]; then dockerfile="${image_dir}/Dockerfile" tag="gcr.io/oss-fuzz-base/${image_name}" else dockerfile="${image_dir}/${VERSION_TAG}.Dockerfile" tag="gcr.io/oss-fuzz-base/${image_name}:${VERSION_TAG}" fi if [ ! -f "${dockerfile}" ]; then echo "Skipping build for ${image_name}:${VERSION_TAG} - Dockerfile not found at ${dockerfile}" continue fi echo "Building ${tag} from ${dockerfile}..." docker build -t "${tag}" -f "${dockerfile}" "${image_dir}" done echo "All builds for version ${VERSION_TAG} completed successfully." ================================================ FILE: infra/base-images/base-builder/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder` were successfully built. These images contain the necessary tools and libraries for building fuzzers. The `ubuntu-24-04` build required a fix to the `ADD` instruction in the Dockerfile to correctly handle multiple files. Both versions install a variety of tools, including Python, Bazel, and various compilers. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The `ubuntu-24-04` image includes newer versions of many packages, including Python 3.11.13. The specific versions of other tools and libraries also differ due to the updated base image. ## Dockerfile Analysis The Dockerfiles for both versions have several key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-clang` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Package Installation:** The `install_deps.sh` script is used to install a base set of dependencies, which differ between the two versions. * **Python Installation:** The `ubuntu-24-04` Dockerfile installs Python 3.11.13 from source, while the `ubuntu-20-04` version uses a different set of commands. * **ADD Instruction:** The `ADD` instruction in the `ubuntu-24-04` Dockerfile was corrected to use the proper syntax for adding multiple files. ================================================ FILE: infra/base-images/base-builder/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-clang COPY install_deps.sh / RUN /install_deps.sh && rm /install_deps.sh # Build and install latest Python 3.11. ENV PYTHON_VERSION 3.11.13 RUN PYTHON_DEPS="\ zlib1g-dev \ libncurses5-dev \ libgdbm-dev \ libnss3-dev \ libssl-dev \ libsqlite3-dev \ libreadline-dev \ libffi-dev \ libbz2-dev \ liblzma-dev" && \ unset CFLAGS CXXFLAGS && \ apt-get install -y $PYTHON_DEPS && \ cd /tmp && \ curl -O https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz && \ tar -xvf Python-$PYTHON_VERSION.tar.xz && \ cd Python-$PYTHON_VERSION && \ ./configure --enable-optimizations --enable-shared && \ make -j$(nproc) && \ make install && \ ldconfig && \ ln -s /usr/local/bin/python3 /usr/local/bin/python && \ cd .. && \ rm -r /tmp/Python-$PYTHON_VERSION.tar.xz /tmp/Python-$PYTHON_VERSION && \ rm -rf /usr/local/lib/python${PYTHON_VERSION%.*}/test && \ python3 -m ensurepip && \ python3 -m pip install --upgrade pip && \ apt-get remove -y $PYTHON_DEPS # https://github.com/google/oss-fuzz/issues/3888 ENV CCACHE_VERSION 4.10.2 RUN cd /tmp && curl -OL https://github.com/ccache/ccache/releases/download/v$CCACHE_VERSION/ccache-$CCACHE_VERSION.tar.xz && \ tar -xvf ccache-$CCACHE_VERSION.tar.xz && cd ccache-$CCACHE_VERSION && \ mkdir build && cd build && \ export LDFLAGS='-lpthread' && \ cmake -D CMAKE_BUILD_TYPE=Release .. && \ make -j && make install && \ rm -rf /tmp/ccache-$CCACHE_VERSION /tmp/ccache-$CCACHE_VERSION.tar.xz # Install six for Bazel rules. RUN unset CFLAGS CXXFLAGS && pip3 install -v --no-cache-dir \ six==1.15.0 absl-py==2.3.0 pyelftools==0.32 && rm -rf /tmp/* # Install Bazel through Bazelisk, which automatically fetches the latest Bazel version. ENV BAZELISK_VERSION 1.9.0 RUN curl -L https://github.com/bazelbuild/bazelisk/releases/download/v$BAZELISK_VERSION/bazelisk-linux-amd64 -o /usr/local/bin/bazel && \ chmod +x /usr/local/bin/bazel # Default build flags for various sanitizers. ENV SANITIZER_FLAGS_address "-fsanitize=address -fsanitize-address-use-after-scope" ENV SANITIZER_FLAGS_hwaddress "-fsanitize=hwaddress -fuse-ld=lld -Wno-unused-command-line-argument" # Set of '-fsanitize' flags matches '-fno-sanitize-recover' + 'unsigned-integer-overflow'. ENV SANITIZER_FLAGS_undefined "-fsanitize=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" # Don't include "function" since it is unsupported on aarch64. ENV SANITIZER_FLAGS_undefined_aarch64 "-fsanitize=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" ENV SANITIZER_FLAGS_memory "-fsanitize=memory -fsanitize-memory-track-origins" ENV SANITIZER_FLAGS_thread "-fsanitize=thread" ENV SANITIZER_FLAGS_introspector "-O0 -flto -fno-inline-functions -fuse-ld=gold -Wno-unused-command-line-argument" # Do not use any sanitizers in the coverage build. ENV SANITIZER_FLAGS_coverage "" # We use unsigned-integer-overflow as an additional coverage signal and have to # suppress error messages. See https://github.com/google/oss-fuzz/issues/910. ENV UBSAN_OPTIONS="silence_unsigned_overflow=1" # To suppress warnings from binaries running during compilation. ENV DFSAN_OPTIONS='warn_unimplemented=0' # Default build flags for coverage feedback. ENV COVERAGE_FLAGS="-fsanitize=fuzzer-no-link" # Use '-Wno-unused-command-line-argument' to suppress "warning: -ldl: 'linker' input unused" # messages which are treated as errors by some projects. ENV COVERAGE_FLAGS_coverage "-fprofile-instr-generate -fcoverage-mapping -pthread -Wl,--no-as-needed -Wl,-ldl -Wl,-lm -Wno-unused-command-line-argument" # Default sanitizer, fuzzing engine and architecture to use. ENV SANITIZER="address" ENV FUZZING_ENGINE="libfuzzer" ENV ARCHITECTURE="x86_64" # DEPRECATED - NEW CODE SHOULD NOT USE THIS. OLD CODE SHOULD STOP. Please use # LIB_FUZZING_ENGINE instead. # Path to fuzzing engine library to support some old users of # LIB_FUZZING_ENGINE. ENV LIB_FUZZING_ENGINE_DEPRECATED="/usr/lib/libFuzzingEngine.a" # Argument passed to compiler to link against fuzzing engine. # Defaults to the path, but is "-fsanitize=fuzzer" in libFuzzer builds. ENV LIB_FUZZING_ENGINE="/usr/lib/libFuzzingEngine.a" # TODO: remove after tpm2 catchup. ENV FUZZER_LDFLAGS "" WORKDIR $SRC COPY afl_llvm22_patch.diff $SRC/ RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflplusplus && \ cd aflplusplus && \ git checkout eadc8a2a7e0fa0338802ee6254bf296489ce4fd7 && \ wget --no-check-certificate -O oss.sh https://raw.githubusercontent.com/vanhauser-thc/binary_blobs/master/oss.sh && \ git apply $SRC/afl_llvm22_patch.diff && \ rm -rf .git && \ chmod 755 oss.sh # Do precompiles before copying other scripts for better cache efficiency. COPY precompile_afl /usr/local/bin/ RUN precompile_afl RUN cd $SRC && \ curl -L -O https://github.com/google/honggfuzz/archive/oss-fuzz.tar.gz && \ mkdir honggfuzz && \ cd honggfuzz && \ tar -xz --strip-components=1 -f $SRC/oss-fuzz.tar.gz && \ rm -rf examples $SRC/oss-fuzz.tar.gz COPY precompile_honggfuzz /usr/local/bin/ RUN precompile_honggfuzz RUN cd $SRC && \ git clone https://github.com/google/fuzztest && \ cd fuzztest && \ git checkout a37d133f714395cabc20dd930969a889495c9f53 && \ rm -rf .git ENV CENTIPEDE_BIN_DIR=$SRC/fuzztest/bazel-bin COPY precompile_centipede /usr/local/bin/ RUN precompile_centipede COPY sanitizers /usr/local/lib/sanitizers COPY bazel_build_fuzz_tests \ cargo \ compile \ compile_afl \ compile_centipede \ compile_honggfuzz \ compile_fuzztests.sh \ compile_go_fuzzer \ compile_javascript_fuzzer \ compile_libfuzzer \ compile_native_go_fuzzer \ compile_native_go_fuzzer_v2 \ go_utils.sh \ compile_python_fuzzer \ debug_afl \ # Go, JavaScript, Java, Python, Rust, and Swift installation scripts. install_go.sh \ install_javascript.sh \ install_java.sh \ install_python.sh \ install_ruby.sh \ install_rust.sh \ install_swift.sh \ make_build_replayable.py \ python_coverage_helper.py \ replay_build.sh \ srcmap \ write_labels.py \ unshallow_repos.py \ /usr/local/bin/ # TODO: Build this as part of a multi-stage build. ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc /usr/local/bin ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc2 /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc2 /usr/local/bin RUN chmod +x /usr/local/bin/clang-jcc /usr/local/bin/clang++-jcc /usr/local/bin/clang-jcc2 /usr/local/bin/clang++-jcc2 COPY llvmsymbol.diff $SRC COPY detect_repo.py /opt/cifuzz/ COPY bazel.bazelrc /root/.bazelrc # Set up ccache binary and cache directory. # /ccache/bin will contain the compiler wrappers, and /ccache/cache will # contain the actual cache, which can be saved. # To use this, set PATH=/ccache/bin:$PATH. RUN mkdir -p /ccache/bin && mkdir -p /ccache/cache && \ ln -s /usr/local/bin/ccache /ccache/bin/clang && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++ && \ ln -s /usr/local/bin/ccache /ccache/bin/clang-jcc && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++-jcc ENV CCACHE_DIR /ccache/cache # Don't check that the compiler is the same, so we can switch between jcc and # clang under the hood and re-use the same build cache. ENV CCACHE_COMPILERCHECK none ENV CCACHE_COMPILERTYPE clang # Build newer patchelf than the one available from Ubuntu. RUN cd /tmp && git clone https://github.com/NixOS/patchelf && \ apt-get update && apt-get install -y autoconf && \ cd patchelf && git checkout 523f401584d9584e76c9c77004e7abeb9e6c4551 && \ unset CFLAGS && export CXXFLAGS='-stdlib=libc++' && export LDFLAGS='-lpthread' && \ ./bootstrap.sh && ./configure && make && \ cp /tmp/patchelf/src/patchelf /usr/local/bin && \ rm -rf /tmp/patchelf && apt-get remove -y autoconf COPY indexer /opt/indexer COPY --from=gcr.io/oss-fuzz-base/indexer /indexer/build/indexer /opt/indexer/indexer RUN chmod a+x /opt/indexer/indexer /opt/indexer/index_build.py CMD ["compile"] ================================================ FILE: infra/base-images/base-builder/README.md ================================================ # base-builder > Abstract base image for project builders. Every project image supports multiple commands that can be invoked through docker after the image is built:
docker run --rm -ti gcr.io/oss-fuzz/$project <command> <arguments...>
# Supported Commands | Command | Description | |---------|-------------| | `compile` (default) | build all fuzz targets | `/bin/bash` | drop into shell, execute `compile` script to start build. # Build Configuration A single build image can build same set of fuzzers in many configurations. The configuration is picked through one or more environment variables. | Env Variable | Description | ------------- | -------- | `$SANITIZER ("address")` | Specifies predefined sanitizer configuration to use. `address` or `memory` or `undefined`. | `$SANITIZER_FLAGS` | Specify compiler sanitizer flags directly. Overrides `$SANITIZER`. | `$COVERAGE_FLAGS` | Specify compiler flags to use for fuzzer feedback coverage. | `$BUILD_UID` | User id to use while building fuzzers. ## Examples - *building sqlite3 fuzzer with UBSan (`SANITIZER=undefined`):*
docker run --rm -ti -e SANITIZER=undefined gcr.io/oss-fuzz/sqlite3
# Image Files Layout | Location|Env| Description | |---------| -------- | ---------- | | `/out/` | `$OUT` | Directory to store build artifacts (fuzz targets, dictionaries, options files, seed corpus archives). | | `/src/` | `$SRC` | Directory to checkout source files | | `/work/`| `$WORK` | Directory for storing intermediate files | | `/usr/lib/libFuzzingEngine.a` | `$LIB_FUZZING_ENGINE` | Location of prebuilt fuzzing engine library (e.g. libFuzzer) that needs to be linked with all fuzz targets. While files layout is fixed within a container, the environment variables are provided to be able to write retargetable scripts. ## Compiler Flags You *must* use special compiler flags to build your project and fuzz targets. These flags are provided in following environment variables: | Env Variable | Description | ------------- | -------- | `$CC` | The C compiler binary. | `$CXX`, `$CCC` | The C++ compiler binary. | `$CFLAGS` | C compiler flags. | `$CXXFLAGS` | C++ compiler flags. Most well-crafted build scripts will automatically use these variables. If not, pass them manually to the build tool. # Child Image Interface ## Sources Child image has to checkout all sources that it needs to compile fuzz targets into `$SRC` directory. When the image is executed, a directory could be mounted on top of these with local checkouts using `docker run -v $HOME/my_project:/src/my_project ...`. ## Other Required Files Following files have to be added by child images: | File Location | Description | | ------------- | ----------- | | `$SRC/build.sh` | build script to build the project and its fuzz targets | ================================================ FILE: infra/base-images/base-builder/afl_llvm22_patch.diff ================================================ diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 2cde89d9..7cafd3f5 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -32,7 +32,7 @@ VERSION = $(shell grep '^ *$(HASH)define VERSION ' ./config.h | cut -d '"' - SYS = $(shell uname -s) -override LLVM_TOO_NEW_DEFAULT := 21 +override LLVM_TOO_NEW_DEFAULT := 22 override LLVM_TOO_OLD_DEFAULT := 14 ifeq "$(SYS)" "OpenBSD" @@ -69,7 +69,7 @@ endif LLVM_STDCXX := gnu++11 LLVM_LTO := 0 -LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.|^2[2-9]\.' && echo 1 || echo 0) +LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-7]\.|^2[3-9]\.' && echo 1 || echo 0) # Uncomment to see the values assigned above # $(foreach var,_CLANG_VERSIONS_TO_TEST LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var)))) ================================================ FILE: infra/base-images/base-builder/bazel.bazelrc ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Pass variables from environment. build --action_env=FUZZ_INTROSPECTOR build --action_env=FUZZINTRO_OUTDIR ================================================ FILE: infra/base-images/base-builder/bazel_build_fuzz_tests ================================================ #!/bin/bash -eu # # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ : "${BAZEL_FUZZ_TEST_TAG:=fuzz-test}" : "${BAZEL_FUZZ_TEST_EXCLUDE_TAG:=no-oss-fuzz}" : "${BAZEL_PACKAGE_SUFFIX:=_oss_fuzz}" : "${BAZEL_TOOL:=bazel}" : "${BAZEL_EXTRA_BUILD_FLAGS:=}" if [ "$FUZZING_LANGUAGE" = "jvm" ]; then BAZEL_LANGUAGE=java else BAZEL_LANGUAGE=cc fi if [[ -z "${BAZEL_FUZZ_TEST_QUERY:-}" ]]; then BAZEL_FUZZ_TEST_QUERY=" let all_fuzz_tests = attr(tags, \"${BAZEL_FUZZ_TEST_TAG}\", \"//...\") in let lang_fuzz_tests = attr(generator_function, \"^${BAZEL_LANGUAGE}_fuzz_test\$\", \$all_fuzz_tests) in \$lang_fuzz_tests - attr(tags, \"${BAZEL_FUZZ_TEST_EXCLUDE_TAG}\", \$lang_fuzz_tests) " fi echo "Using Bazel query to find fuzz targets: ${BAZEL_FUZZ_TEST_QUERY}" declare -r OSS_FUZZ_TESTS=( $(bazel query "${BAZEL_FUZZ_TEST_QUERY}" | sed "s/$/${BAZEL_PACKAGE_SUFFIX}/") ) echo "Found ${#OSS_FUZZ_TESTS[@]} fuzz test packages:" for oss_fuzz_test in "${OSS_FUZZ_TESTS[@]}"; do echo " ${oss_fuzz_test}" done declare -r BAZEL_BUILD_FLAGS=( "--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine" \ "--@rules_fuzzing//fuzzing:java_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_java_engine" \ "--@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz" \ "--@rules_fuzzing//fuzzing:cc_engine_sanitizer=none" \ "--cxxopt=-stdlib=libc++" \ "--linkopt=-lc++" \ "--verbose_failures" \ "--spawn_strategy=standalone" \ "--action_env=CC=${CC}" "--action_env=CXX=${CXX}" \ ${BAZEL_EXTRA_BUILD_FLAGS[*]} ) echo "Building the fuzz tests with the following Bazel options:" echo " ${BAZEL_BUILD_FLAGS[@]}" ${BAZEL_TOOL} build "${BAZEL_BUILD_FLAGS[@]}" "${OSS_FUZZ_TESTS[@]}" echo "Extracting the fuzz test packages in the output directory." for oss_fuzz_archive in $(find bazel-bin/ -name "*${BAZEL_PACKAGE_SUFFIX}.tar"); do tar --no-same-owner -xvf "${oss_fuzz_archive}" -C "${OUT}" done if [ "$SANITIZER" = "coverage" ]; then echo "Collecting the repository source files for coverage tracking." declare -r COVERAGE_SOURCES="${OUT}/proc/self/cwd" mkdir -p "${COVERAGE_SOURCES}" declare -r RSYNC_FILTER_ARGS=( "--include" "*.h" "--include" "*.cc" "--include" "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*.inc" "--include" "*/" "--exclude" "*" ) rsync -avLk "${RSYNC_FILTER_ARGS[@]}" \ "$(bazel info execution_root)/" \ "${COVERAGE_SOURCES}/" fi ================================================ FILE: infra/base-images/base-builder/bisect_clang.py ================================================ #!/usr/bin/env python3 # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Use git bisect to find the Clang/LLVM commit causing a regression.""" import logging import os import re import shutil import subprocess import sys def execute(command, *args, expect_zero=True, **kwargs): """Execute |command| and return the returncode, stdout and stderr.""" kwargs['stdout'] = subprocess.PIPE kwargs['stderr'] = subprocess.PIPE logging.debug('Running command: "%s"', str(command)) process = subprocess.Popen(command, *args, **kwargs) stdout, stderr = process.communicate() stdout = stdout.decode('utf-8') stderr = stderr.decode('utf-8') retcode = process.returncode logging.info('Command: "%s" returned: %d.\nStdout: %s.\nStderr: %s', str(command), retcode, stdout, stderr) if expect_zero and retcode != 0: raise subprocess.CalledProcessError(retcode, command) return retcode, stdout, stderr def search_bisect_output(output): """Search |output| for a message indicating the culprit commit has been found.""" # TODO(metzman): Is it necessary to look for "good"? culprit_regex = re.compile('([a-z0-9]{40}) is the first (good|bad) commit') match = re.match(culprit_regex, output) return match.group(1) if match is not None else None class GitRepo: """Class for executing commmands on a git repo.""" def __init__(self, repo_dir): self.repo_dir = repo_dir def do_command(self, git_subcommand): """Execute a |git_subcommand| (a list of strings).""" command = ['git', '-C', self.repo_dir] + git_subcommand return execute(command) def test_commit(self, test_command): """Build LLVM at the currently checkedout commit, then run |test_command|. If returncode is 0 run 'git bisect good' otherwise return 'git bisect bad'. Return None if bisect didn't finish yet. Return the culprit commit if it does.""" build_clang(self.repo_dir) retcode, _, _ = execute(test_command, shell=True, expect_zero=False) if retcode == 0: retcode, stdout, _ = self.do_bisect_command('good') else: retcode, stdout, _ = self.do_bisect_command('bad') return search_bisect_output(stdout) def bisect(self, good_commit, bad_commit, test_command): """Do git bisect assuming |good_commit| is good, |bad_commit| is bad and |test_command| is an oracle. Return the culprit commit.""" self.bisect_start(good_commit, bad_commit, test_command) result = self.test_commit(test_command) while result is None: result = self.test_commit(test_command) return result def bisect_start(self, good_commit, bad_commit, test_command): """Start doing git bisect.""" self.do_bisect_command('start') # Do bad commit first since it is more likely to be recent. self.test_start_commit(bad_commit, 'bad', test_command) self.test_start_commit(good_commit, 'good', test_command) def do_bisect_command(self, subcommand): """Execute a git bisect |subcommand| (string) and return the result.""" return self.do_command(['bisect', subcommand]) def test_start_commit(self, commit, label, test_command): """Use |test_command| to test the first good or bad |commit| (depending on |label|).""" assert label in ('good', 'bad'), label self.do_command(['checkout', commit]) build_clang(self.repo_dir) retcode, _, _ = execute(test_command, shell=True, expect_zero=False) if label == 'good' and retcode != 0: raise BisectError('Test command "%s" returns %d on first good commit %s' % (test_command, retcode, commit)) if label == 'bad' and retcode == 0: raise BisectError('Test command "%s" returns %d on first bad commit %s' % (test_command, retcode, commit)) self.do_bisect_command(label) class BisectError(Exception): """Error that was encountered during bisection.""" def get_clang_build_env(): """Get an environment for building Clang.""" env = os.environ.copy() for variable in ['CXXFLAGS', 'CFLAGS']: if variable in env: del env[variable] return env def install_clang_build_deps(): """Instal dependencies necessary to build clang.""" execute([ 'apt-get', 'install', '-y', 'build-essential', 'make', 'cmake', 'ninja-build', 'git', 'subversion', 'g++-multilib' ]) def clone_with_retries(repo, local_path, num_retries=10): """Clone |repo| to |local_path| if it doesn't exist already. Try up to |num_retries| times. Return False if unable to checkout.""" if os.path.isdir(local_path): return for _ in range(num_retries): if os.path.isdir(local_path): shutil.rmtree(local_path) retcode, _, _ = execute(['git', 'clone', repo, local_path], expect_zero=False) if retcode == 0: return raise Exception('Could not checkout %s.' % repo) def get_clang_target_arch(): """Get target architecture we want clang to target when we build it.""" _, arch, _ = execute(['uname', '-m']) if 'x86_64' in arch: return 'X86' if 'aarch64' in arch: return 'AArch64' raise Exception('Unsupported target: %s.' % arch) def prepare_build(llvm_project_path): """Prepare to build clang.""" llvm_build_dir = os.path.join(os.getenv('WORK'), 'llvm-build') if not os.path.exists(llvm_build_dir): os.mkdir(llvm_build_dir) execute([ 'cmake', '-G', 'Ninja', '-DLIBCXX_ENABLE_SHARED=OFF', '-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON', '-DLIBCXXABI_ENABLE_SHARED=OFF', '-DCMAKE_BUILD_TYPE=Release', '-DLLVM_ENABLE_PROJECTS=libcxx;libcxxabi;compiler-rt;clang', '-DLLVM_TARGETS_TO_BUILD=' + get_clang_target_arch(), os.path.join(llvm_project_path, 'llvm') ], env=get_clang_build_env(), cwd=llvm_build_dir) return llvm_build_dir def build_clang(llvm_project_path): """Checkout, build and install Clang.""" # TODO(metzman): Merge Python checkout and build code with # checkout_build_install_llvm.sh. # TODO(metzman): Look into speeding this process using ccache. # TODO(metzman): Make this program capable of handling MSAN and i386 Clang # regressions. llvm_build_dir = prepare_build(llvm_project_path) execute(['ninja', '-C', llvm_build_dir, 'install'], env=get_clang_build_env()) def find_culprit_commit(test_command, good_commit, bad_commit): """Returns the culprit LLVM commit that introduced a bug revealed by running |test_command|. Uses git bisect and treats |good_commit| as the first latest known good commit and |bad_commit| as the first known bad commit.""" llvm_project_path = os.path.join(os.getenv('SRC'), 'llvm-project') clone_with_retries('https://github.com/llvm/llvm-project.git', llvm_project_path) git_repo = GitRepo(llvm_project_path) result = git_repo.bisect(good_commit, bad_commit, test_command) print('Culprit commit', result) return result def main(): # pylint: disable=line-too-long """Finds the culprit LLVM commit that introduced a clang regression. Can be tested using this command in a libsodium shell: python3 bisect_clang.py "cd /src/libsodium; make clean; cd -; compile && /out/secret_key_auth_fuzzer -runs=100" \ f7e52fbdb5a7af8ea0808e98458b497125a5eca1 \ 8288453f6aac05080b751b680455349e09d49825 """ # pylint: enable=line-too-long # TODO(metzman): Check CFLAGS for things like -fsanitize=fuzzer-no-link. # TODO(metzman): Allow test_command to be optional and for just build.sh to be # used instead. test_command = sys.argv[1] # TODO(metzman): Add in more automation so that the script can automatically # determine the commits used in last Clang roll. good_commit = sys.argv[2] bad_commit = sys.argv[3] # TODO(metzman): Make verbosity configurable. logging.getLogger().setLevel(logging.DEBUG) install_clang_build_deps() find_culprit_commit(test_command, good_commit, bad_commit) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-builder/bisect_clang_test.py ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for bisect_clang.py""" import os from unittest import mock import unittest import bisect_clang FILE_DIRECTORY = os.path.dirname(__file__) LLVM_REPO_PATH = '/llvm-project' def get_git_command(*args): """Returns a git command for the LLVM repo with |args| as arguments.""" return ['git', '-C', LLVM_REPO_PATH] + list(args) def patch_environ(testcase_obj): """Patch environment.""" env = {} patcher = mock.patch.dict(os.environ, env) testcase_obj.addCleanup(patcher.stop) patcher.start() class BisectClangTestMixin: # pylint: disable=too-few-public-methods """Useful mixin for bisect_clang unittests.""" def setUp(self): # pylint: disable=invalid-name """Initialization method for unittests.""" patch_environ(self) os.environ['SRC'] = '/src' os.environ['WORK'] = '/work' class GetClangBuildEnvTest(BisectClangTestMixin, unittest.TestCase): """Tests for get_clang_build_env.""" def test_cflags(self): """Test that CFLAGS are not used compiling clang.""" os.environ['CFLAGS'] = 'blah' self.assertNotIn('CFLAGS', bisect_clang.get_clang_build_env()) def test_cxxflags(self): """Test that CXXFLAGS are not used compiling clang.""" os.environ['CXXFLAGS'] = 'blah' self.assertNotIn('CXXFLAGS', bisect_clang.get_clang_build_env()) def test_other_variables(self): """Test that other env vars are used when compiling clang.""" key = 'other' value = 'blah' os.environ[key] = value self.assertEqual(value, bisect_clang.get_clang_build_env()[key]) def read_test_data(filename): """Returns data from |filename| in the test_data directory.""" with open(os.path.join(FILE_DIRECTORY, 'test_data', filename)) as file_handle: return file_handle.read() class SearchBisectOutputTest(BisectClangTestMixin, unittest.TestCase): """Tests for search_bisect_output.""" def test_search_bisect_output(self): """Test that search_bisect_output finds the responsible commit when one exists.""" test_data = read_test_data('culprit-commit.txt') self.assertEqual('ac9ee01fcbfac745aaedca0393a8e1c8a33acd8d', bisect_clang.search_bisect_output(test_data)) def test_search_bisect_output_none(self): """Test that search_bisect_output doesnt find a non-existent culprit commit.""" self.assertIsNone(bisect_clang.search_bisect_output('hello')) def create_mock_popen( output=bytes('', 'utf-8'), err=bytes('', 'utf-8'), returncode=0): """Creates a mock subprocess.Popen.""" class MockPopen: """Mock subprocess.Popen.""" commands = [] testcases_written = [] def __init__(self, command, *args, **kwargs): # pylint: disable=unused-argument """Inits the MockPopen.""" stdout = kwargs.pop('stdout', None) self.command = command self.commands.append(command) self.stdout = None self.stderr = None self.returncode = returncode if hasattr(stdout, 'write'): self.stdout = stdout def communicate(self, input_data=None): # pylint: disable=unused-argument """Mock subprocess.Popen.communicate.""" if self.stdout: self.stdout.write(output) if self.stderr: self.stderr.write(err) return output, err def poll(self, input_data=None): # pylint: disable=unused-argument """Mock subprocess.Popen.poll.""" return self.returncode return MockPopen def mock_prepare_build_impl(llvm_project_path): # pylint: disable=unused-argument """Mocked prepare_build function.""" return '/work/llvm-build' class BuildClangTest(BisectClangTestMixin, unittest.TestCase): """Tests for build_clang.""" def test_build_clang_test(self): """Tests that build_clang works as intended.""" with mock.patch('subprocess.Popen', create_mock_popen()) as mock_popen: with mock.patch('bisect_clang.prepare_build', mock_prepare_build_impl): llvm_src_dir = '/src/llvm-project' bisect_clang.build_clang(llvm_src_dir) self.assertEqual([['ninja', '-C', '/work/llvm-build', 'install']], mock_popen.commands) class GitRepoTest(BisectClangTestMixin, unittest.TestCase): """Tests for GitRepo.""" # TODO(metzman): Mock filesystem. Until then, use a real directory. def setUp(self): super().setUp() self.git = bisect_clang.GitRepo(LLVM_REPO_PATH) self.good_commit = 'good_commit' self.bad_commit = 'bad_commit' self.test_command = 'testcommand' def test_do_command(self): """Test do_command creates a new process as intended.""" # TODO(metzman): Test directory changing behavior. command = ['subcommand', '--option'] with mock.patch('subprocess.Popen', create_mock_popen()) as mock_popen: self.git.do_command(command) self.assertEqual([get_git_command('subcommand', '--option')], mock_popen.commands) def _test_test_start_commit_unexpected(self, label, commit, returncode): """Tests test_start_commit works as intended when the test returns an unexpected value.""" def mock_execute_impl(command, *args, **kwargs): # pylint: disable=unused-argument if command == self.test_command: return returncode, '', '' return 0, '', '' with mock.patch('bisect_clang.execute', mock_execute_impl): with mock.patch('bisect_clang.prepare_build', mock_prepare_build_impl): with self.assertRaises(bisect_clang.BisectError): self.git.test_start_commit(commit, label, self.test_command) def test_test_start_commit_bad_zero(self): """Tests test_start_commit works as intended when the test on the first bad commit returns 0.""" self._test_test_start_commit_unexpected('bad', self.bad_commit, 0) def test_test_start_commit_good_nonzero(self): """Tests test_start_commit works as intended when the test on the first good commit returns nonzero.""" self._test_test_start_commit_unexpected('good', self.good_commit, 1) def test_test_start_commit_good_zero(self): """Tests test_start_commit works as intended when the test on the first good commit returns 0.""" self._test_test_start_commit_expected('good', self.good_commit, 0) # pylint: disable=no-value-for-parameter @mock.patch('bisect_clang.build_clang') def _test_test_start_commit_expected(self, label, commit, returncode, mock_build_clang): """Tests test_start_commit works as intended when the test returns an expected value.""" command_args = [] def mock_execute_impl(command, *args, **kwargs): # pylint: disable=unused-argument command_args.append(command) if command == self.test_command: return returncode, '', '' return 0, '', '' with mock.patch('bisect_clang.execute', mock_execute_impl): self.git.test_start_commit(commit, label, self.test_command) self.assertEqual([ get_git_command('checkout', commit), self.test_command, get_git_command('bisect', label) ], command_args) mock_build_clang.assert_called_once_with(LLVM_REPO_PATH) def test_test_start_commit_bad_nonzero(self): """Tests test_start_commit works as intended when the test on the first bad commit returns nonzero.""" self._test_test_start_commit_expected('bad', self.bad_commit, 1) # pylint: disable=no-value-for-parameter @mock.patch('bisect_clang.GitRepo.test_start_commit') def test_bisect_start(self, mock_test_start_commit): """Tests bisect_start works as intended.""" with mock.patch('subprocess.Popen', create_mock_popen()) as mock_popen: self.git.bisect_start(self.good_commit, self.bad_commit, self.test_command) self.assertEqual(get_git_command('bisect', 'start'), mock_popen.commands[0]) mock_test_start_commit.assert_has_calls([ mock.call('bad_commit', 'bad', 'testcommand'), mock.call('good_commit', 'good', 'testcommand') ]) def test_do_bisect_command(self): """Test do_bisect_command executes a git bisect subcommand as intended.""" subcommand = 'subcommand' with mock.patch('subprocess.Popen', create_mock_popen()) as mock_popen: self.git.do_bisect_command(subcommand) self.assertEqual([get_git_command('bisect', subcommand)], mock_popen.commands) @mock.patch('bisect_clang.build_clang') def _test_test_commit(self, label, output, returncode, mock_build_clang): """Test test_commit works as intended.""" command_args = [] def mock_execute_impl(command, *args, **kwargs): # pylint: disable=unused-argument command_args.append(command) if command == self.test_command: return returncode, output, '' return 0, output, '' with mock.patch('bisect_clang.execute', mock_execute_impl): result = self.git.test_commit(self.test_command) self.assertEqual([self.test_command, get_git_command('bisect', label)], command_args) mock_build_clang.assert_called_once_with(LLVM_REPO_PATH) return result def test_test_commit_good(self): """Test test_commit labels a good commit as good.""" self.assertIsNone(self._test_test_commit('good', '', 0)) # pylint: disable=no-value-for-parameter def test_test_commit_bad(self): """Test test_commit labels a bad commit as bad.""" self.assertIsNone(self._test_test_commit('bad', '', 1)) # pylint: disable=no-value-for-parameter def test_test_commit_culprit(self): """Test test_commit returns the culprit""" test_data = read_test_data('culprit-commit.txt') self.assertEqual('ac9ee01fcbfac745aaedca0393a8e1c8a33acd8d', self._test_test_commit('good', test_data, 0)) # pylint: disable=no-value-for-parameter class GetTargetArchToBuildTest(unittest.TestCase): """Tests for get_target_arch_to_build.""" def test_unrecognized(self): """Test that an unrecognized architecture raises an exception.""" with mock.patch('bisect_clang.execute') as mock_execute: mock_execute.return_value = (None, 'mips', None) with self.assertRaises(Exception): bisect_clang.get_clang_target_arch() def test_recognized(self): """Test that a recognized architecture returns the expected value.""" arch_pairs = {'x86_64': 'X86', 'aarch64': 'AArch64'} for uname_result, clang_target in arch_pairs.items(): with mock.patch('bisect_clang.execute') as mock_execute: mock_execute.return_value = (None, uname_result, None) self.assertEqual(clang_target, bisect_clang.get_clang_target_arch()) ================================================ FILE: infra/base-images/base-builder/cargo ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This is a wrapper around calling cargo # This just expands RUSTFLAGS in case of a coverage build # We need this until https://github.com/rust-lang/cargo/issues/5450 is merged # because cargo uses relative paths for the current crate # and absolute paths for its dependencies # ################################################################################ if [ "$SANITIZER" = "coverage" ] && [ $1 = "build" ] then crate_src_abspath=`cargo metadata --no-deps --format-version 1 | jq -r '.workspace_root'` export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix src=$crate_src_abspath/src" fi if [ "$SANITIZER" = "coverage" ] && [ $1 = "fuzz" ] && [ $2 = "build" ] then # hack to turn cargo fuzz build into cargo build so as to get coverage # cargo fuzz adds "--target" "x86_64-unknown-linux-gnu" ( # go into fuzz directory if not already the case cd fuzz || true fuzz_src_abspath=`pwd` # Default directory is fuzz_targets, but some projects like image-rs use fuzzers. while read i; do export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix $i=$fuzz_src_abspath/$i" # Bash while syntax so that we modify RUSTFLAGS in main shell instead of a subshell. done <<< "$(find . -name "*.rs" | cut -d/ -f2 | uniq)" # we do not want to trigger debug assertions and stops export RUSTFLAGS="$RUSTFLAGS -C debug-assertions=no" # do not optimize with --release, leading to Malformed instrumentation profile data cargo build --bins # copies the build output in the expected target directory cd `cargo metadata --format-version 1 --no-deps | jq -r '.target_directory'` mkdir -p x86_64-unknown-linux-gnu/release cp -r debug/* x86_64-unknown-linux-gnu/release/ ) exit 0 fi /rust/bin/cargo "$@" ================================================ FILE: infra/base-images/base-builder/compile ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "---------------------------------------------------------------" sysctl -w vm.mmap_rnd_bits=28 OSS_FUZZ_ON_DEMAND="${OSS_FUZZ_ON_DEMAND:-0}" # Used for Rust introspector builds RUST_SANITIZER=$SANITIZER if [ "$FUZZING_LANGUAGE" = "jvm" ]; then if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "undefined" ] && [ "$SANITIZER" != "none" ] && [ "$SANITIZER" != "introspector" ]; then echo "ERROR: JVM projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer or Introspector only." exit 1 fi if [ "$ARCHITECTURE" != "x86_64" ]; then echo "ERROR: JVM projects can be fuzzed on x86_64 architecture only." exit 1 fi fi if [ "$FUZZING_LANGUAGE" = "rust" ]; then if [ "$SANITIZER" = "introspector" ]; then # introspector sanitizer flag will cause cargo build to fail. Rremove it # temporarily, RUST_SANITIZER will hold the original sanitizer. export SANITIZER=address fi fi if [ "$FUZZING_LANGUAGE" = "javascript" ]; then if [ "$FUZZING_ENGINE" != "libfuzzer" ]; then echo "ERROR: JavaScript projects can be fuzzed with libFuzzer engine only." exit 1 fi if [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "none" ]; then echo "ERROR: JavaScript projects cannot be fuzzed with sanitizers." exit 1 fi if [ "$ARCHITECTURE" != "x86_64" ]; then echo "ERROR: JavaScript projects can be fuzzed on x86_64 architecture only." exit 1 fi fi if [ "$FUZZING_LANGUAGE" = "python" ]; then if [ "$FUZZING_ENGINE" != "libfuzzer" ]; then echo "ERROR: Python projects can be fuzzed with libFuzzer engine only." exit 1 fi if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "undefined" ] && [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "introspector" ]; then echo "ERROR: Python projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer or Coverage or Fuzz Introspector only." exit 1 fi if [ "$ARCHITECTURE" != "x86_64" ]; then echo "ERROR: Python projects can be fuzzed on x86_64 architecture only." exit 1 fi fi if [ -z "${SANITIZER_FLAGS-}" ]; then FLAGS_VAR="SANITIZER_FLAGS_${SANITIZER}" export SANITIZER_FLAGS=${!FLAGS_VAR-} fi if [[ $ARCHITECTURE == "i386" ]]; then export CFLAGS="-m32 $CFLAGS" cp -R /usr/i386/lib/* /usr/local/lib cp -R /usr/i386/include/* /usr/local/include fi # Don't use a fuzzing engine with Jazzer which has libFuzzer built-in or with # FuzzBench which will provide the fuzzing engine. if [[ $FUZZING_ENGINE != "none" ]] && [[ $FUZZING_LANGUAGE != "jvm" ]] && [[ "${OSS_FUZZ_ON_DEMAND}" == "0" ]] ; then # compile script might override environment, use . to call it. . compile_${FUZZING_ENGINE} fi if [[ $SANITIZER_FLAGS = *sanitize=memory* ]] then # Take all libraries from lib/msan # export CXXFLAGS_EXTRA="-L/usr/msan/lib $CXXFLAGS_EXTRA" cp -R /usr/msan/lib/* /usr/local/lib/x86_64-unknown-linux-gnu/ cp -R /usr/msan/include/* /usr/local/include echo 'Building without MSan instrumented libraries.' fi # Coverage flag overrides. COVERAGE_FLAGS_VAR="COVERAGE_FLAGS_${SANITIZER}" if [[ -n ${!COVERAGE_FLAGS_VAR+x} ]] then export COVERAGE_FLAGS="${!COVERAGE_FLAGS_VAR}" fi # Only need the default coverage instrumentation for libFuzzer or honggfuzz. # Other engines bring their own. if [ $FUZZING_ENGINE = "none" ] || [ $FUZZING_ENGINE = "afl" ] || [ $FUZZING_ENGINE = "centipede" ] || [ "${OSS_FUZZ_ON_DEMAND}" != "0" ]; then export COVERAGE_FLAGS= fi # Rust does not support sanitizers and coverage flags via CFLAGS/CXXFLAGS, so # use RUSTFLAGS. # FIXME: Support code coverage once support is in. # See https://github.com/rust-lang/rust/issues/34701. if [ "$RUST_SANITIZER" == "introspector" ]; then export RUSTFLAGS="-Cdebuginfo=2 -Cforce-frame-pointers" elif [ "$SANITIZER" != "undefined" ] && [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "none" ] && [ "$ARCHITECTURE" != 'i386' ]; then export RUSTFLAGS="--cfg fuzzing -Zsanitizer=${SANITIZER} -Cdebuginfo=1 -Cforce-frame-pointers" else export RUSTFLAGS="--cfg fuzzing -Cdebuginfo=1 -Cforce-frame-pointers" fi if [ "$SANITIZER" = "coverage" ] then # link to C++ from comment in f5098035eb1a14aa966c8651d88ea3d64323823d export RUSTFLAGS="$RUSTFLAGS -Cinstrument-coverage -C link-arg=-lc++" fi # Add Rust libfuzzer flags. # See https://github.com/rust-fuzz/libfuzzer/blob/master/build.rs#L12. export CUSTOM_LIBFUZZER_PATH="$LIB_FUZZING_ENGINE_DEPRECATED" export CUSTOM_LIBFUZZER_STD_CXX=c++ export CFLAGS="$CFLAGS $SANITIZER_FLAGS $COVERAGE_FLAGS" export CXXFLAGS="$CFLAGS $CXXFLAGS_EXTRA" if [ "$SANITIZER" = "undefined" ]; then # Disable "function" sanitizer for C code for now, because many projects, # possibly via legacy C code are affected. # The projects should be fixed and this workaround be removed in the future. # TODO(#11778): # https://github.com/google/oss-fuzz/issues/11778 export CFLAGS="$CFLAGS -fno-sanitize=function" fi if [ "$FUZZING_LANGUAGE" = "go" ]; then # required by Go 1.20 export CXX="${CXX} -lresolv" fi if [ "$FUZZING_LANGUAGE" = "python" ]; then sanitizer_with_fuzzer_lib_dir=`python3 -c "import atheris; import os; print(atheris.path())"` sanitizer_with_fuzzer_output_lib=$OUT/sanitizer_with_fuzzer.so if [ "$SANITIZER" = "address" ]; then cp $sanitizer_with_fuzzer_lib_dir/asan_with_fuzzer.so $sanitizer_with_fuzzer_output_lib elif [ "$SANITIZER" = "undefined" ]; then cp $sanitizer_with_fuzzer_lib_dir/ubsan_with_fuzzer.so $sanitizer_with_fuzzer_output_lib fi # Disable leak checking as it is unsupported. export CFLAGS="$CFLAGS -fno-sanitize=function,leak,vptr," export CXXFLAGS="$CXXFLAGS -fno-sanitize=function,leak,vptr" fi # Copy latest llvm-symbolizer in $OUT for stack symbolization. cp $(which llvm-symbolizer) $OUT/ # Copy Jazzer to $OUT if needed. if [ "$FUZZING_LANGUAGE" = "jvm" ]; then cp $(which jazzer_agent_deploy.jar) $(which jazzer_driver) $(which jazzer_junit.jar) $OUT/ jazzer_driver_with_sanitizer=$OUT/jazzer_driver_with_sanitizer if [ "$SANITIZER" = "address" ]; then cat > $jazzer_driver_with_sanitizer << 'EOF' #!/bin/bash this_dir=$(dirname "$0") "$this_dir/jazzer_driver" --asan "$@" EOF elif [ "$SANITIZER" = "undefined" ]; then cat > $jazzer_driver_with_sanitizer << 'EOF' #!/bin/bash this_dir=$(dirname "$0") "$this_dir/jazzer_driver" --ubsan "$@" EOF elif [ "$SANITIZER" = "coverage" ] || [ "$SANITIZER" = "introspector" ]; then # Coverage & introspector builds require no instrumentation. cp $(which jazzer_driver) $jazzer_driver_with_sanitizer fi chmod +x $jazzer_driver_with_sanitizer # Disable leak checking since the JVM triggers too many false positives. export CFLAGS="$CFLAGS -fno-sanitize=leak" export CXXFLAGS="$CXXFLAGS -fno-sanitize=leak" fi if [ "$SANITIZER" = "introspector" ] || [ "$RUST_SANITIZER" = "introspector" ]; then export AR=llvm-ar export NM=llvm-nm export RANLIB=llvm-ranlib export CFLAGS="$CFLAGS -g" export CXXFLAGS="$CXXFLAGS -g" export FI_BRANCH_PROFILE=1 export FUZZ_INTROSPECTOR=1 export FUZZ_INTROSPECTOR_AUTO_FUZZ=1 # Move ar and ranlib mv /usr/bin/ar /usr/bin/old-ar mv /usr/bin/nm /usr/bin/old-nm mv /usr/bin/ranlib /usr/bin/old-ranlib ln -sf /usr/local/bin/llvm-ar /usr/bin/ar ln -sf /usr/local/bin/llvm-nm /usr/bin/nm ln -sf /usr/local/bin/llvm-ranlib /usr/bin/ranlib apt-get install -y libjpeg-dev zlib1g-dev libyaml-dev python3 -m pip install --upgrade pip setuptools python3 -m pip install cxxfilt pyyaml beautifulsoup4 lxml soupsieve rust-demangler python3 -m pip install --prefer-binary matplotlib # Install Fuzz-Introspector pushd /fuzz-introspector/src python3 -m pip install -e . popd if [ "$FUZZING_LANGUAGE" = "python" ]; then python3 /fuzz-introspector/src/main.py light --language=python cp -rf $SRC/inspector/ /tmp/inspector-saved elif [ "$FUZZING_LANGUAGE" = "jvm" ]; then python3 /fuzz-introspector/src/main.py light --language=jvm cp -rf $SRC/inspector/ /tmp/inspector-saved elif [ "$FUZZING_LANGUAGE" = "rust" ]; then python3 /fuzz-introspector/src/main.py light --language=rust cp -rf $SRC/inspector/ /tmp/inspector-saved else python3 /fuzz-introspector/src/main.py light # Make a copy of the light. This is needed because we run two versions of # introspector: one based on pure statis analysis and one based on # regular LTO. cp -rf $SRC/inspector/ /tmp/inspector-saved # Move coverage report. if [ -d "$OUT/textcov_reports" ] then find $OUT/textcov_reports/ -name "*.covreport" -exec cp {} $SRC/inspector/ \; find $OUT/textcov_reports/ -name "*.json" -exec cp {} $SRC/inspector/ \; fi # Make fuzz-introspector HTML report using light approach. REPORT_ARGS="--name=$PROJECT_NAME" # Only pass coverage_url when COVERAGE_URL is set (in cloud builds) if [[ ! -z "${COVERAGE_URL+x}" ]]; then REPORT_ARGS="$REPORT_ARGS --coverage-url=${COVERAGE_URL}" fi # Run pure static analysis fuzz introspector fuzz-introspector full --target-dir=$SRC \ --language=${FUZZING_LANGUAGE} \ --out-dir=$SRC/inspector \ ${REPORT_ARGS} fi rsync -avu --delete "$SRC/inspector/" "$OUT/inspector" fi echo "---------------------------------------------------------------" echo "CC=$CC" echo "CXX=$CXX" echo "CFLAGS=$CFLAGS" echo "CXXFLAGS=$CXXFLAGS" echo "RUSTFLAGS=$RUSTFLAGS" echo "---------------------------------------------------------------" if [ "${OSS_FUZZ_ON_DEMAND}" != "0" ]; then fuzzbench_build cp $(which llvm-symbolizer) $OUT/ exit 0 fi # Prepare the build command to run the project's build script. if [[ ! -z "${REPLAY_ENABLED-}" ]]; then # If this is a replay, then use replay_build.sh. This is expected to be # running in a cached container where a build has already happened prior. BUILD_CMD="bash -eux $SRC/replay_build.sh $@" else BUILD_CMD="bash -eux $SRC/build.sh $@" fi # Set +u temporarily to continue even if GOPATH and OSSFUZZ_RUSTPATH are undefined. set +u # We need to preserve source code files for generating a code coverage report. # We need exact files that were compiled, so copy both $SRC and $WORK dirs. COPY_SOURCES_CMD="cp -rL --parents $SRC $WORK /usr/include /usr/local/include $GOPATH $OSSFUZZ_RUSTPATH /rustc $OUT" set -u if [ "$FUZZING_LANGUAGE" = "rust" ]; then # Copy rust std lib to its path with a hash. export rustch=`rustc --version --verbose | grep commit-hash | cut -d' ' -f2` mkdir -p /rustc/$rustch/ export rustdef=`rustup toolchain list | grep default | cut -d' ' -f1` cp -r /rust/rustup/toolchains/$rustdef/lib/rustlib/src/rust/library/ /rustc/$rustch/ fi if [ "${BUILD_UID-0}" -ne "0" ]; then adduser -u $BUILD_UID --disabled-password --gecos '' builder chown -R builder $SRC $OUT $WORK su -c "$BUILD_CMD" builder if [ "$SANITIZER" = "coverage" ]; then # Some directories have broken symlinks (e.g. honggfuzz), ignore the errors. su -c "$COPY_SOURCES_CMD" builder 2>/dev/null || true fi else $BUILD_CMD if [ "$SANITIZER" = "coverage" ]; then # Some directories have broken symlinks (e.g. honggfuzz), ignore the errors. $COPY_SOURCES_CMD 2>/dev/null || true fi fi if [ "$SANITIZER" = "introspector" ] || [ "$RUST_SANITIZER" = "introspector" ]; then unset CXXFLAGS unset CFLAGS export G_ANALYTICS_TAG="G-8WTFM1Y62J" # If we get to here, it means the e.g. LTO had no problems and succeeded. # TO this end, we wlil restore the original light analysis and used the # LTO processing itself. rm -rf $SRC/inspector cp -rf /tmp/inspector-saved $SRC/inspector cd /fuzz-introspector/src python3 -m pip install -e . cd /src/ if [ "$FUZZING_LANGUAGE" = "rust" ]; then # Restore the sanitizer flag for rust export SANITIZER="introspector" fi mkdir -p $SRC/inspector find $SRC/ -name "fuzzerLogFile-*.data" -exec cp {} $SRC/inspector/ \; find $SRC/ -name "fuzzerLogFile-*.data.yaml" -exec cp {} $SRC/inspector/ \; find $SRC/ -name "fuzzerLogFile-*.data.debug_*" -exec cp {} $SRC/inspector/ \; find $SRC/ -name "allFunctionsWithMain-*.yaml" -exec cp {} $SRC/inspector/ \; # Move coverage report. if [ -d "$OUT/textcov_reports" ] then find $OUT/textcov_reports/ -name "*.covreport" -exec cp {} $SRC/inspector/ \; find $OUT/textcov_reports/ -name "*.json" -exec cp {} $SRC/inspector/ \; fi cd $SRC/inspector # Make fuzz-introspector HTML report. REPORT_ARGS="--name=$PROJECT_NAME" # Only pass coverage_url when COVERAGE_URL is set (in cloud builds) if [[ ! -z "${COVERAGE_URL+x}" ]]; then REPORT_ARGS="$REPORT_ARGS --coverage-url=${COVERAGE_URL}" fi # Do different things depending on languages if [ "$FUZZING_LANGUAGE" = "python" ]; then echo "GOING python route" set -x REPORT_ARGS="$REPORT_ARGS --target-dir=$SRC/inspector" REPORT_ARGS="$REPORT_ARGS --language=python" fuzz-introspector report $REPORT_ARGS rsync -avu --delete "$SRC/inspector/" "$OUT/inspector" elif [ "$FUZZING_LANGUAGE" = "jvm" ]; then echo "GOING jvm route" set -x find $OUT/ -name "jacoco.xml" -exec cp {} $SRC/inspector/ \; REPORT_ARGS="$REPORT_ARGS --target-dir=$SRC --out-dir=$SRC/inspector" REPORT_ARGS="$REPORT_ARGS --language=jvm" fuzz-introspector full $REPORT_ARGS rsync -avu --delete "$SRC/inspector/" "$OUT/inspector" elif [ "$FUZZING_LANGUAGE" = "rust" ]; then echo "GOING rust route" REPORT_ARGS="$REPORT_ARGS --target-dir=$SRC --out-dir=$SRC/inspector" REPORT_ARGS="$REPORT_ARGS --language=rust" fuzz-introspector full $REPORT_ARGS rsync -avu --delete "$SRC/inspector/" "$OUT/inspector" else # C/C++ mkdir -p $SRC/inspector # Correlate fuzzer binaries to fuzz-introspector's raw data fuzz-introspector correlate --binaries-dir=$OUT/ # Generate fuzz-introspector HTML report, this generates # the file exe_to_fuzz_introspector_logs.yaml REPORT_ARGS="$REPORT_ARGS --target-dir=$SRC/inspector" # Use the just-generated correlation file REPORT_ARGS="$REPORT_ARGS --correlation-file=exe_to_fuzz_introspector_logs.yaml" fuzz-introspector report $REPORT_ARGS rsync -avu --delete "$SRC/inspector/" "$OUT/inspector" fi fi ================================================ FILE: infra/base-images/base-builder/compile_afl ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # If LLVM once again does weird changes then enable this: #export AFL_LLVM_INSTRUMENT=LLVM-NATIVE # AFL++ setup echo "Copying precompiled AFL++" # Copy AFL++ tools necessary for fuzzing. pushd $SRC/aflplusplus > /dev/null cp -f libAFLDriver.a $LIB_FUZZING_ENGINE # Some important projects include libraries, copy those even when they don't # start with "afl-". Use "sort -u" to avoid a warning about duplicates. ls afl-* *.txt *.a *.o *.so | sort -u | xargs cp -t $OUT export CC="$SRC/aflplusplus/afl-clang-fast" export CXX="$SRC/aflplusplus/afl-clang-fast++" # Set sane AFL++ environment defaults: # Be quiet, otherwise this can break some builds. export AFL_QUIET=1 # No leak errors during builds. export ASAN_OPTIONS="detect_leaks=0:symbolize=0:detect_odr_violation=0:abort_on_error=1" # Do not abort on any problems (because this is during build where it is ok) export AFL_IGNORE_PROBLEMS=1 # No complain on unknown AFL environment variables export AFL_IGNORE_UNKNOWN_ENVS=1 # Provide a way to document the AFL++ options used in this build: echo echo AFL++ target compilation setup: env | egrep '^AFL_' | tee "$OUT/afl_options.txt" echo popd > /dev/null echo " done." ================================================ FILE: infra/base-images/base-builder/compile_centipede ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Skipping compilation; using precompiled centipede" if [[ "$SANITIZER" == 'none' ]]; then cp "$CENTIPEDE_BIN_DIR/centipede" "$OUT" fi cp "$CENTIPEDE_BIN_DIR/libcentipede_runner.pic.a" "$LIB_FUZZING_ENGINE" export CENTIPEDE_FLAGS=`cat "$SRC/fuzztest/centipede/clang-flags.txt" | tr '\n' ' '` export LIBRARIES_FLAGS="-Wno-unused-command-line-argument -Wl,-ldl -Wl,-lrt -Wl,-lpthread -Wl,$SRC/fuzztest/centipede/weak.o" export CFLAGS="$CFLAGS $CENTIPEDE_FLAGS $LIBRARIES_FLAGS" export CXXFLAGS="$CXXFLAGS $CENTIPEDE_FLAGS $LIBRARIES_FLAGS" echo 'done.' ================================================ FILE: infra/base-images/base-builder/compile_fuzztests.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -x # In order to identify fuzztest test case "bazel query" is used to search # the project. A search of the entire project is done with a default "...", # however, some projects may fail to, or have very long processing time, if # searching the entire project. Additionally, it may include fuzzers in # dependencies, which should not be build as part of a given project. # Tensorflow is an example project that will fail when the entire project is # queried. FUZZTEST_TARGET_FOLDER makes it posible to specify the folder # where fuzztest fuzzers should be search for. FUZZTEST_TARGET_FOLDER is passed # to "bazel query" below. if [[ ${FUZZTEST_TARGET_FOLDER:-"unset"} == "unset" ]]; then export TARGET_FOLDER="..." else TARGET_FOLDER=${FUZZTEST_TARGET_FOLDER} fi BUILD_ARGS="--config=oss-fuzz --subcommands" if [[ ${FUZZTEST_EXTRA_ARGS:-"unset"} != "unset" ]]; then BUILD_ARGS="$BUILD_ARGS ${FUZZTEST_EXTRA_ARGS}" fi # Trigger setup_configs rule of fuzztest as it generates the necessary # configuration file based on OSS-Fuzz environment variables. bazel run @com_google_fuzztest//bazel:setup_configs >> /etc/bazel.bazelrc # Bazel target names of the fuzz binaries. FUZZ_TEST_BINARIES=$(bazel query "kind(\"cc_test\", rdeps(${TARGET_FOLDER}, @com_google_fuzztest//fuzztest:fuzztest_gtest_main))") # Bazel output paths of the fuzz binaries. FUZZ_TEST_BINARIES_OUT_PATHS=$(bazel cquery "kind(\"cc_test\", rdeps(${TARGET_FOLDER}, @com_google_fuzztest//fuzztest:fuzztest_gtest_main))" --output=files) # Build the project and fuzz binaries # Expose `FUZZTEST_EXTRA_TARGETS` environment variable, in the event a project # includes non-FuzzTest fuzzers then this can be used to compile these in the # same `bazel build` command as when building the FuzzTest fuzzers. # This is to avoid having to call `bazel build` twice. bazel build $BUILD_ARGS -- ${FUZZ_TEST_BINARIES[*]} ${FUZZTEST_EXTRA_TARGETS:-} # Iterate the fuzz binaries and list each fuzz entrypoint in the binary. For # each entrypoint create a wrapper script that calls into the binaries the # given entrypoint as argument. # The scripts will be named: # {binary_name}@{fuzztest_entrypoint} for fuzz_main_file in $FUZZ_TEST_BINARIES_OUT_PATHS; do FUZZ_TESTS=$($fuzz_main_file --list_fuzz_tests) cp ${fuzz_main_file} $OUT/ fuzz_basename=$(basename $fuzz_main_file) chmod -x $OUT/$fuzz_basename for fuzz_entrypoint in $FUZZ_TESTS; do TARGET_FUZZER="${fuzz_basename}@$fuzz_entrypoint" # Write executer script echo "#!/bin/sh # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") chmod +x \$this_dir/$fuzz_basename \$this_dir/$fuzz_basename --fuzz=$fuzz_entrypoint -- \$@" > $OUT/$TARGET_FUZZER chmod +x $OUT/$TARGET_FUZZER done done # Synchronise coverage directory to bazel output artifacts. This is a # best-effort basis in that it will include source code in common # bazel output folders. # For projects that store results in non-standard folders or want to # manage what code to include in the coverage report more specifically, # the FUZZTEST_DO_SYNC environment variable is made available. Projects # can then implement a custom way of synchronising source code with the # coverage build. Set FUZZTEST_DO_SYNC to something other than "yes" and # no effort will be made to automatically synchronise the source code with # the code coverage visualisation utility. if [[ "$SANITIZER" = "coverage" && ${FUZZTEST_DO_SYNC:-"yes"} == "yes" ]] then # Synchronize bazel source files to coverage collection. declare -r REMAP_PATH="${OUT}/proc/self/cwd" mkdir -p "${REMAP_PATH}" # Synchronize the folder bazel-BAZEL_OUT_PROJECT. declare -r RSYNC_FILTER_ARGS=("--include" "*.h" "--include" "*.cc" "--include" \ "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*/" "--include" "*.inc" \ "--exclude" "*") project_folders="$(find . -name 'bazel-*' -type l -printf '%P\n' | \ grep -v -x -F \ -e 'bazel-bin' \ -e 'bazel-testlogs')" for link in $project_folders; do if [[ -d "${PWD}"/$link/external ]] then rsync -avLk "${RSYNC_FILTER_ARGS[@]}" "${PWD}"/$link/external "${REMAP_PATH}" fi # k8-opt is a common path for storing bazel output artifacts, e.g. bazel-out/k8-opt. # It's the output folder for default amd-64 builds, but projects may specify custom # platform output directories, see: https://github.com/bazelbuild/bazel/issues/13818 # We support the default at the moment, and if a project needs custom synchronizing of # output artifacts and code coverage we currently recommend using FUZZTEST_DO_SYNC. if [[ -d "${PWD}"/$link/k8-opt ]] then rsync -avLk "${RSYNC_FILTER_ARGS[@]}" "${PWD}"/$link/k8-opt "${REMAP_PATH}"/$link fi done # Delete symlinks and sync the current folder. find . -type l -ls -delete rsync -av ${PWD}/ "${REMAP_PATH}" fi ================================================ FILE: infra/base-images/base-builder/compile_go_fuzzer ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ path=$1 function=$2 fuzzer=$3 tags="-tags gofuzz" if [[ $# -eq 4 ]]; then tags="-tags $4" fi # Import go_utils.sh SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/go_utils.sh" # makes directory change temporary ( cd $GOPATH/src/$path || true # in the case we are in the right directory, with go.mod but no go.sum go mod tidy || true # project was downloaded with go get if go list fails go list $tags $path || { cd $GOPATH/pkg/mod/ && cd `echo $path | cut -d/ -f1-3 | awk '{print $1"@*"}'`; } || cd - # project does not have go.mod if go list fails again go list $tags $path || { go mod init $path && go mod tidy ;} if [[ $SANITIZER = *coverage* ]]; then fuzzed_package=`go list $tags -f '{{.Name}}' $path` abspath=`go list $tags -f {{.Dir}} $path` cd $abspath cp $GOPATH/ossfuzz_coverage_runner.go ./"${function,,}"_test.go sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go # The repo is the module path/name, which is already created above in case it doesn't exist, # but not always the same as the module path. This is necessary to handle SIV properly. fuzzed_repo=$(go list $tags -f {{.Module}} "$path") abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo` # give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath # Additional packages for which to get coverage. pkgaddcov="" # to prevent bash from failing about unbound variable GO_COV_ADD_PKG_SET=${GO_COV_ADD_PKG:-} if [[ -n "${GO_COV_ADD_PKG_SET}" ]]; then pkgaddcov=","$GO_COV_ADD_PKG abspath_repo=`go list -m $tags -f {{.Dir}} $GO_COV_ADD_PKG || go list $tags -f {{.Dir}} $GO_COV_ADD_PKG` echo "s=^$GO_COV_ADD_PKG"="$abspath_repo"= >> $OUT/$fuzzer.gocovpath fi go test $tags \ -c \ -o $OUT/$fuzzer \ -v \ -covermode=atomic \ -coverpkg $fuzzed_repo/...$pkgaddcov \ $path function_names_file="$OUT/fuzzer_function_names.json" save_function_name "$fuzzer" "Test${function}Corpus" "$function_names_file" else # Compile and instrument all Go files relevant to this fuzz target. echo "Running go-fuzz $tags -func $function -o $fuzzer.a $path" go-fuzz $tags -func $function -o $fuzzer.a $path # Link Go code ($fuzzer.a) with fuzzing engine to produce fuzz target binary. $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer fi ) ================================================ FILE: infra/base-images/base-builder/compile_honggfuzz ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Skipping compilation; using precompiled honggfuzz" cp $SRC/honggfuzz/honggfuzz.a $LIB_FUZZING_ENGINE cp $SRC/honggfuzz/honggfuzz $OUT/ # Set flags necessary for netdriver compilation. export LIB_HFND="-Wl,-u,LIBHFNETDRIVER_module_netdriver -Wl,--start-group $SRC/honggfuzz/libhfnetdriver/libhfnetdriver.a $SRC/honggfuzz/libhfcommon/libhfcommon.a -Wl,--end-group" export HFND_CXXFLAGS='-DHFND_FUZZING_ENTRY_FUNCTION_CXX(x,y)=extern const char* LIBHFNETDRIVER_module_netdriver;const char** LIBHFNETDRIVER_tmp1 = &LIBHFNETDRIVER_module_netdriver;extern "C" int HonggfuzzNetDriver_main(x,y);int HonggfuzzNetDriver_main(x,y)' export HFND_CFLAGS='-DHFND_FUZZING_ENTRY_FUNCTION(x,y)=extern const char* LIBHFNETDRIVER_module_netdriver;const char** LIBHFNETDRIVER_tmp1 = &LIBHFNETDRIVER_module_netdriver;int HonggfuzzNetDriver_main(x,y);int HonggfuzzNetDriver_main(x,y)' # Custom coverage flags, roughly in sync with: # https://github.com/google/honggfuzz/blob/oss-fuzz/hfuzz_cc/hfuzz-cc.c export COVERAGE_FLAGS="-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp" echo " done." ================================================ FILE: infra/base-images/base-builder/compile_javascript_fuzzer ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ project=$1 # Path the fuzz target source file relative to the project's root. fuzz_target=$2 # Arguments to pass to Jazzer.js jazzerjs_args=${@:3} # Copy source code into the $OUT directory and install Jazzer.js into the project. if [ ! -d $OUT/$project ]; then cp -r $SRC/$project $OUT/$project fi fuzzer_basename=$(basename -s .js $fuzz_target) # Create an execution wrapper that executes Jazzer.js with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput so that the wrapper script is recognized as a fuzz target for 'check_build'. project_dir=\$(dirname \"\$0\")/$project \$project_dir/node_modules/@jazzer.js/core/dist/cli.js \$project_dir/$fuzz_target $jazzerjs_args \$JAZZERJS_EXTRA_ARGS -- \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename ================================================ FILE: infra/base-images/base-builder/compile_libfuzzer ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo -n "Compiling libFuzzer to $LIB_FUZZING_ENGINE... " export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" if [ "$FUZZING_LANGUAGE" = "go" ]; then export LIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE $GOPATH/gosigfuzz/gosigfuzz.o" fi cp /usr/local/lib/clang/*/lib/$ARCHITECTURE-unknown-linux-gnu/libclang_rt.fuzzer.a $LIB_FUZZING_ENGINE_DEPRECATED echo " done." ================================================ FILE: infra/base-images/base-builder/compile_native_go_fuzzer ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ path=$1 function=$2 fuzzer=$3 tags="-tags gofuzz" # Get absolute path. abs_file_dir=$(go list $tags -f {{.Dir}} $path) # TODO(adamkorcz): Get rid of "-r" flag here. export fuzzer_filename=$(grep -r -l --include='*.go' -s "$function" "${abs_file_dir}") # Import build_native_go_fuzzer_legacy SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/go_utils.sh" # Test if file contains a line with "func $function" and "testing.F". if [ $(grep -r "func $function" $fuzzer_filename | grep "testing.F" | wc -l) -eq 1 ] then build_native_go_fuzzer_legacy $fuzzer $function $abs_file_dir $path else echo "Could not find the function: func ${function}(f *testing.F)" fi ================================================ FILE: infra/base-images/base-builder/compile_native_go_fuzzer_v2 ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ path=$1 function=$2 fuzzer=$3 tags="-tags gofuzz" # Get absolute path. abs_file_dir=$(go list $tags -f {{.Dir}} $path) # Find the file containing the fuzzer function definition. # Search for the actual function signature with testing.F to avoid false matches # in files that only reference the function name (e.g., in comments or helper functions). export fuzzer_filename=$(grep -r -l --include='*.go' "func ${function}(.*testing\.F" "${abs_file_dir}") # Import build_native_go_fuzzer SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/go_utils.sh" # Verify we found exactly one file with the fuzzer function. file_count=$(echo "$fuzzer_filename" | wc -w) if [ "$file_count" -eq 1 ] && [ -n "$fuzzer_filename" ] && [ -f "$fuzzer_filename" ] then build_native_go_fuzzer $fuzzer $function $abs_file_dir $path elif [ "$file_count" -gt 1 ] then echo "Error: Found multiple files with func ${function}(f *testing.F):" echo "$fuzzer_filename" exit 1 else echo "Could not find the function: func ${function}(f *testing.F)" fi ================================================ FILE: infra/base-images/base-builder/compile_python_fuzzer ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # In order to enable PySecSan for a given module, set the environment # variable ENABLE_PYSECSAN="YES" fuzzer_path=$1 shift 1 fuzzer_basename=$(basename -s .py $fuzzer_path) fuzzer_package=${fuzzer_basename}.pkg PYFUZZ_WORKPATH=$SRC/pyfuzzworkdir/ FUZZ_WORKPATH=$PYFUZZ_WORKPATH/$fuzzer_basename if [[ $SANITIZER = *introspector* ]]; then # Extract the source package the fuzzer targets. This must happen before # we enter the virtual environment in the following lines because we need # to use the same python environment that installed the fuzzer dependencies. python3 /fuzz-introspector/frontends/python/prepare_fuzz_imports.py $fuzzer_path isossfuzz # We must ensure python3.9, this is because we use certain # AST logic from there. # The below should probably be refined apt-get install -y python3.9 apt-get update apt-get install -y python3-pip python3.9 -m pip install virtualenv python3.9 -m virtualenv .venv . .venv/bin/activate pip3 install pyyaml export PYTHONPATH="/fuzz-introspector/frontends/python/PyCG" ARGS="--fuzzer $fuzzer_path" if [ -n "${PYFUZZPACKAGE-}" ]; then ARGS="$ARGS --package=${PYFUZZPACKAGE}" fi python /fuzz-introspector/frontends/python/main.py $ARGS ls -la ./ exit 0 fi # In coverage mode prepend coverage logic to the fuzzer source if [[ $SANITIZER = *coverage* ]]; then cat < coverage_wrapper.py ###### Coverage stub import atexit import coverage cov = coverage.coverage(data_file='.coverage', cover_pylib=True) cov.start() # Register an exist handler that will print coverage def exit_handler(): cov.stop() cov.save() atexit.register(exit_handler) ####### End of coverage stub EOF # Prepend stub and create tmp file cat coverage_wrapper.py $fuzzer_path > tmp_fuzzer_coverage.py # Overwrite existing fuzzer with new fuzzer that has stub mv tmp_fuzzer_coverage.py $fuzzer_path fi # If PYSECSAN is enabled, ensure that we can build with it. if [[ ${ENABLE_PYSECSAN:-"0"} != "0" ]]; then # Make sure pysecsan is installed if [[ ! -d "/pysecsan" ]]; then pushd /usr/local/lib/sanitizers/pysecsan python3 -m pip install . popd fi cat < pysecsan_wrapper.py import pysecsan; pysecsan.add_hooks(); EOF # Prepend stub and create tmp file cat pysecsan_wrapper.py $fuzzer_path > tmp_fuzzer_pysecsan.py # Overwrite existing fuzzer with new fuzzer that has stub mv tmp_fuzzer_pysecsan.py $fuzzer_path fi rm -rf $PYFUZZ_WORKPATH mkdir $PYFUZZ_WORKPATH $FUZZ_WORKPATH pyinstaller --distpath $OUT --workpath=$FUZZ_WORKPATH --onefile --name $fuzzer_package "$@" $fuzzer_path # Disable executable bit from package as OSS-Fuzz uses executable bits to # identify fuzz targets. We re-enable the executable bit in wrapper script # below. chmod -x $OUT/$fuzzer_package # In coverage mode save source files of dependencies in pyinstalled binary if [[ $SANITIZER = *coverage* ]]; then rm -rf /medio/ python3 /usr/local/bin/python_coverage_helper.py $FUZZ_WORKPATH "/medio" zip -r $fuzzer_package.deps.zip /medio mv $fuzzer_package.deps.zip $OUT/ fi # Create execution wrapper. echo "#!/bin/sh # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") chmod +x \$this_dir/$fuzzer_package LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \ ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \ \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename ================================================ FILE: infra/base-images/base-builder/debug_afl ================================================ #!/bin/bash # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Source this file for afl++ debug sessions. apt-get update apt-get install -y strace gdb vim joe psmisc pushd $SRC/aflplusplus > /dev/null git checkout dev git pull test -n "$1" && { git checkout "$1" ; git pull ; } CFLAGS_SAVE="$CFLAGS" CXXFLAGS_SAVE="$CXXFLAGS" unset CFLAGS unset CXXFLAGS make export CFLAGS="$CFLAGS_SAVE" export CXXFLAGS="$CXXFLAGS_SAVE" popd > /dev/null export ASAN_OPTIONS="detect_leaks=0:symbolize=0:detect_odr_violation=0:abort_on_error=1" export AFL_LLVM_LAF_ALL=1 export AFL_LLVM_CMPLOG=1 touch "$OUT/afl_cmplog.txt" export AFL_LLVM_DICT2FILE=$OUT/afl++.dict ulimit -c unlimited ================================================ FILE: infra/base-images/base-builder/detect_repo.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module to get the the name of a git repo containing a specific commit inside of an OSS-Fuzz project. Example Usage: python detect_repo.py --src_dir /src --example_commit b534f03eecd8a109db2b085ab24d419b6486de97 Prints the location of the git remote repo as well as the repo's name seperated by a space. https://github.com/VirusTotal/yara.git yara """ import argparse import logging import os import subprocess GO_PATH = '/root/go/src/' def main(): """Function to get a git repo's url and name referenced by OSS-Fuzz Dockerfile. Raises: ValueError when a commit or a ref is not provided. """ parser = argparse.ArgumentParser( description= 'Finds a specific git repo in an oss-fuzz project\'s docker file.') parser.add_argument('--repo_name', help='The name of the git repo.') parser.add_argument('--src_dir', help='The location of the possible repo.') parser.add_argument('--example_commit', help='A commit SHA referencing the project\'s main repo.') args = parser.parse_args() if not args.repo_name and not args.example_commit: raise ValueError( 'Requires an example commit or a repo name to find repo location.') if args.src_dir: src_dir = args.src_dir else: src_dir = os.environ.get('SRC', '/src') for single_dir in get_dirs_to_search(src_dir, args.repo_name): full_path = os.path.join(src_dir, single_dir) if not os.path.isdir(full_path): continue if args.example_commit and check_for_commit(full_path, args.example_commit): print('Detected repo:', get_repo(full_path), full_path) return if args.repo_name and check_for_repo_name(full_path, args.repo_name): print('Detected repo:', get_repo(full_path), full_path) return logging.error('No git repos with specific commit: %s found in %s', args.example_commit, src_dir) def get_dirs_to_search(src_dir, repo_name): """Gets a list of directories to search for the main git repo. Args: src_dir: The location set for the projects SRC. repo_name: The name of the repo you are searching for. Returns: A list of directorys to search. """ dirs_to_search = os.listdir(src_dir) if os.path.exists(GO_PATH) and repo_name: for root, dirs, _ in os.walk(GO_PATH): for test_dir in dirs: if repo_name in test_dir: dirs_to_search.append(os.path.join(root, test_dir)) return dirs_to_search def get_repo(repo_path): """Gets a git repo link from a specific directory in a docker image. Args: repo_path: The directory on the image where the git repo exists. Returns: The repo location or None. """ output, return_code = execute(['git', 'config', '--get', 'remote.origin.url'], location=repo_path, check_result=True) if return_code == 0 and output: return output.rstrip() return None def check_for_repo_name(repo_path, expected_repo_name): """Returns True if the repo at |repo_path| repo_name matches |expected_repo_name|. Args: repo_path: The directory of a git repo. expected_repo_name: The name of the target git repo. """ if not os.path.exists(os.path.join(repo_path, '.git')): return False repo_url, _ = execute(['git', 'config', '--get', 'remote.origin.url'], location=repo_path) # Handle two common cases: # https://github.com/google/syzkaller/ # https://github.com/google/syzkaller.git repo_url = repo_url.replace('.git', '').rstrip().rstrip('/') actual_repo_name = repo_url.split('/')[-1] return actual_repo_name == expected_repo_name def check_for_commit(repo_path, commit): """Checks a directory for a specific commit. Args: repo_path: The name of the directory to test for the commit. commit: The commit SHA to check for. Returns: True if directory contains that commit. """ # Check if valid git repo. if not os.path.exists(os.path.join(repo_path, '.git')): return False # Check if history fetch is needed. if os.path.exists(os.path.join(repo_path, '.git', 'shallow')): execute(['git', 'fetch', '--unshallow'], location=repo_path) # Check if commit is in history. _, return_code = execute(['git', 'cat-file', '-e', commit], location=repo_path) return return_code == 0 def execute(command, location, check_result=False): """Runs a shell command in the specified directory location. Args: command: The command as a list to be run. location: The directory the command is run in. check_result: Should an exception be thrown on failed command. Returns: The stdout of the command, the error code. Raises: RuntimeError: running a command resulted in an error. """ process = subprocess.Popen(command, stdout=subprocess.PIPE, cwd=location) output, err = process.communicate() if check_result and (process.returncode or err): raise RuntimeError( 'Error: %s\n running command: %s\n return code: %s\n out %s\n' % (err, command, process.returncode, output)) if output is not None: output = output.decode('ascii') return output, process.returncode if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/detect_repo_test.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the functionality of the detect_repo module. This will consist of the following functional test: 1. Determine if an OSS-Fuzz projects main repo can be detected from example commits. 2. Determine if an OSS-Fuzz project main repo can be detected from a repo name. """ import os import re import sys import tempfile import unittest from unittest import mock import detect_repo # Appending to path for access to repo_manager module. # pylint: disable=wrong-import-position sys.path.append( os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__))))) import repo_manager import test_repos # pylint: enable=wrong-import-position class TestCheckForRepoName(unittest.TestCase): """Tests for check_for_repo_name.""" @mock.patch('os.path.exists', return_value=True) @mock.patch('detect_repo.execute', return_value=('https://github.com/google/syzkaller/', None)) def test_go_get_style_url(self, _, __): """Tests that check_for_repo_name works on repos that were downloaded using go get.""" self.assertTrue(detect_repo.check_for_repo_name('fake-path', 'syzkaller')) @mock.patch('os.path.exists', return_value=True) @mock.patch('detect_repo.execute', return_value=('https://github.com/google/syzkaller', None)) def test_missing_git_and_slash_url(self, _, __): """Tests that check_for_repo_name works on repos who's URLs do not end in ".git" or "/".""" self.assertTrue(detect_repo.check_for_repo_name('fake-path', 'syzkaller')) @mock.patch('os.path.exists', return_value=True) @mock.patch('detect_repo.execute', return_value=('https://github.com/google/syzkaller.git', None)) def test_normal_style_repo_url(self, _, __): """Tests that check_for_repo_name works on normally cloned repos.""" self.assertTrue(detect_repo.check_for_repo_name('fake-path', 'syzkaller')) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class DetectRepoIntegrationTest(unittest.TestCase): """Class to test the functionality of the detect_repo module.""" def test_infer_main_repo_from_commit(self): """Tests that the main repo can be inferred based on an example commit.""" with tempfile.TemporaryDirectory() as tmp_dir: # Construct example repo's to check for commits. for test_repo in test_repos.TEST_REPOS: repo_manager.clone_repo_and_get_manager(test_repo.git_url, tmp_dir) self.check_with_repo(test_repo.git_url, test_repo.git_repo_name, tmp_dir, commit=test_repo.old_commit) def test_infer_main_repo_from_name(self): """Tests that the main project repo can be inferred from a repo name.""" with tempfile.TemporaryDirectory() as tmp_dir: for test_repo in test_repos.TEST_REPOS: repo_manager.clone_repo_and_get_manager(test_repo.git_url, tmp_dir) self.check_with_repo(test_repo.git_url, test_repo.git_repo_name, tmp_dir) def check_with_repo(self, repo_origin, repo_name, tmp_dir, commit=None): """Checks the detect repo's main method for a specific set of inputs. Args: repo_origin: URL of the git repo. repo_name: The name of the directory it is cloned to. tmp_dir: The location of the directory of git repos to be searched. commit: The commit that should be used to look up the repo. """ command = ['python3', 'detect_repo.py', '--src_dir', tmp_dir] if commit: command += ['--example_commit', commit] else: command += ['--repo_name', repo_name] out, _ = detect_repo.execute(command, location=os.path.dirname( os.path.realpath(__file__))) match = re.search(r'\bDetected repo: ([^ ]+) ([^ ]+)', out.rstrip()) if match and match.group(1) and match.group(2): self.assertEqual(match.group(1), repo_origin) self.assertEqual(match.group(2), os.path.join(tmp_dir, repo_name)) else: self.assertIsNone(repo_origin) self.assertIsNone(repo_name) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/base-images/base-builder/go_utils.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Adds a fuzzer to a json list stored in $OUT # so we can easily check later if a fuzzer # is a std lib fuzzer add_to_list_of_native_fuzzers() { local new_element="$1" local file="$OUT/native_go_fuzzers.json" if [ -z "$new_element" ]; then echo "Usage: add_to_list \"element to add\"" return 1 fi # Ensure the directory exists if [ ! -d "$(dirname "$file")" ]; then echo "Error: Directory $(dirname "$file") does not exist." return 1 fi # Initialize the file if it doesn't exist or is empty if [ ! -s "$file" ]; then echo "[]" > "$file" fi # Append the new element to the list using jq jq --arg item "$new_element" '. += [$item]' "$file" > "$file.tmp" && mv "$file.tmp" "$file" } # Save a key-value pair to a JSON file. We use this to # store the fuzzer function name with the fuzzer # executable name; we need the function name in the # coverage build. save_function_name() { local key="$1" local value="$2" local file="$3" if [ -z "$key" ] || [ -z "$value" ] || [ -z "$file" ]; then echo "Usage: save_function_name " return 1 fi # If file doesn't exist or is empty, initialize it as empty object if [ ! -s "$file" ]; then echo "{}" > "$file" fi # Update or add the key-value pair jq --arg k "$key" --arg v "$value" '.[$k] = $v' "$file" > "$file.tmp" && mv "$file.tmp" "$file" } function build_native_go_fuzzer_legacy() { fuzzer=$1 function=$2 path=$3 tags="-tags gofuzz" if [[ $SANITIZER == *coverage* ]]; then current_dir=$(pwd) mkdir $OUT/rawfuzzers || true cd $abs_file_dir go test $tags -c -run $fuzzer -o $OUT/$fuzzer -cover cp "${fuzzer_filename}" "${OUT}/rawfuzzers/${fuzzer}" fuzzed_repo=$(go list $tags -f {{.Module}} "$path") abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo` # give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath cd $current_dir else go-118-fuzz-build $tags -o $fuzzer.a -func $function $abs_file_dir $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer fi } function build_native_go_fuzzer() { fuzzer=$1 function=$2 abs_path=$3 package_path=$4 tags="-tags gofuzz" if [[ $SANITIZER == *coverage* ]]; then function_names_file="$OUT/fuzzer_function_names.json" # Save the current dir to return later current_dir=$(pwd) fuzzed_repo=$(go list $tags -f {{.Module}} "$abs_path") cd $abs_file_dir go test $tags \ -c \ -o "$OUT/$fuzzer" \ -coverpkg="$fuzzed_repo/..." \ -covermode=atomic \ "$package_path" save_function_name "$fuzzer" "$function" "$function_names_file" abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo` # give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath add_to_list_of_native_fuzzers "${fuzzer}" # Store the function signature in $OUT/fuzzer-parameters.json # so we can read it when running helper.py coverage. We need # this to convert corpus to a readable format by the test. convertLibFuzzerTestcaseToStdLibGo \ -write-params \ -file $fuzzer_filename \ -fuzzer-func $function \ -fuzzerBinaryName $fuzzer \ -json-out $OUT/fuzzer-parameters.json cd $current_dir else go-118-fuzz-build_v2 $tags -o $fuzzer.a -func $function $abs_file_dir $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer fi } ================================================ FILE: infra/base-images/base-builder/indexer/README.md ================================================ # Indexer snapshot builds This directory provides the tooling to be able to build "indexed" OSS-Fuzz builds, which are snapshots which provide the binary, source code, and a source code index. Snapshots are also built by our infrastructure and available at `gs://clusterfuzz-builds/indexer_indexes`. ## Building project snapshots ```bash python infra/helper.py build_image python infra/helper.py index # Only build snapshots for `target1` and `target2`. python infra/helper.py index --targets 'target1,target2' # Drop into /bin/bash instead of automatically running /opt/indexer/index_build.py. python infra/helper.py index --shell # Add additional docker args. python infra/helper.py index --docker_arg="-eFOO=123" --docker_arg="-eBAR=456" # Pass through flags to the entrypoint. python infra/helper.py index -- --target-args '123' ``` The resulting snapshots will be found in `/build/out/`. ## Development For faster local development on the scripts in this directory, we can mount in everything inside this directory to overwrite the scripts in the base image by passing `--dev` to the index command. If the `indexer` binary does not exist, a prebuilt binary is [downloaded](https://clusterfuzz-builds.storage.googleapis.com/oss-fuzz-artifacts/indexer). ``` cd $OSS_FUZZ_CHECKOUT python infra/helper.py index --dev ``` The resulting snapshots will be found in `/build/out/`. ## Testing We have some basic tests to make sure the snapshots we're generating have the correct format. For this to work, you need to run `python infra/helper.py index --dev ` at least once, or make sure you have the `indexer` binary in this directory. ``` sudo INDEX_BUILD_TESTS=1 python3 -m unittest index_build_test ``` ================================================ FILE: infra/base-images/base-builder/indexer/clang_wrapper.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Compiler Wrapper. This is copied into the OSS-Fuzz container image and run there as part of the instrumentation process. """ from collections.abc import Iterator, MutableSequence, Sequence import contextlib import dataclasses import fcntl import hashlib import json import os from pathlib import Path # pylint: disable=g-importing-member import shlex import shutil import subprocess import sys import time from typing import Any, Iterable, Set import dwarf_info import index_build _LLVM_READELF_PATH = "/usr/local/bin/llvm-readelf" _INDEXER_PATH = "/opt/indexer/indexer" _IGNORED_DEPS_PATH = os.path.join( os.path.dirname(_INDEXER_PATH), "ignored_deps.json" ) _INTERNAL_PATHS = ("/src/llvm-project/",) # When we notice a project using these flags, # we should figure out how to handle them. _DISALLOWED_CLANG_FLAGS = ( "-fdebug-prefix-map=", "-ffile-prefix-map=", ) # Chromium GN builds use these flags with a period to make paths relative to # the out directory. This is OK. _ALLOWED_CLANG_FLAGS_ONLY_WITH_PERIOD = ( "-fdebug-compilation-dir=", "-ffile-compilation-dir=", ) _IGNORED_FILES = ( # This file seems to cause a crash in the indexer, as well as performance # issues. "simdutf.cpp", ) _INDEXER_THREADS_PER_MERGE_QUEUE = 16 _INDEXER_PER_THREAD_MEMORY = 2 * 1024**3 # 2 GiB _CDB_FRAGMENT_DELIMITER = ",\n" SRC = Path(os.getenv("SRC", "/src")) # On OSS-Fuzz build infra, $OUT is not /out. OUT = Path(os.getenv("OUT", "/out")) INDEXES_PATH = Path(os.getenv("INDEXES_PATH", "/indexes")) FUZZER_ENGINE = os.getenv("LIB_FUZZING_ENGINE", "/usr/lib/libFuzzingEngine.a") def _get_available_memory() -> int: """Returns the available memory in bytes.""" with open("/proc/meminfo", "r") as f: for line in f: if line.startswith("MemAvailable:"): return int(line.split()[1]) * 1024 raise RuntimeError("Failed to get available memory") def rewrite_argv0(argv: Sequence[str], clang_toolchain: str) -> list[str]: """Rewrite argv[0] to point to the real clang location.""" # We do this because we've set PATH to our wrapper. rewritten = [os.path.join(clang_toolchain, "bin", os.path.basename(argv[0]))] rewritten.extend(argv[1:]) return rewritten def execute(argv: Sequence[str], clang_toolchain: str) -> None: argv = rewrite_argv0(argv, clang_toolchain) print("About to execute...", argv) os.execv(argv[0], tuple(argv)) def run(argv: Sequence[str], clang_toolchain: str) -> None: argv = rewrite_argv0(argv, clang_toolchain) print("About to run...", argv) ret = subprocess.run(argv, check=False) if ret.returncode != 0: sys.exit(ret.returncode) def sha256(file: Path) -> str: hash_value = hashlib.sha256() with open(file, "rb") as f: # We can't use hashlib.file_digest here because OSS-Fuzz is still on # Python 3.10. for chunk in iter(lambda: f.read(4096), b""): hash_value.update(chunk) return hash_value.hexdigest() def get_flag_value(argv: Sequence[str], flag: str) -> str | None: for i in range(len(argv) - 1): if argv[i] == flag: return argv[i + 1] elif flag == "-o" and argv[i].startswith(flag): return argv[i][2:] return None def remove_flag_if_present(argv: Iterable[str], flag: str) -> list[str]: return [arg for arg in argv if arg != flag] def remove_flag_and_value(argv: list[str], flag: str) -> list[str] | None: """Removes a flag and its value (as a separate token, --a=b not supported.)""" for i in range(len(argv) - 1): if argv[i] == flag: return argv[:i] + argv[i + 2 :] return argv def parse_dependency_file( file_path: Path, output_file: Path, ignored_deps: frozenset[str] ) -> Sequence[str]: """Parses the dependency file generated by the linker.""" output_file = output_file.resolve() with file_path.open("r") as f: lines = [line.strip() for line in f] # The first line should have the format "/path/to/file: \" # Make sure the binary name matches. if output_file.name != Path(lines[0].split(":")[0].strip()).name: raise RuntimeError( f"dependency file has invalid first line: {lines[0]}. " f"Expected to see {output_file.name}." ) deps = [] ignored_dep_paths = ["/usr", "/clang", "/lib"] for line in lines[1:]: if not line: break if line.endswith(" \\"): line = line[:-2] dep = os.path.realpath(line) # We don"t care about system-wide dependencies. if any([True for p in ignored_dep_paths if dep.startswith(p)]): continue if dep in ignored_deps: continue deps.append(dep) return deps def files_by_creation_time(folder_path: Path) -> Sequence[Path]: files = [path for path in folder_path.iterdir() if path.is_file()] files.sort(key=os.path.getctime) return files def _wait_for_cdb_fragment(file: Path) -> Sequence[str]: """Returns the CDB fragment from the given file, waiting if needed.""" num_retries = 3 for i in range(1 + num_retries): data = file.read_text() if data.endswith(_CDB_FRAGMENT_DELIMITER): return data.split(_CDB_FRAGMENT_DELIMITER)[:-1] if i < num_retries: print( f"WARNING: CDB fragment {file} appears to be invalid: {data}, " f"sleeping for 2^{i+1} seconds before retrying.", file=sys.stderr, ) time.sleep(2 ** (i + 1)) else: error = f"CDB fragment {file} is invalid even after retries: {data}" if "test.c" in file.name or "conftest.c" in file.name: # Some build systems seem to have a weird issue where the autotools # generated `test.c` or `conftest.c` for testing compilers doesn't # result in valid cdb fragments. print(f"WARNING: {error}", file=sys.stderr) else: raise RuntimeError(error) return () def read_cdb_fragments(cdb_path: Path) -> Any: """Iterates through the CDB fragments to reconstruct the compile commands.""" files = files_by_creation_time(cdb_path) contents = [] for file in files: # Don't read previously generated linker commands files. if file.name.endswith("_linker_commands.json"): continue if not file.name.endswith(".json"): continue fragments = _wait_for_cdb_fragment(file) contents.extend(fragments) contents = _CDB_FRAGMENT_DELIMITER.join(contents) contents = "[" + contents + "]" return json.loads(contents) def _index_dir_path(output_file: Path) -> Path: """Returns the path to the index directory for the given output binary.""" # This mirrors the absolute path of the output file. absolute_path = (Path(os.getcwd()) / output_file).resolve() return INDEXES_PATH / absolute_path.relative_to("/") def run_indexer( output_file: Path, build_id: str, linker_commands: dict[str, Any], allow_errors: bool = False, ): """Run the indexer.""" # Use a build-specific compile commands directory, since there could be # parallel linking happening at the same time. compile_commands_dir = INDEXES_PATH / f"compile_commands_{build_id}" try: compile_commands_dir.mkdir(exist_ok=False) except FileExistsError: # Somehow we've already seen this link command, don't try to redo the # indexing. # TODO: check if this is the safest behaviour. print( f"WARNING: Compile commands directory {compile_commands_dir} " "already created.", file=sys.stderr, ) return # Indexes can be built incrementally, so use the same directory for each # output binary. index_dir = _index_dir_path(output_file) index_dir.mkdir(parents=True, exist_ok=True) # Symlink by build ID, because `index_build.py` relies on build IDs to match # the binaries (which may have moved around) to indexes. build_id_symlink = INDEXES_PATH / build_id if not build_id_symlink.exists(): os.symlink(index_dir, build_id_symlink) if not linker_commands["compile_commands"]: # Nothing to index. return with (compile_commands_dir / "compile_commands.json").open("wt") as f: json.dump(linker_commands["compile_commands"], f, indent=2) with (compile_commands_dir / "full_compile_commands.json").open("wt") as f: json.dump(linker_commands["full_compile_commands"], f, indent=2) # Auto-tune the number of threads and merge queues according to the number # of cores and available memory. # Note: this might require further tuning -- this might not work well if there # are multiple binaries being linked/indexed at the same time. num_cores = len(os.sched_getaffinity(0)) num_threads = max( 1, min(_get_available_memory() // _INDEXER_PER_THREAD_MEMORY, num_cores) ) merge_queues = max(1, num_threads // _INDEXER_THREADS_PER_MERGE_QUEUE) # TODO: b/447468859 - Use database_only once users are ready. cmd = [ _INDEXER_PATH, "--build_dir", compile_commands_dir, "--index_dir", index_dir.as_posix(), "--source_dir", SRC.as_posix(), "--index_threads", str(num_threads), "--merge_queues", str(merge_queues), ] if (index_dir / "db.sqlite").exists(): cmd.append("--delta") if allow_errors: cmd.append("--ignore_indexing_errors") result = subprocess.run(cmd, check=False, capture_output=True) if result.returncode != 0: raise RuntimeError( "Running indexer failed\n" f"stdout:\n```\n{result.stdout.decode()}\n```\n" f"stderr:\n```\n{result.stderr.decode()}\n```\n" ) def check_fuzzing_engine_and_fix_argv(argv: MutableSequence[str]) -> bool: """Check if this command is linking in a fuzzing engine.""" # Also fix up incorrect link flags so we link in the correct fuzzing # engine. fuzzing_engine_in_argv = False idx = 0 for arg in argv[:]: if arg == "-fsanitize=fuzzer": argv[idx] = "-lFuzzingEngine" fuzzing_engine_in_argv = True elif arg == "-fsanitize=fuzzer-no-link": argv.remove("-fsanitize=fuzzer-no-link") idx -= 1 elif arg.startswith("-fsanitize="): # This could be -fsanitize=address,fuzzer. sanitize_vals = arg.split("=")[1].split(",") if "fuzzer" in sanitize_vals: sanitize_vals.remove("fuzzer") arg = "-fsanitize=" + ",".join(sanitize_vals) fuzzing_engine_in_argv = True elif "fuzzer-no-link" in sanitize_vals: sanitize_vals.remove("fuzzer-no-link") arg = "-fsanitize=" + ",".join(sanitize_vals) argv[idx] = arg if fuzzing_engine_in_argv: idx += 1 argv.insert(idx, "-lFuzzingEngine") idx += 1 if "libFuzzingEngine.a" in arg or "-lFuzzingEngine" in arg: fuzzing_engine_in_argv = True return fuzzing_engine_in_argv def _has_disallowed_clang_flags(argv: Sequence[str]) -> bool: """Checks if the command line arguments contain disallowed flags.""" if any(arg.startswith(_DISALLOWED_CLANG_FLAGS) for arg in argv): return True if any( arg.startswith(_ALLOWED_CLANG_FLAGS_ONLY_WITH_PERIOD) and not arg.endswith("=.") for arg in argv ): return True return False @dataclasses.dataclass(frozen=True) class FilteredCompileCommands: filtered_compile_commands: Sequence[dict[str, str]] unused_cu_paths: Set[Path] unused_cc_paths: Set[Path] def _filter_compile_commands( elf_path: Path, compile_commands: Sequence[dict[str, str]] ) -> FilteredCompileCommands: """Extracts compile commands from the DWARF information of an ELF file. Args: elf_path: The path to the ELF file. compile_commands: The compile commands to filter. Returns: The filtered compile commands. """ compilation_units = dwarf_info.get_all_compilation_units(elf_path) cu_paths = set([Path(cu.compdir) / cu.name for cu in compilation_units]) used_cu_paths = set() filtered_compile_commands = [] unused_cc_paths = set() for compile_command in compile_commands: if ( "-ffile-compilation-dir=." in compile_command["arguments"] or "-fdebug-compilation-dir=." in compile_command["arguments"] ): # Handle build systems that make their debug paths relative. directory = Path(".") else: directory = Path(compile_command["directory"]) cc_path = Path(directory / compile_command["file"]) if cc_path in cu_paths and cc_path.name not in _IGNORED_FILES: filtered_compile_commands.append(compile_command) used_cu_paths.add(cc_path) else: unused_cc_paths.add(cc_path) unused_cu_paths = cu_paths - used_cu_paths return FilteredCompileCommands( filtered_compile_commands=filtered_compile_commands, unused_cu_paths=unused_cu_paths, unused_cc_paths=unused_cc_paths, ) def _write_filter_log( filter_log_file: Path, filtered_compile_commands: FilteredCompileCommands, ) -> None: """Writes the filter log file.""" with open(filter_log_file, "wt") as f: f.write("The following files were not used in the final binary:\n") for cc_path in sorted(filtered_compile_commands.unused_cc_paths): f.write(f"\t{cc_path}\n") f.write( "The following compilation units were not matched with any compile" " commands:\n" ) for cu_path in sorted(filtered_compile_commands.unused_cu_paths): if cu_path.as_posix().startswith(_INTERNAL_PATHS): continue f.write(f"\t{cu_path}\n") def expand_rsp_file(argv: Sequence[str]) -> list[str]: # https://llvm.org/docs/CommandLine.html#response-files expanded = [] for arg in argv: if arg.startswith("@"): with open(arg[1:], "r") as f: expanded_args = shlex.split(f.read()) expanded.extend(expanded_args) else: expanded.append(arg) return expanded def force_optimization_flag(argv: Sequence[str]) -> list[str]: """Forces -O0 in the given argument list.""" args = [] for arg in argv: if arg.startswith("-O") and arg != "-O0": arg = "-O0" args.append(arg) return args def fix_coverage_flags( argv: Sequence[str], expected_coverage_flags: str ) -> list[str]: """Makes sure that the right coverage flags are set.""" args = [] for arg in argv: # Some projects use -fsanitize-coverage-allowlist/ignorelist to optimize # fuzzing feedback. For the indexer case, we would prefer to have all code # instrumented, so we remove these flags. # Some projects hardcode -fsanitize-coverage= options that cause conflicts # with our indexer / tracer options. if (arg.startswith("-fsanitize-coverage-allowlist=") or arg.startswith("-fsanitize-coverage-ignorelist=") or arg.startswith("-fsanitize-coverage=")): continue args.append(arg) args.append(expected_coverage_flags) return args @contextlib.contextmanager def _file_lock(lock_path: Path): """Context manager for acquiring an exclusive file lock.""" fd = os.open(lock_path.as_posix(), os.O_CREAT | os.O_RDWR) fcntl.flock(fd, fcntl.LOCK_EX) try: yield finally: fcntl.flock(fd, fcntl.LOCK_UN) os.close(fd) def merge_incremental_cdb(cdb_path: Path, merged_cdb_path: Path) -> None: """Merges new CDB fragments into the incremental CDB.""" # Map of output file to the path of the file in the incremental CDB. # Use the output file path as the key for merging. existing_output_files: dict[Path, Path] = {} def load_cdbs(directory: Path) -> Iterator[tuple[Path, dict[str, Any]]]: for file in directory.iterdir(): if file.suffix != ".json": continue if file.name.endswith("_linker_commands.json"): continue fragments_data = _wait_for_cdb_fragment(file) for fragment_data in fragments_data: fragment = json.loads(fragment_data) if "output" not in fragment: continue yield file, fragment # We could be running multiple linking steps in parallel, so serialize merges. with _file_lock(merged_cdb_path / ".lock"): # Load existing CDB fragments, and build the map of output file -> fragment. for file, fragment in load_cdbs(merged_cdb_path): output_path = Path(fragment["directory"]) / fragment["output"] existing_output_files[output_path] = file # Load new CDB fragments, replacing existing fragments for the same output # file. for file, fragment in load_cdbs(cdb_path): output_path = Path(fragment["directory"]) / fragment["output"] if output_path in existing_output_files: # Remove existing entry for the output file. os.unlink(existing_output_files[output_path]) del existing_output_files[output_path] shutil.copy2(file, merged_cdb_path / file.name) def main(argv: list[str]) -> None: compile_settings = index_build.read_compile_settings() argv = expand_rsp_file(argv) argv = remove_flag_if_present(argv, "-gline-tables-only") argv = force_optimization_flag(argv) argv = fix_coverage_flags(argv, compile_settings.coverage_flags) if _has_disallowed_clang_flags(argv): raise ValueError("Disallowed clang flags found, aborting.") # TODO: b/441872725 - Migrate more flags to be appended in the clang wrapper # instead. cdb_path = index_build.OUT / "cdb" argv.extend(("-gen-cdb-fragment-path", cdb_path.as_posix())) argv.extend(( "-isystem", ( f"{compile_settings.clang_toolchain}/lib/clang/" f"{compile_settings.clang_version}" ), "-resource-dir", ( f"{compile_settings.clang_toolchain}/lib/clang/" f"{compile_settings.clang_version}" ), )) if "-E" in argv: # Preprocessor-only invocation. modified_argv = remove_flag_and_value(argv, "-gen-cdb-fragment-path") execute(modified_argv, compile_settings.clang_toolchain) fuzzing_engine_in_argv = check_fuzzing_engine_and_fix_argv(argv) indexer_targets: list[str] = [ t for t in os.getenv("INDEXER_TARGETS", "").split(",") if t ] # If we are linking, collect the relevant flags and dependencies. output_file = get_flag_value(argv, "-o") if not output_file: execute(argv, compile_settings.clang_toolchain) # Missing output file output_file = Path(output_file) if output_file.name.endswith(".o"): execute(argv, compile_settings.clang_toolchain) # Not a real linker command if indexer_targets: if output_file.name not in indexer_targets: # Not a relevant linker command print(f"Not indexing as {output_file} is not in the allowlist") execute(argv, compile_settings.clang_toolchain) elif not fuzzing_engine_in_argv: # Not a fuzz target. execute(argv, compile_settings.clang_toolchain) print(f"Linking {argv}") # We can now run the linker and look at the output of some files. dependency_file = (cdb_path / output_file.name).with_suffix(".deps") why_extract_file = (cdb_path / output_file.name).with_suffix(".why_extract") argv.append("-fuse-ld=lld") argv.append(f"-Wl,--dependency-file={dependency_file}") argv.append(f"-Wl,--why-extract={why_extract_file}") argv.append("-Wl,--build-id") # We force lld, but it doesn't include this dir by default. argv.append("-L/usr/local/lib") argv.append("-Qunused-arguments") if compile_settings.coverage_flags == index_build.TRACING_COVERAGE_FLAGS: argv.append("/opt/indexer/coverage.o") run(argv, compile_settings.clang_toolchain) build_id = index_build.get_build_id(output_file) assert build_id is not None output_hash = sha256(output_file) with open(_IGNORED_DEPS_PATH) as f: ignored_deps = frozenset(json.load(f)["deps"]) deps = parse_dependency_file(dependency_file, output_file, ignored_deps) obj_deps = [dep for dep in deps if dep.endswith(".o")] ar_deps = [dep for dep in deps if dep.endswith(".a") and dep != FUZZER_ENGINE] archive_deps = [] for archive in ar_deps: res = subprocess.run(["ar", "-t", archive], capture_output=True, check=True) archive_deps += [dep.decode() for dep in res.stdout.splitlines()] # Incremental index building relies on merging all new compilation fragments # since the initial indexing. cdb_fragments_dir = cdb_path if _index_dir_path(output_file).exists(): merge_incremental_cdb(cdb_path, index_build.INCREMENTAL_CDB_PATH) cdb_fragments_dir = index_build.INCREMENTAL_CDB_PATH # We only care about the compile commands that emitted an output file. full_compile_commands = [ cc for cc in read_cdb_fragments(cdb_fragments_dir) if "output" in cc ] # Discard compile commands that didn't end up in the final binary. filtered_compile_commands = _filter_compile_commands( output_file, full_compile_commands ) linker_commands = { "output": output_file.as_posix(), "directory": os.getcwd(), "deps": obj_deps + archive_deps, "args": argv, "sha256": output_hash, "gnu_build_id": build_id, "compile_commands": filtered_compile_commands.filtered_compile_commands, "full_compile_commands": full_compile_commands, } filter_log_file = Path(cdb_path) / f"{build_id}_filter_log.txt" _write_filter_log(filter_log_file, filtered_compile_commands) if not os.getenv("INDEXER_BINARIES_ONLY"): is_custom_toolchain = ( compile_settings.clang_toolchain != index_build.DEFAULT_CLANG_TOOLCHAIN ) run_indexer( output_file, build_id, linker_commands, allow_errors=is_custom_toolchain ) linker_commands = json.dumps(linker_commands) commands_path = Path(cdb_path) / f"{build_id}_linker_commands.json" commands_path.write_text(linker_commands) if __name__ == "__main__": main(sys.argv) ================================================ FILE: infra/base-images/base-builder/indexer/clang_wrapper_test.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """clang_wrapper tests.""" import json import pathlib import clang_wrapper import unittest class ClangWrapperTest(unittest.TestCase): def test_force_optimization_flag_no_optimization(self): """Tests that optimization flags are not forced when not present.""" argv = ["clang", "-c", "test.c", "-o", "test.o"] modified_argv = clang_wrapper.force_optimization_flag(argv) self.assertCountEqual(modified_argv, argv) def test_force_optimization_flag(self): """Tests that optimization flags are forced when present.""" argv = ["clang", "-O2", "-c", "test.c", "-o", "test.o", "-O1"] modified_argv = clang_wrapper.force_optimization_flag(argv) self.assertCountEqual( modified_argv, ["clang", "-O0", "-c", "test.c", "-o", "test.o", "-O0"] ) def test_remove_invalid_coverage_flags(self): """Tests that invalid coverage flags are removed.""" argv = [ "clang", "-foo", "-fsanitize-coverage-allowlist=allowlist", "-fsanitize-coverage-ignorelist=ignorelist", "-fsanitize-coverage=edge", "-c", "test.c", ] modified_argv = clang_wrapper.fix_coverage_flags( argv, "-fsanitize-coverage=bb,no-prune,trace-pc-guard" ) self.assertCountEqual( modified_argv, [ "clang", "-foo", "-c", "test.c", "-fsanitize-coverage=bb,no-prune,trace-pc-guard", ], ) def test_merge_incremental_cdb(self): """Tests that incremental cdb is merged correctly.""" cdb_path = pathlib.Path(self.create_tempdir().full_path) merged_cdb_path = pathlib.Path(self.create_tempdir().full_path) old_cdb_fragments = { "test.c.123.json": { "directory": "/build", "file": "test.c", "output": "test.o", "arguments": ["-c", "test.c"], }, "test.c.455.json": { "directory": "/build/subdir", "file": "test.c", "output": "test.o", "arguments": ["-c", "test.c"], }, "foo.c.455.json": { "directory": "/build", "file": "foo.c", "output": "foo.o", "arguments": ["-c", "foo.c"], }, "foo.123_linker_commands.json": {"invalid": "foo"}, } new_cdb_fragments = { "test.c.aaa.json": [{ "directory": "/build/subdir", "file": "test.c", "output": "test.o", "arguments": ["-c", "test.c"], }], "bar.c.bbb.json": [ { "directory": "/build/subdir", "file": "bar.c", "output": "bar.o", "arguments": ["-c", "bar.c"], }, { "directory": "/build/subdir", "file": "bar2.c", "output": "bar2.o", "arguments": ["-c", "bar2.c"], }, ], } for cdb_fragment_path, cdb_fragment in old_cdb_fragments.items(): suffix = ( ",\n" if not cdb_fragment_path.endswith("_linker_commands.json") else "" ) (merged_cdb_path / cdb_fragment_path).write_text( json.dumps(cdb_fragment) + suffix ) for cdb_fragment_path, cdb_fragment in new_cdb_fragments.items(): (cdb_path / cdb_fragment_path).write_text( ",\n".join([json.dumps(frag) for frag in cdb_fragment]) + ",\n" ) (cdb_path / "not_a_json").write_text("not a json") clang_wrapper.merge_incremental_cdb(cdb_path, merged_cdb_path) self.assertCountEqual( merged_cdb_path.iterdir(), [ pathlib.Path(merged_cdb_path) / ".lock", pathlib.Path(merged_cdb_path) / "test.c.123.json", pathlib.Path(merged_cdb_path) / "test.c.aaa.json", pathlib.Path(merged_cdb_path) / "foo.c.455.json", pathlib.Path(merged_cdb_path) / "foo.123_linker_commands.json", pathlib.Path(merged_cdb_path) / "bar.c.bbb.json", ], ) def test_merge_incremental_cdb_duplicate_outputs(self): """Tests that incremental cdb is merged correctly with duplicate outputs.""" cdb_path = pathlib.Path(self.create_tempdir().full_path) merged_cdb_path = pathlib.Path(self.create_tempdir().full_path) fragment1 = { "directory": "/build", "file": "test.c", "output": "test.o", } (merged_cdb_path / "1.json").write_text(json.dumps(fragment1) + ",\n") fragment2 = { "directory": "/build", "file": "test.c", "output": "test.o", } (cdb_path / "2.json").write_text(json.dumps(fragment2) + ",\n") (cdb_path / "3.json").write_text(json.dumps(fragment2) + ",\n") clang_wrapper.merge_incremental_cdb(cdb_path, merged_cdb_path) self.assertCountEqual( merged_cdb_path.iterdir(), [ merged_cdb_path / ".lock", merged_cdb_path / "2.json", merged_cdb_path / "3.json", ], ) self.assertFalse((merged_cdb_path / "1.json").exists()) if __name__ == "__main__": unittest.main() ================================================ FILE: infra/base-images/base-builder/indexer/coverage.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include #include namespace { constexpr int kMaxTraceSize = 64 * 1024; struct CoverageData { void* pcs[kMaxTraceSize]; size_t idx; // TODO: b/441647761 - Handle multiple threads. pid_t main_thread_id; bool finished; }; static CoverageData* coverage_data; bool IsStandardLibrary(const char* file_path) { return (strstr(file_path, "include/c++/v1") || strstr(file_path, "src/libcxx/include") || strstr(file_path, "src/libcxx/staging/include") || strncmp(file_path, "/usr/include", 12) == 0 || strstr(file_path, "libc++/src/include") || strstr(file_path, "/absl/")); } void WriteTrace() { coverage_data->finished = true; char* trace_dump_file = getenv("TRACE_DUMP_FILE"); if (!trace_dump_file) { return; } int fd = open(trace_dump_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } // TODO: b/441647761 - This format likely needs iteration. This just prints // symbolized function names, but this could still be ambiguous. for (size_t i = 0; i < coverage_data->idx; ++i) { char symbol[1024]; char file_path[1024]; // This always null terminates. __sanitizer_symbolize_pc(coverage_data->pcs[i], "%f", symbol, sizeof(symbol)); __sanitizer_symbolize_pc(coverage_data->pcs[i], "%s", file_path, sizeof(file_path)); if (IsStandardLibrary(file_path)) continue; write(fd, symbol, strlen(symbol)); write(fd, "\n", 1); } close(fd); } pid_t GetTID() { return static_cast(syscall(SYS_gettid)); } void Init() { coverage_data = static_cast(malloc(sizeof(CoverageData))); coverage_data->finished = false; coverage_data->idx = 0; // For now, only record PCs from the main thread. coverage_data->main_thread_id = GetTID(); // Dump coverage on exit. atexit(WriteTrace); __sanitizer_set_death_callback(WriteTrace); } } // namespace extern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) { Init(); static uint32_t N; // Counter for the guards. if (start == stop || *start) return; for (uint32_t* x = start; x < stop; x++) *x = ++N; } extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { thread_local bool in_callback = false; if (!coverage_data || coverage_data->finished) return; if (*guard == 0) return; if (in_callback) return; in_callback = true; class ResetInCallback { public: ~ResetInCallback() { in_callback = false; } } reset_in_callback; thread_local pid_t thread_id = GetTID(); if (thread_id != coverage_data->main_thread_id) { return; } if (coverage_data->idx >= kMaxTraceSize) { return; } *guard = 0; // Don't trace the same PC more than once. coverage_data->pcs[coverage_data->idx++] = reinterpret_cast(__builtin_return_address(0)); } ================================================ FILE: infra/base-images/base-builder/indexer/dwarf_info.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """DWARF info parser for ELF files.""" import dataclasses import io import os from typing import Sequence from absl import logging from elftools.elf import elffile _IGNORED_UNIT_TYPES = ("DW_UT_type", "DW_UT_split_type") @dataclasses.dataclass class CompilationUnit: """Represents a DWARF compilation unit. Attributes: producer: The producer of the compilation unit. name: The name of the compilation unit. compdir: The compilation directory of the compilation unit. language: The language of the compilation unit. apple_flags: Flags used in the compilation unit (if compiled with `-glldb`). isysroot: The isysroot of the compilation unit. """ producer: str name: str compdir: str language: int apple_flags: str | None isysroot: str | None def get_all_compilation_units( elf_file_path: os.PathLike[str], ) -> list[CompilationUnit]: """Parses compilation units from an ELF file. Args: elf_file_path: The path to the ELF file. Returns: A list of CompilationUnit objects. """ result = [] with open(elf_file_path, "rb") as f: elf_file = elffile.ELFFile(f) if not elf_file.has_dwarf_info(): logging.error("No DWARF info found in %s", elf_file_path) return [] dwarf_info = elf_file.get_dwarf_info() for compilation_unit in dwarf_info.iter_CUs(): if compilation_unit.header.version < 5: # Only DWARF5 has a unit_type field in the header. # For older versions, we do a best effort approach. logging.warning( "[!] Compilation Unit with unsupported DWARF version %d", compilation_unit.header.version, ) elif compilation_unit.header.unit_type in _IGNORED_UNIT_TYPES: # Type units are not interesting for us. continue elif compilation_unit.header.unit_type not in ( "DW_UT_compile", "DW_UT_partial", ): raise ValueError( "Unsupported DWARF compilation unit type" f" {compilation_unit.header.unit_type}" ) top_debug_info_entry = compilation_unit.get_top_DIE() if top_debug_info_entry.tag != "DW_TAG_compile_unit": logging.error("Top DIE is not a full compile unit") producer = top_debug_info_entry.attributes[ "DW_AT_producer" ].value.decode() name = top_debug_info_entry.attributes["DW_AT_name"].value.decode() language = top_debug_info_entry.attributes["DW_AT_language"].value compdir = top_debug_info_entry.attributes["DW_AT_comp_dir"].value.decode() # When using `-glldb`, the compile flags are stored # in the DW_AT_APPLE_flags attribute apple_flags = None if top_debug_info_entry.attributes.get("DW_AT_APPLE_flags", None): apple_flags = top_debug_info_entry.attributes[ "DW_AT_APPLE_flags" ].value.decode() isysroot = None if top_debug_info_entry.attributes.get("DW_AT_LLVM_isysroot", None): isysroot = top_debug_info_entry.attributes[ "DW_AT_LLVM_isysroot" ].value.decode() result.append( CompilationUnit( producer=producer, name=name, compdir=compdir, language=language, apple_flags=apple_flags, isysroot=isysroot, ) ) return result def parse_clang_record_command_line_value(command: str) -> Sequence[str]: """Parses the value of a `-frecord-command-line` entry from clang. Separate arguments within a command line are combined with spaces. Spaces and backslashes within an argument are escaped with backslashes. Args: command: The command line string to split. Returns: A sequence of strings, each representing a single argument. Raises: ValueError: If the command line contains an invalid escape sequence. ValueError: If the command line contains an empty argument. """ value = io.StringIO(command) args = [] current_arg = "" while True: c = value.read(1) match c: case "": # We found the end of the string. break case "\\": # We found a backslash, the next character should be either a space or # another backslash. c = value.read(1) if c not in (" ", "\\"): raise ValueError(f"Invalid Escape Sequence: \\{c}") current_arg += c case " ": # unescaped spaces separate arguments. if not current_arg: raise ValueError("Arguments should not be empty.") args.append(current_arg) current_arg = "" case _: # Anything else is part of the current argument. current_arg += c if not current_arg: raise ValueError("Last argument should not be empty.") args.append(current_arg) return args ================================================ FILE: infra/base-images/base-builder/indexer/dwarf_info_diff.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Diffs compile commands generated via DWARF info and compilation databases.""" import collections from collections.abc import Sequence import json import pathlib from absl import app from absl import flags from absl import logging import dwarf_info _BINARY_PATH = flags.DEFINE_string( "binary_path", None, "Path to the binary file.", required=True ) _COMPILE_COMMANDS_PATH = flags.DEFINE_string( "compile_commands_path", None, "Path to the compile commands file.", required=True, ) def main(argv: Sequence[str]) -> None: if len(argv) > 1: raise app.UsageError("Too many command-line arguments.") binary_path = pathlib.Path(_BINARY_PATH.value) compilation_units = dwarf_info.get_all_compilation_units(binary_path) logging.info("Found %d compilation units.", len(compilation_units)) # Question 1: Do we have repeated CU names in the binary? cu_files = collections.Counter([cu.name for cu in compilation_units]) logging.info("Most Common CU names: %s", cu_files.most_common(1)) libs = binary_path.parent / "lib" for lib in libs.iterdir(): new_cus = dwarf_info.get_all_compilation_units(lib) logging.info("Found %d compilation units in %s", len(new_cus), lib) compilation_units.extend(new_cus) with open(_COMPILE_COMMANDS_PATH.value, "r") as f: compile_commands = json.load(f) # Question 2: Do we have repeated files in the compile commands? cc_files = collections.Counter([cc["file"] for cc in compile_commands]) logging.info("Most Common commands files: %s", cc_files.most_common(1)) cc_files = set(cc_files) cu_files = set(cu_files) for file in cc_files - cu_files: logging.info("File not found in CU: %s", file) for file in cu_files - cc_files: logging.info("File not found in CC: %s", file) for file in cu_files.intersection(cc_files): logging.info("File found in both: %s", file) if __name__ == "__main__": app.run(main) ================================================ FILE: infra/base-images/base-builder/indexer/fuzzing_engine.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t n); extern "C" __attribute__((weak)) int LLVMFuzzerInitialize(int* argc, char*** argv); // Projects can call LLVMFuzzerMutate, but should only do it from // LLVMFuzzerCustomMutator, which should be called from the fuzzing engine (we // don't need to). extern "C" size_t LLVMFuzzerMutate([[maybe_unused]] uint8_t* Data, [[maybe_unused]] size_t Size, [[maybe_unused]] size_t MaxSize) { fprintf(stderr, "LLVMFuzzerMutate was called. This should never happen.\n"); __builtin_trap(); } int main(int argc, char* argv[]) { if (LLVMFuzzerInitialize) { LLVMFuzzerInitialize(&argc, &argv); } if (argc != 2) { // Special-case because curl invokes the fuzzer binaries without arguments // during make, and will fail if they don't return success. if (strstr(argv[0], "curl_fuzzer")) { fprintf(stderr, "Exiting early for curl_fuzzer\n"); exit(EXIT_SUCCESS); } fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } int fd = open(argv[1], O_RDONLY); if (fd == -1) { perror("open"); exit(EXIT_FAILURE); } struct stat st; if (fstat(fd, &st) == -1) { perror("stat"); exit(EXIT_FAILURE); } size_t size = static_cast(st.st_size); uint8_t* data = static_cast(malloc(size)); if (!data) { perror("malloc"); exit(EXIT_FAILURE); } size_t bytes_read = 0; while (bytes_read < size) { ssize_t res = read(fd, data + bytes_read, size - bytes_read); if (res == -1) { perror("read"); exit(EXIT_FAILURE); } if (res == 0) { fprintf(stderr, "Unexpected EOF.\n"); exit(EXIT_FAILURE); } bytes_read += static_cast(res); } close(fd); int res = LLVMFuzzerTestOneInput(data, size); free(data); return res; } ================================================ FILE: infra/base-images/base-builder/indexer/ignored_deps.json ================================================ { "deps" : [ ] } ================================================ FILE: infra/base-images/base-builder/indexer/index_build.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """This runs the actual build process to generate a snapshot.""" import argparse import dataclasses import hashlib import json import logging import os import pathlib from pathlib import Path # pylint: disable=g-importing-member import shlex import shutil import stat import subprocess import tempfile from typing import Any, Sequence import manifest_types import pathlib PROJECT = Path(os.getenv('PROJECT_NAME', 'project')).name SNAPSHOT_DIR = Path('/snapshot') SRC = Path(os.getenv('SRC', '/src')) # On OSS-Fuzz build infra, $OUT is not /out. OUT = Path(os.getenv('OUT', '/out')) INDEXES_PATH = Path(os.getenv('INDEXES_PATH', '/indexes')) INCREMENTAL_CDB_PATH = Path('/incremental_cdb') _GCC_BASE_PATH = Path('/usr/lib/gcc/x86_64-linux-gnu') _LD_BINARY = 'ld-linux-x86-64.so.2' _LD_PATH = Path('/lib64') / _LD_BINARY _DEFAULT_GCC_VERSION = '9' _LLVM_READELF_PATH = '/usr/local/bin/llvm-readelf' DEFAULT_COVERAGE_FLAGS = '-fsanitize-coverage=bb,no-prune,trace-pc-guard' TRACING_COVERAGE_FLAGS = '-fsanitize-coverage=func,trace-pc-guard' DEFAULT_FUZZING_ENGINE = 'fuzzing_engine.cc' DEFAULT_CLANG_TOOLCHAIN = '/usr/local' _CLANG_TOOLCHAIN = Path(os.getenv('CLANG_TOOLCHAIN', DEFAULT_CLANG_TOOLCHAIN)) _TOOLCHAIN_WITH_WRAPPER = Path('/opt/toolchain') INDEXER_DIR = Path(__file__).parent # Some build systems isolate the compiler environment from the parent process, # so we can't always rely on using environment variables to pass settings to the # wrapper. Get around this by writing to a file instead. COMPILE_SETTINGS_PATH = INDEXER_DIR / 'compile_settings.json' CLANG_TOOLCHAIN_BINARY_PREFIXES = ( 'clang-', 'ld', 'lld', 'llvm-', ) EXTRA_CFLAGS = ( '-fno-omit-frame-pointer ' '-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ' '-O0 -glldb ' '-fsanitize=address ' '-Wno-invalid-offsetof ' '{coverage_flags} ' '-Qunused-arguments ' ) @dataclasses.dataclass(slots=True, frozen=True) class CompileSettings: coverage_flags: str clang_toolchain: str clang_version: str def read_compile_settings() -> CompileSettings: """Gets compile settings from file.""" with COMPILE_SETTINGS_PATH.open('r') as f: settings_dict = json.load(f) return CompileSettings(**settings_dict) def write_compile_settings(compile_settings: CompileSettings) -> None: """Writes compile settings to file.""" with COMPILE_SETTINGS_PATH.open('w') as f: json.dump(dataclasses.asdict(compile_settings), f) def set_env_vars(coverage_flags: str): """Set up build environment variables.""" os.environ['SANITIZER'] = 'address' # Prevent ASan leak checker from running on `configure` script targets. # At the time of writing, this helps prevent a slowdown in `hunspell` build. os.environ['ASAN_OPTIONS'] = 'detect_leaks=0' os.environ['FUZZING_ENGINE'] = 'none' os.environ['LIB_FUZZING_ENGINE'] = '/usr/lib/libFuzzingEngine.a' os.environ['FUZZING_LANGUAGE'] = 'c++' os.environ['CXX'] = 'clang++' os.environ['CC'] = 'clang' os.environ['COMPILING_PROJECT'] = 'True' # Force users of clang to use our wrapper. This fixes e.g. libcups. os.environ['PATH'] = ( f"{_TOOLCHAIN_WITH_WRAPPER / 'bin'}:{os.environ.get('PATH')}" ) existing_cflags = os.environ.get('CFLAGS', '') extra_cflags = EXTRA_CFLAGS.format(coverage_flags=coverage_flags) os.environ['CFLAGS'] = f'{existing_cflags} {extra_cflags}'.strip() def set_up_wrapper_dir(): """Sets up a shadow toolchain. This sets up our clang wrapper for clang/clang++ and symlinks everything else to point to the real toolchain. """ if _TOOLCHAIN_WITH_WRAPPER.exists(): shutil.rmtree(_TOOLCHAIN_WITH_WRAPPER) _TOOLCHAIN_WITH_WRAPPER.mkdir(parents=True) # Set up symlinks to toolchain binaries. wrapper_bin_dir = _TOOLCHAIN_WITH_WRAPPER / 'bin' wrapper_bin_dir.mkdir() for name in os.listdir(_CLANG_TOOLCHAIN / 'bin'): # Symlink clang/llvm toolchain binaries, except for clang itself. # We have to be careful not to symlink other unrelated binaries, since other # parts of the build process may wrap those binaries (e.g. # make_build_replayable.py in OSS-Fuzz). if not name.startswith(CLANG_TOOLCHAIN_BINARY_PREFIXES): continue os.symlink(_CLANG_TOOLCHAIN / 'bin' / name, wrapper_bin_dir / name) os.symlink(_CLANG_TOOLCHAIN / 'lib', _TOOLCHAIN_WITH_WRAPPER / 'lib') # Set up our compiler wrappers. os.symlink(INDEXER_DIR / 'clang_wrapper.py', wrapper_bin_dir / 'clang') os.symlink(INDEXER_DIR / 'clang_wrapper.py', wrapper_bin_dir / 'clang++') @dataclasses.dataclass(slots=True, frozen=True) class BinaryMetadata: binary_config: manifest_types.CommandLineBinaryConfig build_id: str build_id_matches: bool compile_commands: list[dict[str, Any]] def _get_build_id_from_elf_notes(elf_file: Path, contents: bytes) -> str | None: """Extracts the build id from the ELF notes of a binary. The ELF notes are obtained with `llvm-readelf --notes --elf-output-style=JSON`. Args: elf_file: The ELF file name. contents: The contents of the ELF notes, as a JSON string. Returns: The build id, or None if it could not be found. """ try: elf_data = json.loads(contents) except json.JSONDecodeError: logging.error('failed to decode ELF notes for %s', elf_file) return None assert elf_data # Example output of llvm-readelf JSON output for llvm 19+: # [ # { # "FileSummary": { # "File": "binary", # "Format": "elf64-x86-64", # "Arch": "x86_64", # "AddressSize": "64bit", # "LoadName": "" # }, # "NoteSections": [ # { # "NoteSection": { # "Name": ".note.gnu.property", # "Offset": 904, # "Size": 32, # "Notes": [ # { # "Owner": "GNU", # "Data size": 16, # "Type": "NT_GNU_PROPERTY_TYPE_0 (property note)", # "Property": [ # "x86 ISA needed: x86-64-baseline" # ] # } # ] # } # }, # { # "NoteSection": { # "Name": ".note.gnu.build-id", # "Offset": 936, # "Size": 36, # "Notes": [ # { # "Owner": "GNU", # "Data size": 20, # "Type": "NT_GNU_BUILD_ID (unique build ID bitstring)", # "Build ID": "182a06c3dca5ee4d7e9c1d94b432c8bd9279438f" # } # ] # } # }, # { # "NoteSection": { # "Name": ".note.ABI-tag", # "Offset": 1630064, # "Size": 32, # "Notes": [ # { # "Owner": "GNU", # "Data size": 16, # "Type": "NT_GNU_ABI_TAG (ABI version tag)", # "OS": "Linux", # "ABI": "3.2.0" # } # ] # } # } # ] # } # ] for file_info in elf_data: if 'Notes' in file_info: # llvm < 19 for note_entry in file_info['Notes']: note_section = note_entry['NoteSection'] if note_section['Name'] == '.note.gnu.build-id': note_details = note_section['Note'] if 'Build ID' in note_details: return note_details['Build ID'] elif 'NoteSections' in file_info: # llvm 19+ for note_entry in file_info['NoteSections']: note_section = note_entry['NoteSection'] if note_section['Name'] == '.note.gnu.build-id': note_details = note_section['Notes'] for note_detail in note_details: if 'Build ID' in note_detail: return note_detail['Build ID'] else: raise ValueError('Unknown ELF notes format.') return None def _get_clang_version(toolchain: Path) -> str: """Returns the clang version.""" clang = toolchain / 'bin' / 'clang' clang_version = subprocess.run( [clang, '-dumpversion'], capture_output=True, check=True, text=True ).stdout return clang_version.split('.')[0] def get_build_id(elf_file: Path) -> str | None: """This invokes llvm-readelf to get the build ID of the given ELF file.""" ret = subprocess.run( [ _LLVM_READELF_PATH, '--notes', '--elf-output-style=JSON', elf_file.as_posix(), ], capture_output=True, check=False, ) if ret.returncode != 0: return None return _get_build_id_from_elf_notes(elf_file, ret.stdout) def find_fuzzer_binaries(out_dir: Path, build_id: str) -> Sequence[Path]: """Find fuzzer binary with a given build ID.""" binaries = [] for root, _, files in os.walk(out_dir): for file in files: file_path = Path(root, file) if get_build_id(file_path) == build_id: binaries.append(file_path) return binaries def enumerate_build_targets( binary_config: manifest_types.CommandLineBinaryConfig, ) -> Sequence[BinaryMetadata]: """Enumerates the build targets in the project. Args: binary_config: The binary config applied to all targets. Returns: A sequence of target descriptions, in BinaryMetadata form. """ logging.info('enumerate_build_targets') linker_json_paths = list((OUT / 'cdb').glob('*_linker_commands.json')) logging.info('Found %i linker JSON files.', len(linker_json_paths)) binary_to_build_metadata: dict[str, BinaryMetadata] = {} for linker_json_path in linker_json_paths: build_id = linker_json_path.name.split('_')[0] with linker_json_path.open('rt') as f: data = json.load(f) binary_path = Path(data['output']) name = binary_path.name # Some projects may move build files around, so being more careful about # the binary path and checking the build id should improve the success # rate. if (OUT / name).exists(): # Just because the name matches, doesn't mean it's the right one for # this linker command. # Only set this if we haven't already found an exact build ID match. # We can't always rely on build ID matching, because some builds will # modify the binary after the linker runs. if ( name in binary_to_build_metadata and binary_to_build_metadata[name].build_id_matches ): continue build_id_matches = build_id == get_build_id(binary_path) target_binary_config = manifest_types.CommandLineBinaryConfig( **dict(binary_config.to_dict(), binary_name=name) ) binary_to_build_metadata[name] = BinaryMetadata( binary_config=target_binary_config, compile_commands=data['compile_commands'], build_id=build_id, build_id_matches=build_id_matches, ) else: logging.info('trying to find %s with build id %s', name, build_id) binary_paths = find_fuzzer_binaries(OUT, build_id) logging.info('found matching binaries: %s', binary_paths) if not binary_paths: logging.error('could not find %s with build id %s', name, build_id) continue for binary_path in binary_paths: compile_commands = data['compile_commands'] target_binary_config = manifest_types.CommandLineBinaryConfig( **dict(binary_config.to_dict(), binary_name=binary_path.name) ) binary_to_build_metadata[binary_path.name] = BinaryMetadata( binary_config=target_binary_config, compile_commands=compile_commands, build_id=build_id, build_id_matches=True, ) return tuple(binary_to_build_metadata.values()) def copy_fuzzing_engine(fuzzing_engine: str) -> Path: """Copy fuzzing engine.""" # Not every project saves source to $SRC/$PROJECT_NAME fuzzing_engine_dir = SRC / PROJECT if not fuzzing_engine_dir.exists(): fuzzing_engine_dir = SRC / 'fuzzing_engine' fuzzing_engine_dir.mkdir(exist_ok=True) shutil.copy(f'/opt/indexer/{fuzzing_engine}', fuzzing_engine_dir) return fuzzing_engine_dir def _get_latest_gcc_version() -> str: """Finds the latest GCC version installed. Defaults to '9' for backward compatibility if detection fails. Returns: The latest GCC version found, or the default. """ if _GCC_BASE_PATH.exists(): versions = [] for d in _GCC_BASE_PATH.iterdir(): if d.is_dir() and d.name.isdigit(): versions.append(int(d.name)) if versions: return str(max(versions)) return _DEFAULT_GCC_VERSION def build_project( targets_to_index: Sequence[str] | None = None, compile_args: Sequence[str] | None = None, binaries_only: bool = False, coverage_flags: str = DEFAULT_COVERAGE_FLAGS, ): """Build the actual project.""" set_env_vars(coverage_flags) if targets_to_index: os.environ['INDEXER_TARGETS'] = ','.join(targets_to_index) if binaries_only: os.environ['INDEXER_BINARIES_ONLY'] = '1' clang_version = _get_clang_version(_CLANG_TOOLCHAIN) write_compile_settings( CompileSettings( coverage_flags=coverage_flags, clang_toolchain=_CLANG_TOOLCHAIN.as_posix(), clang_version=clang_version, ) ) fuzzing_engine_dir = copy_fuzzing_engine(DEFAULT_FUZZING_ENGINE) gcc_version = _get_latest_gcc_version() build_fuzzing_engine_command = [ f'{_CLANG_TOOLCHAIN}/bin/clang++', '-c', '-Wall', '-Wextra', '-pedantic', '-std=c++20', '-fno-rtti', '-fno-exceptions', '-glldb', '-O0', (fuzzing_engine_dir / DEFAULT_FUZZING_ENGINE).as_posix(), '-o', f'{OUT}/fuzzing_engine.o', '-gen-cdb-fragment-path', f'{OUT}/cdb', '-Qunused-arguments', f'-isystem {_CLANG_TOOLCHAIN}/lib/clang/{clang_version}', f'/usr/lib/gcc/x86_64-linux-gnu/{gcc_version}/../../../../include/c++/{gcc_version}', '-I', f'/usr/lib/gcc/x86_64-linux-gnu/{gcc_version}/../../../../include/x86_64-linux-gnu/c++/{gcc_version}', '-I', f'/usr/lib/gcc/x86_64-linux-gnu/{gcc_version}/../../../../include/c++/{gcc_version}/backward', '-I', f'{_CLANG_TOOLCHAIN}/lib/clang/{clang_version}/include', '-I', f'{_CLANG_TOOLCHAIN}/include', '-I', '/usr/include/x86_64-linux-gnu', '-I', '/usr/include', ] subprocess.run(build_fuzzing_engine_command, check=True, cwd='/opt/indexer') build_cov_instrumentation_command = [ f'{_CLANG_TOOLCHAIN}/bin/clang++', '-fno-rtti', '-fno-exceptions', '-c', '/opt/indexer/coverage.cc', ] subprocess.run( build_cov_instrumentation_command, check=True, cwd='/opt/indexer' ) ar_cmd = [ 'ar', 'rcs', '/opt/indexer/fuzzing_engine.a', f'{OUT}/fuzzing_engine.o', ] subprocess.run(ar_cmd, check=True) lib_fuzzing_engine = '/usr/lib/libFuzzingEngine.a' if os.path.exists(lib_fuzzing_engine): os.remove(lib_fuzzing_engine) os.symlink('/opt/indexer/fuzzing_engine.a', lib_fuzzing_engine) compile_command = ['/usr/local/bin/compile'] if compile_args: compile_command.extend(compile_args) subprocess.run(compile_command, check=True) def test_target( target: BinaryMetadata, ) -> bool: """Tests a single target.""" target_path = OUT / target.binary_config.binary_name result = subprocess.run( [str(target_path)], stderr=subprocess.PIPE, check=False ) expected_error = f'Usage: {target_path} \n' if expected_error not in result.stderr.decode() or result.returncode != 1: logging.error( 'Target %s failed to run: %s', target_path, result.stderr.decode(), ) return False return True def set_interpreter(target_path: Path, lib_mount_path: pathlib.PurePath): subprocess.run( [ 'patchelf', '--set-interpreter', (lib_mount_path / _LD_BINARY).as_posix(), target_path.as_posix(), ], check=True, ) def set_target_rpath(binary_artifact: Path, lib_mount_path: pathlib.PurePath): subprocess.run( [ 'patchelf', '--set-rpath', lib_mount_path, '--force-rpath', binary_artifact.as_posix(), ], check=True, ) def copy_shared_libraries( fuzz_target_path: Path, libs_path: Path, lib_mount_path: pathlib.PurePath ) -> None: """Copies the shared libraries to the shared directory.""" env = os.environ.copy() env['LD_TRACE_LOADED_OBJECTS'] = '1' env['LD_BIND_NOW'] = '1' # TODO: Should we take ld.so from interp? res = subprocess.run( [_LD_PATH.as_posix(), fuzz_target_path.as_posix()], capture_output=True, env=env, check=True, ) output = res.stdout.decode() if 'statically linked' in output: return # Example output: # linux-vdso.so.1 => (0x00007f40afc0f000) # linux-vdso.so.1 (0x00007f76b9377000) # lib foo.so => /tmp/sharedlib/lib foo.so (0x00007f76b9367000) # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f76b9157000) # /lib64/ld-linux-x86-64.so.2 (0x00007f76b9379000) # # The lines that do not have a => should be skipped. # The dynamic linker should always be copied. # The lines that have a => could contain a space, but we copy whatever on the # right side of the =>, removing the load address. shutil.copy2(_LD_PATH, libs_path / _LD_PATH.name) lines = output.splitlines() for line in lines: if '=>' not in line: continue parts = line.split('=>') lib_name = parts[0].strip() right_side = parts[1].strip().rsplit(' ', maxsplit=1)[0].strip() if not right_side: continue library_path = Path(right_side) logging.info('Copying %s => %s', lib_name, library_path) if library_path.is_relative_to(libs_path): # This can happen if the project build is doing the same thing as us and # already copied the library to the library_path. continue try: shutil.copy2(library_path, libs_path / library_path.name) dst = libs_path / library_path.name # Need to preserve world writeable permissions. shutil.copy2(library_path, dst) # If we don't do this, our shared objects load the system's shared # objects. What about their shared objects you may ask? Well they # will all be from this directory where every so has the directory # as its rpath. set_target_rpath(dst, lib_mount_path) except FileNotFoundError as e: logging.exception('Could not copy %s', library_path) raise e def archive_target(target: BinaryMetadata, file_extension: str) -> Path | None: """Archives a single target in the project using the exported rootfs.""" logging.info('archive_target %s', target.binary_config.binary_name) index_dir = INDEXES_PATH / target.build_id if not index_dir.exists(): logging.error("didn't find index dir %s", index_dir) return None source_map = subprocess.run( ['srcmap'], capture_output=True, check=True ).stdout target_hash = hashlib.sha256(source_map).hexdigest()[:16] name = f'{PROJECT}.{target.binary_config.binary_name}' uuid = f'{PROJECT}.{target.binary_config.binary_name}.{target_hash}' lib_mount_path = pathlib.Path('/tmp') / (uuid + '_lib') libs_path = OUT / 'lib' # Keep a backup of the original 'lib' dir, in case the upstream project also # bundles libs using the same directory name. libs_backup_path = OUT / 'lib.backup' if libs_path.exists(): shutil.copytree(libs_path, libs_backup_path) else: libs_path.mkdir(parents=False) target_path = OUT / target.binary_config.binary_name copy_shared_libraries(target_path, libs_path, lib_mount_path) # We may want to eventually re-enable SRC copying (with some filtering to only # include source files). with tempfile.TemporaryDirectory() as empty_src_dir, \ tempfile.TemporaryDirectory() as backup_dir: # Make a backup of the target binary so we can undo the rpath/interpreter # changes in OUT. backup_path = Path(backup_dir) / target_path.name shutil.copy2(target_path, backup_path) # This is to handle `target_path` being a hard link, where other target # binaries share the same inode. os.unlink(target_path) shutil.copy2(backup_path, target_path) set_interpreter(target_path, lib_mount_path) set_target_rpath(target_path, lib_mount_path) archive_path = SNAPSHOT_DIR / f'{uuid}{file_extension}' # For `/` in $PROJECT. archive_path.parent.mkdir(parents=True, exist_ok=True) manifest_types.Manifest( name=name, uuid=uuid, binary_config=target.binary_config, source_map=manifest_types.source_map_from_dict(json.loads(source_map)), lib_mount_path=lib_mount_path, ).save_build( source_dir=Path(empty_src_dir), build_dir=OUT, index_dir=index_dir, archive_path=archive_path, out_dir=OUT, ) shutil.move(backup_path, target_path) logging.info('Wrote archive to: %s', archive_path) shutil.rmtree(libs_path) if libs_backup_path.exists(): shutil.move(libs_backup_path, libs_path) return archive_path def test_and_archive( binary_config: manifest_types.CommandLineBinaryConfig, targets_to_index: Sequence[str] | None, file_extension: str, ): """Test target and archive.""" targets = enumerate_build_targets(binary_config) if targets_to_index: targets = [ t for t in targets if t.binary_config.binary_name in targets_to_index ] missing_targets = set(targets_to_index) - set( t.binary_config.binary_name for t in targets ) if missing_targets: raise ValueError(f'Could not find specified targets {missing_targets}.') logging.info('targets %s', targets) for target in targets: try: # Check that the target binary behaves like a fuzz target, # unless the caller specifically asked for a list of targets. if not targets_to_index and not test_target(target): # TODO: Figure out if this is a good idea, it makes some things # pass that should but causes some things to pass that shouldn't. continue except Exception: # pylint: disable=broad-exception-caught logging.exception('Error testing target.') continue archive_target(target, file_extension) def clear_out(): """Clean up the OUT directory.""" for i in OUT.iterdir(): if i.is_dir(): shutil.rmtree(i) else: i.unlink() def main(): logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser(description='Index builder.') parser.add_argument( '-t', '--targets', help=( 'Comma separated list of targets to build for. ' 'If this is omitted, snapshots are built for all fuzz targets. ' 'If specified, this can include binaries which are not fuzz targets ' '(e.g., CLI targets which are built as part of the build ' 'integration).' ), ) parser.add_argument( '--targets-all-index', action='store_true', help=( 'When -t/--targets is set, allow the indexer to run on all of them, ' 'but only archive snapshots for the specified targets. This is ' 'useful to save some time for projects where the binary name during ' 'build time does not match the final name in the output directory.' ), ) parser.add_argument( '--target-args', default=None, help=( 'Arguments to pass to the target when executing it. ' 'This string is shell-escaped (interpreted with `shlex.split`). ' 'The substring will be replaced with the input path.' 'Note: This is deprecated, use --target-arg instead.' ), ) parser.add_argument( '--target-arg', action='append', help=( 'An argument to pass to the target binary. ' 'The substring will be replaced with the input path.' 'If you want to pass custom args, pass --harness-kind=binary as well.' ), ) parser.add_argument( '--target-env', action='append', default=[], help=( 'Environment variables (key=value) to pass to the target when ' 'executing it. The substring in a value will be ' 'replaced with the input path.' ), ) parser.add_argument( '--binary-config', default=None, help=( 'JSON serialized OSS_FUZZ BinaryConfig object containing ' 'binary_args, binary_env, harness_kind, etc. If this value is set, ' 'redundant flags like target-arg, etc., may not be used. ' 'The binary_name field of this BinaryConfig object is ignored, all ' 'other fields will be applied to all targets.' ), ) parser.add_argument( '--no-clear-out', action='store_true', help='Do not clear out the OUT directory before building.', ) parser.add_argument( '--compile-arg', action='append', help='An argument to pass to the `compile` script.', ) parser.add_argument( '--compressed', action='store_true', help='Use gzipped tar (.tgz) for the output snapshot', ) parser.add_argument( '--binaries-only', action='store_true', help='Build target binaries only, and not index archives.', ) parser.add_argument( '--harness-kind', choices=[str(x) for x in manifest_types.HarnessKind], default=manifest_types.HarnessKind.LIBFUZZER, help=( 'The harness kind to use for the fuzz target. In order to pass custom' ' args, set this to binary.' ), ) parser.add_argument( '--tracing-instrumentation', action='store_true', help='Enable tracing coverage instrumentation.', ) args = parser.parse_args() INDEXES_PATH.mkdir(exist_ok=True) INCREMENTAL_CDB_PATH.mkdir(exist_ok=True) # Clean up the existing OUT by default, otherwise we may run into various # build errors. if not args.no_clear_out: clear_out() if args.target_args and args.target_arg: raise ValueError( 'Only one of --target-args or --target-arg can be specified.' ) if args.binary_config: if ( args.target_arg or args.target_args or args.target_env or args.harness_kind != manifest_types.HarnessKind.LIBFUZZER ): raise ValueError( 'If --binary-config is specified, redundant flags may not be set.' ) binary_config = manifest_types.BinaryConfig.from_dict( json.loads(args.binary_config) ) if ( binary_config.kind != manifest_types.BinaryConfigKind.OSS_FUZZ or not isinstance(binary_config, manifest_types.CommandLineBinaryConfig) ): raise ValueError( 'Only OSS_FUZZ binary configs are supported with --binary-config.' ) else: if args.target_args and args.target_arg: raise ValueError( 'Only one of --target-args or --target-arg can be specified.' ) elif args.target_arg: target_args = args.target_arg elif args.target_args: logging.warning('--target-args is deprecated, use --target-arg instead.') target_args = shlex.split(args.target_args) else: logging.info('No target args specified.') target_args = [] if args.target_env: target_env = manifest_types.parse_env(args.target_env) else: logging.info('No target env specified.') target_env = {} harness_kind = manifest_types.HarnessKind(args.harness_kind) match harness_kind: case manifest_types.HarnessKind.LIBFUZZER: if target_args and target_args != [manifest_types.INPUT_FILE]: raise ValueError( 'Unsupported target args for harness_kind libfuzzer:' f' {target_args}' ) target_args = [manifest_types.INPUT_FILE] case _: pass binary_config = manifest_types.CommandLineBinaryConfig( kind=manifest_types.BinaryConfigKind.OSS_FUZZ, binary_name='oss-fuzz', # The name will be replaced with the target. binary_args=target_args, binary_env=target_env, harness_kind=harness_kind, ) targets_to_index = None if args.targets: targets_to_index = args.targets.split(',') for directory in ['aflplusplus', 'fuzztest', 'honggfuzz', 'libfuzzer']: path = os.path.join(os.environ['SRC'], directory) shutil.rmtree(path, ignore_errors=True) # Initially, we put snapshots directly in /out. This caused a bug where each # snapshot was added to the next because they contain the contents of /out. SNAPSHOT_DIR.mkdir(exist_ok=True) # We don't have an existing /out dir on oss-fuzz's build infra. OUT.mkdir(parents=True, exist_ok=True) set_up_wrapper_dir() build_project( None if args.targets_all_index else targets_to_index, args.compile_arg, args.binaries_only, TRACING_COVERAGE_FLAGS if args.tracing_instrumentation else DEFAULT_COVERAGE_FLAGS, ) if not args.binaries_only: file_extension = '.tgz' if args.compressed else '.tar' test_and_archive(binary_config, targets_to_index, file_extension) for snapshot in SNAPSHOT_DIR.iterdir(): shutil.move(str(snapshot), OUT) # By default, this directory has o-rwx and its contents can't be deleted # by a non-root user from outside the container. The rest of the files are # unaffected because to delete a file, a write permission on its enclosing # directory is sufficient regardless of the owner. cdb_dir = OUT / 'cdb' try: cdb_dir.chmod( cdb_dir.stat().st_mode | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH ) except OSError: pass if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/indexer/index_build_test.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """index_build tests. This is only runnable on OSS-Fuzz infrastructure. """ import json import os import pathlib import subprocess import tarfile from typing import Sequence import unittest import manifest_types THIS_DIR = pathlib.Path(__file__).parent OSS_FUZZ_DIR = THIS_DIR.parent.parent.parent.parent @unittest.skipUnless( os.getenv('INDEX_BUILD_TESTS'), 'Tests do not run on infra' ) class IndexBuildTest(unittest.TestCase): def _build_project( self, project: str, *additional_args, compressed: bool ) -> Sequence[pathlib.Path]: subprocess.run( ('python3', 'infra/helper.py', 'build_image', '--no-pull', project), cwd=OSS_FUZZ_DIR, check=True, ) out_dir = OSS_FUZZ_DIR / f'build/out/{project}' docker_args = [ 'docker', 'run', '--rm', '-e', f'PROJECT_NAME={project}', '-v', f'{THIS_DIR}:/opt/indexer', '-v', f'{out_dir}:/out', f'gcr.io/oss-fuzz/{project}', '/opt/indexer/index_build.py', ] if additional_args: docker_args.extend(additional_args) file_suffix = '.tar' if compressed: docker_args.append('--compressed') file_suffix = '.tgz' subprocess.run(docker_args, cwd=OSS_FUZZ_DIR, check=True) return [ file for file in out_dir.iterdir() if file.suffix == file_suffix and file.name.startswith(project) ] def _check_archive(self, archive_path: pathlib.Path): has_obj_lib = False has_idx_sqlite = False has_idx_absolute = False has_idx_relative = False manifest = None print(f'Testing {archive_path}') with tarfile.open(archive_path) as tar: members = tar.getmembers() for member in members: if member.name.startswith('obj/lib/'): has_obj_lib = True if member.name.startswith('idx/absolute/'): has_idx_absolute = True if member.name.startswith('idx/relative/'): has_idx_relative = True if member.name == 'idx/db.sqlite': has_idx_sqlite = True if member.name == 'manifest.json': file = tar.extractfile(member) self.assertIsNotNone(file) if file: # Make type checkers happy. manifest = json.load(file) self.assertTrue(manifest['lib_mount_path']) self.assertIsNotNone( tar.getmember('obj/' + manifest['binary_config']['binary_name']) ) self.assertEqual( manifest['binary_config']['binary_args'], [manifest_types.INPUT_FILE], ) self.assertTrue(has_obj_lib, 'obj/lib/ was not found in the archive.') self.assertTrue( has_idx_sqlite, 'idx/db.sqlite was not found in the archive.' ) self.assertTrue( has_idx_absolute, 'idx/absolute/ was not found in the archive.' ) self.assertTrue( has_idx_relative, 'idx/relative/ was not found in the archive.' ) self.assertIsNotNone( manifest, 'manifest.json was not found or is empty in the archive.' ) def test_basic_build(self): """Test basic build.""" for compressed in (False, True): archives = self._build_project('expat', compressed=compressed) self.assertGreater(len(archives), 0) for archive in archives: self._check_archive(archive) def test_build_with_target_allowlist(self): """Test basic build with target allowlist.""" for compressed in (False, True): archives = self._build_project( 'expat', '--targets', 'xml_parse_fuzzer_UTF-8', compressed=compressed, ) self.assertEqual(len(archives), 1) self.assertIn('xml_parse_fuzzer_UTF-8', archives[0].name) for archive in archives: self._check_archive(archive) ================================================ FILE: infra/base-images/base-builder/indexer/manifest_constants.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Constants pertaining to snapshot manifests.""" # pylint: disable=g-import-not-at-top try: import pathlib Path = pathlib.Path except ImportError: import pathlib Path = pathlib.Path # Source directory. SRC_DIR = Path("src") # Object directory. OBJ_DIR = Path("obj") # Directory for indexer data. INDEX_DIR = Path("idx") # Relative source file root in the index. INDEX_RELATIVE_SOURCES = INDEX_DIR / "relative" # Absolute source file root in the index. INDEX_ABSOLUTE_SOURCES = INDEX_DIR / "absolute" # The index database filename. INDEX_DB = Path("db.sqlite") # Library directory, where shared libraries are copied - inside obj. LIB_DIR = OBJ_DIR / "lib" # Manifest location MANIFEST_PATH = Path("manifest.json") # Where archive version 1 expects the lib directory to be mounted. LIB_MOUNT_PATH_V1 = Path("/ossfuzzlib") # Will be replaced with the input file for target execution. INPUT_FILE = "" # A file the target can write output to. OUTPUT_FILE = "" # Will be replaced with any dynamic arguments. DYNAMIC_ARGS = "" ================================================ FILE: infra/base-images/base-builder/indexer/manifest_types.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Classes and tools to build an indexer snapshot according to the spec. A snapshot is a tarball containing the following: - source files - build artifacts (e.g. object files, shared libraries) - indexer artifacts (e.g. clang command lines, symbol files) - the manifest.json file, according to the Manifest class below. """ import dataclasses import enum import inspect import io import json import logging import os import pathlib import shlex import shutil import tarfile import tempfile from typing import Any, Callable, Mapping, Self, Sequence import urllib.request import manifest_constants import pathlib SRC_DIR = manifest_constants.SRC_DIR OBJ_DIR = manifest_constants.OBJ_DIR INDEX_DIR = manifest_constants.INDEX_DIR INDEX_DB = manifest_constants.INDEX_DB LIB_DIR = manifest_constants.LIB_DIR MANIFEST_PATH = manifest_constants.MANIFEST_PATH LIB_MOUNT_PATH_V1 = manifest_constants.LIB_MOUNT_PATH_V1 INPUT_FILE = manifest_constants.INPUT_FILE OUTPUT_FILE = manifest_constants.OUTPUT_FILE DYNAMIC_ARGS = manifest_constants.DYNAMIC_ARGS # Min archive version we currently support. _MIN_SUPPORTED_ARCHIVE_VERSION = 1 # The current version of the build archive format. ARCHIVE_VERSION = 5 # OSS-Fuzz $OUT dir. OUT = pathlib.Path(os.getenv("OUT", "/out")) # OSS-Fuzz coverage info. _COVERAGE_INFO_URL = ( "https://storage.googleapis.com/oss-fuzz-coverage/" f"latest_report_info/{os.getenv('PROJECT_NAME')}.json" ) class RepositoryType(enum.StrEnum): """The type of repository.""" GIT = enum.auto() SVN = enum.auto() HG = enum.auto() @dataclasses.dataclass(frozen=True) class SourceRef: """The reference to a source code repository. Attributes: type: The type of repository. url: The URL of the repository. rev: The revision of the repository. """ type: RepositoryType url: str rev: str @classmethod def from_dict(cls, data: dict[str, Any]) -> Self: """Creates a SourceRef object from a deserialized dict.""" return SourceRef( url=data["url"], rev=data["rev"], type=RepositoryType(data["type"]) ) @dataclasses.dataclass(frozen=True) class Reproducibility: """A report of how reproducible a known bug is.""" # How many of the trials succeeded in reproducing the behavior? success_count: int = 0 # How many reproduction trials were attempted? trial_count: int = 0 @classmethod def from_dict(cls, data: dict[str, Any]) -> Self: """Creates a Reproducibility object from a deserialized dict.""" return Reproducibility( success_count=data["success_count"], trial_count=data["trial_count"], ) class BinaryConfigKind(enum.StrEnum): """The kind of binary configurations.""" OSS_FUZZ = enum.auto() BINARY = enum.auto() def validate_in(self, options: list[Self]): if self not in options: raise ValueError( f"Expected one of the following binary config kinds: {options}, " f"but got {self}" ) @dataclasses.dataclass(frozen=True, kw_only=True) class BinaryConfig: """Base binary configuration. Attributes: kind: The kind of binary configuration. binary_name: The name of the executable file. """ kind: BinaryConfigKind binary_name: str @property def uses_stdin(self) -> bool: """Whether the binary uses stdin.""" del self return False @classmethod def from_dict(cls, config_dict: Mapping[str, Any]) -> Self: """Deserializes the correct `BinaryConfig` subclass from a dict.""" mapping = { BinaryConfigKind.OSS_FUZZ: CommandLineBinaryConfig, BinaryConfigKind.BINARY: CommandLineBinaryConfig, } kind = config_dict["kind"] if kind not in mapping: raise ValueError(f"Unknown BinaryConfigKind: {kind}") val = config_dict if isinstance(val.get("binary_args"), str): logging.warning( "BinaryConfig: binary_args is type string instead of list." " This is deprecated. Converting to list. Args: %s", val["binary_args"], ) val = dict(val, binary_args=shlex.split(val["binary_args"])) return mapping[kind].from_dict(val) def to_dict(self) -> dict[str, Any]: """Converts a BinaryConfig object to a serializable dict.""" return dataclasses.asdict(self) class HarnessKind(enum.StrEnum): """The target/harness kind.""" LIBFUZZER = enum.auto() BINARY = enum.auto() # The target is a JavaScript shell that consumes JavaScript code. JS = enum.auto() @dataclasses.dataclass(frozen=True, kw_only=True) class CommandLineBinaryConfig(BinaryConfig): """Configuration for a command-line userspace binary.""" binary_args: list[str] # Additional environment variables to pass to the binary. They will overwrite # any existing environment variables with the same name. # Input replacement works on these variables as well. binary_env: dict[str, str] = dataclasses.field(default_factory=dict) harness_kind: HarnessKind # Whether to filter the compile commands to only include object files that # are directly linked into the target binary. Should usually be true but # some targets like V8 require this to be false, see b/433718862. filter_compile_commands: bool = True @property def uses_stdin(self) -> bool: """Whether the binary uses stdin.""" return manifest_constants.INPUT_FILE not in self.binary_args @classmethod def from_dict(cls, config_dict: Mapping[str, Any]) -> Self: """Deserializes the `CommandLineBinaryConfig` from a dict.""" kind = BinaryConfigKind(config_dict["kind"]) kind.validate_in([BinaryConfigKind.OSS_FUZZ, BinaryConfigKind.BINARY]) # Default to "binary" for backwards compatibility. harness_kind = HarnessKind( config_dict.get("harness_kind", HarnessKind.BINARY) ) return CommandLineBinaryConfig( kind=kind, harness_kind=harness_kind, binary_name=config_dict["binary_name"], binary_args=config_dict["binary_args"], binary_env=config_dict.get("binary_env", {}), filter_compile_commands=config_dict.get( "filter_compile_commands", True ), ) def _get_sqlite_db_user_version(sqlite_db_path: pathlib.Path) -> int: """Retrieves `PRAGMA user_version;` value without connecting to the database.""" with sqlite_db_path.open("rb") as stream: # https://www.sqlite.org/pragma.html#pragma_user_version - a big-endian # 32-bit number at offset 60 of the database header. too_small_error = ValueError( f"The file '{sqlite_db_path}' is too small for an SQLite database." ) try: stream.seek(60) except OSError as e: raise too_small_error from e version_bytes = stream.read(4) if len(version_bytes) < 4: raise too_small_error return int.from_bytes(version_bytes, byteorder="big") @dataclasses.dataclass(frozen=True) class Manifest: """Contains general meta-information about the snapshot.""" # The name of the target. name: str # A unique identifier for the snapshot (not necessarily a valid UUID). uuid: str # A fixed path that shared libraries stored at `./obj/lib` should be mounted # at before running the target. lib_mount_path: pathlib.Path | None # The binary configuration used to build the snapshot. binary_config: BinaryConfig # The path prefix of the actual build directory (e.g., a temporary file in # the build host). It's used during replay to remove noisy source-file # prefixes from reports. source_dir_prefix: str | None = None # The reproducibility information about the bug in this snapshot. reproducibility: Reproducibility | None = None # Example source map: # { # "/src/hunspell": { # "type": "git", # "url": "https://github.com/hunspell/hunspell.git", # "rev": "a9b7270c1c2832312cfb20c3d1cf5c5080bf221b" # } # } source_map: dict[pathlib.Path, SourceRef] | None = None # Version of the manifest spec. version: int = ARCHIVE_VERSION # Version of the index database schema. index_db_version: int | None = None @classmethod def from_dict(cls, data: dict[str, Any]) -> Self: """Creates a Manifest object from a deserialized dict.""" if data["version"] == 1: lib_mount_path = LIB_MOUNT_PATH_V1 else: lib_mount_path = _get_mapped(data, "lib_mount_path", pathlib.Path) if data["version"] < 3: if not isinstance(data.get("binary_args"), str): raise RuntimeError( "binary_args must be a string in version 1 and 2, but got" f" {type(data.get('binary_args'))}" ) binary_args = _get_mapped(data, "binary_args", shlex.split) else: binary_args = data.get("binary_args") if data["version"] < 4: binary_config = CommandLineBinaryConfig( kind=BinaryConfigKind.BINARY, binary_name=data["binary_name"], binary_args=binary_args or [], harness_kind=HarnessKind.BINARY, binary_env={}, ) else: binary_config = _get_mapped(data, "binary_config", BinaryConfig.from_dict) version = data["version"] if _MIN_SUPPORTED_ARCHIVE_VERSION <= version <= ARCHIVE_VERSION: # Upgrade archive version - we have upgraded all necessary fields. version = ARCHIVE_VERSION else: logging.warning( "Unsupported manifest version %s detected. Not upgrading.", version ) return Manifest( version=version, index_db_version=data.get("index_db_version"), name=data["name"], uuid=data["uuid"], lib_mount_path=lib_mount_path, source_map=_get_mapped(data, "source_map", source_map_from_dict), source_dir_prefix=data.get("source_dir_prefix"), reproducibility=_get_mapped( data, "reproducibility", Reproducibility.from_dict ), binary_config=binary_config, ) def to_dict(self) -> dict[str, Any]: """Converts a Manifest object to a serializable dict.""" data = dataclasses.asdict(self) data["binary_config"] = self.binary_config.to_dict() data["lib_mount_path"] = _get_mapped( data, "lib_mount_path", lambda x: x.as_posix() ) data["source_map"] = _get_mapped(data, "source_map", source_map_to_dict) return data def validate(self) -> None: """Validates the manifest with some simple checks. Raises: RuntimeError: If the manifest is invalid. """ if self.version < _MIN_SUPPORTED_ARCHIVE_VERSION: raise RuntimeError( f"Build archive version too low: {self.version}. Supporting at" f" least {_MIN_SUPPORTED_ARCHIVE_VERSION}." ) if self.version > ARCHIVE_VERSION: raise RuntimeError( f"Build archive version too high: {self.version}. Only supporting" f" up to {ARCHIVE_VERSION}." ) if self.version == 1 and LIB_MOUNT_PATH_V1 != self.lib_mount_path: raise RuntimeError( "Build archive with version 1 has an alternative lib_mount_path set" f" ({self.lib_mount_path}). This is not a valid archive." ) if not self.name or not self.uuid or not self.binary_config: raise RuntimeError( "Attempting to load a manifest with missing fields. Expected all" " fields to be set, but got {self}" ) if self.source_map is not None: for _, ref in self.source_map.items(): if not ref.url: raise RuntimeError( "Attempting to load a manifest with a source map entry with an" " empty URL. Source map entry: {ref}" ) # check very simple basic types. for k, v in inspect.get_annotations(type(self)).items(): if not isinstance(v, type): continue if not isinstance(getattr(self, k), v): raise RuntimeError( f"Type mismatch for field {k}: expected {v}, got" f" {type(getattr(self, k))}" ) # We updated from string to list in version 3, make sure this propagated. binary_config = self.binary_config if hasattr(binary_config, "binary_args"): if not isinstance(binary_config.binary_args, list): raise RuntimeError( "Type mismatch for field binary_config.binary_args: expected list," f"got {type(binary_config.binary_args)}" ) def save_build( self, *, source_dir: pathlib.PurePath | None, build_dir: pathlib.PurePath, index_dir: pathlib.PurePath, archive_path: pathlib.PurePath, out_dir: pathlib.PurePath = pathlib.Path("/out"), overwrite: bool = True, ) -> Self: """Saves a build archive with this Manifest.""" if os.path.exists(archive_path) and not overwrite: raise FileExistsError(f"Not overwriting existing archive {archive_path}") self.validate() with tempfile.NamedTemporaryFile() as tmp: mode = "w:gz" if archive_path.suffix.endswith("gz") else "w" with tarfile.open(tmp.name, mode) as tar: def _save_dir( path: pathlib.PurePath, prefix: pathlib.Path, exclude_build_artifacts: bool = False, only_include_target: str | None = None, ): prefix = prefix.as_posix() + "/" for root, _, files in os.walk(path): for file in files: if file.endswith("_seed_corpus.zip"): # Don't copy over the seed corpus -- it's not necessary. continue if "/.git/" in root or root.endswith("/.git"): # Skip the .git directory -- it can be large. continue file = pathlib.Path(root, file) if exclude_build_artifacts and _is_elf(file): continue if only_include_target and _is_elf(file): # Skip ELF files that aren't the relevant target (unless it's a # shared library). if ( file.name != only_include_target and ".so" not in file.name and not file.absolute().is_relative_to(out_dir / "lib") ): continue tar.add( # Don't try to replicate symlinks in the tarfile, because they # can lead to various issues (e.g. absolute symlinks). file.resolve().as_posix(), arcname=prefix + str(file.relative_to(path)), ) dumped_self = self if self.index_db_version is None: index_db_version = _get_sqlite_db_user_version( pathlib.Path(index_dir) / INDEX_DB ) dumped_self = dataclasses.replace( self, index_db_version=index_db_version ) # Make sure the manifest is the first file in the archive to avoid # seeking when we only need the manifest. _add_string_to_tar( tar, MANIFEST_PATH.as_posix(), json.dumps( dumped_self.to_dict(), indent=2, ), ) # Make sure the index databases (the only files directly in `INDEX_DIR`) # are early in the archive for the same reason. _save_dir(index_dir, INDEX_DIR) if source_dir: _save_dir(source_dir, SRC_DIR, exclude_build_artifacts=True) # Only include the relevant target for the snapshot, to save on disk # space. _save_dir( build_dir, OBJ_DIR, only_include_target=self.binary_config.binary_name, ) if self.binary_config.kind == BinaryConfigKind.OSS_FUZZ: copied_files = [tar_info.name for tar_info in tar.getmembers()] try: report_missing_source_files( self.binary_config.binary_name, copied_files, tar ) except Exception as e: # pylint: disable=broad-except logging.warning("Failed to report missing source files: %s", e) shutil.copyfile(tmp.name, archive_path) return dumped_self def report_missing_source_files( binary_name: str, copied_files: list[str], tar: tarfile.TarFile ): """Saves a report of missing source files to the snapshot tarball.""" copied_files = {_get_comparable_path(file) for file in copied_files} covered_files = { _get_comparable_path(path): path for path in get_covered_files(binary_name) } missing = set(covered_files) - copied_files if not missing: return logging.info("Reporting missing files: %s", missing) missing_report_lines = sorted([covered_files[k] for k in missing]) report_name = f"{binary_name}_missing_files.txt" tar_info = tarfile.TarInfo(name=report_name) missing_report = " ".join(missing_report_lines) missing_report_bytes = missing_report.encode("utf-8") tar.addfile(tarinfo=tar_info, fileobj=io.BytesIO(missing_report_bytes)) with open(os.path.join(OUT, report_name), "w") as fp: fp.write(missing_report) def _get_comparable_path(path: str) -> tuple[str, str]: return os.path.basename(os.path.dirname(path)), os.path.basename(path) def get_covered_files(target: str) -> Sequence[str]: """Returns the files covered by fuzzing on OSS-Fuzz by the target.""" with urllib.request.urlopen(_COVERAGE_INFO_URL) as resp: latest_info = json.load(resp) stats_url = latest_info.get("fuzzer_stats_dir").replace( "gs://", "https://storage.googleapis.com/" ) target_url = f"{stats_url}/{target}.json" with urllib.request.urlopen(target_url) as resp: target_cov = json.load(resp) files = target_cov["data"][0]["files"] return [ file["filename"] for file in files if file["summary"]["regions"]["covered"] ] def _get_mapped( data: dict[str, Any], key: str, mapper: Callable[[Any], Any] ) -> Any | None: """Get a value from a dict and apply a mapper to it, if it's not None.""" value = data.get(key) if value is None: return None return mapper(value) def source_map_from_dict(data: dict[str, Any]) -> dict[pathlib.Path, SourceRef]: """Converts a path: obj dict to a dictionary of SourceRef objects.""" return {pathlib.Path(x): SourceRef.from_dict(y) for x, y in data.items()} def source_map_to_dict( x: dict[pathlib.Path, SourceRef], ) -> dict[str, Any]: """Converts a dictionary of SourceRef objects to a string: obj dict.""" return {k.as_posix(): v for k, v in x.items()} def _add_string_to_tar(tar: tarfile.TarFile, name: str, data: str) -> None: bytesio = io.BytesIO(data.encode("utf-8")) tar_info = tarfile.TarInfo(name) tar_info.size = len(bytesio.getvalue()) tar.addfile(tarinfo=tar_info, fileobj=bytesio) def _is_elf(path: pathlib.PurePath) -> bool: """Checks if a file is an ELF file.""" try: with open(path, "rb") as f: return f.read(4) == b"\x7fELF" except OSError: # Can happen if the file is a symlink, etc. return False def parse_env(env_list: list[str]) -> dict[str, str]: """Helper function to parse environment variables from a list. Args: env_list: A list of environment variables in the format of "key=value". Returns: A dictionary of environment variables. Raises: ValueError: If a key is empty or invalid. """ env = {} def assert_key_valid(key: str) -> None: if not key: raise ValueError("Environment variable key is empty.") # Check that the key looks like a valid environment variable name. if key in env: raise ValueError( f"Environment variable key {key} is defined twice. " f"Existing value: {env[key]}, new value: {value}." ) for entry in env_list: if "=" not in entry: logging.warning( "Environment variable string is not in the format of 'key=value': %s", entry, ) key, _, value = entry.partition("=") assert_key_valid(key) env[key] = value return env ================================================ FILE: infra/base-images/base-builder/indexer/utils.py ================================================ #!/usr/bin/env python3 # Copyright 2026 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utils for snapshotting shared libraries.""" from collections.abc import Mapping, Sequence import dataclasses import os import pathlib import re import subprocess from typing import Final, Protocol from absl import logging from google3.pyglib import gfile import pathlib LD_BINARY_PATH_X86_64: Final[pathlib.Path] = ( pathlib.Path("/lib64/ld-linux-x86-64.so.2") ) LD_BINARY_PATH_X86: Final[pathlib.Path] = pathlib.Path("/lib32/ld-linux.so.2") @dataclasses.dataclass(frozen=True) class SharedLibrary: """A shared library with its name and path.""" name: str path: pathlib.Path def _parse_ld_trace_output( output: str, ld_binary_path: pathlib.Path ) -> Sequence[SharedLibrary]: """Parses the output of `LD_TRACE_LOADED_OBJECTS=1 ld.so`.""" if "statically linked" in output: return [] # Example output: # linux-vdso.so.1 => (0x00007f40afc0f000) # linux-vdso.so.1 (0x00007f76b9377000) # lib foo.so => /tmp/sharedlib/lib foo.so (0x00007f76b9367000) # libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f76b9157000) # /lib64/ld-linux-x86-64.so.2 (0x00007f76b9379000) # The last line can also be: # /grte/lib64/lib64/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 # (0x00007f76b9379000) # # The lines that do not have a => should be skipped. # The dynamic linker should always be copied AND have its executable bit set. # The lines that have a => could contain a space, but we copy whatever is on # the right side of the =>, removing the load address. shared_libraries = [ SharedLibrary(name=ld_binary_path.name, path=ld_binary_path) ] for lib_name, lib_path in re.findall(r"(\S+) => .*?(\S+) \(", output): lib_path = pathlib.Path(lib_path) if lib_path == ld_binary_path: continue shared_libraries.append(SharedLibrary(name=lib_name, path=lib_path)) return shared_libraries class CommandRunner(Protocol): """Runs `command` with environment `env` and returns its stdout.""" def __call__( self, command: Sequence[str | os.PathLike[str]], env: Mapping[str, str] | None = None, ) -> bytes: pass def run_subprocess( command: Sequence[str | os.PathLike[str]], env: Mapping[str, str] | None = None, ) -> bytes: return subprocess.run( command, capture_output=True, env=env, check=True, ).stdout def get_shared_libraries( binary_path: os.PathLike[str], command_runner: CommandRunner = run_subprocess, ld_binary_path: pathlib.Path = LD_BINARY_PATH_X86_64, ) -> Sequence[SharedLibrary]: """Enumerates the shared libraries required by the given binary.""" env = os.environ | { "LD_TRACE_LOADED_OBJECTS": "1", "LD_BIND_NOW": "1", } stdout_bytes = command_runner([ld_binary_path, binary_path], env=env) return _parse_ld_trace_output(stdout_bytes.decode(), ld_binary_path) def copy_shared_libraries( libraries: Sequence[SharedLibrary], dst_path: pathlib.Path ) -> None: """Copies the shared libraries to the shared directory.""" for lib in libraries: try: logging.info("Copying %s => %s", lib.name, lib.path) gfile.Copy(lib.path, dst_path / lib.path.name, overwrite=True, mode=0o755) except gfile.GOSError: logging.exception("Could not copy %s to %s", lib.path, dst_path) raise def patch_binary_rpath_and_interpreter( binary_path: os.PathLike[str], lib_mount_path: pathlib.Path, ld_binary_path: pathlib.Path = LD_BINARY_PATH_X86_64, ): """Patches the binary rpath and interpreter.""" subprocess.run( [ "patchelf", "--set-rpath", lib_mount_path.as_posix(), "--force-rpath", binary_path, ], check=True, ) subprocess.run( [ "patchelf", "--set-interpreter", (lib_mount_path / ld_binary_path.name).as_posix(), binary_path, ], check=True, ) def get_library_mount_path(binary_id: str) -> pathlib.Path: return pathlib.Path("/tmp") / (binary_id + "_lib") def report_progress(stage: str, is_done: bool = False) -> None: """Reports progress of a stage of the snapshotting process.""" logging.info("%s%s", stage, "..." if not is_done else "") ================================================ FILE: infra/base-images/base-builder/install_deps.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install base-builder's dependencies in a architecture-aware way. case $(uname -m) in x86_64) dpkg --add-architecture i386 ;; esac apt-get update && \ apt-get install -y \ binutils-dev \ build-essential \ curl \ wget \ git \ jq \ patchelf \ rsync \ subversion \ zip case $(uname -m) in x86_64) apt-get install -y libc6-dev-i386 ;; esac ================================================ FILE: infra/base-images/base-builder/install_deps_ubuntu-20-04.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install base-builder's dependencies in a architecture-aware way. case $(uname -m) in x86_64) dpkg --add-architecture i386 ;; esac apt-get update && \ apt-get install -y \ binutils-dev \ build-essential \ curl \ wget \ git \ jq \ patchelf \ rsync \ subversion \ zip case $(uname -m) in x86_64) apt-get install -y libc6-dev-i386 ;; esac ================================================ FILE: infra/base-images/base-builder/install_deps_ubuntu-24-04.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install base-builder's dependencies in a architecture-aware way. case $(uname -m) in x86_64) dpkg --add-architecture i386 ;; esac apt-get update && \ apt-get install -y \ binutils-dev \ build-essential \ curl \ wget \ git \ jq \ patchelf \ rsync \ subversion \ zip case $(uname -m) in x86_64) apt-get install -y libc6-dev-i386 ;; esac # Ubuntu 24.04 does not have lcab. Install an older .deb from Ubuntu repos. curl -LO https://mirrors.edge.kernel.org/ubuntu/pool/universe/l/lcab/lcab_1.0b12-7_amd64.deb && \ apt-get install -y ./lcab_1.0b12-7_amd64.deb && \ rm lcab_1.0b12-7_amd64.deb # Create a custom apt configuration to allow downgrades and non-interactive installs. cat < /etc/apt/apt.conf.d/99-oss-fuzz-apt-defaults // OSS-Fuzz custom apt configuration. // Automatically allow downgrades and assume "yes" to all prompts. APT::Get::Allow-Downgrades "true"; APT::Get::Assume-Yes "true"; EOF ================================================ FILE: infra/base-images/base-builder/install_go.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd /tmp export GOROOT=/root/.go wget https://go.dev/dl/go1.25.0.linux-amd64.tar.gz mkdir temp-go tar -C temp-go/ -xzf go1.25.0.linux-amd64.tar.gz mkdir /root/.go/ mv temp-go/go/* /root/.go/ rm -rf temp-go echo 'Set "GOPATH=/root/go"' echo 'Set "PATH=$PATH:/root/.go/bin:$GOPATH/bin"' go install github.com/mdempsky/go114-fuzz-build@latest ln -s $GOPATH/bin/go114-fuzz-build $GOPATH/bin/go-fuzz # Build signal handler if [ -f "$GOPATH/gosigfuzz/gosigfuzz.c" ]; then clang -c $GOPATH/gosigfuzz/gosigfuzz.c -o $GOPATH/gosigfuzz/gosigfuzz.o fi cd /tmp git clone https://github.com/AdamKorcz/go-118-fuzz-build cd go-118-fuzz-build go build mv go-118-fuzz-build $GOPATH/bin/ # Build v2 binaries git checkout v2 go build . mv go-118-fuzz-build $GOPATH/bin/go-118-fuzz-build_v2 pushd cmd/convertLibFuzzerTestcaseToStdLibGo go build . && mv convertLibFuzzerTestcaseToStdLibGo $GOPATH/bin/ popd pushd cmd/addStdLibCorpusToFuzzer go build . && mv addStdLibCorpusToFuzzer $GOPATH/bin/ popd ================================================ FILE: infra/base-images/base-builder/install_java.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install OpenJDK 17 and trim its size by removing unused components. This enables using Jazzer's mutation framework. cd /tmp curl --silent -L -O https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16+8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz && \ mkdir -p $JAVA_HOME tar -xz --strip-components=1 -f OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz --directory $JAVA_HOME && \ rm -f OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip # Install OpenJDK 15 and trim its size by removing unused components. Some projects only run with Java 15. curl --silent -L -O https://download.java.net/java/GA/jdk15.0.2/0d1cfde4252546c6931946de8db48ee2/7/GPL/openjdk-15.0.2_linux-x64_bin.tar.gz && \ mkdir -p $JAVA_15_HOME tar -xz --strip-components=1 -f openjdk-15.0.2_linux-x64_bin.tar.gz --directory $JAVA_15_HOME && \ rm -f openjdk-15.0.2_linux-x64_bin.tar.gz rm -rf $JAVA_15_HOME/jmods $JAVA_15_HOME/lib/src.zip ================================================ FILE: infra/base-images/base-builder/install_javascript.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # see installation instructions: https://github.com/nodesource/distributions#available-architectures apt-get update apt-get install -y ca-certificates curl gnupg mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=20 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list apt-get update apt-get install nodejs -y ================================================ FILE: infra/base-images/base-builder/install_python.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "ATHERIS INSTALL" unset CFLAGS CXXFLAGS # PYI_STATIC_ZLIB=1 is needed for installing pyinstaller 5.0 export PYI_STATIC_ZLIB=1 LIBFUZZER_LIB=$( echo /usr/local/lib/clang/*/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer_no_main.a ) pip3 install -v --no-cache-dir "atheris>=2.3.0" "pyinstaller==6.10.0" "setuptools==72.1.0" "coverage==6.3.2" rm -rf /tmp/* ================================================ FILE: infra/base-images/base-builder/install_ruby.sh ================================================ #!/bin/bash -eux # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Starting ruby installation" RUBY_VERSION=3.3.1 RUBY_DEPS="binutils xz-utils libyaml-dev libffi-dev zlib1g-dev" apt update && apt install -y $RUBY_DEPS curl -O https://cache.ruby-lang.org/pub/ruby/3.3/ruby-$RUBY_VERSION.tar.gz tar -xvf ruby-$RUBY_VERSION.tar.gz cd ruby-$RUBY_VERSION ./configure --disable-install-doc --disable-install-rdoc --disable-install-capi make -j$(nproc) make install cd ../ # Clean up the sources. rm -rf ./ruby-$RUBY_VERSION ruby-$RUBY_VERSION.tar.gz echo "Finished installing ruby" ================================================ FILE: infra/base-images/base-builder/install_rust.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ curl https://sh.rustup.rs | sh -s -- -y --default-toolchain=$RUSTUP_TOOLCHAIN --profile=minimal cargo install cargo-fuzz --locked && rm -rf /rust/registry # Needed to recompile rust std library for MSAN rustup component add rust-src cp -r /usr/local/lib/x86_64-unknown-linux-gnu/* /usr/local/lib/ ================================================ FILE: infra/base-images/base-builder/install_swift.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SWIFT_PACKAGES="wget \ binutils \ git \ gnupg2 \ libc6-dev \ libcurl4 \ libedit2 \ libgcc-9-dev \ libpython2.7 \ libsqlite3-0 \ libstdc++-9-dev \ libxml2 \ libz3-dev \ pkg-config \ tzdata \ uuid-dev \ zlib1g-dev" SWIFT_SYMBOLIZER_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev" apt-get update && apt install -y $SWIFT_PACKAGES && \ apt install -y $SWIFT_SYMBOLIZER_PACKAGES --no-install-recommends wget -q https://download.swift.org/swift-6.1.3-release/ubuntu2004/swift-6.1.3-RELEASE/swift-6.1.3-RELEASE-ubuntu20.04.tar.gz tar xzf swift-6.1.3-RELEASE-ubuntu20.04.tar.gz cp -r swift-6.1.3-RELEASE-ubuntu20.04/usr/* /usr/ rm -rf swift-6.1.3-RELEASE-ubuntu20.04.tar.gz swift-6.1.3-RELEASE-ubuntu20.04/ # TODO: Move to a seperate work dir git clone https://github.com/llvm/llvm-project.git cd llvm-project git checkout 63bf228450b8403e0c5e828d276be47ffbcd00d0 # TODO: Keep in sync with base-clang. git apply ../llvmsymbol.diff --verbose cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_TARGETS_TO_BUILD=X86 \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_BUILD_TESTS=OFF \ -DLLVM_INCLUDE_TESTS=OFF llvm ninja -j$(nproc) llvm-symbolizer cp bin/llvm-symbolizer /usr/local/bin/llvm-symbolizer-swift cd $SRC rm -rf llvm-project llvmsymbol.diff # TODO: Cleanup packages apt-get remove --purge -y wget apt-get autoremove -y ================================================ FILE: infra/base-images/base-builder/install_swift_ubuntu-20-04.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SWIFT_PACKAGES="wget \ binutils \ git \ gnupg2 \ libc6-dev \ libcurl4 \ libedit2 \ libgcc-9-dev \ libpython2.7 \ libsqlite3-0 \ libstdc++-9-dev \ libxml2 \ libz3-dev \ pkg-config \ tzdata \ uuid-dev \ zlib1g-dev" SWIFT_SYMBOLIZER_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev" apt-get update && apt install -y $SWIFT_PACKAGES && \ apt install -y $SWIFT_SYMBOLIZER_PACKAGES --no-install-recommends wget -q https://download.swift.org/swift-6.1.3-release/ubuntu2004/swift-6.1.3-RELEASE/swift-6.1.3-RELEASE-ubuntu20.04.tar.gz tar xzf swift-6.1.3-RELEASE-ubuntu20.04.tar.gz cp -r swift-6.1.3-RELEASE-ubuntu20.04/usr/* /usr/ rm -rf swift-6.1.3-RELEASE-ubuntu20.04.tar.gz swift-6.1.3-RELEASE-ubuntu20.04/ # TODO: Move to a seperate work dir git clone https://github.com/llvm/llvm-project.git cd llvm-project git checkout 63bf228450b8403e0c5e828d276be47ffbcd00d0 # TODO: Keep in sync with base-clang. git apply ../llvmsymbol.diff --verbose cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_TARGETS_TO_BUILD=X86 \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_BUILD_TESTS=OFF \ -DLLVM_INCLUDE_TESTS=OFF llvm ninja -j$(nproc) llvm-symbolizer cp bin/llvm-symbolizer /usr/local/bin/llvm-symbolizer-swift cd $SRC rm -rf llvm-project llvmsymbol.diff # TODO: Cleanup packages apt-get remove --purge -y wget apt-get autoremove -y ================================================ FILE: infra/base-images/base-builder/install_swift_ubuntu-24-04.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Detect Ubuntu version source /etc/os-release if [[ "$VERSION_ID" == "20.04" ]]; then SWIFT_PACKAGES="wget \ binutils \ git \ gnupg2 \ libc6-dev \ libcurl4 \ libedit2 \ libgcc-9-dev \ libpython2.7 \ libsqlite3-0 \ libstdc++-9-dev \ libxml2 \ libz3-dev \ pkg-config \ tzdata \ uuid-dev \ zlib1g-dev" SWIFT_URL="https://download.swift.org/swift-6.1.3-release/ubuntu2004/swift-6.1.3-RELEASE/swift-6.1.3-RELEASE-ubuntu20.04.tar.gz" SWIFT_DIR="swift-6.1.3-RELEASE-ubuntu20_04" elif [[ "$VERSION_ID" == "24.04" ]]; then SWIFT_PACKAGES="wget \ binutils \ git \ gnupg2 \ libc6-dev \ libcurl4-openssl-dev \ libedit2 \ libgcc-13-dev \ libncurses-dev \ libpython3-dev \ libsqlite3-0 \ libstdc++-13-dev \ libxml2-dev \ libz3-dev \ pkg-config \ tzdata \ zip \ unzip \ zlib1g-dev" SWIFT_URL="https://download.swift.org/swift-6.1.3-release/ubuntu2404/swift-6.1.3-RELEASE/swift-6.1.3-RELEASE-ubuntu24.04.tar.gz" SWIFT_DIR="swift-6.1.3-RELEASE-ubuntu24.04" else echo "Unsupported Ubuntu version: $VERSION_ID" exit 1 fi SWIFT_SYMBOLIZER_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev" apt-get update && apt install -y $SWIFT_PACKAGES && \ apt install -y $SWIFT_SYMBOLIZER_PACKAGES --no-install-recommends wget -q $SWIFT_URL tar xzf $(basename $SWIFT_URL) cp -r $SWIFT_DIR/usr/* /usr/ rm -rf $(basename $SWIFT_URL) $SWIFT_DIR # TODO: Move to a seperate work dir git clone https://github.com/llvm/llvm-project.git cd llvm-project git checkout 63bf228450b8403e0c5e828d276be47ffbcd00d0 # TODO: Keep in sync with base-clang. git apply ../llvmsymbol.diff --verbose cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_TARGETS_TO_BUILD=X86 \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_BUILD_TESTS=OFF \ -DLLVM_INCLUDE_TESTS=OFF llvm ninja -j$(nproc) llvm-symbolizer cp bin/llvm-symbolizer /usr/local/bin/llvm-symbolizer-swift cd $SRC rm -rf llvm-project llvmsymbol.diff # TODO: Cleanup packages apt-get remove --purge -y wget apt-get autoremove -y ================================================ FILE: infra/base-images/base-builder/jcc/build_jcc.bash ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go build jcc.go go build jcc2.go gsutil cp jcc gs://clusterfuzz-builds/jcc/clang++-jcc gsutil cp jcc gs://clusterfuzz-builds/jcc/clang-jcc gsutil cp jcc2 gs://clusterfuzz-builds/jcc/clang++-jcc2 gsutil cp jcc2 gs://clusterfuzz-builds/jcc/clang-jcc2 ================================================ FILE: infra/base-images/base-builder/jcc/go.mod ================================================ module github.com/google/jcc go 1.21 ================================================ FILE: infra/base-images/base-builder/jcc/jcc.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "bytes" "fmt" "log" "os" "os/exec" "path/filepath" ) func ExecBuildCommand(bin string, args []string) (int, string, string) { // Executes the original command. cmd := exec.Command(bin, args...) var outb, errb bytes.Buffer cmd.Stdout = &outb cmd.Stderr = &errb cmd.Stdin = os.Stdin cmd.Run() return cmd.ProcessState.ExitCode(), outb.String(), errb.String() } func Compile(bin string, args []string) (int, string, string) { // Run the actual command. return ExecBuildCommand(bin, args) } func AppendStringToFile(filepath, new_content string) error { // Appends |new_content| to the content of |filepath|. file, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer file.Close() _, err = file.WriteString(new_content) return err } func WriteStdErrOut(args []string, outstr string, errstr string) { // Prints |outstr| to stdout, prints |errstr| to stderr, and saves |errstr| to err.log. fmt.Print(outstr) fmt.Fprint(os.Stderr, errstr) // Record what compile args produced the error and the error itself in log file. AppendStringToFile("/tmp/err.log", fmt.Sprintf("%s\n", args)+errstr) } func main() { f, err := os.OpenFile("/tmp/jcc.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Println(err) } defer f.Close() if _, err := f.WriteString(fmt.Sprintf("%s\n", os.Args)); err != nil { log.Println(err) } args := os.Args[1:] basename := filepath.Base(os.Args[0]) isCPP := basename == "clang++-jcc" newArgs := args var bin string if isCPP { bin = "clang++" } else { bin = "clang" } fullCmdArgs := append([]string{bin}, newArgs...) retcode, out, errstr := Compile(bin, newArgs) WriteStdErrOut(fullCmdArgs, out, errstr) os.Exit(retcode) } ================================================ FILE: infra/base-images/base-builder/jcc/jcc2.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "bytes" "encoding/json" "errors" "fmt" "io/fs" "io/ioutil" "log" "os" "os/exec" "path/filepath" "regexp" "strings" ) var MaxMissingHeaderFiles = 10 var CppifyHeadersMagicString = "\n/* JCCCppifyHeadersMagicString */\n" func CopyFile(src string, dst string) { contents, err := ioutil.ReadFile(src) if err != nil { panic(err) } err = ioutil.WriteFile(dst, contents, 0644) if err != nil { panic(err) } } func TryFixCCompilation(cmdline []string) ([]string, int, string, string) { var newFile string = "" for i, arg := range cmdline { if !strings.HasSuffix(arg, ".c") { continue } if _, err := os.Stat(arg); errors.Is(err, os.ErrNotExist) { continue } newFile = strings.TrimSuffix(arg, ".c") newFile += ".cpp" CopyFile(arg, newFile) CppifyHeaderIncludesFromFile(newFile) cmdline[i] = newFile break } if newFile == "" { return []string{}, 1, "", "" } cppBin := "clang++" newCmdline := []string{"-stdlib=libc++"} newCmdline = append(cmdline, newCmdline...) newFullArgs := append([]string{cppBin}, newCmdline...) retcode, out, err := Compile(cppBin, newCmdline) if retcode == 0 { return newFullArgs, retcode, out, err } correctedCmdline, corrected, _ := CorrectMissingHeaders(cppBin, newCmdline) if corrected { return append([]string{cppBin}, correctedCmdline...), 0, "", "" } return newFullArgs, retcode, out, err } func ExtractMissingHeader(compilerOutput string) (string, bool) { r := regexp.MustCompile(`fatal error: ['|<](?P
[a-zA-z0-9\/\.]+)['|>] file not found`) matches := r.FindStringSubmatch(compilerOutput) if len(matches) == 0 { return "", false } return matches[1], true } func ReplaceMissingHeaderInFile(srcFilename, curHeader, replacementHeader string) error { srcFile, err := os.Open(srcFilename) if err != nil { return err } srcBytes, err := ioutil.ReadAll(srcFile) if err != nil { return err } src := string(srcBytes) newSrc := ReplaceMissingHeader(src, curHeader, replacementHeader) b := []byte(newSrc) err = ioutil.WriteFile(srcFilename, b, 0644) if err != nil { return err } return nil } func ReplaceMissingHeader(src, curHeader, replacementHeader string) string { re := regexp.MustCompile(`#include ["|<]` + curHeader + `["|>]\n`) replacement := "#include \"" + replacementHeader + "\"\n" return re.ReplaceAllString(src, replacement) } func GetHeaderCorrectedFilename(compilerErr string) (string, string, bool) { re := regexp.MustCompile(`(?P[a-z\/\-\_0-9A-z\.]+):.* fatal error: .* file not found`) matches := re.FindStringSubmatch(compilerErr) if len(matches) < 2 { return "", "", false } oldFilename := matches[1] base := filepath.Base(oldFilename) root := filepath.Dir(oldFilename) newFilename := root + "/jcc-corrected-" + base return oldFilename, newFilename, true } func GetHeaderCorrectedCmd(cmd []string, compilerErr string) ([]string, string, error) { oldFilename, newFilename, success := GetHeaderCorrectedFilename(compilerErr) if !success { return cmd, "", errors.New("Couldn't find buggy file") } // Make new cmd. newCmd := make([]string, len(cmd)) for i, part := range cmd { newCmd[i] = part } found := false for i, filename := range newCmd { if filename == oldFilename { newCmd[i] = newFilename found = true break } } CopyFile(oldFilename, newFilename) if found { return newCmd, newFilename, nil } return cmd, "", errors.New("Couldn't find file") } func CorrectMissingHeaders(bin string, cmd []string) ([]string, bool, error) { _, _, stderr := Compile(bin, cmd) cmd, correctedFilename, err := GetHeaderCorrectedCmd(cmd, stderr) if err != nil { return cmd, false, err } for i := 0; i < MaxMissingHeaderFiles; i++ { fixed, hasBrokenHeaders := TryCompileAndFixHeadersOnce(bin, cmd, correctedFilename) if fixed { return cmd, true, nil } if !hasBrokenHeaders { return cmd, false, nil } } return cmd, false, nil } func ExecBuildCommand(bin string, args []string) (int, string, string) { // Executes the original command. cmd := exec.Command(bin, args...) var outb, errb bytes.Buffer cmd.Stdout = &outb cmd.Stderr = &errb cmd.Stdin = os.Stdin cmd.Run() return cmd.ProcessState.ExitCode(), outb.String(), errb.String() } func Compile(bin string, args []string) (int, string, string) { // Run the actual command. return ExecBuildCommand(bin, args) } func TryCompileAndFixHeadersOnce(bin string, cmd []string, filename string) (fixed, hasBrokenHeaders bool) { retcode, _, err := Compile(bin, cmd) if retcode == 0 { fixed = true hasBrokenHeaders = false return } missingHeader, isMissing := ExtractMissingHeader(err) if !isMissing { fixed = false hasBrokenHeaders = false return } newHeaderPath, found := FindMissingHeader(missingHeader) if !found { fixed = false hasBrokenHeaders = true return false, true } ReplaceMissingHeaderInFile(filename, missingHeader, newHeaderPath) return false, true } func FindMissingHeader(missingHeader string) (string, bool) { envVar := "JCC_MISSING_HEADER_SEARCH_PATH" var searchPath string searchPath, exists := os.LookupEnv(envVar) if !exists { searchPath = "/src" } searchPath, _ = filepath.Abs(searchPath) var headerLocation string missingHeader = "/" + missingHeader find := func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { return nil } if strings.HasSuffix(path, missingHeader) { headerLocation = path return nil } return nil } filepath.WalkDir(searchPath, find) if headerLocation == "" { return "", false } return headerLocation, true } func CppifyHeaderIncludesFromFile(srcFile string) error { contentsBytes, err := ioutil.ReadFile(srcFile) if err != nil { return err } contents := string(contentsBytes[:]) contents, err = CppifyHeaderIncludes(contents) if err != nil { return err } b := []byte(contents) err = ioutil.WriteFile(srcFile, b, 0644) return err } func CppifyHeaderIncludes(contents string) (string, error) { shouldCppify, exists := os.LookupEnv("JCC_CPPIFY_PROJECT_HEADERS") if !exists || strings.Compare(shouldCppify, "0") == 0 { return contents, nil } if strings.Contains(contents, CppifyHeadersMagicString) { return contents, nil } re := regexp.MustCompile(`\#include \"(?P
.+)\"\n`) matches := re.FindAllStringSubmatch(contents, -1) if len(matches) == 0 { return "", nil // !!! } for i, match := range matches { if i == 0 { // So we don't cppify twice. contents += CppifyHeadersMagicString } oldStr := match[0] replacement := "extern \"C\" {\n#include \"" + match[1] + "\"\n}\n" contents = strings.Replace(contents, oldStr, replacement, 1) if strings.Compare(contents, "") == 0 { panic("Failed to replace") } } return contents, nil } func AppendStringToFile(filepath, new_content string) error { // Appends |new_content| to the content of |filepath|. file, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { return err } defer file.Close() _, err = file.WriteString(new_content) return err } func WriteStdErrOut(args []string, outstr string, errstr string) { // Prints |outstr| to stdout, prints |errstr| to stderr, and saves |errstr| to err.log. fmt.Print(outstr) fmt.Fprint(os.Stderr, errstr) // Record what compile args produced the error and the error itself in log file. AppendStringToFile("/workspace/err.log", fmt.Sprintf("%s\n", args)+errstr) } func main() { f, err := os.OpenFile("/tmp/jcc.log", os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Println(err) } defer f.Close() if _, err := f.WriteString(fmt.Sprintf("%s\n", os.Args)); err != nil { log.Println(err) } args := os.Args[1:] if args[0] == "unfreeze" { fmt.Println("unfreeze") unfreeze() } basename := filepath.Base(os.Args[0]) isCPP := basename == "clang++-jcc" newArgs := append(args, "-w") var bin string if isCPP { bin = "clang++" newArgs = append(args, "-stdlib=libc++") } else { bin = "clang" } fullCmdArgs := append([]string{bin}, newArgs...) if IsCompilingTarget(fullCmdArgs) { WriteTargetArgsAndCommitImage(fullCmdArgs) os.Exit(0) } retcode, out, errstr := Compile(bin, newArgs) WriteStdErrOut(fullCmdArgs, out, errstr) os.Exit(retcode) } type BuildCommand struct { CWD string `json:"CWD"` CMD []string `json:"CMD"` } func WriteTargetArgsAndCommitImage(cmdline []string) { log.Println("WRITE COMMAND") f, _ := os.OpenFile("/out/statefile.json", os.O_CREATE|os.O_WRONLY, 0644) wd, _ := os.Getwd() buildcmd := BuildCommand{ CWD: wd, CMD: cmdline, } jsonData, _ := json.Marshal(buildcmd) f.Write(jsonData) f.Close() hostname, _ := os.Hostname() dockerArgs := []string{"commit", hostname, "frozen"} cmd := exec.Command("docker", dockerArgs...) var outb, errb bytes.Buffer cmd.Stdout = &outb cmd.Stderr = &errb cmd.Stdin = os.Stdin cmd.Run() fmt.Println(outb.String(), errb.String()) fmt.Println("COMMIT IMAGE") } func IsCompilingTarget(cmdline []string) bool { for _, arg := range cmdline { // This can fail if people do crazy things they aren't supposed // to such as using some other means to link in libFuzzer. if arg == "-fsanitize=fuzzer" { return true } if arg == "-lFuzzingEngine" { return true } } return false } func parseCommand(command string) (string, []string) { args := strings.Fields(command) commandBin := args[0] commandArgs := args[1:] return commandBin, commandArgs } func unfreeze() { content, err := ioutil.ReadFile("/out/statefile.json") if err != nil { log.Fatal(err) } var command BuildCommand json.Unmarshal(content, &command) bin, args := parseCommand(strings.Join(command.CMD, " ")) os.Chdir(command.CWD) ExecBuildCommand(bin, args) os.Exit(0) } ================================================ FILE: infra/base-images/base-builder/jcc/jcc_test.go ================================================ package main import ( "fmt" "os" "strings" "testing" ) func TestExtractMissingHeader(t *testing.T) { missingHeaderMessage := `path/to/file.cpp:8:10: fatal error: 'missingheader.h' file not found #include "missingheader.h" ^~~~~~~~~~~~ 1 error generated. ` res, _ := ExtractMissingHeader(missingHeaderMessage) expected := "missingheader.h" if strings.Compare(res, expected) != 0 { t.Errorf("Got: %s. Expected: %s.", res, expected) } } func TestGetHeaderCorrectedFilename(t *testing.T) { missingHeaderMessage := `path/to/file.cpp:8:10: fatal error: 'missingheader.h' file not found #include "missingheader.h" ^~~~~~~~~~~~ 1 error generated. ` _, correctedFilename, _ := GetHeaderCorrectedFilename(missingHeaderMessage) expected := "path/to/jcc-corrected-file.cpp" if strings.Compare(correctedFilename, expected) != 0 { t.Errorf("Got: %s. Expected: %s.", correctedFilename, expected) } } func TestFindMissingHeader(t *testing.T) { pwd, _ := os.Getwd() t.Setenv("JCC_MISSING_HEADER_SEARCH_PATH", pwd) location, _ := FindMissingHeader("header.h") expected := pwd + "/testdata/path/to/header.h" if strings.Compare(location, expected) != 0 { t.Errorf("Got: %s. Expected: %s.", location, expected) } } func TestCorrectMissingHeaders(t *testing.T) { pwd, _ := os.Getwd() t.Setenv("JCC_MISSING_HEADER_SEARCH_PATH", pwd) cfile := pwd + "/testdata/cfile.c" cmd := [4]string{"-fsanitize=address", cfile, "-o", "/tmp/blah"} res, err := CorrectMissingHeaders("clang", cmd[:]) if !res { fmt.Println(err) t.Errorf("Expected successful compilation") } } func TestGetHeaderCorrectedCmd(t *testing.T) { compilerErr := `testdata/cpp.cc:8:10: fatal error: 'missingheader.h' file not found #include "missingheader.h" ^~~~~~~~~~~~ 1 error generated. ` cmd := [3]string{"-fsanitize=address", "file.cpp", "path/to/cpp.cc"} expectedFixedCmd := [3]string{"-fanitize=address", "file.cpp", "path/to/jcc-corrected-cpp.cc"} fixedCmd, _, _ := GetHeaderCorrectedCmd(cmd[:], compilerErr) if strings.Compare(fixedCmd[1], expectedFixedCmd[1]) != 0 { t.Errorf("Expected %s, got: %s", expectedFixedCmd, fixedCmd) } } func TestCppifyHeaderIncludes(t *testing.T) { t.Setenv("JCC_CPPIFY_PROJECT_HEADERS", "1") src := `// Copyright blah #include #include "fuzz.h" #include "x/y.h" extern "C" LLVMFuzzerTestOneInput(uint8_t* data, size_t sz) { return 0; }` newFile, _ := CppifyHeaderIncludes(src) expected := `// Copyright blah #include extern "C" { #include "fuzz.h" } extern "C" { #include "x/y.h" } extern "C" LLVMFuzzerTestOneInput(uint8_t* data, size_t sz) { return 0; } /* JCCCppifyHeadersMagicString */ ` if strings.Compare(newFile, expected) != 0 { t.Errorf("Expected: %s, got: %s", expected, newFile) } } func TestCppifyHeaderIncludesShouldnt(t *testing.T) { src := `// Copyright blah #include #include "fuzz.h" #include "x/y.h" extern "C" LLVMFuzzerTestOneInput(uint8_t* data, size_t sz) { return 0; }` newFile, _ := CppifyHeaderIncludes(src) if strings.Compare(newFile, src) != 0 { t.Errorf("Expected: %s. Got: %s", src, newFile) } } func TestCppifyHeaderIncludesAlready(t *testing.T) { src := `// Copyright blah #include #include "fuzz.h" #include "x/y.h" extern "C" LLVMFuzzerTestOneInput(uint8_t* data, size_t sz) { return 0; } /* JCCCppifyHeadersMagicString */ ` newFile, _ := CppifyHeaderIncludes(src) if strings.Compare(newFile, src) != 0 { t.Errorf("Expected %s, got: %s", src, newFile) } } func TestExtractMissingHeaderNonHeaderFailure(t *testing.T) { missingHeaderMessage := `clang: error: no such file or directory: 'x' clang: error: no input files` header, res := ExtractMissingHeader(missingHeaderMessage) if res { t.Errorf("Expected no match, got: %s", header) } } func TestReplaceMissingHeader(t *testing.T) { cfile := `// Copyright 2035 Robots #include #include // Some libraries like OpenSSL will use brackets for their own headers. #include int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { return 0; } ` res := ReplaceMissingHeader(cfile, "missingheader.h", "path/to/includes/missingheader.h") expected := `// Copyright 2035 Robots #include #include // Some libraries like OpenSSL will use brackets for their own headers. #include "path/to/includes/missingheader.h" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { return 0; } ` if strings.Compare(res, expected) != 0 { t.Errorf("Got: %s. Expected: %s.", res, expected) } } ================================================ FILE: infra/base-images/base-builder/jcc/testdata/.gitignore ================================================ jcc-corrected-cfile.c jcc-corrected-cfile.cpp ================================================ FILE: infra/base-images/base-builder/jcc/testdata/cfile.c ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "header.h" int main() { return 0; } ================================================ FILE: infra/base-images/base-builder/jcc/testdata/cpp.cc ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "header.h" int main() { return 0; } ================================================ FILE: infra/base-images/base-builder/jcc/testdata/path/to/header.h ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. int xhg(void); ================================================ FILE: infra/base-images/base-builder/llvmsymbol.diff ================================================ diff --git a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt index acfb3bd0e..a499ee2e0 100644 --- a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt +++ b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt @@ -12,4 +12,8 @@ add_llvm_component_library(LLVMSymbolize Object Support Demangle - ) + + LINK_LIBS + /usr/lib/swift_static/linux/libswiftCore.a + /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +) diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index fb4875f79..0030769ee 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -36,6 +36,13 @@ #include #include + +extern "C" char *swift_demangle(const char *mangledName, + size_t mangledNameLength, + char *outputBuffer, + size_t *outputBufferSize, + uint32_t flags); + namespace llvm { namespace symbolize { @@ -678,6 +685,14 @@ LLVMSymbolizer::DemangleName(const std::string &Name, free(DemangledName); return Result; } + if (!Name.empty() && Name.front() == '$') { + char *DemangledName = swift_demangle(Name.c_str(), Name.length(), 0, 0, 0); + if (DemangledName) { + std::string Result = DemangledName; + free(DemangledName); + return Result; + } + } if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) return std::string(demanglePE32ExternCFunc(Name)); ================================================ FILE: infra/base-images/base-builder/make_build_replayable.py ================================================ #!/usr/bin/env python3 # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #!/usr/bin/env python import os import shutil _REAL_SUFFIX = '.real' _WRAPPER_TEMPLATE = """#!/usr/bin/env python3 import sys import os def main(): target = sys.argv[0] + '.real' {contents} os.execv(target, sys.argv) if __name__ == '__main__': main() """ def create_wrapper(contents: str): return _WRAPPER_TEMPLATE.format(contents=contents) def main(): dummy_script_content = '#!/bin/sh' dummy_scripts = [ '/usr/bin/autoconf', '/usr/bin/autoheader', '/usr/bin/autom4te', '/usr/bin/automake', '/usr/bin/autopoint', '/usr/bin/autoreconf', '/usr/bin/autoscan', '/usr/bin/autoupdate', # Applying patches is not idempotent. '/usr/bin/patch', ] for script_path in dummy_scripts: with open(script_path, 'w') as f: f.write(dummy_script_content) os.chmod(script_path, 0o755) files_to_move = ( '/usr/bin/cmake', '/usr/local/bin/cmake', '/bin/sh', '/bin/bash', '/usr/bin/git', '/usr/bin/ln', '/usr/bin/make', '/usr/bin/meson', '/usr/bin/mkdir', '/usr/bin/zip', ) for src in files_to_move: if os.path.exists(src): shutil.move(src, src + _REAL_SUFFIX) # Create a shell wrapper that stubs out `configure` and `autogen`. with open('/bin/sh', 'w') as f: f.write( create_wrapper(""" if any(os.path.basename(arg) in ('configure', 'autogen.sh') for arg in sys.argv[1:]): sys.exit(0) """)) shutil.copyfile('/bin/sh', '/bin/bash') # Stub out `make clean`. with open('/usr/bin/make', 'w') as f: f.write( create_wrapper(""" if any(arg == 'clean' for arg in sys.argv[1:]): sys.exit(0) """)) # Stub out `meson setup`. with open('/usr/bin/meson', 'w') as f: f.write( create_wrapper(""" if any(arg == 'setup' for arg in sys.argv[1:]): sys.exit(0) """)) # Stub out cmake, but allow cmake --build, --install, -E (command mode), -P # (script mode). with open('/usr/bin/cmake', 'w') as f: f.write( create_wrapper(""" if not any(arg in ('--build', '--install', '-E', '-P', '--version') for arg in sys.argv[1:]): sys.exit(0) """)) shutil.copyfile('/usr/bin/cmake', '/usr/local/bin/cmake') # Add -p to mkdir calls to allow it to be run twice. with open('/usr/bin/mkdir', 'w') as f: f.write( create_wrapper(""" if not any(arg == '-p' for arg in sys.argv[1:]): sys.argv.insert(1, '-p') """)) # Don't zip something that already exists. with open('/usr/bin/zip', 'w') as f: f.write( create_wrapper(""" if (any(arg.endswith('.zip') and os.path.exists(arg) for arg in sys.argv[1:])): sys.exit(0) """)) # Add -f to ln. with open('/usr/bin/ln', 'w') as f: f.write( create_wrapper(""" if not any(arg == '-f' for arg in sys.argv[1:]): sys.argv.insert(1, '-f') """)) # Don't allow git `reset` or `clean` or `apply`. # reset/clean might remove build artifacts. # clone is not idempotent. # applying patches is not idempotent. with open('/usr/bin/git', 'w') as f: f.write( create_wrapper(""" if any(arg in ('clean', 'clone', 'reset', 'apply', 'submodule') for arg in sys.argv[1:]): sys.exit(0) """)) for file_path in files_to_move: if os.path.exists(file_path): os.chmod(file_path, 0o755) if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/ossfuzz_coverage_runner.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mypackagebeingfuzzed import ( "io/ioutil" "os" "runtime/pprof" "testing" ) func TestFuzzCorpus(t *testing.T) { dir := os.Getenv("FUZZ_CORPUS_DIR") if dir == "" { t.Logf("No fuzzing corpus directory set") return } infos, err := ioutil.ReadDir(dir) if err != nil { t.Logf("Not fuzzing corpus directory %s", err) return } filename := "" defer func() { if r := recover(); r != nil { t.Error("Fuzz panicked in "+filename, r) } }() profname := os.Getenv("FUZZ_PROFILE_NAME") if profname != "" { f, err := os.Create(profname + ".cpu.prof") if err != nil { t.Logf("error creating profile file %s\n", err) } else { _ = pprof.StartCPUProfile(f) } } for i := range infos { filename = dir + infos[i].Name() data, err := ioutil.ReadFile(filename) if err != nil { t.Error("Failed to read corpus file", err) } FuzzFunction(data) } if profname != "" { pprof.StopCPUProfile() f, err := os.Create(profname + ".heap.prof") if err != nil { t.Logf("error creating heap profile file %s\n", err) } if err = pprof.WriteHeapProfile(f); err != nil { t.Logf("error writing heap profile file %s\n", err) } f.Close() } } ================================================ FILE: infra/base-images/base-builder/precompile_afl ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Precompiling AFLplusplus" pushd $SRC/aflplusplus > /dev/null make clean # Unset CFLAGS and CXXFLAGS while building AFL since we don't want to slow it # down with sanitizers. SAVE_CXXFLAGS=$CXXFLAGS SAVE_CFLAGS=$CFLAGS unset CXXFLAGS unset CFLAGS export AFL_IGNORE_UNKNOWN_ENVS=1 make clean AFL_NO_X86=1 PYTHON_INCLUDE=/ make make -C utils/aflpp_driver popd > /dev/null echo "Done." ================================================ FILE: infra/base-images/base-builder/precompile_centipede ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo -n "Precompiling centipede" # Build Centipede with bazel. cd "$SRC/fuzztest/centipede/" apt-get update && apt-get install libssl-dev -y unset CXXFLAGS CFLAGS # We need to use an older version of BAZEL because fuzztest relies on WORKSPACE # Ref: https://github.com/google/oss-fuzz/pull/12838#issue-2733821058 export USE_BAZEL_VERSION=7.4.0 echo 'build --cxxopt=-stdlib=libc++ --linkopt=-lc++' >> /tmp/centipede.bazelrc bazel --bazelrc=/tmp/centipede.bazelrc build -c opt :all unset USE_BAZEL_VERSION # Prepare the weak symbols: # This is necessary because we compile the target binary and the intermediate # auxiliary binaries with the same cflags. The auxiliary binaries do not need # data-flow tracing flags, but will still throw errors when they cannot find # the corresponding functions. # The weak symbols provides fake implementations for intermediate binaries. $CXX "$SRC/fuzztest/centipede/weak_sancov_stubs.cc" -c -o "$SRC/fuzztest/centipede/weak.o" echo 'Removing extra stuff leftover to avoid bloating image.' rm -rf /clang-*.tgz /clang BAZEL_BIN_REAL_DIR=$(readlink -f $CENTIPEDE_BIN_DIR) rm -rf $CENTIPEDE_BIN_DIR mkdir -p $CENTIPEDE_BIN_DIR mv $BAZEL_BIN_REAL_DIR/centipede/{centipede,libcentipede_runner.pic.a} $CENTIPEDE_BIN_DIR rm -rf /root/.cache echo 'Done.' ================================================ FILE: infra/base-images/base-builder/precompile_honggfuzz ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Precompiling honggfuzz" export BUILD_OSSFUZZ_STATIC=true PACKAGES=( libunwind8-dev libblocksruntime-dev liblzma-dev libiberty-dev zlib1g-dev pkg-config) apt-get update && apt-get install -y ${PACKAGES[@]} pushd $SRC/honggfuzz > /dev/null make clean # These CFLAGs match honggfuzz's default, with the exception of -mtune to # improve portability and `-D_HF_LINUX_NO_BFD` to remove assembly instructions # from the filenames. sed -i 's/-Werror//g' Makefile CC=clang CFLAGS="-O3 -funroll-loops -D_HF_LINUX_NO_BFD -Wno-unterminated-string-initialization -Wno-error" make # libhfuzz.a will be added by CC/CXX linker directly during linking, # but it's defined here to satisfy the build infrastructure ar rcs honggfuzz.a libhfuzz/*.o libhfcommon/*.o popd > /dev/null apt-get remove -y --purge ${PACKAGES[@]} apt-get autoremove -y echo "Done." ================================================ FILE: infra/base-images/base-builder/precompile_honggfuzz_ubuntu_20_04 ================================================ #!/bin/bash -eux # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Precompiling honggfuzz" export BUILD_OSSFUZZ_STATIC=true PACKAGES=( libunwind8-dev libblocksruntime-dev liblzma-dev libiberty-dev zlib1g-dev pkg-config) apt-get update && apt-get install -y ${PACKAGES[@]} pushd $SRC/honggfuzz > /dev/null make clean # These CFLAGs match honggfuzz's default, with the exception of -mtune to # improve portability and `-D_HF_LINUX_NO_BFD` to remove assembly instructions # from the filenames. sed -i 's/-Werror//g' Makefile CC=clang CFLAGS="-O3 -funroll-loops -D_HF_LINUX_NO_BFD -Wno-unterminated-string-initialization -Wno-error" make # libhfuzz.a will be added by CC/CXX linker directly during linking, # but it's defined here to satisfy the build infrastructure ar rcs honggfuzz.a libhfuzz/*.o libhfcommon/*.o popd > /dev/null apt-get remove -y --purge ${PACKAGES[@]} apt-get autoremove -y echo "Done." ================================================ FILE: infra/base-images/base-builder/precompile_honggfuzz_ubuntu_24_04 ================================================ #!/bin/bash -eux # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "Precompiling honggfuzz" export BUILD_OSSFUZZ_STATIC=true PACKAGES=( libunwind8-dev libblocksruntime-dev liblzma-dev libiberty-dev zlib1g-dev pkg-config) apt-get update && apt-get install -y ${PACKAGES[@]} pushd $SRC/honggfuzz > /dev/null make clean # These CFLAGs match honggfuzz's default, with the exception of -mtune to # improve portability and `-D_HF_LINUX_NO_BFD` to remove assembly instructions # from the filenames. sed -i 's/-Werror//g' Makefile CC=clang CFLAGS="-O3 -funroll-loops -D_HF_LINUX_NO_BFD -Wno-unterminated-string-initialization -Wno-error" make LDFLAGS="-lBlocksRuntime -lunwind-ptrace -lunwind-generic" # libhfuzz.a will be added by CC/CXX linker directly during linking, # but it's defined here to satisfy the build infrastructure ar rcs honggfuzz.a libhfuzz/*.o libhfcommon/*.o popd > /dev/null apt-get remove -y --purge ${PACKAGES[@]} apt-get autoremove -y echo "Done." ================================================ FILE: infra/base-images/base-builder/python_coverage_helper.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Extracts file paths to copy files from pyinstaller-generated executables""" import os import sys import shutil import zipfile # Finds all *.toc files in ./workpath and reads these files in order to # identify Python files associated with a pyinstaller packaged executable. # Copies all of the Python files to a temporary directory (/medio) following # the original directory structure. def get_all_files_from_toc(toc_file, file_path_set): """ Extract filepaths from a .toc file and add to file_path_set """ with open(toc_file, 'rb') as toc_file_fd: for line in toc_file_fd: try: line = line.decode() except: # pylint:disable=bare-except continue if '.py' not in line: continue split_line = line.split(' ') for word in split_line: word = word.replace('\'', '').replace(',', '').replace('\n', '') if '.py' not in word: continue # Check if .egg is in the path and if so we need to split it if os.path.isfile(word): file_path_set.add(word) elif '.egg' in word: # check if this is an egg egg_path_split = word.split('.egg') if len(egg_path_split) != 2: continue egg_path = egg_path_split[0] + '.egg' if not os.path.isfile(egg_path): continue print('Unzipping contents of %s' % egg_path) # We have an egg. This needs to be unzipped and then replaced # with the unzipped data. tmp_dir_name = 'zipdcontents' if os.path.isdir(tmp_dir_name): shutil.rmtree(tmp_dir_name) # unzip egg and replace path with unzipped content with zipfile.ZipFile(egg_path, 'r') as zip_f: zip_f.extractall(tmp_dir_name) os.remove(egg_path) shutil.copytree(tmp_dir_name, egg_path) # Now the lines should be accessible, so check again if os.path.isfile(word): file_path_set.add(word) def create_file_structure_from_tocs(work_path, out_path): """ Extract the Python files that are added as paths in the output of a pyinstaller operation. The files are determined by reading through all of the *.toc files in the workpath of pyinstaller. The files will be copied into the out_path using a similar file path as they originally are. If any archive (.egg) files are present in the .toc files, then unzip the archives and substitute the archive for the unzipped content, i.e. we will extract the archives and collect the source files. """ print('Extracts files from the pyinstaller workpath') file_path_set = set() for path1 in os.listdir(work_path): full_path = os.path.join(work_path, path1) if not os.path.isdir(full_path): continue # We have a directory for path2 in os.listdir(full_path): if not '.toc' in path2: continue full_toc_file = os.path.join(full_path, path2) get_all_files_from_toc(full_toc_file, file_path_set) for file_path in file_path_set: relative_src = file_path[1:] if file_path[0] == '/' else file_path dst_path = os.path.join(out_path, relative_src) os.makedirs(os.path.dirname(dst_path), exist_ok=True) shutil.copy(file_path, dst_path) def main(): """ Main handler. """ if len(sys.argv) != 3: print('Use: python3 python_coverage_helper.py pyinstaller_workpath ' 'destination_for_output') sys.exit(1) work_path = sys.argv[1] out_path = sys.argv[2] create_file_structure_from_tocs(work_path, out_path) if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/replay_build.sh ================================================ #!/bin/bash -x # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ ! -f /usr/bin/bash.real ]; then # Only run this once. python /usr/local/bin/make_build_replayable.py fi . $SRC/build.sh "$@" ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/.gitignore ================================================ dist pysecsan.egg-info* build .venv ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/LICENSE ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/README.md ================================================ # pysecsan Security sanitizers for vulnerability detection during runtime. ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pyproject.toml ================================================ [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "pysecsan" version = "0.1.0" authors = [ { name="David Korczynski", email="david@adalogics.com" }, ] description = "Sanitizers to detect security vulnerabilities at runtime." readme = "README.md" requires-python = ">=3.7" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", ] [project.urls] "Homepage" = "https://github.com/google/oss-fuzz/tree/master/infra/sanitizers/pysecsan" "Bug Tracker" = "https://github.com/google/oss-fuzz/issues" ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pysecsan/__init__.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Glue for pysecsan library.""" # Import sanlib and expose only needs functionality by way of __all__ from .sanlib import * # pylint: disable=undefined-all-variable __all__ = ['add_hooks'] ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pysecsan/command_injection.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Sanitizers for capturing code injections.""" from typing import Optional from pysecsan import sanlib def get_all_substr_prefixes(main_str, sub_str): """Yields all strings prefixed with sub_str in main_str.""" idx = 0 while True: idx = main_str.find(sub_str, idx) if idx == -1: return yield main_str[0:idx] # Increase idx the length of the substring from the current position # where an occurence of the substring was found. idx += len(sub_str) # pylint: disable=unsubscriptable-object def check_code_injection_match(elem, check_unquoted=False) -> Optional[str]: """identify if elem is an injection match.""" # Check exact match if elem == 'exec-sanitizer': return 'Explicit command injection found.' # Check potential for injecting into a string if 'FROMFUZZ' in elem: if check_unquoted: # return true if any index is unquoted for sub_str in get_all_substr_prefixes(elem, 'FROMFUZZ'): if sub_str.count('\"') % 2 == 0: return 'Fuzzer controlled content in data. Code injection potential.' # Return None if all fuzzer taints were quoted return None return 'Fuzzer-controlled data in command string. Injection potential.' return None # pylint: disable=invalid-name def hook_pre_exec_subprocess_Popen(cmd, **kwargs): """Hook for subprocess.Popen.""" arg_shell = 'shell' in kwargs and kwargs['shell'] # Command injections depend on whether the first argument is a list of # strings or a string. Handle this now. # Example: tests/poe/ansible-runner-cve-2021-4041 if isinstance(cmd, str): res = check_code_injection_match(cmd, check_unquoted=True) if res is not None: # if shell arg is true and string is tainted and unquoted that's a # definite code injection. if arg_shell is True: sanlib.abort_with_issue('Code injection in Popen', 'Command injection') # It's a maybe: will not report this to avoid false positives. # TODO: add more precise detection here. # Check for hg command injection # Example: tests/poe/libvcs-cve-2022-21187 if cmd[0] == 'hg': # Check if the arguments are controlled by the fuzzer, and this given # arg is not preceded by -- found_dashes = False for idx in range(1, len(cmd)): if cmd[0] == '--': found_dashes = True if not found_dashes and check_code_injection_match(cmd[idx]): sanlib.abort_with_issue( 'command injection likely by way of mercurial. The following' f'command {str(cmd)} is executed, and if you substitute {cmd[idx]} ' 'with \"--config=alias.init=!touch HELLO_PY\" then you will ' 'create HELLO_PY', 'Command injection') def hook_pre_exec_os_system(cmd): """Hook for os.system.""" res = check_code_injection_match(cmd) if res is not None: sanlib.abort_with_issue(f'code injection by way of os.system\n{res}', 'Command injection') def hook_pre_exec_eval(cmd, *args, **kwargs): """Hook for eval. Experimental atm.""" res = check_code_injection_match(cmd, check_unquoted=True) if res is not None: sanlib.abort_with_issue(f'Potential code injection by way of eval\n{res}', 'Command injection') ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pysecsan/redos.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Sanitizer for regular expression dos.""" # pylint: disable=protected-access import time import os from pysecsan import sanlib START_RE_TIME = None # Hooks for regular expressions. # Main problem is to identify ReDOS attemps. This is a non-trivial task # - https://arxiv.org/pdf/1701.04045.pdf # - https://dl.acm.org/doi/pdf/10.1145/3236024.3236027 # and the current approach we use is simply check for extensive computing time. # In essence, this is more of a refinement of traditional timeout checker from # the fuzzer, which, effectively will detect these types of attacks by way of # timeouts. # # Perhaps the smartest would be to use something like e.g. # https://github.com/doyensec/regexploit to scan the regex patterns. # Other heuristics without going too technical on identifying super-linear # regexes: # - check # - if 'taint' exists in re.compile(xx) # - check # - for backtracking possbility in PATTERN within re.comile(PATTERN) # - and # - 'taint' in findall(XX) calls. # pylint: disable=global-statement def hook_post_exec_re_pattern_findall(self, re_str): """Hook post exeution re.compile().findall().""" _ = self # Satisfy lint global START_RE_TIME try: endtime = time.time() - START_RE_TIME if endtime > 4: sanlib.abort_with_issue(f'Potential ReDOS attack.\n {re_str}', 'ReDOS') except NameError: sanlib.sanitizer_log( 'starttime is not set, which it should have. Error in PySecSan', sanlib.LOG_INFO) os._exit(1) def hook_pre_exec_re_pattern_findall(self, string): """Hook pre execution of re.pattern().findall().""" _ = (self, string) # Satisfy lint global START_RE_TIME START_RE_TIME = time.time() def hook_post_exec_re_compile(retval, pattern, flags=None): """Hook for re.compile post execution to hook returned objects functions.""" _ = (pattern, flags) # Satisfy lint sanlib.sanitizer_log('Inside of post compile hook', sanlib.LOG_DEBUG) wrapper_object = sanlib.create_object_wrapper( findall=(hook_pre_exec_re_pattern_findall, hook_post_exec_re_pattern_findall)) hooked_object = wrapper_object(retval) return hooked_object def hook_pre_exec_re_compile(pattern, flags=None): """Check if tainted input exists in pattern. If so, likely chance of making ReDOS possible.""" _ = (pattern, flags) # Satisfy lint sanlib.sanitizer_log('Inside re compile hook', sanlib.LOG_DEBUG) ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pysecsan/sanlib.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Core routines for pysecsan library.""" # pylint: disable=protected-access import re import os import functools import subprocess import traceback import importlib.util from typing import Any, Callable, Optional from pysecsan import command_injection, redos, yaml_deserialization LOG_DEBUG = 0 LOG_INFO = 1 PYSECSAN_LOG_LVL = LOG_INFO # Message that will be printed to stdout when an issue is found. PYSECSAN_BUG_LABEL = r'===BUG DETECTED: PySecSan:' # pylint: disable=global-statement def sanitizer_log(msg, log_level, force=False, log_prefix=True): """Helper printing function.""" global PYSECSAN_LOG_LVL if log_level >= PYSECSAN_LOG_LVL or force: if log_prefix: print(f'[PYSECSAN] {msg}') else: print(f'{msg}') def sanitizer_log_always(msg, log_prefix=True): """Wrapper for sanitizer logging. Will always log""" sanitizer_log(msg, 0, force=True, log_prefix=log_prefix) def is_module_present(mod_name): """Identify if module is importable.""" # pylint: disable=deprecated-method return importlib.util.find_spec(mod_name) is not None def _log_bug(bug_title): sanitizer_log_always('%s %s ===' % (PYSECSAN_BUG_LABEL, bug_title), log_prefix=False) def abort_with_issue(msg, bug_title): """Print message, display stacktrace and force process exit. Use this function for signalling an issue is found and use the messages logged from this function to determine if a fuzzer found a bug. """ # Show breaker string using an ASAN approach (uses 65 =) sanitizer_log_always("=" * 65, log_prefix=False) # Log issue message _log_bug(bug_title) sanitizer_log_always(msg) # Log stacktrace sanitizer_log_always("Stacktrace:") traceback.print_stack() # Force exit # Use os._exit here to force exit. sys.exit will exit # by throwing a SystemExit exception which the interpreter # handles by exiting. However, code may catch this exception, # and thus to avoid this we exit the process without exceptions. # pylint: disable=protected-access sanitizer_log_always("Exiting") os._exit(1) def is_exact_taint(stream) -> bool: """Checks if stream is an exact match for taint from fuzzer.""" # The fuzzer has to get 8 characters right. This may be a bit much, # however, when found it shows a high level of control over the data. if stream == 'FROMFUZZ': return True return False def create_object_wrapper(**methods): """Hooks functions in an object. This is needed for hooking built-in types and object attributes. Example use case is if we want to find ReDOS vulnerabilities, that have a pattern of ``` import re r = re.compile(REGEX) for _ in r.findall(...) ``` In the above case r.findall is a reference to re.Pattern.findall, which is a built-in type that is non-writeable. In order to hook such calls we need to wrap the object, and also hook the re.compile function to return the wrapped/hooked object. """ class Wrapper(): """Wrap an object by hiding attributes.""" def __init__(self, instance): object.__setattr__(self, 'instance', instance) def __setattr__(self, name, value): object.__setattr__(object.__getattribute__(self, 'instance'), name, value) def __getattribute__(self, name): instance = object.__getattribute__(self, 'instance') def _hook_func(self, pre_hook, post_hook, orig, *args, **kargs): if pre_hook is not None: pre_hook(self, *args, **kargs) # No need to pass instance here because when we extracted # the function we used instance.__getattribute__(name) which # seems to include it. I think. orig_retval = orig(*args, **kargs) if post_hook is not None: post_hook(self, *args, **kargs) return orig_retval # If this is a wrapped method, return a bound method if name in methods: pre_hook = methods[name][0] post_hook = methods[name][1] orig = instance.__getattribute__(name) return (lambda *args, **kargs: _hook_func(self, pre_hook, post_hook, orig, *args, **kargs)) # Otherwise, just return attribute of instance return instance.__getattribute__(name) return Wrapper # pylint: disable=unsubscriptable-object def add_hook(function: Callable[[Any], Any], pre_exec_hook: Optional[Callable[[Any], Any]] = None, post_exec_hook: Optional[Callable[[Any], Any]] = None): """Hook a function. Hooks can be placed pre and post function call. At least one hook is needed. This hooking is intended on non-object hooks. In order to hook functions in objects the `create_object_wrapper` function is used in combination with function hooking initialisation functions post execution. """ if pre_exec_hook is None and post_exec_hook is None: raise Exception('Some hooks must be included') @functools.wraps(function) def run(*args, **kwargs): sanitizer_log(f'Hook start {str(function)}', LOG_DEBUG) # Call hook if pre_exec_hook is not None: pre_exec_hook(*args, **kwargs) # Call the original function in the even the hook did not indicate # failure. ret = function(*args, **kwargs) # Post execution hook. Overwrite return value if anything is returned # by post hook. if post_exec_hook is not None: tmp_ret = post_exec_hook(ret, *args, **kwargs) if tmp_ret is not None: sanitizer_log('Overwriting return value', LOG_DEBUG) ret = tmp_ret sanitizer_log(f'Hook end {str(function)}', LOG_DEBUG) return ret return run def add_hooks(): """Sets up hooks.""" sanitizer_log('Starting', LOG_INFO) os.system = add_hook(os.system, pre_exec_hook=command_injection.hook_pre_exec_os_system) subprocess.Popen = add_hook( subprocess.Popen, pre_exec_hook=command_injection.hook_pre_exec_subprocess_Popen) __builtins__['eval'] = add_hook( __builtins__['eval'], pre_exec_hook=command_injection.hook_pre_exec_eval) re.compile = add_hook(re.compile, pre_exec_hook=redos.hook_pre_exec_re_compile, post_exec_hook=redos.hook_post_exec_re_compile) # Hack to determine if yaml is elligible, because pkg_resources does # not seem to work from pyinstaller. # pylint: disable=import-outside-toplevel if is_module_present('yaml'): import yaml sanitizer_log('Hooking pyyaml.load', LOG_DEBUG) yaml.load = add_hook( yaml.load, pre_exec_hook=yaml_deserialization.hook_pre_exec_pyyaml_load, ) ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/pysecsan/yaml_deserialization.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Catches vulnerable yaml desrializations that can potentially lead to arbitrary code execution.""" from pysecsan import sanlib try: import yaml # pylint: disable=broad-except except Exception: pass def hook_pre_exec_pyyaml_load(stream, loader): """Hook for pyyaml.load_yaml. Exits if the loader is unsafe or vanilla loader and the stream passed to the loader is controlled by the fuzz data """ # Ensure loader is the unsafe loader or vanilla loader if loader not in (yaml.loader.Loader, yaml.loader.UnsafeLoader): return # Check for exact taint in stream if sanlib.is_exact_taint(stream): msg = ( 'Yaml deserialization issue.\n' 'Unsafe deserialization can be used to execute arbitrary commands.\n') sanlib.abort_with_issue(msg, 'Yaml deserialisation') ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/setup.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Config for installing python as package.""" from setuptools import setup, find_packages setup(name='pysecsan', version='0.1', author='David Korczynski', author_email='david@adalogics.com', packages=find_packages(exclude='tests')) ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/README.md ================================================ # Tests including Proof of Exploits ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/eval_command_injection.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer targetting command injection of eval.""" # pylint: disable=eval-used import sys import atheris import pysecsan pysecsan.add_hooks() def list_files_perhaps(param, magicval): """Pass fuzzer data into eval.""" if len(param) < 3: return if magicval == 1337: try: eval("FROMFUZZ") except ValueError: pass def test_one_input(data): """Fuzzer entrypoint.""" fdp = atheris.FuzzedDataProvider(data) list_files_perhaps(fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeIntInRange(500, 1500)) def main(): """Set up and start fuzzing.""" atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/os_command_injection.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer targetting command injection of os.system.""" import os import sys import atheris import pysecsan def list_files_perhaps(param, magicval): """Pass fuzzer data into os.system.""" if 'B' not in param: return if magicval == 1338: os.system('exec-san') elif magicval == 1339: os.system('ls -la FROMFUZZ') else: os.system('ls -la ./') def test_one_input(data): """Fuzzer entrypoint.""" fdp = atheris.FuzzedDataProvider(data) list_files_perhaps(fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeIntInRange(500, 1500)) def main(): """Set up and start fuzzing.""" pysecsan.add_hooks() atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/ansible-runner-cve-2021-4041/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install pysecsan git clone https://github.com/ansible/ansible-runner/ cd ansible-runner git checkout cdc0961df51fa1e10b44371944aafe5ae140b98c python3 -m pip install . cd .. python3 fuzz_ansible_runner.py ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/ansible-runner-cve-2021-4041/fuzz_ansible_runner.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Targets: https://github.com/advisories/GHSA-6j58-grhv-2769.""" import sys import atheris import pexpect import pysecsan import ansible_runner from ansible_runner.config.runner import RunnerConfig pysecsan.add_hooks() def test_one_input(data): """Fuzzer entrypoint.""" fdp = atheris.FuzzedDataProvider(data) conf = RunnerConfig('/tmp/') conf.suppress_ansible_output = True conf.expect_passwords = {pexpect.TIMEOUT: None, pexpect.EOF: None} conf.cwd = str('/tmp/') conf.env = {} conf.job_timeout = 10 conf.idle_timeout = 0 conf.pexpect_timeout = 2. conf.pexpect_use_poll = True conf.command = 'from_fuzzer' runner = ansible_runner.Runner(conf) runner.resource_profiling = True # rc.resource_profiling_base_cgroup = "; exec-san" assistance = True if assistance and fdp.ConsumeIntInRange(1, 100) > 80: conf.resource_profiling_base_cgroup = 'FROMFUZZ' else: conf.resource_profiling_base_cgroup = fdp.ConsumeUnicodeNoSurrogates(24) try: runner.run() except (RuntimeError, ValueError, TypeError) as _: pass def main(): """Set up and start fuzzing.""" atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/libvcs-cve-2022-21187/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install pysecsan python3 -m pip install libvcs==0.11.0 python3 ./fuzz_libvcs.py ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/libvcs-cve-2022-21187/fuzz_libvcs.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Targets https://github.com/advisories/GHSA-mv2w-4jqc-6fg4.""" import sys import atheris import pysecsan from libvcs.shortcuts import create_repo pysecsan.add_hooks() def test_one_input(data): """Target code injection in libvcs.""" fdp = atheris.FuzzedDataProvider(data) mercurial_repo = create_repo(url=fdp.ConsumeUnicodeNoSurrogates(128), vcs='hg', repo_dir='./') try: mercurial_repo.update_repo() except (ValueError, FileNotFoundError) as exception: _ = exception # Satisfy lint def main(): """Set up and start fuzzing.""" atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/python-ldap-GHSL-2021-117/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install pysecsan git clone https://github.com/python-ldap/python-ldap cd python-ldap git checkout 404c36b702c5b3a7e60729745c8bda16098b1472 python3 -m pip install . cd ../ python3 ./fuzz_ldap.py ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/python-ldap-GHSL-2021-117/fuzz_ldap.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Targets: https://github.com/python-ldap/python-ldap/security/advisories/GHSA-r8wq-qrxc-hmcm""" # pylint: disable=line-too-long import sys import atheris import pysecsan import ldap.schema pysecsan.add_hooks() def test_one_input(data): """Fuzzer targetting regex dos in ldap.""" fdp = atheris.FuzzedDataProvider(data) try: ldap.schema.split_tokens(fdp.ConsumeUnicodeNoSurrogates(1024)) except ValueError: pass def main(): """Set up and start fuzzing.""" atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/pytorch-lightning-1.5.10/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git clone --depth 1 --branch 1.5.10 https://github.com/PyTorchLightning/pytorch-lightning.git cd pytorch-lightning python3 -m pip install . cd ../ python3 ./fuzz_pytorch_lightning.py ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/pytorch-lightning-1.5.10/fuzz_pytorch_lightning.dict ================================================ "os.system('exec-sanitizer')" ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/poe/pytorch-lightning-1.5.10/fuzz_pytorch_lightning.py ================================================ #!/usr/local/bin/python3 # # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Exploit pytorch lightning with fuzzer's input as a random env variable. This PoC is extended from a report in GitHub Advisory Database: https://github.com/advisories/GHSA-r5qj-cvf9-p85h The original report documents an exploit using a specific environment variable, we show a way to achieve the same exploit with an arbitrary env variable. """ import os import sys import atheris import pysecsan pysecsan.add_hooks() with atheris.instrument_imports(): from pytorch_lightning import Trainer from pytorch_lightning.utilities.argparse import parse_env_variables def prepare_fuzzing_input(data): """Prepare the data needed by the exploit with input data from fuzzers.""" data = data.replace(b'\0', b'') env_name = 'AN_ARBITRARY_ENV_NAME' return data, env_name def exploit_target(env_value, env_name): """This target is based on a snippet from the official documentation of `parse_env_variables`: https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.utilities.argparse.html # pylint: disable=line-too-long It might not be the most realistic example, but serves as a PoC to show that SystemSan works for Python.""" os.environb[env_name.encode()] = env_value parse_env_variables(Trainer, template=env_name) def TestOneInput(data): # pylint: disable=invalid-name """Exploit the target only with input data from fuzzers.""" env_value, env_name = prepare_fuzzing_input(data) exploit_target(env_value, env_name) def main(): """Fuzz target with atheris.""" atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/subprocess_popen_injection.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer displaying insecure use of subprocess.Popen.""" import sys import subprocess import atheris import pysecsan def list_files_perhaps(param): """Insecure call to Popen.""" try: subprocess.Popen(' '.join(['ls', '-la', param]), shell=True) except ValueError: pass def test_one_input(data): """Fuzzer entrypoint.""" fdp = atheris.FuzzedDataProvider(data) if fdp.ConsumeIntInRange(1, 10) == 5: list_files_perhaps('FROMFUZZ') else: list_files_perhaps('.') def main(): """Set up and start fuzzing.""" pysecsan.add_hooks() atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/yaml_deserialization_general.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer for insecure yaml deserialization.""" import sys import yaml import atheris import pysecsan def serialize_with_tainted_data(param): """Hit insecure yaml function.""" try: yaml.load(param, yaml.Loader) except yaml.YAMLError: pass def test_one_input(data): """Fuzzer routine.""" fdp = atheris.FuzzedDataProvider(data) serialize_with_tainted_data(fdp.ConsumeUnicodeNoSurrogates(32)) def main(): """Set up and start fuzzing.""" pysecsan.add_hooks() atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/sanitizers/pysecsan/tests/yaml_deserialization_simple.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer triggering insecure yaml serialization.""" import sys import yaml import atheris import pysecsan def serialize_with_tainted_data(param, magicval): """Pass data to insecure yaml functions.""" if magicval == 1337: try: yaml.load(param, yaml.Loader) except yaml.YAMLError: pass elif magicval == 1338: try: yaml.load('FROMFUZZ', yaml.Loader) except yaml.YAMLError: pass def test_one_input(data): """Fuzzer entrypoint.""" fdp = atheris.FuzzedDataProvider(data) serialize_with_tainted_data(fdp.ConsumeUnicodeNoSurrogates(32), fdp.ConsumeIntInRange(500, 1500)) def main(): """Set up and start fuzzing.""" pysecsan.add_hooks() atheris.instrument_all() atheris.Setup(sys.argv, test_one_input, enable_python_coverage=True) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/srcmap ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Deterimine srcmap of checked out source code SRCMAP=$(tempfile) echo "{}" > $SRCMAP # $1 - json file, $2 - jq program function jq_inplace() { F=$(tempfile) && cat $1 | jq "$2" > $F && mv $F $1 } PATHS_TO_SCAN="$SRC" if [[ $FUZZING_LANGUAGE == "go" ]]; then PATHS_TO_SCAN="$PATHS_TO_SCAN $GOPATH" fi # Git for DOT_GIT_DIR in $(find $PATHS_TO_SCAN -name ".git" -type d); do GIT_DIR=$(dirname $DOT_GIT_DIR) cd $GIT_DIR GIT_URL=$(git config --get remote.origin.url) GIT_REV=$(git rev-parse HEAD) jq_inplace $SRCMAP ".\"$GIT_DIR\" = { type: \"git\", url: \"$GIT_URL\", rev: \"$GIT_REV\" }" done # Subversion for DOT_SVN_DIR in $(find $PATHS_TO_SCAN -name ".svn" -type d); do SVN_DIR=$(dirname $DOT_SVN_DIR) cd $SVN_DIR SVN_URL=$(svn info | grep "^URL:" | sed 's/URL: //g') SVN_REV=$(svn info -r HEAD | grep "^Revision:" | sed 's/Revision: //g') jq_inplace $SRCMAP ".\"$SVN_DIR\" = { type: \"svn\", url: \"$SVN_URL\", rev: \"$SVN_REV\" }" done # Mercurial for DOT_HG_DIR in $(find $PATHS_TO_SCAN -name ".hg" -type d); do HG_DIR=$(dirname $DOT_HG_DIR) cd $HG_DIR HG_URL=$(hg paths default) HG_REV=$(hg --debug id -r. -i) jq_inplace $SRCMAP ".\"$HG_DIR\" = { type: \"hg\", url: \"$HG_URL\", rev: \"$HG_REV\" }" done if [ "${OSSFUZZ_REVISION-}" != "" ]; then jq_inplace $SRCMAP ".\"/src\" = { type: \"git\", url: \"https://github.com/google/oss-fuzz.git\", rev: \"$OSSFUZZ_REVISION\" }" fi cat $SRCMAP rm $SRCMAP ================================================ FILE: infra/base-images/base-builder/test_data/culprit-commit.txt ================================================ ac9ee01fcbfac745aaedca0393a8e1c8a33acd8d is the first bad commit commit ac9ee01fcbfac745aaedca0393a8e1c8a33acd8d Author: John Doe Date: Tue Aug 6 08:41:53 2019 +0000 [compiler-rt] Implement getrandom interception Summary: Straightforward implementation of `getrandom` syscall and libc hooks. Test Plan: Local MSAN failures caused by uninstrumented `getrandom` calls stop failing. Patch by John Doe 3. Reviewers: jonhdoe2, johndoe Reviewed By: johndoe Subscribers: johndoe4, johndoe5, #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D65551 llvm-svn: 367999 :040000 040000 8db10511ca83cc7b0265c7703684cd386350151b 62508fdc5e8919bbb2a0bd185cc109868192cdb0 M compiler-rt bisect run success ================================================ FILE: infra/base-images/base-builder/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-clang:ubuntu-20-04 COPY install_deps_ubuntu-20-04.sh install_swift_ubuntu-20-04.sh / RUN /install_deps_ubuntu-20-04.sh # Build and install latest Python 3.11. ENV PYTHON_VERSION 3.11.13 RUN PYTHON_DEPS="\ zlib1g-dev \ libncurses5-dev \ libgdbm-dev \ libnss3-dev \ libssl-dev \ libsqlite3-dev \ libreadline-dev \ libffi-dev \ libbz2-dev \ liblzma-dev" && \ unset CFLAGS CXXFLAGS && \ apt-get install -y $PYTHON_DEPS && \ cd /tmp && \ curl -O https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz && \ tar -xvf Python-$PYTHON_VERSION.tar.xz && \ cd Python-$PYTHON_VERSION && \ ./configure --enable-optimizations --enable-shared && \ make -j$(nproc) && \ make install && \ ldconfig && \ ln -s /usr/local/bin/python3 /usr/local/bin/python && \ cd .. && \ rm -r /tmp/Python-$PYTHON_VERSION.tar.xz /tmp/Python-$PYTHON_VERSION && \ rm -rf /usr/local/lib/python${PYTHON_VERSION%.*}/test && \ python3 -m ensurepip && \ python3 -m pip install --upgrade pip && \ apt-get remove -y $PYTHON_DEPS # https://github.com/google/oss-fuzz/issues/3888 ENV CCACHE_VERSION 4.10.2 RUN cd /tmp && curl -OL https://github.com/ccache/ccache/releases/download/v$CCACHE_VERSION/ccache-$CCACHE_VERSION.tar.xz && \ tar -xvf ccache-$CCACHE_VERSION.tar.xz && cd ccache-$CCACHE_VERSION && \ mkdir build && cd build && \ export LDFLAGS='-lpthread' && \ cmake -D CMAKE_BUILD_TYPE=Release .. && \ make -j && make install && \ rm -rf /tmp/ccache-$CCACHE_VERSION /tmp/ccache-$CCACHE_VERSION.tar.xz # Install six for Bazel rules. RUN unset CFLAGS CXXFLAGS && pip3 install -v --no-cache-dir \ six==1.15.0 absl-py==2.3.0 pyelftools==0.32 && rm -rf /tmp/* # Install Bazel through Bazelisk, which automatically fetches the latest Bazel version. ENV BAZELISK_VERSION 1.9.0 RUN curl -L https://github.com/bazelbuild/bazelisk/releases/download/v$BAZELISK_VERSION/bazelisk-linux-amd64 -o /usr/local/bin/bazel && \ chmod +x /usr/local/bin/bazel # Default build flags for various sanitizers. ENV SANITIZER_FLAGS_address "-fsanitize=address -fsanitize-address-use-after-scope" ENV SANITIZER_FLAGS_hwaddress "-fsanitize=hwaddress -fuse-ld=lld -Wno-unused-command-line-argument" # Set of '-fsanitize' flags matches '-fno-sanitize-recover' + 'unsigned-integer-overflow'. ENV SANITIZER_FLAGS_undefined "-fsanitize=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" # Don't include "function" since it is unsupported on aarch64. ENV SANITIZER_FLAGS_undefined_aarch64 "-fsanitize=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" ENV SANITIZER_FLAGS_memory "-fsanitize=memory -fsanitize-memory-track-origins" ENV SANITIZER_FLAGS_thread "-fsanitize=thread" ENV SANITIZER_FLAGS_introspector "-O0 -flto -fno-inline-functions -fuse-ld=gold -Wno-unused-command-line-argument" # Do not use any sanitizers in the coverage build. ENV SANITIZER_FLAGS_coverage "" # We use unsigned-integer-overflow as an additional coverage signal and have to # suppress error messages. See https://github.com/google/oss-fuzz/issues/910. ENV UBSAN_OPTIONS="silence_unsigned_overflow=1" # To suppress warnings from binaries running during compilation. ENV DFSAN_OPTIONS='warn_unimplemented=0' # Default build flags for coverage feedback. ENV COVERAGE_FLAGS="-fsanitize=fuzzer-no-link" # Use '-Wno-unused-command-line-argument' to suppress "warning: -ldl: 'linker' input unused" # messages which are treated as errors by some projects. ENV COVERAGE_FLAGS_coverage "-fprofile-instr-generate -fcoverage-mapping -pthread -Wl,--no-as-needed -Wl,-ldl -Wl,-lm -Wno-unused-command-line-argument" # Default sanitizer, fuzzing engine and architecture to use. ENV SANITIZER="address" ENV FUZZING_ENGINE="libfuzzer" ENV ARCHITECTURE="x86_64" # DEPRECATED - NEW CODE SHOULD NOT USE THIS. OLD CODE SHOULD STOP. Please use # LIB_FUZZING_ENGINE instead. # Path to fuzzing engine library to support some old users of # LIB_FUZZING_ENGINE. ENV LIB_FUZZING_ENGINE_DEPRECATED="/usr/lib/libFuzzingEngine.a" # Argument passed to compiler to link against fuzzing engine. # Defaults to the path, but is "-fsanitize=fuzzer" in libFuzzer builds. ENV LIB_FUZZING_ENGINE="/usr/lib/libFuzzingEngine.a" # TODO: remove after tpm2 catchup. ENV FUZZER_LDFLAGS "" WORKDIR $SRC COPY afl_llvm22_patch.diff $SRC/ RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflplusplus && \ cd aflplusplus && \ git checkout eadc8a2a7e0fa0338802ee6254bf296489ce4fd7 && \ wget --no-check-certificate -O oss.sh https://raw.githubusercontent.com/vanhauser-thc/binary_blobs/master/oss.sh && \ git apply $SRC/afl_llvm22_patch.diff && \ rm -rf .git && \ chmod 755 oss.sh # Do precompiles before copying other scripts for better cache efficiency. COPY precompile_afl /usr/local/bin/ RUN precompile_afl RUN cd $SRC && \ curl -L -O https://github.com/google/honggfuzz/archive/oss-fuzz.tar.gz && \ mkdir honggfuzz && \ cd honggfuzz && \ tar -xz --strip-components=1 -f $SRC/oss-fuzz.tar.gz && \ rm -rf examples $SRC/oss-fuzz.tar.gz COPY precompile_honggfuzz_ubuntu_20_04 /usr/local/bin/ RUN precompile_honggfuzz_ubuntu_20_04 RUN cd $SRC && \ git clone https://github.com/google/fuzztest && \ cd fuzztest && \ git checkout a37d133f714395cabc20dd930969a889495c9f53 && \ rm -rf .git ENV CENTIPEDE_BIN_DIR=$SRC/fuzztest/bazel-bin COPY precompile_centipede /usr/local/bin/ RUN precompile_centipede COPY sanitizers /usr/local/lib/sanitizers COPY bazel_build_fuzz_tests \ cargo \ compile \ compile_afl \ compile_centipede \ compile_honggfuzz \ compile_fuzztests.sh \ compile_go_fuzzer \ compile_javascript_fuzzer \ compile_libfuzzer \ compile_native_go_fuzzer \ compile_native_go_fuzzer_v2 \ go_utils.sh \ compile_python_fuzzer \ debug_afl \ # Go, JavaScript, Java, Python, Rust, and Swift installation scripts. install_go.sh \ install_javascript.sh \ install_java.sh \ install_python.sh \ install_ruby.sh \ install_rust.sh \ install_swift_ubuntu-20-04.sh \ make_build_replayable.py \ python_coverage_helper.py \ replay_build.sh \ srcmap \ write_labels.py \ unshallow_repos.py \ /usr/local/bin/ # TODO: Build this as part of a multi-stage build. ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc /usr/local/bin ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc2 /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc2 /usr/local/bin RUN chmod +x /usr/local/bin/clang-jcc /usr/local/bin/clang++-jcc /usr/local/bin/clang-jcc2 /usr/local/bin/clang++-jcc2 COPY llvmsymbol.diff $SRC COPY detect_repo.py /opt/cifuzz/ COPY bazel.bazelrc /root/.bazelrc # Set up ccache binary and cache directory. # /ccache/bin will contain the compiler wrappers, and /ccache/cache will # contain the actual cache, which can be saved. # To use this, set PATH=/ccache/bin:$PATH. RUN mkdir -p /ccache/bin && mkdir -p /ccache/cache && \ ln -s /usr/local/bin/ccache /ccache/bin/clang && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++ && \ ln -s /usr/local/bin/ccache /ccache/bin/clang-jcc && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++-jcc ENV CCACHE_DIR /ccache/cache # Don't check that the compiler is the same, so we can switch between jcc and # clang under the hood and re-use the same build cache. ENV CCACHE_COMPILERCHECK none ENV CCACHE_COMPILERTYPE clang # Build newer patchelf than the one available from Ubuntu. RUN cd /tmp && git clone https://github.com/NixOS/patchelf && \ apt-get update && apt-get install -y autoconf && \ cd patchelf && git checkout 523f401584d9584e76c9c77004e7abeb9e6c4551 && \ unset CFLAGS && export CXXFLAGS='-stdlib=libc++' && export LDFLAGS='-lpthread' && \ ./bootstrap.sh && ./configure && make && \ cp /tmp/patchelf/src/patchelf /usr/local/bin && \ rm -rf /tmp/patchelf && apt-get remove -y autoconf COPY indexer /opt/indexer COPY --from=gcr.io/oss-fuzz-base/indexer /indexer/build/indexer /opt/indexer/indexer RUN chmod a+x /opt/indexer/indexer /opt/indexer/index_build.py CMD ["compile"] ================================================ FILE: infra/base-images/base-builder/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-clang:ubuntu-24-04 COPY install_deps_ubuntu-24-04.sh install_swift_ubuntu-24-04.sh / RUN /install_deps_ubuntu-24-04.sh # Build and install latest Python 3.11. ENV PYTHON_VERSION 3.11.13 RUN PYTHON_DEPS="\ zlib1g-dev \ libncurses-dev \ libgdbm-dev \ libnss3-dev \ libssl-dev \ libsqlite3-dev \ libreadline-dev \ libffi-dev \ libbz2-dev \ liblzma-dev" && \ unset CFLAGS CXXFLAGS && \ apt-get install -y $PYTHON_DEPS && \ cd /tmp && \ curl -O https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tar.xz && \ tar -xvf Python-$PYTHON_VERSION.tar.xz && \ cd Python-$PYTHON_VERSION && \ ./configure --enable-optimizations --enable-shared && \ make -j$(nproc) && \ make install && \ ldconfig && \ ln -s /usr/local/bin/python3 /usr/local/bin/python && \ cd .. && \ rm -r /tmp/Python-$PYTHON_VERSION.tar.xz /tmp/Python-$PYTHON_VERSION && \ rm -rf /usr/local/lib/python${PYTHON_VERSION%.*}/test && \ python3 -m ensurepip && \ python3 -m pip install --upgrade pip && \ apt-get remove -y $PYTHON_DEPS # https://github.com/google/oss-fuzz/issues/3888 ENV CCACHE_VERSION 4.10.2 RUN cd /tmp && curl -OL https://github.com/ccache/ccache/releases/download/v$CCACHE_VERSION/ccache-$CCACHE_VERSION.tar.xz && \ tar -xvf ccache-$CCACHE_VERSION.tar.xz && cd ccache-$CCACHE_VERSION && \ mkdir build && cd build && \ export LDFLAGS='-lpthread' && \ cmake -D CMAKE_BUILD_TYPE=Release .. && \ make -j && make install && \ rm -rf /tmp/ccache-$CCACHE_VERSION /tmp/ccache-$CCACHE_VERSION.tar.xz # Install six for Bazel rules. RUN unset CFLAGS CXXFLAGS && pip3 install -v --no-cache-dir \ six==1.15.0 absl-py==2.3.0 pyelftools==0.32 && rm -rf /tmp/* # Install Bazel through Bazelisk, which automatically fetches the latest Bazel version. ENV BAZELISK_VERSION 1.9.0 RUN curl -L https://github.com/bazelbuild/bazelisk/releases/download/v$BAZELISK_VERSION/bazelisk-linux-amd64 -o /usr/local/bin/bazel && \ chmod +x /usr/local/bin/bazel # Default build flags for various sanitizers. ENV SANITIZER_FLAGS_address "-fsanitize=address -fsanitize-address-use-after-scope" ENV SANITIZER_FLAGS_hwaddress "-fsanitize=hwaddress -fuse-ld=lld -Wno-unused-command-line-argument" # Set of '-fsanitize' flags matches '-fno-sanitize-recover' + 'unsigned-integer-overflow'. ENV SANITIZER_FLAGS_undefined "-fsanitize=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" # Don't include "function" since it is unsupported on aarch64. ENV SANITIZER_FLAGS_undefined_aarch64 "-fsanitize=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr" ENV SANITIZER_FLAGS_memory "-fsanitize=memory -fsanitize-memory-track-origins" ENV SANITIZER_FLAGS_thread "-fsanitize=thread" ENV SANITIZER_FLAGS_introspector "-O0 -flto -fno-inline-functions -fuse-ld=gold -Wno-unused-command-line-argument" # Do not use any sanitizers in the coverage build. ENV SANITIZER_FLAGS_coverage "" # We use unsigned-integer-overflow as an additional coverage signal and have to # suppress error messages. See https://github.com/google/oss-fuzz/issues/910. ENV UBSAN_OPTIONS="silence_unsigned_overflow=1" # To suppress warnings from binaries running during compilation. ENV DFSAN_OPTIONS='warn_unimplemented=0' # Default build flags for coverage feedback. ENV COVERAGE_FLAGS="-fsanitize=fuzzer-no-link" # Use '-Wno-unused-command-line-argument' to suppress "warning: -ldl: 'linker' input unused" # messages which are treated as errors by some projects. ENV COVERAGE_FLAGS_coverage "-fprofile-instr-generate -fcoverage-mapping -pthread -Wl,--no-as-needed -Wl,-ldl -Wl,-lm -Wno-unused-command-line-argument" # Default sanitizer, fuzzing engine and architecture to use. ENV SANITIZER="address" ENV FUZZING_ENGINE="libfuzzer" ENV ARCHITECTURE="x86_64" # DEPRECATED - NEW CODE SHOULD NOT USE THIS. OLD CODE SHOULD STOP. Please use # LIB_FUZZING_ENGINE instead. # Path to fuzzing engine library to support some old users of # LIB_FUZZING_ENGINE. ENV LIB_FUZZING_ENGINE_DEPRECATED="/usr/lib/libFuzzingEngine.a" # Argument passed to compiler to link against fuzzing engine. # Defaults to the path, but is "-fsanitize=fuzzer" in libFuzzer builds. ENV LIB_FUZZING_ENGINE="/usr/lib/libFuzzingEngine.a" # TODO: remove after tpm2 catchup. ENV FUZZER_LDFLAGS "" WORKDIR $SRC COPY afl_llvm22_patch.diff $SRC/ RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflplusplus && \ cd aflplusplus && \ git checkout eadc8a2a7e0fa0338802ee6254bf296489ce4fd7 && \ wget --no-check-certificate -O oss.sh https://raw.githubusercontent.com/vanhauser-thc/binary_blobs/master/oss.sh && \ git apply $SRC/afl_llvm22_patch.diff && \ rm -rf .git && \ chmod 755 oss.sh # Do precompiles before copying other scripts for better cache efficiency. COPY precompile_afl /usr/local/bin/ RUN precompile_afl RUN cd $SRC && \ curl -L -O https://github.com/google/honggfuzz/archive/oss-fuzz.tar.gz && \ mkdir honggfuzz && \ cd honggfuzz && \ tar -xz --strip-components=1 -f $SRC/oss-fuzz.tar.gz && \ rm -rf examples $SRC/oss-fuzz.tar.gz COPY precompile_honggfuzz_ubuntu_24_04 /usr/local/bin/ RUN precompile_honggfuzz_ubuntu_24_04 RUN cd $SRC && \ git clone https://github.com/google/fuzztest && \ cd fuzztest && \ git checkout a37d133f714395cabc20dd930969a889495c9f53 && \ rm -rf .git ENV CENTIPEDE_BIN_DIR=$SRC/fuzztest/bazel-bin COPY precompile_centipede /usr/local/bin/ RUN precompile_centipede COPY sanitizers /usr/local/lib/sanitizers COPY bazel_build_fuzz_tests \ cargo \ compile \ compile_afl \ compile_centipede \ compile_honggfuzz \ compile_fuzztests.sh \ compile_go_fuzzer \ compile_javascript_fuzzer \ compile_libfuzzer \ compile_native_go_fuzzer \ compile_native_go_fuzzer_v2 \ go_utils.sh \ compile_python_fuzzer \ debug_afl \ # Go, JavaScript, Java, Python, Rust, and Swift installation scripts. install_go.sh \ install_javascript.sh \ install_java.sh \ install_python.sh \ install_ruby.sh \ install_rust.sh \ install_swift_ubuntu-24-04.sh \ make_build_replayable.py \ python_coverage_helper.py \ replay_build.sh \ srcmap \ write_labels.py \ unshallow_repos.py \ /usr/local/bin/ # TODO: Build this as part of a multi-stage build. ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc /usr/local/bin ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang-jcc2 /usr/local/bin/ ADD https://commondatastorage.googleapis.com/clusterfuzz-builds/jcc/clang++-jcc2 /usr/local/bin RUN chmod +x /usr/local/bin/clang-jcc /usr/local/bin/clang++-jcc /usr/local/bin/clang-jcc2 /usr/local/bin/clang++-jcc2 COPY indexer /opt/indexer COPY --from=gcr.io/oss-fuzz-base/indexer:ubuntu-24-04 /indexer/build/indexer /opt/indexer/indexer RUN chmod a+x /opt/indexer/indexer /opt/indexer/index_build.py COPY llvmsymbol.diff $SRC COPY detect_repo.py /opt/cifuzz/ COPY bazel.bazelrc /root/.bazelrc # Set up ccache binary and cache directory. # /ccache/bin will contain the compiler wrappers, and /ccache/cache will # contain the actual cache, which can be saved. # To use this, set PATH=/ccache/bin:$PATH. RUN mkdir -p /ccache/bin && mkdir -p /ccache/cache && \ ln -s /usr/local/bin/ccache /ccache/bin/clang && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++ && \ ln -s /usr/local/bin/ccache /ccache/bin/clang-jcc && \ ln -s /usr/local/bin/ccache /ccache/bin/clang++-jcc ENV CCACHE_DIR /ccache/cache # Don't check that the compiler is the same, so we can switch between jcc and # clang under the hood and re-use the same build cache. ENV CCACHE_COMPILERCHECK none ENV CCACHE_COMPILERTYPE clang # Build newer patchelf than the one available from Ubuntu. RUN cd /tmp && git clone https://github.com/NixOS/patchelf && \ apt-get update && apt-get install -y autoconf && \ cd patchelf && git checkout 523f401584d9584e76c9c77004e7abeb9e6c4551 && \ unset CFLAGS && export CXXFLAGS='-stdlib=libc++' && export LDFLAGS='-lpthread' && \ ./bootstrap.sh && ./configure && make && \ cp /tmp/patchelf/src/patchelf /usr/local/bin && \ rm -rf /tmp/patchelf && apt-get remove -y autoconf CMD ["compile"] ================================================ FILE: infra/base-images/base-builder/unshallow_repos.py ================================================ #!/usr/bin/env python3 # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Script to unshallow repositories.""" import argparse import os import pathlib import re import subprocess SRC = pathlib.Path(os.getenv('SRC', '/src')) def main(): parser = argparse.ArgumentParser(description='Unshallows repositores.') parser.add_argument('repos', nargs='+', help='Repo URLs') args = parser.parse_args() repos = set() for repo in args.repos: repos.add(_normalize_repo(repo)) for subdir in SRC.iterdir(): if (subdir / '.git').exists(): repo = subprocess.check_output(['git', 'remote', 'get-url', 'origin'], cwd=subdir).decode().strip() if _normalize_repo(repo) in repos: if not _is_shallow_repo(subdir): continue print(f'Unshallowing {repo} at {subdir}.') subprocess.check_call(['git', 'fetch', '--unshallow'], cwd=subdir) def _normalize_repo(repo: str) -> str: return re.sub(r'(.git)?/?$', '', repo) def _is_shallow_repo(directory: pathlib.Path): return subprocess.check_output( ['git', 'rev-parse', '--is-shallow-repository'], cwd=directory).decode().strip() == 'true' if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder/write_labels.py ================================================ #!/usr/bin/env python3 # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Script for writing from project.yaml to .labels file.""" import os import json import sys def main(): """Writes labels.""" if len(sys.argv) != 3: print('Usage: write_labels.py labels_json out_dir', file=sys.stderr) sys.exit(1) labels_by_target = json.loads(sys.argv[1]) out = sys.argv[2] for target_name, labels in labels_by_target.items(): # Skip over wildcard value applying to all fuzz targets if target_name == '*': continue with open(os.path.join(out, target_name + '.labels'), 'w') as file_handle: file_handle.write('\n'.join(labels)) if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-builder-fuzzbench/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-fuzzbench ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-fuzzbench` were successfully built. These images install dependencies for FuzzBench, a service for evaluating fuzzers. The build process required several modifications to the `fuzzbench_install_dependencies` script to handle package version incompatibilities and differences between Ubuntu 20.04 and 24.04. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-fuzzbench:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-fuzzbench:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The `ubuntu-24-04` image includes newer versions of many packages, including Python development libraries. The `fuzzbench_install_dependencies` script was updated to handle these differences. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Dependency Installation:** The `fuzzbench_install_dependencies` script was modified to: * Update the `pytype` version to `2024.4.11`. * Update the `Orange3` package version to `3.39.0`. * Add version detection logic to install the correct Python development packages for each Ubuntu version. * Install `lsb-release` to support the version detection logic. ================================================ FILE: infra/base-images/base-builder-fuzzbench/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Copy/Run this now to make the cache more resilient. COPY fuzzbench_install_dependencies /usr/local/bin RUN fuzzbench_install_dependencies ENV OSS_FUZZ_ON_DEMAND=1 COPY fuzzbench_build fuzzbench_run_fuzzer fuzzbench_measure /usr/local/bin/ ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_build ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # TODO(metzman): Do this in a docket image so we don't need to waste time # reinstalling. PYTHONPATH=$FUZZBENCH_PATH python3 -B -u -c "from fuzzers.$FUZZING_ENGINE import fuzzer; fuzzer.build()" if [ "$FUZZING_ENGINE" = "coverage" ]; then cd $OUT mkdir -p filestore/oss-fuzz-on-demand/coverage-binaries # We expect an error regarding leading slashes. Just assume this step succeeds. # TODO(metzman): Fix this when I get a chance. tar -czvf filestore/oss-fuzz-on-demand/coverage-binaries/coverage-build-$PROJECT.tar.gz * /src /work || exit 0 fi ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_install_dependencies ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ apt-get update && apt-get install -y gcc gfortran python-dev libopenblas-dev liblapack-dev cython libpq-dev wget -O /tmp/requirements.txt https://raw.githubusercontent.com/google/fuzzbench/master/requirements.txt pip3 install pip --upgrade CFLAGS= CXXFLAGS= pip3 install -r /tmp/requirements.txt rm /tmp/requirements.txt ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_install_dependencies_ubuntu_20_04 ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ apt-get update && apt-get install -y gcc gfortran python-dev libopenblas-dev liblapack-dev cython libpq-dev wget -O /tmp/requirements.txt https://raw.githubusercontent.com/google/fuzzbench/master/requirements.txt pip3 install pip --upgrade CFLAGS= CXXFLAGS= pip3 install -r /tmp/requirements.txt rm /tmp/requirements.txt ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_install_dependencies_ubuntu_24_04 ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [[ $(lsb_release -rs) == "20.04" ]]; then apt-get update && apt-get install -y gcc gfortran python-dev libopenblas-dev liblapack-dev cython libpq-dev else apt-get update && apt-get install -y gcc gfortran python3-dev libopenblas-dev liblapack-dev cython3 libpq-dev fi wget -O /tmp/requirements.txt https://raw.githubusercontent.com/google/fuzzbench/master/requirements.txt pip3 install pip --upgrade CFLAGS= CXXFLAGS= pip3 install -r /tmp/requirements.txt rm /tmp/requirements.txt ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_measure ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # TODO(metzman): Make these configurable. export DB_PATH=$OUT/experiment.db export SNAPSHOT_PERIOD=30 export EXPERIMENT_FILESTORE=$OUT/filestore export MAX_TOTAL_TIME=120 export EXPERIMENT=oss-fuzz-on-demand rm -f $DB_PATH # FUZZER=mopt BENCHMARK=skcms export SQL_DATABASE_URL=sqlite:///$DB_PATH cd $FUZZBENCH_PATH PYTHONPATH=. python3 -B experiment/measurer/standalone.py $MAX_TOTAL_TIME ================================================ FILE: infra/base-images/base-builder-fuzzbench/fuzzbench_run_fuzzer ================================================ #! /bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export RUNNER_NICENESS="-5" export EXPERIMENT_FILESTORE=$OUT/filestore export EXPERIMENT=oss-fuzz-on-demand export OSS_FUZZ_ON_DEMAND=1 export OUTPUT_CORPUS_DIR=/output-corpus export SEED_CORPUS_DIR=/input-corpus mkdir $SEED_CORPUS_DIR rm -rf $OUTPUT_CORPUS_DIR mkdir $OUTPUT_CORPUS_DIR export FUZZER=$FUZZING_ENGINE export SNAPSHOT_PERIOD=$((MAX_TOTAL_TIME / 3)) export TRIAL_ID=1 export FORCE_LOCAL=1 # BENCHMARK, FUZZ_TARGET cd $OUT # Prevent permissions issues with pyc files and docker. cp -r $FUZZBENCH_PATH /tmp/fuzzbench PYTHONPATH=/tmp/fuzzbench nice -n $RUNNER_NICENESS python3 -B -u /tmp/fuzzbench/experiment/runner.py cat $EXPERIMENT_FILESTORE/$EXPERIMENT/experiment-folders/$BENCHMARK-$FUZZER/trial-$TRIAL_ID/results/fuzzer-log.txt ================================================ FILE: infra/base-images/base-builder-fuzzbench/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 # Copy/Run this now to make the cache more resilient. COPY fuzzbench_install_dependencies_ubuntu_20_04 /usr/local/bin RUN fuzzbench_install_dependencies_ubuntu_20_04 ENV OSS_FUZZ_ON_DEMAND=1 COPY fuzzbench_build fuzzbench_run_fuzzer fuzzbench_measure /usr/local/bin/ ================================================ FILE: infra/base-images/base-builder-fuzzbench/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 # Copy/Run this now to make the cache more resilient. COPY fuzzbench_install_dependencies_ubuntu_24_04 /usr/local/bin RUN fuzzbench_install_dependencies_ubuntu_24_04 ENV OSS_FUZZ_ON_DEMAND=1 COPY fuzzbench_build fuzzbench_run_fuzzer fuzzbench_measure /usr/local/bin/ ================================================ FILE: infra/base-images/base-builder-go/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-go ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-go` were successfully built. These images install the Go programming language and related fuzzing tools on top of the `base-builder` image. The build process for both versions is nearly identical, with the primary difference being the base image used. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-go:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-go:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) There are no significant package differences introduced in this build stage, as the dependencies are inherited from the `base-builder` image. ## Dockerfile Analysis The Dockerfiles for both versions are very similar and perform the following actions: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Go Installation:** The `install_go.sh` script is used to download and install Go. * **Go Fuzzing Tools:** The Dockerfiles install several Go-based fuzzing tools, including `go114-fuzz-build` and `go-118-fuzz-build`. ================================================ FILE: infra/base-images/base-builder-go/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:/root/.go/bin:$GOPATH/bin COPY gosigfuzz.c $GOPATH/gosigfuzz/ RUN install_go.sh # TODO(jonathanmetzman): Install this file using install_go.sh. COPY ossfuzz_coverage_runner.go \ $GOPATH/ ================================================ FILE: infra/base-images/base-builder-go/gosigfuzz.c ================================================ /* * Copyright 2023 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include static void fixSignalHandler(int signum) { struct sigaction new_action; struct sigaction old_action; sigemptyset (&new_action.sa_mask); sigaction (signum, NULL, &old_action); new_action.sa_flags = old_action.sa_flags | SA_ONSTACK; new_action.sa_sigaction = old_action.sa_sigaction; new_action.sa_handler = old_action.sa_handler; sigaction (signum, &new_action, NULL); } static void FixStackSignalHandler() { fixSignalHandler(SIGSEGV); fixSignalHandler(SIGABRT); fixSignalHandler(SIGALRM); fixSignalHandler(SIGINT); fixSignalHandler(SIGTERM); fixSignalHandler(SIGBUS); fixSignalHandler(SIGFPE); fixSignalHandler(SIGXFSZ); fixSignalHandler(SIGUSR1); fixSignalHandler(SIGUSR2); } int LLVMFuzzerInitialize(int *argc, char ***argv) { FixStackSignalHandler(); return 0; } ================================================ FILE: infra/base-images/base-builder-go/ossfuzz_coverage_runner.go ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mypackagebeingfuzzed import ( "io/fs" "io/ioutil" "os" "path/filepath" "runtime/pprof" "testing" ) func TestFuzzCorpus(t *testing.T) { dir := os.Getenv("FUZZ_CORPUS_DIR") if dir == "" { t.Logf("No fuzzing corpus directory set") return } filename := "" defer func() { if r := recover(); r != nil { t.Error("Fuzz panicked in "+filename, r) } }() profname := os.Getenv("FUZZ_PROFILE_NAME") if profname != "" { f, err := os.Create(profname + ".cpu.prof") if err != nil { t.Logf("error creating profile file %s\n", err) } else { _ = pprof.StartCPUProfile(f) } } _, err := ioutil.ReadDir(dir) if err != nil { t.Logf("Not fuzzing corpus directory %s", err) return } // recurse for regressions subdirectory err = filepath.Walk(dir, func(fname string, info fs.FileInfo, err error) error { if info.IsDir() { return nil } data, err := ioutil.ReadFile(fname) if err != nil { t.Error("Failed to read corpus file", err) return err } filename = fname FuzzFunction(data) return nil }) if err != nil { t.Error("Failed to run corpus", err) } if profname != "" { pprof.StopCPUProfile() f, err := os.Create(profname + ".heap.prof") if err != nil { t.Logf("error creating heap profile file %s\n", err) } if err = pprof.WriteHeapProfile(f); err != nil { t.Logf("error writing heap profile file %s\n", err) } f.Close() } } ================================================ FILE: infra/base-images/base-builder-go/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:/root/.go/bin:$GOPATH/bin COPY gosigfuzz.c $GOPATH/gosigfuzz/ RUN install_go.sh # TODO(jonathanmetzman): Install this file using install_go.sh. COPY ossfuzz_coverage_runner.go \ $GOPATH/ ================================================ FILE: infra/base-images/base-builder-go/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not a use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:/root/.go/bin:$GOPATH/bin COPY gosigfuzz.c $GOPATH/gosigfuzz/ RUN install_go.sh # TODO(jonathanmetzman): Install this file using install_go.sh. COPY ossfuzz_coverage_runner.go \ $GOPATH/ ================================================ FILE: infra/base-images/base-builder-javascript/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-javascript ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-javascript` were successfully built. These images install Node.js and other JavaScript-related tools on top of the `base-builder` image. The build process for both versions is straightforward and relies on the `install_javascript.sh` script, which is compatible with both base images. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-javascript:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-javascript:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The primary difference is the version of Node.js installed, which is Node.js 20.x for both versions, but the underlying dependencies may differ due to the base image. ## Dockerfile Analysis The Dockerfiles for both versions are very similar and perform the following actions: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Node.js Installation:** The `install_javascript.sh` script is used to add the Node.js repository and install Node.js. ================================================ FILE: infra/base-images/base-builder-javascript/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN install_javascript.sh ================================================ FILE: infra/base-images/base-builder-javascript/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 RUN install_javascript.sh ================================================ FILE: infra/base-images/base-builder-javascript/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN install_javascript.sh ================================================ FILE: infra/base-images/base-builder-jvm/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-jvm ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-jvm` were successfully built. These images install the Java Development Kit (JDK) and the Jazzer fuzzer on top of the `base-builder` image. The `ubuntu-24-04` build required fixing syntax errors in the Dockerfile, specifically missing line continuation characters (`\`). After these corrections, both builds completed successfully. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-jvm:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-jvm:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The primary difference is the Java version installed. Both versions install OpenJDK 17 and 15. The underlying dependencies may differ due to the base image. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Java Installation:** The `install_java.sh` script is used to download and install OpenJDK 17 and 15. * **Jazzer Installation:** Both versions clone the Jazzer repository and build it using Bazel. * **Dockerfile Syntax:** The `ubuntu-24-04` Dockerfile had syntax errors that were corrected. ================================================ FILE: infra/base-images/base-builder-jvm/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder AS base ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME /usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server ENV PATH $PATH:$JAVA_HOME/bin ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar" ENV JAZZER_JUNIT_PATH "/usr/local/bin/jazzer_junit.jar" RUN install_java.sh RUN chmod 777 /usr/local/bin && chmod 777 /usr/local/lib FROM base AS builder RUN useradd -m jazzer_user USER jazzer_user WORKDIR $SRC # Install Jazzer version 0.26.0 RUN git clone https://github.com/CodeIntelligenceTesting/jazzer && \ cd jazzer && \ git checkout 86378b7a20f08165e72a45582d6a9a5091212318 WORKDIR $SRC/jazzer RUN echo "build --java_runtime_version=local_jdk_17" >> .bazelrc \ && echo "build --cxxopt=-stdlib=libc++" >> .bazelrc \ && echo "build --linkopt=-lc++" >> .bazelrc RUN bazel build \ //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar \ //deploy:jazzer-api \ //deploy:jazzer-junit \ //launcher:jazzer RUN cp $(bazel cquery --output=files //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar) /usr/local/bin/jazzer_agent_deploy.jar && \ cp $(bazel cquery --output=files //launcher:jazzer) /usr/local/bin/jazzer_driver && \ cp $(bazel cquery --output=files //deploy:jazzer-api) $JAZZER_API_PATH && \ cp $(bazel cquery --output=files //deploy:jazzer-junit) $JAZZER_JUNIT_PATH FROM base AS final COPY --from=builder /usr/local/bin/jazzer_agent_deploy.jar /usr/local/bin/jazzer_agent_deploy.jar COPY --from=builder /usr/local/bin/jazzer_driver /usr/local/bin/jazzer_driver COPY --from=builder $JAZZER_API_PATH $JAZZER_API_PATH COPY --from=builder $JAZZER_JUNIT_PATH $JAZZER_JUNIT_PATH RUN chmod 755 /usr/local/bin && chmod 755 /usr/local/lib WORKDIR $SRC ================================================ FILE: infra/base-images/base-builder-jvm/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 AS base ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME /usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server ENV PATH $PATH:$JAVA_HOME/bin ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar" ENV JAZZER_JUNIT_PATH "/usr/local/bin/jazzer_junit.jar" RUN install_java.sh RUN chmod 777 /usr/local/bin && chmod 777 /usr/local/lib FROM base AS builder RUN useradd -m jazzer_user USER jazzer_user WORKDIR $SRC RUN git clone https://github.com/CodeIntelligenceTesting/jazzer && \ cd jazzer && \ git checkout 11b42852df4344737df54a380c2f522025bb4e84 WORKDIR $SRC/jazzer RUN echo "build --java_runtime_version=local_jdk_17" >> .bazelrc \ && echo "build --cxxopt=-stdlib=libc++" >> .bazelrc \ && echo "build --linkopt=-lc++" >> .bazelrc RUN bazel build \ //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar \ //deploy:jazzer-api \ //deploy:jazzer-junit \ //launcher:jazzer RUN cp $(bazel cquery --output=files //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar) /usr/local/bin/jazzer_agent_deploy.jar && \ cp $(bazel cquery --output=files //launcher:jazzer) /usr/local/bin/jazzer_driver && \ cp $(bazel cquery --output=files //deploy:jazzer-api) $JAZZER_API_PATH && \ cp $(bazel cquery --output=files //deploy:jazzer-junit) $JAZZER_JUNIT_PATH FROM base AS final COPY --from=builder /usr/local/bin/jazzer_agent_deploy.jar /usr/local/bin/jazzer_agent_deploy.jar COPY --from=builder /usr/local/bin/jazzer_driver /usr/local/bin/jazzer_driver COPY --from=builder $JAZZER_API_PATH $JAZZER_API_PATH COPY --from=builder $JAZZER_JUNIT_PATH $JAZZER_JUNIT_PATH RUN chmod 755 /usr/local/bin && chmod 755 /usr/local/lib WORKDIR $SRC ================================================ FILE: infra/base-images/base-builder-jvm/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 AS base ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME /usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server ENV PATH $PATH:$JAVA_HOME/bin ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar" ENV JAZZER_JUNIT_PATH "/usr/local/bin/jazzer_junit.jar" RUN install_java.sh RUN chmod 777 /usr/local/bin && chmod 777 /usr/local/lib FROM base AS builder RUN useradd -m jazzer_user USER jazzer_user WORKDIR $SRC RUN git clone https://github.com/CodeIntelligenceTesting/jazzer && \ cd jazzer && \ git checkout 11b42852df4344737df54a380c2f522025bb4e84 WORKDIR $SRC/jazzer RUN echo "build --java_runtime_version=local_jdk_17" >> .bazelrc \ && echo "build --cxxopt=-stdlib=libc++" >> .bazelrc \ && echo "build --linkopt=-lc++" >> .bazelrc RUN bazel build \ //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar \ //deploy:jazzer-api \ //deploy:jazzer-junit \ //launcher:jazzer RUN cp $(bazel cquery --output=files //src/main/java/com/code_intelligence/jazzer:jazzer_standalone_deploy.jar) /usr/local/bin/jazzer_agent_deploy.jar && \ cp $(bazel cquery --output=files //launcher:jazzer) /usr/local/bin/jazzer_driver && \ cp $(bazel cquery --output=files //deploy:jazzer-api) $JAZZER_API_PATH && \ cp $(bazel cquery --output=files //deploy:jazzer-junit) $JAZZER_JUNIT_PATH FROM base AS final COPY --from=builder /usr/local/bin/jazzer_agent_deploy.jar /usr/local/bin/jazzer_agent_deploy.jar COPY --from=builder /usr/local/bin/jazzer_driver /usr/local/bin/jazzer_driver COPY --from=builder $JAZZER_API_PATH $JAZZER_API_PATH COPY --from=builder $JAZZER_JUNIT_PATH $JAZZER_JUNIT_PATH RUN chmod 755 /usr/local/bin && chmod 755 /usr/local/lib WORKDIR $SRC ================================================ FILE: infra/base-images/base-builder-python/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-python ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-python` were successfully built. These images install Python-specific fuzzing tools, including Atheris and Coverage, on top of the `base-builder` image. The Dockerfile structure was refactored to support multi-version builds by creating separate Dockerfiles for each Ubuntu version and updating the `FROM` instruction accordingly. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-python:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-python:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The primary difference is the version of Python and its dependencies. Both versions install Atheris, PyInstaller, and other Python packages, but the underlying system libraries and Python version are different. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Python Fuzzing Tools:** The `install_python.sh` script is used to install Atheris and other Python fuzzing tools. * **Refactoring:** The original `Dockerfile` was renamed to `ubuntu-20-04.Dockerfile`, and a new `ubuntu-24-04.Dockerfile` was created to support the multi-version build strategy. ================================================ FILE: infra/base-images/base-builder-python/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN install_python.sh ================================================ FILE: infra/base-images/base-builder-python/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 RUN install_python.sh ================================================ FILE: infra/base-images/base-builder-python/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN install_python.sh ================================================ FILE: infra/base-images/base-builder-ruby/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-ruby ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-ruby` were successfully built. These images install Ruby and the Ruzzy fuzzer on top of the `base-builder` image. The Dockerfile structure was refactored to support multi-version builds by creating separate Dockerfiles for each Ubuntu version and updating the `FROM` instruction accordingly. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-ruby:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-ruby:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The primary difference is the version of Ruby and its dependencies. Both versions install Ruby 3.3.1, but the underlying system libraries and dependencies are different. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Ruby Installation:** The `install_ruby.sh` script is used to download and install Ruby. * **Ruzzy Installation:** Both versions clone the Ruzzy repository and install it using `gem`. * **Refactoring:** The original `Dockerfile` was renamed to `ubuntu-20-04.Dockerfile`, and a new `ubuntu-24-04.Dockerfile` was created to support the multi-version build strategy. ================================================ FILE: infra/base-images/base-builder-ruby/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone https://github.com/trailofbits/ruzzy.git $SRC/ruzzy RUN /usr/local/bin/install_ruby.sh RUN /usr/local/bin/gem update --system 3.5.11 # Install ruzzy WORKDIR $SRC/ruzzy # The MAKE variable allows overwriting the make command at runtime. This forces the # Ruby C extension to respect ENV variables when compiling, like CC, CFLAGS, etc. ENV MAKE="make --environment-overrides V=1" RUN CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ gem build RUN MAKE="make --environment-overrides V=1" \ CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ CXXFLAGS="-fPIC" \ CFLAGS="-fPIC" \ RUZZY_DEBUG=1 gem install --install-dir /install/ruzzy --development --verbose ruzzy-*.gem ENV LDSHARED="$CC -shared" ENV LDSHAREDXX="$CXX -shared" ENV GEM_HOME="$OUT/fuzz-gem" ENV GEM_PATH="/install/ruzzy" COPY ruzzy-build /usr/bin/ruzzy-build ================================================ FILE: infra/base-images/base-builder-ruby/ruzzy-build ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ fuzz_target=$(basename "$1") echo "BASENAME: $fuzz_target ---" harness_sh=${fuzz_target::-3} cp $1 $OUT/$fuzz_target echo """#!/usr/bin/env bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") export GEM_HOME=\$this_dir/fuzz-gem ruzzy \$this_dir/$fuzz_target \$@ """ > $OUT/$harness_sh chmod +x $OUT/$harness_sh ================================================ FILE: infra/base-images/base-builder-ruby/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 RUN git clone https://github.com/trailofbits/ruzzy.git $SRC/ruzzy RUN /usr/local/bin/install_ruby.sh RUN /usr/local/bin/gem update --system 3.5.11 # Install ruzzy WORKDIR $SRC/ruzzy # The MAKE variable allows overwriting the make command at runtime. This forces the # Ruby C extension to respect ENV variables when compiling, like CC, CFLAGS, etc. ENV MAKE="make --environment-overrides V=1" RUN CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ gem build RUN MAKE="make --environment-overrides V=1" \ CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ CXXFLAGS="-fPIC" \ CFLAGS="-fPIC" \ RUZZY_DEBUG=1 gem install --install-dir /install/ruzzy --development --verbose ruzzy-*.gem ENV LDSHARED="$CC -shared" ENV LDSHAREDXX="$CXX -shared" ENV GEM_HOME="$OUT/fuzz-gem" ENV GEM_PATH="/install/ruzzy" COPY ruzzy-build /usr/bin/ruzzy-build ================================================ FILE: infra/base-images/base-builder-ruby/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN git clone https://github.com/trailofbits/ruzzy.git $SRC/ruzzy RUN /usr/local/bin/install_ruby.sh RUN /usr/local/bin/gem update --system 3.5.11 RUN gem update --system 3.5.11 # Install ruzzy WORKDIR $SRC/ruzzy # The MAKE variable allows overwriting the make command at runtime. This forces the # Ruby C extension to respect ENV variables when compiling, like CC, CFLAGS, etc. ENV MAKE="make --environment-overrides V=1" RUN CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ gem build RUN MAKE="make --environment-overrides V=1" \ CC="clang" \ CXX="clang++" \ LDSHARED="clang -shared" \ LDSHAREDXX="clang++ -shared" \ CXXFLAGS="-fPIC" \ CFLAGS="-fPIC" \ RUZZY_DEBUG=1 gem install --install-dir /install/ruzzy --development --verbose ruzzy-*.gem ENV LDSHARED="$CC -shared" ENV LDSHAREDXX="$CXX -shared" ENV GEM_HOME="$OUT/fuzz-gem" ENV GEM_PATH="/install/ruzzy" COPY ruzzy-build /usr/bin/ruzzy-build ================================================ FILE: infra/base-images/base-builder-rust/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-rust ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-rust` were successfully built. These images are used for building Rust-based fuzzers and contain the necessary toolchain. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-rust:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-rust:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The `ubuntu-24-04` image includes newer versions of the Rust toolchain and other related dependencies. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Dependency Installation:** The `install_rust.sh` script is used to install the Rust toolchain, which may have version differences between the two Ubuntu versions. ================================================ FILE: infra/base-images/base-builder-rust/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder ENV CARGO_HOME=/rust ENV RUSTUP_HOME=/rust/rustup ENV PATH=$PATH:/rust/bin # Set up custom environment variable for source code copy for coverage reports ENV OSSFUZZ_RUSTPATH /rust # Force rustup to ignore `rust-toolchain` and `rust-toolchain.toml` files by # manually specifying what toolchain to use. Note that this environment variable # is additionally used by `install_rust.sh` as the toolchain to install. # cf https://rust-lang.github.io/rustup/overrides.html ENV RUSTUP_TOOLCHAIN nightly-2025-09-05 # Configure the linker used by default for x86_64 linux to be `clang` instead of # rustc's default of `cc` which is able to find custom-built libraries like # `libc++` by default more easily. ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER clang RUN install_rust.sh ================================================ FILE: infra/base-images/base-builder-rust/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 ENV CARGO_HOME=/rust ENV RUSTUP_HOME=/rust/rustup ENV PATH=$PATH:/rust/bin # Set up custom environment variable for source code copy for coverage reports ENV OSSFUZZ_RUSTPATH /rust # Force rustup to ignore `rust-toolchain` and `rust-toolchain.toml` files by # manually specifying what toolchain to use. Note that this environment variable # is additionally used by `install_rust.sh` as the toolchain to install. # cf https://rust-lang.github.io/rustup/overrides.html ENV RUSTUP_TOOLCHAIN nightly-2024-07-12 # Configure the linker used by default for x86_64 linux to be `clang` instead of # rustc's default of `cc` which is able to find custom-built libraries like # `libc++` by default more easily. ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER clang RUN install_rust.sh ================================================ FILE: infra/base-images/base-builder-rust/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 ENV CARGO_HOME=/rust ENV RUSTUP_HOME=/rust/rustup ENV PATH=$PATH:/rust/bin # Set up custom environment variable for source code copy for coverage reports ENV OSSFUZZ_RUSTPATH /rust # Force rustup to ignore `rust-toolchain` and `rust-toolchain.toml` files by # manually specifying what toolchain to use. Note that this environment variable # is additionally used by `install_rust.sh` as the toolchain to install. # cf https://rust-lang.github.io/rustup/overrides.html ENV RUSTUP_TOOLCHAIN nightly-2024-07-12 # Configure the linker used by default for x86_64 linux to be `clang` instead of # rustc's default of `cc` which is able to find custom-built libraries like # `libc++` by default more easily. ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER clang RUN install_rust.sh ================================================ FILE: infra/base-images/base-builder-swift/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-builder-swift ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-builder-swift` were successfully built. These images install Swift and related tools on top of the `base-builder` image. The build process for both versions is straightforward and relies on the `install_swift.sh` script, which is compatible with both base images. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-builder-swift:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-builder-swift:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) There are no significant package differences introduced in this build stage, as the dependencies are inherited from the `base-builder` image. ## Dockerfile Analysis The Dockerfiles for both versions are very similar and perform the following actions: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-builder` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Swift Installation:** The `install_swift.sh` script is used to download and install Swift. ================================================ FILE: infra/base-images/base-builder-swift/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN install_swift.sh COPY precompile_swift /usr/local/bin/ ================================================ FILE: infra/base-images/base-builder-swift/llvmsymbol.diff ================================================ diff --git a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt index acfb3bd0e..a499ee2e0 100644 --- a/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt +++ b/llvm/lib/DebugInfo/Symbolize/CMakeLists.txt @@ -12,4 +12,8 @@ add_llvm_component_library(LLVMSymbolize Object Support Demangle - ) + + LINK_LIBS + /usr/lib/swift_static/linux/libswiftCore.a + /usr/lib/x86_64-linux-gnu/libstdc++.so.6 +) diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index fb4875f79..0030769ee 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -36,6 +36,13 @@ #include #include + +extern "C" char *swift_demangle(const char *mangledName, + size_t mangledNameLength, + char *outputBuffer, + size_t *outputBufferSize, + uint32_t flags); + namespace llvm { namespace symbolize { @@ -678,6 +685,14 @@ LLVMSymbolizer::DemangleName(const std::string &Name, free(DemangledName); return Result; } + if (!Name.empty() && Name.front() == '$') { + char *DemangledName = swift_demangle(Name.c_str(), Name.length(), 0, 0, 0); + if (DemangledName) { + std::string Result = DemangledName; + free(DemangledName); + return Result; + } + } if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module()) return std::string(demanglePE32ExternCFunc(Name)); ================================================ FILE: infra/base-images/base-builder-swift/precompile_swift ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp /usr/local/bin/llvm-symbolizer-swift $OUT/llvm-symbolizer export SWIFTFLAGS="-Xswiftc -parse-as-library -Xswiftc -static-stdlib --static-swift-stdlib" if [ "$SANITIZER" = "coverage" ] then export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -profile-generate -Xswiftc -profile-coverage-mapping -Xswiftc -sanitize=fuzzer" else export SWIFTFLAGS="$SWIFTFLAGS -Xswiftc -sanitize=fuzzer,$SANITIZER --sanitize=$SANITIZER" for f in $CFLAGS; do export SWIFTFLAGS="$SWIFTFLAGS -Xcc=$f" done for f in $CXXFLAGS; do export SWIFTFLAGS="$SWIFTFLAGS -Xcxx=$f" done fi ================================================ FILE: infra/base-images/base-builder-swift/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 RUN install_swift_ubuntu-20-04.sh COPY precompile_swift /usr/local/bin/ ================================================ FILE: infra/base-images/base-builder-swift/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 COPY llvmsymbol.diff /src/ RUN install_swift_ubuntu-24-04.sh COPY precompile_swift /usr/local/bin/ ================================================ FILE: infra/base-images/base-clang/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-clang ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-clang` were successfully built. Both images install Clang and its dependencies on top of the corresponding `base-image`. The build process for both versions is complex, involving the checkout and compilation of a specific LLVM revision. The primary differences between the two versions are the base image used and the script for checking out and building LLVM. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-clang:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-clang:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The package differences are numerous due to the different base Ubuntu versions. The `ubuntu-24-04` image uses newer versions of essential build tools and libraries, such as `g++`, `python3`, and `zlib1g-dev`. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-image` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **LLVM Build Script:** The `ubuntu-24-04` Dockerfile uses a new script, `checkout_build_install_llvm_24.04.sh`, to handle the LLVM build process, while the `ubuntu-20-04` Dockerfile uses `checkout_build_install_llvm.sh`. This is necessary to accommodate changes in the build environment and dependencies between the two Ubuntu versions. ================================================ FILE: infra/base-images/base-clang/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image with clang installed. FROM gcr.io/oss-fuzz-base/base-image ARG arch=x86_64 ENV FUZZINTRO_OUTDIR=$SRC # Install newer cmake. # Many projects, as well as recent clang versions, need a newer cmake. ENV CMAKE_VERSION 3.29.2 RUN apt-get update && apt-get install -y wget sudo && \ wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-$arch.sh && \ chmod +x cmake-$CMAKE_VERSION-Linux-$arch.sh && \ ./cmake-$CMAKE_VERSION-Linux-$arch.sh --skip-license --prefix="/usr/local" && \ rm cmake-$CMAKE_VERSION-Linux-$arch.sh && \ SUDO_FORCE_REMOVE=yes apt-get autoremove --purge -y wget sudo && \ rm -rf /usr/local/doc/cmake /usr/local/bin/cmake-gui COPY checkout_build_install_llvm.sh /root/ # Keep all steps in the same script to decrease the number of intermediate # layes in docker file. ARG FULL_LLVM_BUILD RUN FULL_LLVM_BUILD=$FULL_LLVM_BUILD /root/checkout_build_install_llvm.sh RUN rm /root/checkout_build_install_llvm.sh # Setup the environment. ENV CC "clang" ENV CXX "clang++" ENV CCC "clang++" # FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is described at # https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode # The implicit-function-declaration and implicit-int errors are downgraded to a # warning, to allow compiling legacy code. # See https://releases.llvm.org/16.0.0/tools/clang/docs/ReleaseNotes.html#potentially-breaking-changes # Same for deprecated-declarations, int-conversion, # incompatible-function-pointer-types, enum-constexpr-conversion, # vla-cxx-extension ENV CFLAGS -O1 \ -fno-omit-frame-pointer \ -gline-tables-only \ -Wno-error=incompatible-function-pointer-types \ -Wno-error=int-conversion \ -Wno-error=deprecated-declarations \ -Wno-error=implicit-function-declaration \ -Wno-error=implicit-int \ -Wno-error=unknown-warning-option \ -Wno-error=vla-cxx-extension \ -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ENV CXXFLAGS_EXTRA "-stdlib=libc++" ENV CXXFLAGS "$CFLAGS $CXXFLAGS_EXTRA" ================================================ FILE: infra/base-images/base-clang/README.md ================================================ # base-builder-clang ## Regular build ``` docker build -t gcr.io/oss-fuzz-base/base-clang . ``` ## Full build For a build including all binaries and libraries, including with everything built against libcxx, do ``` docker build -t gcr.io/oss-fuzz-base/base-clang-full --build-arg FULL_LLVM_BUILD=1 . ``` ================================================ FILE: infra/base-images/base-clang/checkout_build_install_llvm.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ NPROC=$(nproc) # Set this to get a full build with all binaries and libraries, as well as # everything built with libcxx. if [ -z "${FULL_LLVM_BUILD-}" ]; then FULL_LLVM_BUILD= fi TARGET_TO_BUILD= case $(uname -m) in x86_64) TARGET_TO_BUILD=X86 ARCHITECTURE_DEPS="g++-multilib" # Use chromium's clang revision. export CC=$WORK/llvm-stage1/bin/clang export CXX=$WORK/llvm-stage1/bin/clang++ ;; aarch64) TARGET_TO_BUILD=AArch64 # g++ multilib is not needed on AArch64 because we don't care about i386. # We need to install clang and lld using apt because the binary downloaded # from Chrome's developer tools doesn't support AArch64. # TODO(metzman): Make x86_64 use the distro's clang for consistency once # we support AArch64 fully. ARCHITECTURE_DEPS="clang lld g++" export CC=clang export CXX=clang++ ;; *) echo "Error: unsupported target $(uname -m)" exit 1 ;; esac INTROSPECTOR_DEP_PACKAGES="texinfo bison flex" # zlib1g-dev is needed for llvm-profdata to handle coverage data from rust compiler LLVM_DEP_PACKAGES="build-essential make ninja-build git python3 python3-distutils binutils-dev zlib1g-dev $ARCHITECTURE_DEPS $INTROSPECTOR_DEP_PACKAGES" apt-get update && apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends # For manual bumping. # On each bump a full trial run for everything (fuzzing engines, sanitizers, # languages, projects, ...) is needed. # Check CMAKE_VERSION infra/base-images/base-clang/Dockerfile was released # recently enough to fully support this clang version. OUR_LLVM_REVISION=cb2f0d0a5f14 mkdir $SRC/chromium_tools cd $SRC/chromium_tools git clone https://chromium.googlesource.com/chromium/src/tools/clang cd clang # Pin clang script due to https://github.com/google/oss-fuzz/issues/7617 OUR_CLANG_REVISION=063d3766486a820c708e888d737b004d11543410 git checkout $OUR_CLANG_REVISION LLVM_SRC=$SRC/llvm-project # Checkout CHECKOUT_RETRIES=10 function clone_with_retries { REPOSITORY=$1 LOCAL_PATH=$2 CHECKOUT_RETURN_CODE=1 # Disable exit on error since we might encounter some failures while retrying. set +e for i in $(seq 1 $CHECKOUT_RETRIES); do rm -rf $LOCAL_PATH git clone $REPOSITORY $LOCAL_PATH CHECKOUT_RETURN_CODE=$? if [ $CHECKOUT_RETURN_CODE -eq 0 ]; then break fi done # Re-enable exit on error. If checkout failed, script will exit. set -e return $CHECKOUT_RETURN_CODE } clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC git -C $LLVM_SRC checkout $OUR_LLVM_REVISION echo "Using LLVM revision: $OUR_LLVM_REVISION" # Prepare fuzz introspector. echo "Installing fuzz introspector" FUZZ_INTROSPECTOR_CHECKOUT=341ebbd72bc9116733bcfcfab5adfd7f9b633e07 git clone https://github.com/ossf/fuzz-introspector.git /fuzz-introspector cd /fuzz-introspector git checkout $FUZZ_INTROSPECTOR_CHECKOUT git submodule init git submodule update echo "Applying introspector changes" OLD_WORKING_DIR=$PWD cd $LLVM_SRC cp -rf /fuzz-introspector/frontends/llvm/include/llvm/Transforms/FuzzIntrospector/ ./llvm/include/llvm/Transforms/FuzzIntrospector cp -rf /fuzz-introspector/frontends/llvm/lib/Transforms/FuzzIntrospector ./llvm/lib/Transforms/FuzzIntrospector # LLVM currently does not support dynamically loading LTO passes. Thus, we # hardcode it into Clang instead. Ref: https://reviews.llvm.org/D77704 /fuzz-introspector/frontends/llvm/patch-llvm.sh cd $OLD_WORKING_DIR mkdir -p $WORK/llvm-stage2 $WORK/llvm-stage1 python3 $SRC/chromium_tools/clang/scripts/update.py --output-dir $WORK/llvm-stage1 cd $WORK/llvm-stage2 if [[ -n "$FULL_LLVM_BUILD" ]]; then # Bootstrap libc++ so we can build llvm with it. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja runtimes -j $NPROC ninja install-runtimes # Make libc++ discoverable by the linker. export LIBRARY_PATH=/usr/local/lib/x86_64-unknown-linux-gnu/ fi # Note: LLVM_ENABLE_LIBCXX=ON doesn't break the build even if libcxx doesn't # exist. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLLVM_ENABLE_LIBCXX=ON \ -DLLVM_ENABLE_WARNINGS=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja -j $NPROC ninja install rm -rf $WORK/llvm-stage1 $WORK/llvm-stage2 # libFuzzer sources. cp -r $LLVM_SRC/compiler-rt/lib/fuzzer $SRC/libfuzzer # Use the clang we just built from now on. export CC=clang export CXX=clang++ function free_disk_space { rm -rf $LLVM_SRC $SRC/chromium_tools apt-get autoremove --purge -y $LLVM_DEP_PACKAGES if [[ -n "$FULL_LLVM_BUILD" ]]; then return 0 fi # Delete unneeded parts of LLVM to reduce image size. # See https://github.com/google/oss-fuzz/issues/5170 LLVM_TOOLS_TMPDIR=/tmp/llvm-tools mkdir $LLVM_TOOLS_TMPDIR # Move binaries with llvm- prefix that we want into LLVM_TOOLS_TMPDIR. mv \ /usr/local/bin/llvm-ar \ /usr/local/bin/llvm-as \ /usr/local/bin/llvm-config \ /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-link \ /usr/local/bin/llvm-objcopy \ /usr/local/bin/llvm-nm \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-ranlib \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/llvm-undname \ /usr/local/bin/llvm-readelf \ /usr/local/bin/llvm-readobj \ $LLVM_TOOLS_TMPDIR # Delete remaining llvm- binaries. rm -rf /usr/local/bin/llvm-* # Restore the llvm- binaries we want to keep. mv $LLVM_TOOLS_TMPDIR/* /usr/local/bin/ rm -rf $LLVM_TOOLS_TMPDIR # Remove binaries from LLVM build that we don't need. rm -f \ /usr/local/bin/bugpoint \ /usr/local/bin/llc \ /usr/local/bin/lli \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/clang-offload-wrapper \ /usr/local/bin/clang-offload-bundler \ /usr/local/bin/clang-repl \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/c-index-test \ /usr/local/bin/clang-rename \ /usr/local/bin/clang-scan-deps \ /usr/local/bin/clang-extdef-mapping \ /usr/local/bin/diagtool \ /usr/local/bin/sanstats \ /usr/local/bin/dsymutil \ /usr/local/bin/verify-uselistorder \ /usr/local/bin/clang-format # Remove unneeded clang libs, CMake files from LLVM build, lld libs, and the # libraries. # Note: we need fuzzer_no_main libraries for atheris. Don't delete. rm -rf \ /usr/local/lib/libclang* \ /usr/local/lib/liblld* \ /usr/local/lib/cmake/ } if [ "$TARGET_TO_BUILD" == "AArch64" ] then free_disk_space # Exit now on AArch64. We don't need to rebuild libc++ because on AArch64 we # do not support MSAN nor do we care about i386. exit 0 fi function cmake_libcxx { extra_args="$@" cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PIC=ON \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ $extra_args \ -S $LLVM_SRC/runtimes } # 32-bit libraries. mkdir -p $WORK/i386 cd $WORK/i386 cmake_libcxx \ -DCMAKE_INSTALL_PREFIX=/usr/i386/ \ -DCMAKE_C_FLAGS="-m32" \ -DCMAKE_CXX_FLAGS="-m32" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/i386 # MemorySanitizer instrumented libraries. mkdir -p $WORK/msan cd $WORK/msan # https://github.com/google/oss-fuzz/issues/1099 cat < $WORK/msan/ignorelist.txt fun:__gxx_personality_* EOF cmake_libcxx \ -DLLVM_USE_SANITIZER=Memory \ -DCMAKE_INSTALL_PREFIX=/usr/msan/ \ -DCMAKE_CXX_FLAGS="-fsanitize-ignorelist=$WORK/msan/ignorelist.txt" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/msan free_disk_space ================================================ FILE: infra/base-images/base-clang/checkout_build_install_llvm_ubuntu_20_04.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ NPROC=$(nproc) # Set this to get a full build with all binaries and libraries, as well as # everything built with libcxx. if [ -z "${FULL_LLVM_BUILD-}" ]; then FULL_LLVM_BUILD= fi TARGET_TO_BUILD= case $(uname -m) in x86_64) TARGET_TO_BUILD=X86 ARCHITECTURE_DEPS="g++-multilib" # Use chromium's clang revision. export CC=$WORK/llvm-stage1/bin/clang export CXX=$WORK/llvm-stage1/bin/clang++ ;; aarch64) TARGET_TO_BUILD=AArch64 # g++ multilib is not needed on AArch64 because we don't care about i386. # We need to install clang and lld using apt because the binary downloaded # from Chrome's developer tools doesn't support AArch64. # TODO(metzman): Make x86_64 use the distro's clang for consistency once # we support AArch64 fully. ARCHITECTURE_DEPS="clang lld g++" export CC=clang export CXX=clang++ ;; *) echo "Error: unsupported target $(uname -m)" exit 1 ;; esac INTROSPECTOR_DEP_PACKAGES="texinfo bison flex" # zlib1g-dev is needed for llvm-profdata to handle coverage data from rust compiler LLVM_DEP_PACKAGES="build-essential make ninja-build git python3 python3-distutils binutils-dev zlib1g-dev $ARCHITECTURE_DEPS $INTROSPECTOR_DEP_PACKAGES" apt-get update && apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends # For manual bumping. # On each bump a full trial run for everything (fuzzing engines, sanitizers, # languages, projects, ...) is needed. # Check CMAKE_VERSION infra/base-images/base-clang/Dockerfile was released # recently enough to fully support this clang version. OUR_LLVM_REVISION=cb2f0d0a5f14 mkdir $SRC/chromium_tools cd $SRC/chromium_tools git clone https://chromium.googlesource.com/chromium/src/tools/clang cd clang # Pin clang script due to https://github.com/google/oss-fuzz/issues/7617 OUR_CLANG_REVISION=063d3766486a820c708e888d737b004d11543410 git checkout $OUR_CLANG_REVISION LLVM_SRC=$SRC/llvm-project # Checkout CHECKOUT_RETRIES=10 function clone_with_retries { REPOSITORY=$1 LOCAL_PATH=$2 CHECKOUT_RETURN_CODE=1 # Disable exit on error since we might encounter some failures while retrying. set +e for i in $(seq 1 $CHECKOUT_RETRIES); do rm -rf $LOCAL_PATH git clone $REPOSITORY $LOCAL_PATH CHECKOUT_RETURN_CODE=$? if [ $CHECKOUT_RETURN_CODE -eq 0 ]; then break fi done # Re-enable exit on error. If checkout failed, script will exit. set -e return $CHECKOUT_RETURN_CODE } clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC git -C $LLVM_SRC checkout $OUR_LLVM_REVISION echo "Using LLVM revision: $OUR_LLVM_REVISION" # Prepare fuzz introspector. echo "Installing fuzz introspector" FUZZ_INTROSPECTOR_CHECKOUT=341ebbd72bc9116733bcfcfab5adfd7f9b633e07 git clone https://github.com/ossf/fuzz-introspector.git /fuzz-introspector cd /fuzz-introspector git checkout $FUZZ_INTROSPECTOR_CHECKOUT git submodule init git submodule update echo "Applying introspector changes" OLD_WORKING_DIR=$PWD cd $LLVM_SRC cp -rf /fuzz-introspector/frontends/llvm/include/llvm/Transforms/FuzzIntrospector/ ./llvm/include/llvm/Transforms/FuzzIntrospector cp -rf /fuzz-introspector/frontends/llvm/lib/Transforms/FuzzIntrospector ./llvm/lib/Transforms/FuzzIntrospector # LLVM currently does not support dynamically loading LTO passes. Thus, we # hardcode it into Clang instead. Ref: https://reviews.llvm.org/D77704 /fuzz-introspector/frontends/llvm/patch-llvm.sh cd $OLD_WORKING_DIR mkdir -p $WORK/llvm-stage2 $WORK/llvm-stage1 python3 $SRC/chromium_tools/clang/scripts/update.py --output-dir $WORK/llvm-stage1 cd $WORK/llvm-stage2 if [[ -n "$FULL_LLVM_BUILD" ]]; then # Bootstrap libc++ so we can build llvm with it. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja runtimes -j $NPROC ninja install-runtimes # Make libc++ discoverable by the linker. export LIBRARY_PATH=/usr/local/lib/x86_64-unknown-linux-gnu/ fi # Note: LLVM_ENABLE_LIBCXX=ON doesn't break the build even if libcxx doesn\'t # exist. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLLVM_ENABLE_LIBCXX=ON \ -DLLVM_ENABLE_WARNINGS=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja -j $NPROC ninja install rm -rf $WORK/llvm-stage1 $WORK/llvm-stage2 # libFuzzer sources. cp -r $LLVM_SRC/compiler-rt/lib/fuzzer $SRC/libfuzzer # Use the clang we just built from now on. export CC=clang export CXX=clang++ function free_disk_space { rm -rf $LLVM_SRC $SRC/chromium_tools apt-get autoremove --purge -y $LLVM_DEP_PACKAGES if [[ -n "$FULL_LLVM_BUILD" ]]; then return 0 fi # Delete unneeded parts of LLVM to reduce image size. # See https://github.com/google/oss-fuzz/issues/5170 LLVM_TOOLS_TMPDIR=/tmp/llvm-tools mkdir $LLVM_TOOLS_TMPDIR # Move binaries with llvm- prefix that we want into LLVM_TOOLS_TMPDIR. mv \ /usr/local/bin/llvm-ar \ /usr/local/bin/llvm-as \ /usr/local/bin/llvm-config \ /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-link \ /usr/local/bin/llvm-objcopy \ /usr/local/bin/llvm-nm \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-ranlib \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/llvm-undname \ /usr/local/bin/llvm-readelf \ /usr/local/bin/llvm-readobj \ $LLVM_TOOLS_TMPDIR # Delete remaining llvm- binaries. rm -rf /usr/local/bin/llvm-* # Restore the llvm- binaries we want to keep. mv $LLVM_TOOLS_TMPDIR/* /usr/local/bin/ rm -rf $LLVM_TOOLS_TMPDIR # Remove binaries from LLVM build that we don't need. rm -f \ /usr/local/bin/bugpoint \ /usr/local/bin/llc \ /usr/local/bin/lli \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/clang-offload-wrapper \ /usr/local/bin/clang-offload-bundler \ /usr/local/bin/clang-repl \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/c-index-test \ /usr/local/bin/clang-rename \ /usr/local/bin/clang-scan-deps \ /usr/local/bin/clang-extdef-mapping \ /usr/local/bin/diagtool \ /usr/local/bin/sanstats \ /usr/local/bin/dsymutil \ /usr/local/bin/verify-uselistorder \ /usr/local/bin/clang-format # Remove unneeded clang libs, CMake files from LLVM build, lld libs, and the # libraries. # Note: we need fuzzer_no_main libraries for atheris. Don't delete. rm -rf \ /usr/local/lib/libclang* \ /usr/local/lib/liblld* \ /usr/local/lib/cmake/ } if [ "$TARGET_TO_BUILD" == "AArch64" ] then free_disk_space # Exit now on AArch64. We don't need to rebuild libc++ because on AArch64 we # do not support MSAN nor do we care about i386. exit 0 fi function cmake_libcxx { extra_args="$@" cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PIC=ON \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ $extra_args \ -S $LLVM_SRC/runtimes } # 32-bit libraries. mkdir -p $WORK/i386 cd $WORK/i386 cmake_libcxx \ -DCMAKE_INSTALL_PREFIX=/usr/i386/ \ -DCMAKE_C_FLAGS="-m32" \ -DCMAKE_CXX_FLAGS="-m32" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/i386 # MemorySanitizer instrumented libraries. mkdir -p $WORK/msan cd $WORK/msan # https://github.com/google/oss-fuzz/issues/1099 cat < $WORK/msan/ignorelist.txt fun:__gxx_personality_* EOF cmake_libcxx \ -DLLVM_USE_SANITIZER=Memory \ -DCMAKE_INSTALL_PREFIX=/usr/msan/ \ -DCMAKE_CXX_FLAGS="-fsanitize-ignorelist=$WORK/msan/ignorelist.txt" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/msan free_disk_space ================================================ FILE: infra/base-images/base-clang/checkout_build_install_llvm_ubuntu_24_04.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ NPROC=$(nproc) # Set this to get a full build with all binaries and libraries, as well as # everything built with libcxx. if [ -z "${FULL_LLVM_BUILD-}" ]; then FULL_LLVM_BUILD= fi TARGET_TO_BUILD= case $(uname -m) in x86_64) TARGET_TO_BUILD=X86 ARCHITECTURE_DEPS="g++-multilib" # Use chromium's clang revision. export CC=$WORK/llvm-stage1/bin/clang export CXX=$WORK/llvm-stage1/bin/clang++ ;; aarch64) TARGET_TO_BUILD=AArch64 # g++ multilib is not needed on AArch64 because we don't care about i386. # We need to install clang and lld using apt because the binary downloaded # from Chrome's developer tools doesn't support AArch64. # TODO(metzman): Make x86_64 use the distro's clang for consistency once # we support AArch64 fully. ARCHITECTURE_DEPS="clang lld g++" export CC=clang export CXX=clang++ ;; *) echo "Error: unsupported target $(uname -m)" exit 1 ;; esac INTROSPECTOR_DEP_PACKAGES="texinfo bison flex" # zlib1g-dev is needed for llvm-profdata to handle coverage data from rust compiler LLVM_DEP_PACKAGES="build-essential make ninja-build git python3 python3-setuptools binutils-dev zlib1g-dev $ARCHITECTURE_DEPS $INTROSPECTOR_DEP_PACKAGES" apt-get update && apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends # For manual bumping. # On each bump a full trial run for everything (fuzzing engines, sanitizers, # languages, projects, ...) is needed. # Check CMAKE_VERSION infra/base-images/base-clang/Dockerfile was released # recently enough to fully support this clang version. OUR_LLVM_REVISION=cb2f0d0a5f14 mkdir $SRC/chromium_tools cd $SRC/chromium_tools git clone https://chromium.googlesource.com/chromium/src/tools/clang cd clang # Pin clang script due to https://github.com/google/oss-fuzz/issues/7617 git checkout 063d3766486a820c708e888d737b004d11543410 LLVM_SRC=$SRC/llvm-project # Checkout CHECKOUT_RETRIES=10 function clone_with_retries { REPOSITORY=$1 LOCAL_PATH=$2 CHECKOUT_RETURN_CODE=1 # Disable exit on error since we might encounter some failures while retrying. set +e for i in $(seq 1 $CHECKOUT_RETRIES); do rm -rf $LOCAL_PATH git clone $REPOSITORY $LOCAL_PATH CHECKOUT_RETURN_CODE=$? if [ $CHECKOUT_RETURN_CODE -eq 0 ]; then break fi done # Re-enable exit on error. If checkout failed, script will exit. set -e return $CHECKOUT_RETURN_CODE } clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC git -C $LLVM_SRC checkout $OUR_LLVM_REVISION echo "Using LLVM revision: $OUR_LLVM_REVISION" # Prepare fuzz introspector. echo "Installing fuzz introspector" FUZZ_INTROSPECTOR_CHECKOUT=341ebbd72bc9116733bcfcfab5adfd7f9b633e07 git clone https://github.com/ossf/fuzz-introspector.git /fuzz-introspector cd /fuzz-introspector git checkout $FUZZ_INTROSPECTOR_CHECKOUT git submodule init git submodule update # For fuzz introspector. echo "Applying introspector changes" OLD_WORKING_DIR=$PWD cd $LLVM_SRC cp -rf /fuzz-introspector/frontends/llvm/include/llvm/Transforms/FuzzIntrospector/ ./llvm/include/llvm/Transforms/FuzzIntrospector cp -rf /fuzz-introspector/frontends/llvm/lib/Transforms/FuzzIntrospector ./llvm/lib/Transforms/FuzzIntrospector # LLVM currently does not support dynamically loading LTO passes. Thus, we # hardcode it into Clang instead. Ref: https://reviews.llvm.org/D77704 /fuzz-introspector/frontends/llvm/patch-llvm.sh cd $OLD_WORKING_DIR mkdir -p $WORK/llvm-stage2 $WORK/llvm-stage1 python3 $SRC/chromium_tools/clang/scripts/update.py --output-dir $WORK/llvm-stage1 cd $WORK/llvm-stage2 if [[ -n "$FULL_LLVM_BUILD" ]]; then # Bootstrap libc++ so we can build llvm with it. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja runtimes -j $NPROC ninja install-runtimes # Make libc++ discoverable by the linker. export LIBRARY_PATH=/usr/local/lib/x86_64-unknown-linux-gnu/ fi # Note: LLVM_ENABLE_LIBCXX=ON doesn't break the build even if libcxx doesn't # exist. cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLLVM_ENABLE_LIBCXX=ON \ -DLLVM_ENABLE_WARNINGS=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi" \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ $LLVM_SRC/llvm ninja -j $NPROC ninja install rm -rf $WORK/llvm-stage1 $WORK/llvm-stage2 # libFuzzer sources. cp -r $LLVM_SRC/compiler-rt/lib/fuzzer $SRC/libfuzzer # Use the clang we just built from now on. export CC=clang export CXX=clang++ function free_disk_space { rm -rf $LLVM_SRC $SRC/chromium_tools apt-get autoremove --purge -y $LLVM_DEP_PACKAGES if [[ -n "$FULL_LLVM_BUILD" ]]; then return 0 fi # Delete unneeded parts of LLVM to reduce image size. # See https://github.com/google/oss-fuzz/issues/5170 LLVM_TOOLS_TMPDIR=/tmp/llvm-tools mkdir $LLVM_TOOLS_TMPDIR # Move binaries with llvm- prefix that we want into LLVM_TOOLS_TMPDIR. mv \ /usr/local/bin/llvm-ar \ /usr/local/bin/llvm-as \ /usr/local/bin/llvm-config \ /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-objcopy \ /usr/local/bin/llvm-nm \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-ranlib \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/llvm-undname \ /usr/local/bin/llvm-readelf \ /usr/local/bin/llvm-readobj \ $LLVM_TOOLS_TMPDIR # Delete remaining llvm- binaries. rm -rf /usr/local/bin/llvm-* # Restore the llvm- binaries we want to keep. mv $LLVM_TOOLS_TMPDIR/* /usr/local/bin/ rm -rf $LLVM_TOOLS_TMPDIR # Remove binaries from LLVM build that we don't need. rm -f \ /usr/local/bin/bugpoint \ /usr/local/bin/llc \ /usr/local/bin/lli \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/clang-offload-wrapper \ /usr/local/bin/clang-offload-bundler \ /usr/local/bin/clang-repl \ /usr/local/bin/clang-check \ /usr/local/bin/clang-refactor \ /usr/local/bin/c-index-test \ /usr/local/bin/clang-rename \ /usr/local/bin/clang-scan-deps \ /usr/local/bin/clang-extdef-mapping \ /usr/local/bin/diagtool \ /usr/local/bin/sanstats \ /usr/local/bin/dsymutil \ /usr/local/bin/verify-uselistorder \ /usr/local/bin/clang-format # Remove unneeded clang libs, CMake files from LLVM build, lld libs, and the # libraries. # Note: we need fuzzer_no_main libraries for atheris. Don't delete. rm -rf \ /usr/local/lib/libclang* \ /usr/local/lib/liblld* \ /usr/local/lib/cmake/ } if [ "$TARGET_TO_BUILD" == "AArch64" ] then free_disk_space # Exit now on AArch64. We don't need to rebuild libc++ because on AArch64 we # do not support MSAN nor do we care about i386. exit 0 fi function cmake_libcxx { extra_args="$@" cmake -G "Ninja" \ -DLIBCXX_ENABLE_SHARED=OFF \ -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \ -DLIBCXXABI_ENABLE_SHARED=OFF \ -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PIC=ON \ -DLLVM_TARGETS_TO_BUILD="$TARGET_TO_BUILD" \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ -DLLVM_BINUTILS_INCDIR="/usr/include/" \ $extra_args \ -S $LLVM_SRC/runtimes } # 32-bit libraries. mkdir -p $WORK/i386 cd $WORK/i386 cmake_libcxx \ -DCMAKE_INSTALL_PREFIX=/usr/i386/ \ -DCMAKE_C_FLAGS="-m32" \ -DCMAKE_CXX_FLAGS="-m32" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/i386 # MemorySanitizer instrumented libraries. mkdir -p $WORK/msan cd $WORK/msan # https://github.com/google/oss-fuzz/issues/1099 cat < $WORK/msan/ignorelist.txt fun:__gxx_personality_* EOF cmake_libcxx \ -DLLVM_USE_SANITIZER=Memory \ -DCMAKE_INSTALL_PREFIX=/usr/msan/ \ -DCMAKE_CXX_FLAGS="-fsanitize-ignorelist=$WORK/msan/ignorelist.txt" ninja -j $NPROC cxx ninja install-cxx rm -rf $WORK/msan free_disk_space ================================================ FILE: infra/base-images/base-clang/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image with clang installed. FROM gcr.io/oss-fuzz-base/base-image ARG arch=x86_64 ENV FUZZINTRO_OUTDIR=$SRC # Install newer cmake. # Many projects, as well as recent clang versions, need a newer cmake. ENV CMAKE_VERSION 3.29.2 RUN apt-get update && apt-get install -y wget sudo && \ wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-$arch.sh && \ chmod +x cmake-$CMAKE_VERSION-Linux-$arch.sh && \ ./cmake-$CMAKE_VERSION-Linux-$arch.sh --skip-license --prefix="/usr/local" && \ rm cmake-$CMAKE_VERSION-Linux-$arch.sh && \ SUDO_FORCE_REMOVE=yes apt-get autoremove --purge -y wget sudo && \ rm -rf /usr/local/doc/cmake /usr/local/bin/cmake-gui COPY checkout_build_install_llvm_ubuntu_20_04.sh /root/ # Keep all steps in the same script to decrease the number of intermediate # layes in docker file. ARG FULL_LLVM_BUILD RUN FULL_LLVM_BUILD=$FULL_LLVM_BUILD /root/checkout_build_install_llvm_ubuntu_20_04.sh RUN rm /root/checkout_build_install_llvm_ubuntu_20_04.sh # Setup the environment. ENV CC "clang" ENV CXX "clang++" ENV CCC "clang++" # FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is described at # https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode # The implicit-function-declaration and implicit-int errors are downgraded to a # warning, to allow compiling legacy code. # See https://releases.llvm.org/16.0.0/tools/clang/docs/ReleaseNotes.html#potentially-breaking-changes # Same for deprecated-declarations, int-conversion, # incompatible-function-pointer-types, enum-constexpr-conversion, # vla-cxx-extension ENV CFLAGS -O1 \ -fno-omit-frame-pointer \ -gline-tables-only \ -Wno-error=incompatible-function-pointer-types \ -Wno-error=int-conversion \ -Wno-error=deprecated-declarations \ -Wno-error=implicit-function-declaration \ -Wno-error=implicit-int \ -Wno-error=unknown-warning-option \ -Wno-error=vla-cxx-extension \ -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ENV CXXFLAGS_EXTRA "-stdlib=libc++" ENV CXXFLAGS "$CFLAGS $CXXFLAGS_EXTRA" ================================================ FILE: infra/base-images/base-clang/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image with clang installed. FROM gcr.io/oss-fuzz-base/base-image:ubuntu-24-04 ARG arch=x86_64 ENV FUZZINTRO_OUTDIR=$SRC # Install newer cmake. # Many projects, as well as recent clang versions, need a newer cmake. ENV CMAKE_VERSION 3.29.2 RUN apt-get update && apt-get install -y wget sudo && \ wget -q https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-$arch.sh && \ chmod +x cmake-$CMAKE_VERSION-Linux-$arch.sh && \ ./cmake-$CMAKE_VERSION-Linux-$arch.sh --skip-license --prefix="/usr/local" && \ rm cmake-$CMAKE_VERSION-Linux-$arch.sh && \ SUDO_FORCE_REMOVE=yes apt-get autoremove --purge -y wget sudo && \ rm -rf /usr/local/doc/cmake /usr/local/bin/cmake-gui COPY checkout_build_install_llvm_ubuntu_24_04.sh /root/ RUN chmod +x /root/checkout_build_install_llvm_ubuntu_24_04.sh # Keep all steps in the same script to decrease the number of intermediate # layes in docker file. ARG FULL_LLVM_BUILD RUN FULL_LLVM_BUILD=$FULL_LLVM_BUILD /root/checkout_build_install_llvm_ubuntu_24_04.sh RUN rm /root/checkout_build_install_llvm_ubuntu_24_04.sh # Setup the environment. ENV CC "clang" ENV CXX "clang++" ENV CCC "clang++" # FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION is described at # https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode # The implicit-function-declaration and implicit-int errors are downgraded to a # warning, to allow compiling legacy code. # See https://releases.llvm.org/16.0.0/tools/clang/docs/ReleaseNotes.html#potentially-breaking-changes # Same for deprecated-declarations, int-conversion, # incompatible-function-pointer-types, enum-constexpr-conversion, # vla-cxx-extension ENV CFLAGS -O1 \ -fno-omit-frame-pointer \ -gline-tables-only \ -Wno-error=incompatible-function-pointer-types \ -Wno-error=int-conversion \ -Wno-error=deprecated-declarations \ -Wno-error=implicit-function-declaration \ -Wno-error=implicit-int \ -Wno-error=unknown-warning-option \ -Wno-error=vla-cxx-extension \ -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ENV CXXFLAGS_EXTRA "-stdlib=libc++" ENV CXXFLAGS "$CFLAGS $CXXFLAGS_EXTRA" ================================================ FILE: infra/base-images/base-image/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-image ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-image` were successfully built. Both images are based on their respective Ubuntu versions and include essential packages for the fuzzing environment. The primary difference between the two is the version of `libgcc-dev` used, which is `libgcc-9-dev` for Ubuntu 20.04 and `libgcc-13-dev` for Ubuntu 24.04. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-image:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-image:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) | Package | Ubuntu 20.04 Version | Ubuntu 24.04 Version | Notes | | --- | --- | --- | --- | | `libgcc-9-dev` | Installed | - | Specific to Ubuntu 20.04 | | `libgcc-13-dev` | - | Installed | Specific to Ubuntu 24.04 | ## Dockerfile Analysis The Dockerfiles for both versions are very similar, with the main differences being: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding Ubuntu version (`ubuntu:20.04` or `ubuntu:24.04`). * **Package Installation:** The `apt-get install` command is updated to install the correct version of `libgcc-dev` for each Ubuntu release. ================================================ FILE: infra/base-images/base-image/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Base image for all other images. ARG parent_image=ubuntu:20.04@sha256:4a45212e9518f35983a976eead0de5eecc555a2f047134e9dd2cfc589076a00d FROM $parent_image ENV DEBIAN_FRONTEND noninteractive # Install tzadata to match ClusterFuzz # (https://github.com/google/oss-fuzz/issues/9280). RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y libc6-dev binutils libgcc-9-dev tzdata && \ apt-get autoremove -y ENV OUT=/out ENV SRC=/src ENV WORK=/work ENV PATH="$PATH:/out" ENV HWASAN_OPTIONS=random_tags=0 RUN mkdir -p $OUT $SRC $WORK && chmod a+rwx $OUT $SRC $WORK ================================================ FILE: infra/base-images/base-image/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Base image for all other images. ARG parent_image=ubuntu:20.04@sha256:4a45212e9518f35983a976eead0de5eecc555a2f047134e9dd2cfc589076a00d FROM $parent_image ENV DEBIAN_FRONTEND noninteractive # Install tzadata to match ClusterFuzz # (https://github.com/google/oss-fuzz/issues/9280). RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y libc6-dev binutils libgcc-9-dev tzdata && \ apt-get autoremove -y ENV OUT=/out ENV SRC=/src ENV WORK=/work ENV PATH="$PATH:/out" ENV HWASAN_OPTIONS=random_tags=0 RUN mkdir -p $OUT $SRC $WORK && chmod a+rwx $OUT $SRC $WORK ================================================ FILE: infra/base-images/base-image/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Base image for all other images. ARG parent_image=ubuntu:24.04@sha256:9cbed754112939e914291337b5e554b07ad7c392491dba6daf25eef1332a22e8 FROM $parent_image ENV DEBIAN_FRONTEND noninteractive # Install tzadata to match ClusterFuzz # (https://github.com/google/oss-fuzz/issues/9280). RUN apt-get update && \ apt-get upgrade -y && \ apt-get install -y libc6-dev binutils libgcc-13-dev tzdata && \ apt-get autoremove -y ENV OUT=/out ENV SRC=/src ENV WORK=/work ENV PATH="$PATH:/out" ENV HWASAN_OPTIONS=random_tags=0 RUN mkdir -p $OUT $SRC $WORK && chmod a+rwx $OUT $SRC $WORK ================================================ FILE: infra/base-images/base-runner/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-runner ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-runner` were successfully built. These images are used to run fuzzers and contain the necessary runtime dependencies. The initial build failed due to incorrect paths in the `COPY` instructions, which was resolved by making the paths relative to the build context. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-runner:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-runner:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The `ubuntu-24-04` image includes newer versions of many packages, including Python, Java, and Node.js. The specific versions of other tools and libraries also differ due to the updated base image. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-image` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **Dependency Installation:** The `install_deps.sh` script is used to install a base set of dependencies, which differ between the two versions. * **COPY Instructions:** The `COPY` instructions were corrected to use paths relative to the build context. ================================================ FILE: infra/base-images/base-runner/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build rust stuff in its own image. We only need the resulting binaries. # Keeping the rust toolchain in the image wastes 1 GB. FROM gcr.io/oss-fuzz-base/base-image as temp-runner-binary-builder RUN apt-get update && apt-get install -y cargo libyaml-dev RUN cargo install rustfilt # Using multi-stage build to copy some LLVM binaries needed in the runner image. FROM gcr.io/oss-fuzz-base/base-clang AS base-clang FROM gcr.io/oss-fuzz-base/base-builder-ruby AS base-ruby # The base builder image compiles a specific Python version. Using a multi-stage build # to copy that same Python interpreter into the runner image saves build time and keeps # the Python versions in sync. FROM gcr.io/oss-fuzz-base/base-builder AS base-builder # Real image that will be used later. FROM gcr.io/oss-fuzz-base/base-image COPY --from=temp-runner-binary-builder /root/.cargo/bin/rustfilt /usr/local/bin # Copy the binaries needed for code coverage and crash symbolization. COPY --from=base-clang /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/ # Copy the pre-compiled Python binaries and libraries COPY --from=base-builder /usr/local/bin/python3.11 /usr/local/bin/python3.11 COPY --from=base-builder /usr/local/lib/libpython3.11.so.1.0 /usr/local/lib/libpython3.11.so.1.0 COPY --from=base-builder /usr/local/include/python3.11 /usr/local/include/python3.11 COPY --from=base-builder /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=base-builder /usr/local/bin/pip3 /usr/local/bin/pip3 # Create symbolic links to ensure compatibility RUN ldconfig && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python3 && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python COPY install_deps.sh / RUN /install_deps.sh && rm /install_deps.sh ENV CODE_COVERAGE_SRC=/opt/code_coverage # Pin coverage to the same as in the base builder: # https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/install_python.sh#L22 RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage $CODE_COVERAGE_SRC && \ cd /opt/code_coverage && \ git checkout edba4873b5e8a390e977a64c522db2df18a8b27d && \ pip3 install wheel && \ # If version "Jinja2==2.10" is in requirements.txt, bump it to a patch version that # supports upgrading its MarkupSafe dependency to a Python 3.11 compatible release: sed -i 's/Jinja2==2.10/Jinja2==2.10.3/' requirements.txt && \ pip3 install -r requirements.txt && \ pip3 install MarkupSafe==2.0.1 && \ pip3 install coverage==6.3.2 # Default environment options for various sanitizers. # Note that these match the settings used in ClusterFuzz and # shouldn't be changed unless a corresponding change is made on # ClusterFuzz side as well. ENV ASAN_OPTIONS="alloc_dealloc_mismatch=0:allocator_may_return_null=1:allocator_release_to_os_interval_ms=500:check_malloc_usable_size=0:detect_container_overflow=1:detect_odr_violation=0:detect_leaks=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=0:handle_abort=1:handle_segv=1:handle_sigill=1:max_uar_stack_size_log=16:print_scariness=1:quarantine_size_mb=10:strict_memcmp=1:strip_path_prefix=/workspace/:symbolize=1:use_sigaltstack=1:dedup_token_length=3" ENV MSAN_OPTIONS="print_stats=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV UBSAN_OPTIONS="print_stacktrace=1:print_summary=1:silence_unsigned_overflow=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV FUZZER_ARGS="-rss_limit_mb=2560 -timeout=25" ENV AFL_FUZZER_ARGS="-m none" # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:$GOPATH/bin COPY gocoverage $GOPATH/gocoverage COPY install_go.sh / RUN /install_go.sh && rm -rf /install_go.sh /root/.go # Install OpenJDK 15 and trim its size by removing unused components. ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME=/usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server ENV PATH=$PATH:$JAVA_HOME/bin COPY install_java.sh / RUN /install_java.sh && rm /install_java.sh # Install JaCoCo for JVM coverage. RUN wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/0.8.7/org.jacoco.cli-0.8.7-nodeps.jar -O /opt/jacoco-cli.jar && \ wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar -O /opt/jacoco-agent.jar && \ echo "37df187b76888101ecd745282e9cd1ad4ea508d6 /opt/jacoco-agent.jar" | shasum --check && \ echo "c1814e7bba5fd8786224b09b43c84fd6156db690 /opt/jacoco-cli.jar" | shasum --check COPY install_javascript.sh / RUN /install_javascript.sh && rm /install_javascript.sh # Copy built ruby. It is up to the fuzzing harnesses # themselves to set GEM_HOME and GEM_PATH appropriately, as this depends # on how the harnesses are packaged. COPY --from=base-ruby /usr/local/bin/ruby /usr/local/bin/ruby COPY --from=base-ruby /usr/local/bin/gem /usr/local/bin/gem COPY --from=base-ruby /usr/local/lib/ruby /usr/local/lib/ruby COPY --from=base-ruby /usr/local/include/ruby-3.3.0 /usr/local/include/ruby-3.3.0 RUN apt-get update && apt-get install -y luarocks # Do this last to make developing these files easier/faster due to caching. COPY bad_build_check \ coverage \ coverage_helper \ download_corpus \ jacoco_report_converter.py \ nyc_report_converter.py \ rcfilt \ reproduce \ run_fuzzer \ parse_options.py \ generate_differential_cov_report.py \ profraw_update.py \ targets_list \ test_all.py \ test_one.py \ python_coverage_runner_help.py \ /usr/local/bin/ ================================================ FILE: infra/base-images/base-runner/README.md ================================================ # base-runner > Base image for fuzzer runners. ```bash docker run -ti gcr.io/oss-fuzz-base/base-runner ``` ## Commands | Command | Description | |---------|-------------| | `reproduce ` | build all fuzz targets and run specified one with testcase `/testcase` and given options. | `run_fuzzer ` | runs specified fuzzer combining options with `.options` file | | `test_all.py` | runs every binary in `/out` as a fuzzer for a while to ensure it works. | | `coverage ` | generate a coverage report for the given fuzzer. | # Examples - *Reproduce using latest OSS-Fuzz build:*
docker run --rm -ti -v <testcase_path>:/testcase gcr.io/oss-fuzz/$PROJECT_NAME reproduce <fuzzer_name>
- *Reproduce using local source checkout:*
docker run --rm -ti -v <source_path>:/src/$PROJECT_NAME \
                    -v <testcase_path>:/testcase gcr.io/oss-fuzz/$PROJECT_NAME \
                    reproduce <fuzzer_name>
================================================ FILE: infra/base-images/base-runner/bad_build_check ================================================ #!/bin/bash -u # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # A minimal number of runs to test fuzz target with a non-empty input. MIN_NUMBER_OF_RUNS=4 # The "example" target has 73 with ASan, 65 with UBSan, and 6648 with MSan. # Real world targets have greater values (arduinojson: 407, zlib: 664). # Mercurial's bdiff_fuzzer has 116 PCs when built with ASan. THRESHOLD_FOR_NUMBER_OF_EDGES=100 # A fuzz target is supposed to have at least two functions, such as # LLVMFuzzerTestOneInput and an API that is being called from there. THRESHOLD_FOR_NUMBER_OF_FUNCTIONS=2 # Threshold values for different sanitizers used by instrumentation checks. ASAN_CALLS_THRESHOLD_FOR_ASAN_BUILD=1000 ASAN_CALLS_THRESHOLD_FOR_NON_ASAN_BUILD=0 # The value below can definitely be higher (like 500-1000), but avoid being too # agressive here while still evaluating the DFT-based fuzzing approach. DFSAN_CALLS_THRESHOLD_FOR_DFSAN_BUILD=100 DFSAN_CALLS_THRESHOLD_FOR_NON_DFSAN_BUILD=0 MSAN_CALLS_THRESHOLD_FOR_MSAN_BUILD=1000 # Some engines (e.g. honggfuzz) may make a very small number of calls to msan # for memory poisoning. MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD=3 # Usually, a non UBSan build (e.g. ASan) has 165 calls to UBSan runtime. The # majority of targets built with UBSan have 200+ UBSan calls, but there are # some very small targets that may have < 200 UBSan calls even in a UBSan build. # Use the threshold value of 168 (slightly > 165) for UBSan build. UBSAN_CALLS_THRESHOLD_FOR_UBSAN_BUILD=168 # It would be risky to use the threshold value close to 165 for non UBSan build, # as UBSan runtime may change any time and thus we could have different number # of calls to UBSan runtime even in ASan build. With that, we use the threshold # value of 200 that would detect unnecessary UBSan instrumentation in the vast # majority of targets, except of a handful very small ones, which would not be # a big concern either way as the overhead for them would not be significant. UBSAN_CALLS_THRESHOLD_FOR_NON_UBSAN_BUILD=200 # ASan builds on i386 generally have about 250 UBSan runtime calls. if [[ $ARCHITECTURE == 'i386' ]] then UBSAN_CALLS_THRESHOLD_FOR_NON_UBSAN_BUILD=280 fi # Verify that the given fuzz target is correctly built to run with a particular # engine. function check_engine { local FUZZER=$1 local FUZZER_NAME=$(basename $FUZZER) local FUZZER_OUTPUT="/tmp/$FUZZER_NAME.output" local CHECK_FAILED=0 if [[ "$FUZZING_ENGINE" == libfuzzer ]]; then # Store fuzz target's output into a temp file to be used for further checks. $FUZZER -- -seed=1337 -runs=$MIN_NUMBER_OF_RUNS &>$FUZZER_OUTPUT CHECK_FAILED=$(egrep "ERROR: no interesting inputs were found. Is the code instrumented" -c $FUZZER_OUTPUT) if (( $CHECK_FAILED > 0 )); then echo "BAD BUILD: $FUZZER does not seem to have coverage instrumentation." cat $FUZZER_OUTPUT # Bail out as the further check does not make any sense, there are 0 PCs. return 1 fi local NUMBER_OF_EDGES=$(grep -Po "INFO: Loaded [[:digit:]]+ module.*\(.*(counters|guards)\):[[:space:]]+\K[[:digit:]]+" $FUZZER_OUTPUT) # If a fuzz target fails to start, grep won't find anything, so bail out early to let check_startup_crash deal with it. [[ -z "$NUMBER_OF_EDGES" ]] && return if (( $NUMBER_OF_EDGES < $THRESHOLD_FOR_NUMBER_OF_EDGES )); then echo "BAD BUILD: $FUZZER seems to have only partial coverage instrumentation." fi elif [[ "$FUZZING_ENGINE" == afl ]]; then AFL_FORKSRV_INIT_TMOUT=30000 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 35s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT CHECK_PASSED=$(egrep "All set and ready to roll" -c $FUZZER_OUTPUT) if (( $CHECK_PASSED == 0 )); then echo "BAD BUILD: fuzzing $FUZZER with afl-fuzz failed." cat $FUZZER_OUTPUT return 1 fi elif [[ "$FUZZING_ENGINE" == honggfuzz ]]; then SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT CHECK_PASSED=$(egrep "^Sz:[0-9]+ Tm:[0-9]+" -c $FUZZER_OUTPUT) if (( $CHECK_PASSED == 0 )); then echo "BAD BUILD: fuzzing $FUZZER with honggfuzz failed." cat $FUZZER_OUTPUT return 1 fi elif [[ "$FUZZING_ENGINE" == dataflow ]]; then $FUZZER &> $FUZZER_OUTPUT local NUMBER_OF_FUNCTIONS=$(grep -Po "INFO:\s+\K[[:digit:]]+(?=\s+instrumented function.*)" $FUZZER_OUTPUT) [[ -z "$NUMBER_OF_FUNCTIONS" ]] && NUMBER_OF_FUNCTIONS=0 if (( $NUMBER_OF_FUNCTIONS < $THRESHOLD_FOR_NUMBER_OF_FUNCTIONS )); then echo "BAD BUILD: $FUZZER does not seem to be properly built in 'dataflow' config." cat $FUZZER_OUTPUT return 1 fi elif [[ "$FUZZING_ENGINE" == centipede \ && ("${HELPER:-}" == True || "$SANITIZER" == none ) ]]; then # Performs run test on unsanitized binaries with auxiliary sanitized # binaries if they are built with helper.py. # Performs run test on unsanitized binaries without auxiliary sanitized # binaries if they are from trial build and production build. # TODO(Dongge): Support run test with sanitized binaries for trial and # production build. SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT CHECK_PASSED=$(egrep "\[S0.0] begin-fuzz: ft: 0 corp: 0/0" -c $FUZZER_OUTPUT) if (( $CHECK_PASSED == 0 )); then echo "BAD BUILD: fuzzing $FUZZER with centipede failed." cat $FUZZER_OUTPUT return 1 fi fi return 0 } # Verify that the given fuzz target has been built properly and works. function check_startup_crash { local FUZZER=$1 local FUZZER_NAME=$(basename $FUZZER) local FUZZER_OUTPUT="/tmp/$FUZZER_NAME.output" local CHECK_PASSED=0 if [[ "$FUZZING_ENGINE" = libfuzzer ]]; then # Skip seed corpus as there is another explicit check that uses seed corpora. SKIP_SEED_CORPUS=1 run_fuzzer $FUZZER_NAME -seed=1337 -runs=$MIN_NUMBER_OF_RUNS &>$FUZZER_OUTPUT CHECK_PASSED=$(egrep "Done $MIN_NUMBER_OF_RUNS runs" -c $FUZZER_OUTPUT) elif [[ "$FUZZING_ENGINE" = afl ]]; then AFL_FORKSRV_INIT_TMOUT=30000 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 35s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT if [ $(egrep "target binary (crashed|terminated)" -c $FUZZER_OUTPUT) -eq 0 ]; then CHECK_PASSED=1 fi elif [[ "$FUZZING_ENGINE" = dataflow ]]; then # TODO(https://github.com/google/oss-fuzz/issues/1632): add check for # binaries compiled with dataflow engine when the interface becomes stable. CHECK_PASSED=1 else # TODO: add checks for another fuzzing engines if possible. CHECK_PASSED=1 fi if [ "$CHECK_PASSED" -eq "0" ]; then echo "BAD BUILD: $FUZZER seems to have either startup crash or exit:" cat $FUZZER_OUTPUT return 1 fi return 0 } # Mixed sanitizers check for ASan build. function check_asan_build { local FUZZER=$1 local ASAN_CALLS=$2 local DFSAN_CALLS=$3 local MSAN_CALLS=$4 local UBSAN_CALLS=$5 # Perform all the checks for more detailed error message. if (( $ASAN_CALLS < $ASAN_CALLS_THRESHOLD_FOR_ASAN_BUILD )); then echo "BAD BUILD: $FUZZER does not seem to be compiled with ASan." return 1 fi if (( $DFSAN_CALLS > $DFSAN_CALLS_THRESHOLD_FOR_NON_DFSAN_BUILD )); then echo "BAD BUILD: ASan build of $FUZZER seems to be compiled with DFSan." return 1 fi if (( $MSAN_CALLS > $MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD )); then echo "BAD BUILD: ASan build of $FUZZER seems to be compiled with MSan." return 1 fi if (( $UBSAN_CALLS > $UBSAN_CALLS_THRESHOLD_FOR_NON_UBSAN_BUILD )); then echo "BAD BUILD: ASan build of $FUZZER seems to be compiled with UBSan." return 1 fi return 0 } # Mixed sanitizers check for DFSan build. function check_dfsan_build { local FUZZER=$1 local ASAN_CALLS=$2 local DFSAN_CALLS=$3 local MSAN_CALLS=$4 local UBSAN_CALLS=$5 # Perform all the checks for more detailed error message. if (( $ASAN_CALLS > $ASAN_CALLS_THRESHOLD_FOR_NON_ASAN_BUILD )); then echo "BAD BUILD: DFSan build of $FUZZER seems to be compiled with ASan." return 1 fi if (( $DFSAN_CALLS < $DFSAN_CALLS_THRESHOLD_FOR_DFSAN_BUILD )); then echo "BAD BUILD: $FUZZER does not seem to be compiled with DFSan." return 1 fi if (( $MSAN_CALLS > $MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD )); then echo "BAD BUILD: ASan build of $FUZZER seems to be compiled with MSan." return 1 fi if (( $UBSAN_CALLS > $UBSAN_CALLS_THRESHOLD_FOR_NON_UBSAN_BUILD )); then echo "BAD BUILD: ASan build of $FUZZER seems to be compiled with UBSan." return 1 fi return 0 } # Mixed sanitizers check for MSan build. function check_msan_build { local FUZZER=$1 local ASAN_CALLS=$2 local DFSAN_CALLS=$3 local MSAN_CALLS=$4 local UBSAN_CALLS=$5 # Perform all the checks for more detailed error message. if (( $ASAN_CALLS > $ASAN_CALLS_THRESHOLD_FOR_NON_ASAN_BUILD )); then echo "BAD BUILD: MSan build of $FUZZER seems to be compiled with ASan." return 1 fi if (( $DFSAN_CALLS > $DFSAN_CALLS_THRESHOLD_FOR_NON_DFSAN_BUILD )); then echo "BAD BUILD: MSan build of $FUZZER seems to be compiled with DFSan." return 1 fi if (( $MSAN_CALLS < $MSAN_CALLS_THRESHOLD_FOR_MSAN_BUILD )); then echo "BAD BUILD: $FUZZER does not seem to be compiled with MSan." return 1 fi if (( $UBSAN_CALLS > $UBSAN_CALLS_THRESHOLD_FOR_NON_UBSAN_BUILD )); then echo "BAD BUILD: MSan build of $FUZZER seems to be compiled with UBSan." return 1 fi return 0 } # Mixed sanitizers check for UBSan build. function check_ubsan_build { local FUZZER=$1 local ASAN_CALLS=$2 local DFSAN_CALLS=$3 local MSAN_CALLS=$4 local UBSAN_CALLS=$5 if [[ "$FUZZING_ENGINE" != libfuzzer ]]; then # Ignore UBSan checks for fuzzing engines other than libFuzzer because: # A) we (probably) are not going to use those with UBSan # B) such builds show indistinguishable number of calls to UBSan return 0 fi # Perform all the checks for more detailed error message. if (( $ASAN_CALLS > $ASAN_CALLS_THRESHOLD_FOR_NON_ASAN_BUILD )); then echo "BAD BUILD: UBSan build of $FUZZER seems to be compiled with ASan." return 1 fi if (( $DFSAN_CALLS > $DFSAN_CALLS_THRESHOLD_FOR_NON_DFSAN_BUILD )); then echo "BAD BUILD: UBSan build of $FUZZER seems to be compiled with DFSan." return 1 fi if (( $MSAN_CALLS > $MSAN_CALLS_THRESHOLD_FOR_NON_MSAN_BUILD )); then echo "BAD BUILD: UBSan build of $FUZZER seems to be compiled with MSan." return 1 fi if (( $UBSAN_CALLS < $UBSAN_CALLS_THRESHOLD_FOR_UBSAN_BUILD )); then echo "BAD BUILD: $FUZZER does not seem to be compiled with UBSan." return 1 fi } # Verify that the given fuzz target is compiled with correct sanitizer. function check_mixed_sanitizers { local FUZZER=$1 local result=0 local CALL_INSN= if [ "${FUZZING_LANGUAGE:-}" = "jvm" ]; then # Sanitizer runtime is linked into the Jazzer driver, so this check does not # apply. return 0 fi if [ "${FUZZING_LANGUAGE:-}" = "javascript" ]; then # Jazzer.js currently does not support using sanitizers with native Node.js addons. # This is not relevant anyways since supporting this will be done by preloading # the sanitizers in the wrapper script starting Jazzer.js. return 0 fi if [ "${FUZZING_LANGUAGE:-}" = "ruby" ]; then return 0 fi if [ "${FUZZING_LANGUAGE:-}" = "python" ]; then # Sanitizer runtime is loaded via LD_PRELOAD, so this check does not apply. return 0 fi # luzer-based tests. # Sanitizer runtime is loaded via LD_PRELOAD, so this check does # not apply. egrep luarocks $FUZZER && return 0; # For fuzztest fuzzers point to the binary instead of launcher script. if [[ $FUZZER == *"@"* ]]; then FUZZER=(${FUZZER//@/ }[0]) fi CALL_INSN= if [[ $ARCHITECTURE == "x86_64" ]] then CALL_INSN="callq?\s+[0-9a-f]+\s+<" elif [[ $ARCHITECTURE == "i386" ]] then CALL_INSN="call\s+[0-9a-f]+\s+<" elif [[ $ARCHITECTURE == "aarch64" ]] then CALL_INSN="bl\s+[0-9a-f]+\s+<" else echo "UNSUPPORTED ARCHITECTURE" exit 1 fi local ASAN_CALLS=$(objdump -dC $FUZZER | egrep "${CALL_INSN}__asan" -c) local DFSAN_CALLS=$(objdump -dC $FUZZER | egrep "${CALL_INSN}__dfsan" -c) local MSAN_CALLS=$(objdump -dC $FUZZER | egrep "${CALL_INSN}__msan" -c) local UBSAN_CALLS=$(objdump -dC $FUZZER | egrep "${CALL_INSN}__ubsan" -c) if [[ "$SANITIZER" = address ]]; then check_asan_build $FUZZER $ASAN_CALLS $DFSAN_CALLS $MSAN_CALLS $UBSAN_CALLS result=$? elif [[ "$SANITIZER" = dataflow ]]; then check_dfsan_build $FUZZER $ASAN_CALLS $DFSAN_CALLS $MSAN_CALLS $UBSAN_CALLS result=$? elif [[ "$SANITIZER" = memory ]]; then check_msan_build $FUZZER $ASAN_CALLS $DFSAN_CALLS $MSAN_CALLS $UBSAN_CALLS result=$? elif [[ "$SANITIZER" = undefined ]]; then check_ubsan_build $FUZZER $ASAN_CALLS $DFSAN_CALLS $MSAN_CALLS $UBSAN_CALLS result=$? elif [[ "$SANITIZER" = thread ]]; then # TODO(metzman): Implement this. result=0 fi return $result } # Verify that the given fuzz target doesn't crash on the seed corpus. function check_seed_corpus { local FUZZER=$1 local FUZZER_NAME="$(basename $FUZZER)" local FUZZER_OUTPUT="/tmp/$FUZZER_NAME.output" if [[ "$FUZZING_ENGINE" != libfuzzer ]]; then return 0 fi # Set up common fuzzing arguments, otherwise "run_fuzzer" errors out. if [ -z "$FUZZER_ARGS" ]; then export FUZZER_ARGS="-rss_limit_mb=2560 -timeout=25" fi bash -c "run_fuzzer $FUZZER_NAME -runs=0" &> $FUZZER_OUTPUT # Don't output anything if fuzz target hasn't crashed. if [ $? -ne 0 ]; then echo "BAD BUILD: $FUZZER has a crashing input in its seed corpus:" cat $FUZZER_OUTPUT return 1 fi return 0 } function check_architecture { local FUZZER=$1 local FUZZER_NAME=$(basename $FUZZER) if [ "${FUZZING_LANGUAGE:-}" = "jvm" ]; then # The native dependencies of a JVM project are not packaged, but loaded # dynamically at runtime and thus cannot be checked here. return 0; fi if [ "${FUZZING_LANGUAGE:-}" = "javascript" ]; then # Jazzer.js fuzzers are wrapper scripts that start the fuzz target with # the Jazzer.js CLI. return 0; fi if [ "${FUZZING_LANGUAGE:-}" = "ruby" ]; then return 0; fi if [ "${FUZZING_LANGUAGE:-}" = "python" ]; then FUZZER=${FUZZER}.pkg fi # luzer-based tests. egrep luarocks $FUZZER && return 0; # For fuzztest fuzzers point to the binary instead of launcher script. if [[ $FUZZER == *"@"* ]]; then FUZZER=(${FUZZER//@/ }[0]) fi FILE_OUTPUT=$(file $FUZZER) if [[ $ARCHITECTURE == "x86_64" ]] then echo $FILE_OUTPUT | grep "x86-64" > /dev/null elif [[ $ARCHITECTURE == "i386" ]] then echo $FILE_OUTPUT | grep "80386" > /dev/null elif [[ $ARCHITECTURE == "aarch64" ]] then echo $FILE_OUTPUT | grep "aarch64" > /dev/null else echo "UNSUPPORTED ARCHITECTURE" return 1 fi result=$? if [[ $result != 0 ]] then echo "BAD BUILD $FUZZER is not built for architecture: $ARCHITECTURE" echo "file command output: $FILE_OUTPUT" echo "check_mixed_sanitizers test will fail." fi return $result } function main { local FUZZER=$1 local AUXILIARY_FUZZER=${2:-} local checks_failed=0 local result=0 export RUN_FUZZER_MODE="batch" check_engine $FUZZER result=$? checks_failed=$(( $checks_failed + $result )) check_architecture $FUZZER result=$? checks_failed=$(( $checks_failed + $result )) if [[ "$FUZZING_ENGINE" == centipede \ && "$SANITIZER" != none && "${HELPER:-}" == True ]]; then check_mixed_sanitizers $AUXILIARY_FUZZER else check_mixed_sanitizers $FUZZER fi result=$? checks_failed=$(( $checks_failed + $result )) check_startup_crash $FUZZER result=$? checks_failed=$(( $checks_failed + $result )) # TODO: re-enable after introducing bug auto-filing for bad builds. # check_seed_corpus $FUZZER return $checks_failed } if [ $# -ne 1 -a $# -ne 2 ]; then echo "Usage: $0 []" exit 1 fi # Fuzz target path. FUZZER=$1 AUXILIARY_FUZZER=${2:-} main $FUZZER $AUXILIARY_FUZZER exit $? ================================================ FILE: infra/base-images/base-runner/coverage ================================================ #!/bin/bash -u # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $OUT if (( $# > 0 )); then FUZZ_TARGETS="$@" else FUZZ_TARGETS="$(find . -maxdepth 1 -type f -executable -printf '%P\n' | \ grep -v -x -F \ -e 'llvm-symbolizer' \ -e 'jazzer_agent_deploy.jar' \ -e 'jazzer_driver' \ -e 'jazzer_driver_with_sanitizer' \ -e 'sanitizer_with_fuzzer.so')" fi COVERAGE_OUTPUT_DIR=${COVERAGE_OUTPUT_DIR:-$OUT} DUMPS_DIR="$COVERAGE_OUTPUT_DIR/dumps" FUZZERS_COVERAGE_DUMPS_DIR="$DUMPS_DIR/fuzzers_coverage" MERGED_COVERAGE_DIR="$COVERAGE_OUTPUT_DIR/merged_coverage" FUZZER_STATS_DIR="$COVERAGE_OUTPUT_DIR/fuzzer_stats" TEXTCOV_REPORT_DIR="$COVERAGE_OUTPUT_DIR/textcov_reports" LOGS_DIR="$COVERAGE_OUTPUT_DIR/logs" REPORT_ROOT_DIR="$COVERAGE_OUTPUT_DIR/report" REPORT_BY_TARGET_ROOT_DIR="$COVERAGE_OUTPUT_DIR/report_target" PLATFORM=linux REPORT_PLATFORM_DIR="$COVERAGE_OUTPUT_DIR/report/$PLATFORM" for directory in $DUMPS_DIR $FUZZER_STATS_DIR $LOGS_DIR $REPORT_ROOT_DIR $TEXTCOV_REPORT_DIR\ $REPORT_PLATFORM_DIR $REPORT_BY_TARGET_ROOT_DIR $FUZZERS_COVERAGE_DUMPS_DIR $MERGED_COVERAGE_DIR; do rm -rf $directory mkdir -p $directory done PROFILE_FILE="$DUMPS_DIR/merged.profdata" SUMMARY_FILE="$REPORT_PLATFORM_DIR/summary.json" COVERAGE_TARGET_FILE="$FUZZER_STATS_DIR/coverage_targets.txt" # Use path mapping, as $SRC directory from the builder is copied into $OUT/$SRC. PATH_EQUIVALENCE_ARGS="-path-equivalence=/,$OUT" # It's important to use $COVERAGE_EXTRA_ARGS as the last argument, because it # can contain paths to source files / directories which are positional args. LLVM_COV_COMMON_ARGS="$PATH_EQUIVALENCE_ARGS \ -ignore-filename-regex=.*src/libfuzzer/.* $COVERAGE_EXTRA_ARGS" # Options to extract branch coverage. BRANCH_COV_ARGS="--show-branches=count --show-expansions" # Timeout for running a single fuzz target. TIMEOUT=1h # This will be used by llvm-cov command to generate the actual report. objects="" # Number of CPUs available, this is needed for running tests in parallel. # Set the max number of parallel jobs to be the CPU count and a max of 10. NPROC=$(nproc) MAX_PARALLEL_COUNT=10 CORPUS_DIR=${CORPUS_DIR:-"/corpus"} function run_fuzz_target { local target=$1 # '%1m' will produce separate dump files for every object. For example, if a # fuzz target loads a shared library, we will have dumps for both of them. local profraw_file="$DUMPS_DIR/$target.%1m.profraw" local profraw_file_mask="$DUMPS_DIR/$target.*.profraw" local profdata_file="$DUMPS_DIR/$target.profdata" local corpus_real="$CORPUS_DIR/${target}" # -merge=1 requires an output directory, create a new, empty dir for that. local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}" rm -rf $corpus_dummy && mkdir -p $corpus_dummy # Use -merge=1 instead of -runs=0 because merge is crash resistant and would # let to get coverage using all corpus files even if there are crash inputs. # Merge should not introduce any significant overhead compared to -runs=0, # because (A) corpuses are already minimized; (B) we do not use sancov, and so # libFuzzer always finishes merge with an empty output dir. # Use 100s timeout instead of 25s as code coverage builds can be very slow. local args="-merge=1 -timeout=100 $corpus_dummy $corpus_real" export LLVM_PROFILE_FILE=$profraw_file timeout $TIMEOUT $OUT/$target $args &> $LOGS_DIR/$target.log cov_retcode=$? target_error_log="$LOGS_DIR/${target}_error.log" grep -E "^==[0-9]+== ERROR: libFuzzer:" "$LOGS_DIR/$target.log" > "$target_error_log" grep_retcode=$? if (( $cov_retcode != 0 || $grep_retcode == 0 )); then echo "Error occured while running $target:" echo "Cov returncode: $cov_retcode, grep returncode: $grep_retcode" cat $LOGS_DIR/$target.log fi rm -rf $corpus_dummy if (( $(du -c $profraw_file_mask | tail -n 1 | cut -f 1) == 0 )); then # Skip fuzz targets that failed to produce profile dumps. return 0 fi # If necessary translate to latest profraw version. if [[ $target == *"@"* ]]; then # Extract fuzztest binary name from fuzztest wrapper script. target=(${target//@/ }[0]) fi profraw_update.py $OUT/$target -i $profraw_file_mask llvm-profdata merge -j=1 -sparse $profraw_file_mask -o $profdata_file # Delete unnecessary and (potentially) large .profraw files. rm $profraw_file_mask shared_libraries=$(coverage_helper shared_libs -build-dir=$OUT -object=$target) llvm-cov export -summary-only -instr-profile=$profdata_file -object=$target \ $shared_libraries $LLVM_COV_COMMON_ARGS > $FUZZER_STATS_DIR/$target.json # If grep returned zero an error was matched. echo "Coverage error, creating log file: $FUZZER_STATS_DIR/${target}_error.log" if (( $cov_retcode != 0 || $grep_retcode == 0 )); then mv "$target_error_log" "$FUZZER_STATS_DIR/${target}_error.log"; fi # For introspector. llvm-cov show -instr-profile=$profdata_file -object=$target -line-coverage-gt=0 $shared_libraries $BRANCH_COV_ARGS $LLVM_COV_COMMON_ARGS > ${TEXTCOV_REPORT_DIR}/$target.covreport } # The native_go_fuzzers.json file contains a list of # fuzzers that are std lib harnesses. This function # reads that json list to see if the name of a fuzzer # exists in that list. is_std_lib_fuzzer() { local element="$1" local file="$OUT/native_go_fuzzers.json" if [ -z "$element" ]; then echo "Usage: check_in_list \"element to check\"" return 1 fi if [ ! -s "$file" ]; then echo "false" return 0 fi if jq -e --arg item "$element" 'index($item) != null' "$file" > /dev/null; then echo "true" else echo "false" fi } # get_function_name reads a value from a simple json format: # # { # "fuzzerBinaryName1": "FuzzFunctionName1", # "fuzzerBinaryName2": "FuzzFunctionName2" # } # # In this case, we call `get_function_name fuzzerBinaryName1 # $OUT/fuzzer_function_names.json` to get "FuzzFunctionName1". # We need this when setting up a temporary directory for # getting the coverage. # Go reads corpus files from `testdata/fuzz/FuzzFunctionName1`, # so we need the function name instead of the executable binary name. get_function_name() { local key="$1" local file="$2" if [ -z "$key" ] || [ -z "$file" ]; then echo "Usage: get_function_name " return 1 fi # If file doesn't exist or is empty if [ ! -s "$file" ]; then echo "Error: File '$file' does not exist or is empty." return 1 fi # Use jq to extract the value local result result=$(jq -r --arg k "$key" '.[$k] // empty' "$file") if [ -z "$result" ]; then echo "Error: Key '$key' not found in '$file'." return 1 else echo "$result" fi } function run_go_fuzz_target { local target=$1 echo "Running go target $target" export FUZZ_CORPUS_DIR="$CORPUS_DIR/${target}/" export FUZZ_PROFILE_NAME="$DUMPS_DIR/$target.perf" # "NAME" in testdata/fuzz/NAME needs to be the function # name of the fuzz test in the compiled binary. We have # stored that name in $OUT/fuzzer_function_names.json. # We also need this parameter for go-fuzz fuzzers, to # run only the single function. Otherwise, the test may # run other tests that are included in the binary function_names_file="$OUT/fuzzer_function_names.json" function_name=$(get_function_name "$target" "$function_names_file") if [[ "$(is_std_lib_fuzzer "${target}")" == "true" ]]; then # Create the corpus dir testdata/fuzz/NAME mkdir -p "${OUT}/testdata/fuzz/${function_name}" # Now we copy the corpus generated at runtime into FUZZ_CORPUS_DIR. # In the process, we convert it from a raw byte slice to files of # the std lib Go corpus file format, eg: # # go test fuzz v1 # int8(42) # string("hello") # # The convertLibFuzzerTestcaseToStdLibGo binary handles the entire # process for that. convertLibFuzzerTestcaseToStdLibGo -convert-seeds \ -params-json $OUT/fuzzer-parameters.json \ -fuzzer-func "${target}" \ -fuzzerBinaryName $target \ -seeds-dir "${FUZZ_CORPUS_DIR}" \ -out-dir "${OUT}/testdata/fuzz/${function_name}" pushd $OUT timeout "$TIMEOUT" \ "$OUT/$target" \ -test.run="^${function_name}\$" \ -test.coverprofile "$DUMPS_DIR/$target.profdata" \ &> "$LOGS_DIR/$target.log" if (( $? != 0 )); then echo "Error occured while running std lib fuzzer $target:" cat $LOGS_DIR/$target.log fi popd # cleanup after native go fuzzers rm -r "${OUT}/testdata/fuzz/${function_name}" # The std lib fuzzers are renamed to "*_fuzz_.go" during "infra/helper.py build_fuzzers". # They are are therefore refered to as "*_fuzz_.go" in the profdata files. # Since the copies named "*_fuzz_.go" do not exist in the file tree during # the coverage build, we change the references in the .profdata files # to the original file names. sed -i "s/_libFuzzer.go/_test.go/g" $DUMPS_DIR/$target.profdata else timeout "$TIMEOUT" \ "$OUT/$target" \ -test.run="^${function_name}\$" \ -test.coverprofile "$DUMPS_DIR/$target.profdata" \ &> "$LOGS_DIR/$target.log" if (( $? != 0 )); then echo "Error occured while running $target:" cat $LOGS_DIR/$target.log fi fi # translate from golangish paths to current absolute paths cat $OUT/$target.gocovpath | while read i; do sed -i $i $DUMPS_DIR/$target.profdata; done # cf PATH_EQUIVALENCE_ARGS sed -i 's=/='$OUT'/=' $DUMPS_DIR/$target.profdata $SYSGOPATH/bin/gocovsum $DUMPS_DIR/$target.profdata > $FUZZER_STATS_DIR/$target.json } function run_python_fuzz_target { local target=$1 local zipped_sources="$DUMPS_DIR/$target.deps.zip" local corpus_real="$CORPUS_DIR/${target}" # Write dummy stats file echo "{}" > "$FUZZER_STATS_DIR/$target.json" # Run fuzzer $OUT/$target $corpus_real -atheris_runs=$(ls -la $corpus_real | wc -l) > $LOGS_DIR/$target.log 2>&1 if (( $? != 0 )); then echo "Error happened getting coverage of $target" echo "This is likely because Atheris did not exit gracefully" cat $LOGS_DIR/$target.log return 0 fi mv .coverage $OUT/.coverage_$target } function run_java_fuzz_target { local target=$1 local exec_file="$DUMPS_DIR/$target.exec" local class_dump_dir="$DUMPS_DIR/${target}_classes/" mkdir "$class_dump_dir" local corpus_real="$CORPUS_DIR/${target}" # -merge=1 requires an output directory, create a new, empty dir for that. local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}" rm -rf $corpus_dummy && mkdir -p $corpus_dummy # Use 100s timeout instead of 25s as code coverage builds can be very slow. local jacoco_args="destfile=$exec_file,classdumpdir=$class_dump_dir,excludes=com.code_intelligence.jazzer.*\\:com.sun.tools.attach.VirtualMachine" local args="-merge=1 -timeout=100 --nohooks \ --additional_jvm_args=-javaagent\\:/opt/jacoco-agent.jar=$jacoco_args \ $corpus_dummy $corpus_real" timeout $TIMEOUT $OUT/$target $args &> $LOGS_DIR/$target.log if (( $? != 0 )); then echo "Error occured while running $target:" cat $LOGS_DIR/$target.log fi if (( $(du -c $exec_file | tail -n 1 | cut -f 1) == 0 )); then # Skip fuzz targets that failed to produce .exec files. echo "$target failed to produce .exec file." return 0 fi # Generate XML report only as input to jacoco_report_converter. # Source files are not needed for the summary. local xml_report="$DUMPS_DIR/${target}.xml" local summary_file="$FUZZER_STATS_DIR/$target.json" java -jar /opt/jacoco-cli.jar report $exec_file \ --xml $xml_report \ --classfiles $class_dump_dir # Write llvm-cov summary file. jacoco_report_converter.py $xml_report $summary_file } function run_javascript_fuzz_target { local target=$1 local corpus_real="$CORPUS_DIR/${target}" # -merge=1 requires an output directory, create a new, empty dir for that. local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}" rm -rf $corpus_dummy && mkdir -p $corpus_dummy # IstanbulJS currently does not work when the tested program creates # subprocesses. For this reason, we first minimize the corpus removing # any crashing inputs so that we can report source-based code coverage # with a single sweep over the minimized corpus local merge_args="-merge=1 -timeout=100 $corpus_dummy $corpus_real" timeout $TIMEOUT $OUT/$target $merge_args &> $LOGS_DIR/$target.log # nyc saves the coverage reports in a directory with the default name "coverage" local coverage_dir="$DUMPS_DIR/coverage_dir_for_${target}" rm -rf $coverage_dir && mkdir -p $coverage_dir local nyc_json_coverage_file="$coverage_dir/coverage-final.json" local nyc_json_summary_file="$coverage_dir/coverage-summary.json" local args="-runs=0 $corpus_dummy" local jazzerjs_args="--coverage --coverageDirectory $coverage_dir --coverageReporters json --coverageReporters json-summary" JAZZERJS_EXTRA_ARGS=$jazzerjs_args $OUT/$target $args &> $LOGS_DIR/$target.log if (( $? != 0 )); then echo "Error occured while running $target:" cat $LOGS_DIR/$target.log fi if [ ! -s $nyc_json_coverage_file ]; then # Skip fuzz targets that failed to produce coverage-final.json file. echo "$target failed to produce coverage-final.json file." return 0 fi cp $nyc_json_coverage_file $FUZZERS_COVERAGE_DUMPS_DIR/$target.json local summary_file="$FUZZER_STATS_DIR/$target.json" nyc_report_converter.py $nyc_json_summary_file $summary_file } function generate_html { local profdata=$1 local shared_libraries=$2 local objects=$3 local output_dir=$4 rm -rf "$output_dir" mkdir -p "$output_dir/$PLATFORM" local llvm_cov_args="-instr-profile=$profdata $objects $LLVM_COV_COMMON_ARGS" llvm-cov show -format=html -output-dir=$output_dir -Xdemangler rcfilt $llvm_cov_args # Export coverage summary in JSON format. local summary_file=$output_dir/$PLATFORM/summary.json llvm-cov export -summary-only $llvm_cov_args > $summary_file coverage_helper -v post_process -src-root-dir=/ -summary-file=$summary_file \ -output-dir=$output_dir $PATH_EQUIVALENCE_ARGS } export SYSGOPATH=$GOPATH export GOPATH=$OUT/$GOPATH # Run each fuzz target, generate raw coverage dumps. for fuzz_target in $FUZZ_TARGETS; do # Test if fuzz target is a golang one. if [[ $FUZZING_LANGUAGE == "go" ]]; then # Continue if not a fuzz target. if [[ $FUZZING_ENGINE != "none" ]]; then grep "FUZZ_CORPUS_DIR" $fuzz_target > /dev/null 2>&1 || grep "testing\.T" $fuzz_target > /dev/null 2>&1 || continue fi # Log the target in the targets file. echo ${fuzz_target} >> $COVERAGE_TARGET_FILE # Run the coverage collection. run_go_fuzz_target $fuzz_target & elif [[ $FUZZING_LANGUAGE == "python" ]]; then echo "Entering python fuzzing" # Log the target in the targets file. echo ${fuzz_target} >> $COVERAGE_TARGET_FILE # Run the coverage collection. run_python_fuzz_target $fuzz_target elif [[ $FUZZING_LANGUAGE == "jvm" ]]; then # Continue if not a fuzz target. if [[ $FUZZING_ENGINE != "none" ]]; then grep "LLVMFuzzerTestOneInput" $fuzz_target > /dev/null 2>&1 || continue fi echo "Running $fuzz_target" # Log the target in the targets file. echo ${fuzz_target} >> $COVERAGE_TARGET_FILE # Run the coverage collection. run_java_fuzz_target $fuzz_target & elif [[ $FUZZING_LANGUAGE == "javascript" ]]; then # Continue if not a fuzz target. if [[ $FUZZING_ENGINE != "none" ]]; then grep "LLVMFuzzerTestOneInput" $fuzz_target > /dev/null 2>&1 || continue fi echo "Running $fuzz_target" # Log the target in the targets file. echo ${fuzz_target} >> $COVERAGE_TARGET_FILE # Run the coverage collection. run_javascript_fuzz_target $fuzz_target & else # Continue if not a fuzz target. if [[ $FUZZING_ENGINE != "none" ]]; then grep "LLVMFuzzerTestOneInput" $fuzz_target > /dev/null 2>&1 || continue fi echo "Running $fuzz_target" # Log the target in the targets file. echo ${fuzz_target} >> $COVERAGE_TARGET_FILE # Run the coverage collection. run_fuzz_target $fuzz_target & # Rewrite object if its a FUZZTEST target if [[ $fuzz_target == *"@"* ]]; then # Extract fuzztest binary name from fuzztest wrapper script. fuzz_target=(${fuzz_target//@/ }[0]) fi if [[ -z $objects ]]; then # The first object needs to be passed without -object= flag. objects="$fuzz_target" else objects="$objects -object=$fuzz_target" fi fi # Limit the number of processes to be spawned. n_child_proc=$(jobs -rp | wc -l) while [[ "$n_child_proc" -eq "$NPROC" || "$n_child_proc" -gt "$MAX_PARALLEL_COUNT" ]]; do sleep 4 n_child_proc=$(jobs -rp | wc -l) done done # Wait for background processes to finish. wait if [[ $FUZZING_LANGUAGE == "go" ]]; then echo $DUMPS_DIR $SYSGOPATH/bin/gocovmerge $DUMPS_DIR/*.profdata > fuzz.cov gotoolcover -html=fuzz.cov -o $REPORT_ROOT_DIR/index.html $SYSGOPATH/bin/gocovsum fuzz.cov > $SUMMARY_FILE cp $REPORT_ROOT_DIR/index.html $REPORT_PLATFORM_DIR/index.html $SYSGOPATH/bin/pprof-merge $DUMPS_DIR/*.perf.cpu.prof mv merged.data $REPORT_ROOT_DIR/cpu.prof $SYSGOPATH/bin/pprof-merge $DUMPS_DIR/*.perf.heap.prof mv merged.data $REPORT_ROOT_DIR/heap.prof #TODO some proxy for go tool pprof -http=127.0.0.1:8001 $DUMPS_DIR/cpu.prof echo "Finished generating code coverage report for Go fuzz targets." elif [[ $FUZZING_LANGUAGE == "python" ]]; then # Extract source files from all dependency zip folders mkdir -p /pythoncovmergedfiles/medio PYCOVDIR=/pycovdir/ mkdir $PYCOVDIR for fuzzer in $FUZZ_TARGETS; do fuzzer_deps=${fuzzer}.pkg.deps.zip unzip $OUT/${fuzzer_deps} rsync -r ./medio /pythoncovmergedfiles/medio rm -rf ./medio # Translate paths in unzipped folders to paths that we can use mv $OUT/.coverage_$fuzzer .coverage python3 /usr/local/bin/python_coverage_runner_help.py translate /pythoncovmergedfiles/medio cp .new_coverage $PYCOVDIR/.coverage_$fuzzer cp .new_coverage $OUT/coverage_d_$fuzzer done # Combine coverage cd $PYCOVDIR python3 /usr/local/bin/python_coverage_runner_help.py combine .coverage_* python3 /usr/local/bin/python_coverage_runner_help.py html # Produce all_cov file used by fuzz introspector. python3 /usr/local/bin/python_coverage_runner_help.py json -o ${TEXTCOV_REPORT_DIR}/all_cov.json # Generate .json with similar format to llvm-cov output. python3 /usr/local/bin/python_coverage_runner_help.py \ convert-to-summary-json ${TEXTCOV_REPORT_DIR}/all_cov.json $SUMMARY_FILE # Copy coverage date out cp htmlcov/status.json ${TEXTCOV_REPORT_DIR}/html_status.json mv htmlcov/* $REPORT_PLATFORM_DIR/ mv .coverage_* $REPORT_PLATFORM_DIR/ elif [[ $FUZZING_LANGUAGE == "jvm" ]]; then # From this point on the script does not tolerate any errors. set -e # Merge .exec files from the individual targets. jacoco_merged_exec=$DUMPS_DIR/jacoco.merged.exec java -jar /opt/jacoco-cli.jar merge $DUMPS_DIR/*.exec \ --destfile $jacoco_merged_exec # Prepare classes directory for jacoco process classes_dir=$DUMPS_DIR/classes mkdir $classes_dir # Only copy class files found in $OUT/$SRC to ensure they are # lively compiled from the project, avoiding inclusion of # dependency classes. This also includes the fuzzer classes. find "$OUT/$SRC" -type f -name "*.class" | while read -r class_file; do # Skip module-info.class if [[ "$(basename "$class_file")" == "module-info.class" ]]; then continue fi # Use javap to extract the fully qualified name of the class and copy it to $classes_dir fqn=$(javap -verbose "$class_file" 2>/dev/null | grep "this_class:" | grep -oP '(?<=// ).*') if [ -n "$fqn" ]; then mkdir -p $classes_dir/$(dirname $fqn) cp $class_file $classes_dir/$fqn.class fi done # Heuristically determine source directories based on Maven structure. # Always include the $SRC root as it likely contains the fuzzer sources. sourcefiles_args=(--sourcefiles $OUT/$SRC) source_dirs=$(find $OUT/$SRC -type d -name 'java') for source_dir in $source_dirs; do sourcefiles_args+=(--sourcefiles "$source_dir") done # Generate HTML and XML reports. xml_report=$REPORT_PLATFORM_DIR/index.xml java -jar /opt/jacoco-cli.jar report $jacoco_merged_exec \ --html $REPORT_PLATFORM_DIR \ --xml $xml_report \ --classfiles $classes_dir \ "${sourcefiles_args[@]}" # Also serve the raw exec file and XML report, which can be useful for # automated analysis. cp $jacoco_merged_exec $REPORT_PLATFORM_DIR/jacoco.exec cp $xml_report $REPORT_PLATFORM_DIR/jacoco.xml cp $xml_report $TEXTCOV_REPORT_DIR/jacoco.xml # Write llvm-cov summary file. jacoco_report_converter.py $xml_report $SUMMARY_FILE set +e elif [[ $FUZZING_LANGUAGE == "javascript" ]]; then # From this point on the script does not tolerate any errors. set -e json_report=$MERGED_COVERAGE_DIR/coverage.json nyc merge $FUZZERS_COVERAGE_DUMPS_DIR $json_report nyc report -t $MERGED_COVERAGE_DIR --report-dir $REPORT_PLATFORM_DIR --reporter=html --reporter=json-summary nyc_json_summary_file=$REPORT_PLATFORM_DIR/coverage-summary.json # Write llvm-cov summary file. nyc_report_converter.py $nyc_json_summary_file $SUMMARY_FILE set +e else # From this point on the script does not tolerate any errors. set -e # Merge all dumps from the individual targets. rm -f $PROFILE_FILE llvm-profdata merge -sparse $DUMPS_DIR/*.profdata -o $PROFILE_FILE # TODO(mmoroz): add script from Chromium for rendering directory view reports. # The first path in $objects does not have -object= prefix (llvm-cov format). shared_libraries=$(coverage_helper shared_libs -build-dir=$OUT -object=$objects) objects="$objects $shared_libraries" generate_html $PROFILE_FILE "$shared_libraries" "$objects" "$REPORT_ROOT_DIR" # Per target reports. for fuzz_target in $FUZZ_TARGETS; do if [[ $fuzz_target == *"@"* ]]; then profdata_path=$DUMPS_DIR/$fuzz_target.profdata report_dir=$REPORT_BY_TARGET_ROOT_DIR/$fuzz_target # Extract fuzztest binary name from fuzztest wrapper script. fuzz_target=(${fuzz_target//@/ }[0]) else profdata_path=$DUMPS_DIR/$fuzz_target.profdata report_dir=$REPORT_BY_TARGET_ROOT_DIR/$fuzz_target fi if [[ ! -f "$profdata_path" ]]; then echo "WARNING: $fuzz_target has no profdata generated." continue fi generate_html $profdata_path "$shared_libraries" "$fuzz_target" "$report_dir" done set +e fi # Make sure report is readable. chmod -R +r $REPORT_ROOT_DIR $REPORT_BY_TARGET_ROOT_DIR find $REPORT_ROOT_DIR $REPORT_BY_TARGET_ROOT_DIR -type d -exec chmod +x {} + # HTTP_PORT is optional. set +u if [[ -n $HTTP_PORT ]]; then # Serve the report locally. echo "Serving the report on http://127.0.0.1:$HTTP_PORT/linux/index.html" cd $REPORT_ROOT_DIR python3 -m http.server $HTTP_PORT fi ================================================ FILE: infra/base-images/base-runner/coverage_helper ================================================ #!/bin/bash -u # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 $CODE_COVERAGE_SRC/coverage_utils.py $@ ================================================ FILE: infra/base-images/base-runner/download_corpus ================================================ #!/bin/bash -u # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if (( $# < 1 )); then echo "Usage: $0 \"path_download_to url_download_from\" (can be repeated)" >&2 exit 1 fi for pair in "$@"; do read path url <<< "$pair" wget -q -O $path $url done # Always exit with 0 as we do not track wget return codes and should not rely # on the latest command execution. exit 0 ================================================ FILE: infra/base-images/base-runner/generate_differential_cov_report.py ================================================ #!/usr/bin/env python3 # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for generating differential coverage reports. generate_differential_cov_report.py \ """ import os import shutil import subprocess import sys class ProfData: """Class representing a profdata file.""" def __init__(self, text): self.function_profs = [] for function_prof in text.split('\n\n'): if not function_prof: continue self.function_profs.append(FunctionProf(function_prof)) def to_string(self): """Convert back to a string.""" return '\n'.join( [function_prof.to_string() for function_prof in self.function_profs]) def find_function(self, function, idx=None): """Find the same function in this profdata.""" if idx is not None: try: possibility = self.function_profs[idx] if function.func_hash == possibility.func_hash: return possibility except IndexError: pass for function_prof in self.function_profs: if function_prof.func_hash == function.func_hash: return function_prof return None def subtract(self, subtrahend): """Subtract subtrahend from this profdata.""" for idx, function_prof in enumerate(self.function_profs): subtrahend_function_prof = subtrahend.find_function(function_prof, idx) function_prof.subtract(subtrahend_function_prof) class FunctionProf: """Profile of a function.""" FUNC_HASH_COMMENT_LINE = '# Func Hash:' NUM_COUNTERS_COMMENT_LINE = '# Num Counters:' COUNTER_VALUES_COMMENT_LINE = '# Counter Values:' def __init__(self, text): print(text) lines = text.splitlines() self.function = lines[0] assert self.FUNC_HASH_COMMENT_LINE == lines[1] self.func_hash = lines[2] assert self.NUM_COUNTERS_COMMENT_LINE == lines[3] self.num_counters = int(lines[4]) assert self.COUNTER_VALUES_COMMENT_LINE == lines[5] self.counter_values = [1 if int(line) else 0 for line in lines[6:]] def to_string(self): """Convert back to text.""" lines = [ self.function, self.FUNC_HASH_COMMENT_LINE, self.func_hash, self.NUM_COUNTERS_COMMENT_LINE, str(self.num_counters), self.COUNTER_VALUES_COMMENT_LINE, ] + [str(num) for num in self.counter_values] return '\n'.join(lines) def subtract(self, subtrahend_prof): """Subtract this other function from this function.""" if not subtrahend_prof: print(self.function, 'has no subtrahend') # Nothing to subtract. return self.counter_values = [ max(counter1 - counter2, 0) for counter1, counter2 in zip( self.counter_values, subtrahend_prof.counter_values) ] def get_profdata_files(directory): """Returns profdata files in |directory|.""" profdatas = [] for filename in os.listdir(directory): filename = os.path.join(directory, filename) if filename.endswith('.profdata'): profdatas.append(filename) return profdatas def convert_profdata_to_text(profdata): """Convert a profdata binary file to a profdata text file.""" profdata_text = f'{profdata}.txt' if os.path.exists(profdata_text): os.remove(profdata_text) command = [ 'llvm-profdata', 'merge', '-j=1', '-sparse', profdata, '--text', '-o', profdata_text ] print(command) subprocess.run(command, check=True) return profdata_text def convert_text_profdata_to_bin(profdata_text): """Convert a profdata text file to a profdata binary file.""" profdata = profdata_text.replace('.txt', '').replace('.profdata', '') + '.profdata' print('bin profdata', profdata) if os.path.exists(profdata): os.remove(profdata) command = [ 'llvm-profdata', 'merge', '-j=1', '-sparse', profdata_text, '-o', profdata ] print(command) subprocess.run(command, check=True) return profdata def get_difference(minuend_filename, subtrahend_filename): """Subtract subtrahend_filename from minuend_filename.""" with open(minuend_filename, 'r', encoding='utf-8') as minuend_file: print('minuend', minuend_filename) minuend = ProfData(minuend_file.read()) with open(subtrahend_filename, 'r', encoding='utf-8') as subtrahend_file: print('subtrahend', subtrahend_filename) subtrahend = ProfData(subtrahend_file.read()) minuend.subtract(subtrahend) return minuend def profdatas_to_objects(profdatas): """Get the corresponding objects for each profdata.""" return [ os.path.splitext(os.path.basename(profdata))[0] for profdata in profdatas ] def generate_differential_cov_reports(minuend_profdatas, subtrahend_profdatas, difference_dir): """Calculate the differences between all profdatas and generate differential coverage reports.""" profdata_objects = profdatas_to_objects(minuend_profdatas) real_profdata_objects = [ binobject for binobject in profdata_objects if binobject != 'merged' ] for minuend, subtrahend, binobject in zip(minuend_profdatas, subtrahend_profdatas, profdata_objects): minuend_text = convert_profdata_to_text(minuend) subtrahend_text = convert_profdata_to_text(subtrahend) difference = get_difference(minuend_text, subtrahend_text) basename = os.path.basename(minuend_text) difference_text = os.path.join(difference_dir, basename) with open(difference_text, 'w', encoding='utf-8') as file_handle: file_handle.write(difference.to_string()) difference_profdata = convert_text_profdata_to_bin(difference_text) if not difference_profdata.endswith('merged.profdata'): generate_html_report(difference_profdata, [binobject], os.path.join(difference_dir, binobject)) else: generate_html_report(difference_profdata, real_profdata_objects, os.path.join(difference_dir, 'merged')) def generate_html_report(profdata, objects, directory): """Generate an HTML coverage report.""" # TODO(metzman): Deal with shared libs. html_dir = os.path.join(directory, 'reports') if os.path.exists(html_dir): os.remove(html_dir) os.makedirs(html_dir) out_dir = os.getenv('OUT', '/out') command = [ 'llvm-cov', 'show', f'-path-equivalence=/,{out_dir}', '-format=html', '-Xdemangler', 'rcfilt', f'-instr-profile={profdata}' ] objects = [os.path.join(out_dir, binobject) for binobject in objects] command += objects + ['-o', html_dir] print(' '.join(command)) subprocess.run(command, check=True) def main(): """Generate differential coverage reports.""" if len(sys.argv) != 4: print( f'Usage: {sys.argv[0]} ') minuend_dir = sys.argv[1] subtrahend_dir = sys.argv[2] difference_dir = sys.argv[3] if os.path.exists(difference_dir): shutil.rmtree(difference_dir) os.makedirs(difference_dir, exist_ok=True) minuend_profdatas = get_profdata_files(minuend_dir) subtrahend_profdatas = get_profdata_files(subtrahend_dir) generate_differential_cov_reports(minuend_profdatas, subtrahend_profdatas, difference_dir) if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-runner/gocoverage/go.mod ================================================ module oss-fuzz.com/gocoverage go 1.14 require ( github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 golang.org/x/tools v0.1.0 ) ================================================ FILE: infra/base-images/base-runner/gocoverage/go.sum ================================================ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5 h1:zIaiqGYDQwa4HVx5wGRTXbx38Pqxjemn4BP98wpzpXo= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ================================================ FILE: infra/base-images/base-runner/gocoverage/gocovmerge/LICENSE ================================================ Copyright (c) 2015, Wade Simmons All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: infra/base-images/base-runner/gocoverage/gocovmerge/gocovmerge.go ================================================ // gocovmerge takes the results from multiple `go test -coverprofile` runs and // merges them into one profile package main import ( "flag" "fmt" "io" "log" "os" "sort" "golang.org/x/tools/cover" ) func mergeProfiles(p *cover.Profile, merge *cover.Profile) { if p.Mode != merge.Mode { log.Fatalf("cannot merge profiles with different modes") } // Since the blocks are sorted, we can keep track of where the last block // was inserted and only look at the blocks after that as targets for merge startIndex := 0 for _, b := range merge.Blocks { startIndex = mergeProfileBlock(p, b, startIndex) } } func mergeProfileBlock(p *cover.Profile, pb cover.ProfileBlock, startIndex int) int { sortFunc := func(i int) bool { pi := p.Blocks[i+startIndex] return pi.StartLine >= pb.StartLine && (pi.StartLine != pb.StartLine || pi.StartCol >= pb.StartCol) } i := 0 if sortFunc(i) != true { i = sort.Search(len(p.Blocks)-startIndex, sortFunc) } i += startIndex if i < len(p.Blocks) && p.Blocks[i].StartLine == pb.StartLine && p.Blocks[i].StartCol == pb.StartCol { if p.Blocks[i].EndLine != pb.EndLine || p.Blocks[i].EndCol != pb.EndCol { log.Fatalf("OVERLAP MERGE: %v %v %v", p.FileName, p.Blocks[i], pb) } switch p.Mode { case "set": p.Blocks[i].Count |= pb.Count case "count", "atomic": p.Blocks[i].Count += pb.Count default: log.Fatalf("unsupported covermode: '%s'", p.Mode) } } else { if i > 0 { pa := p.Blocks[i-1] if pa.EndLine >= pb.EndLine && (pa.EndLine != pb.EndLine || pa.EndCol > pb.EndCol) { log.Fatalf("OVERLAP BEFORE: %v %v %v", p.FileName, pa, pb) } } if i < len(p.Blocks)-1 { pa := p.Blocks[i+1] if pa.StartLine <= pb.StartLine && (pa.StartLine != pb.StartLine || pa.StartCol < pb.StartCol) { log.Fatalf("OVERLAP AFTER: %v %v %v", p.FileName, pa, pb) } } p.Blocks = append(p.Blocks, cover.ProfileBlock{}) copy(p.Blocks[i+1:], p.Blocks[i:]) p.Blocks[i] = pb } return i + 1 } func addProfile(profiles []*cover.Profile, p *cover.Profile) []*cover.Profile { i := sort.Search(len(profiles), func(i int) bool { return profiles[i].FileName >= p.FileName }) if i < len(profiles) && profiles[i].FileName == p.FileName { mergeProfiles(profiles[i], p) } else { profiles = append(profiles, nil) copy(profiles[i+1:], profiles[i:]) profiles[i] = p } return profiles } func dumpProfiles(profiles []*cover.Profile, out io.Writer) { if len(profiles) == 0 { return } fmt.Fprintf(out, "mode: %s\n", profiles[0].Mode) for _, p := range profiles { for _, b := range p.Blocks { fmt.Fprintf(out, "%s:%d.%d,%d.%d %d %d\n", p.FileName, b.StartLine, b.StartCol, b.EndLine, b.EndCol, b.NumStmt, b.Count) } } } func main() { flag.Parse() var merged []*cover.Profile for _, file := range flag.Args() { profiles, err := cover.ParseProfiles(file) if err != nil { log.Fatalf("failed to parse profiles: %v", err) } for _, p := range profiles { merged = addProfile(merged, p) } } dumpProfiles(merged, os.Stdout) } ================================================ FILE: infra/base-images/base-runner/gocoverage/gocovsum/gocovsum.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "encoding/json" "flag" "fmt" "log" "go/ast" "go/parser" "go/token" "golang.org/x/tools/cover" ) type CoverageTotal struct { Count int `json:"count"` Covered int `json:"covered"` Uncovered int `json:"notcovered"` Percent float64 `json:"percent"` } type CoverageTotals struct { Functions CoverageTotal `json:"functions,omitempty"` Lines CoverageTotal `json:"lines,omitempty"` Regions CoverageTotal `json:"regions,omitempty"` Instantiations CoverageTotal `json:"instantiations,omitempty"` Branches CoverageTotal `json:"branches,omitempty"` } type CoverageFile struct { Summary CoverageTotals `json:"summary,omitempty"` Filename string `json:"filename,omitempty"` } type CoverageData struct { Totals CoverageTotals `json:"totals,omitempty"` Files []CoverageFile `json:"files,omitempty"` } type PositionInterval struct { start token.Position end token.Position } type CoverageSummary struct { Data []CoverageData `json:"data,omitempty"` Type string `json:"type,omitempty"` Version string `json:"version,omitempty"` } func isFunctionCovered(s token.Position, e token.Position, blocks []cover.ProfileBlock) bool { for _, b := range blocks { if b.StartLine >= s.Line && b.StartLine <= e.Line && b.EndLine >= s.Line && b.EndLine <= e.Line { if b.Count > 0 { return true } } } return false } func computePercent(s *CoverageTotals) { if s.Regions.Count > 0 { s.Regions.Percent = float64(100*s.Regions.Covered) / float64(s.Regions.Count) } if s.Lines.Count > 0 { s.Lines.Percent = float64(100*s.Lines.Covered) / float64(s.Lines.Count) } if s.Functions.Count > 0 { s.Functions.Percent = float64(100*s.Functions.Covered) / float64(s.Functions.Count) } } func main() { flag.Parse() if len(flag.Args()) != 1 { log.Fatalf("needs exactly one argument") } profiles, err := cover.ParseProfiles(flag.Args()[0]) if err != nil { log.Fatalf("failed to parse profiles: %v", err) } r := CoverageSummary{} r.Type = "oss-fuzz.go.coverage.json.export" r.Version = "2.0.1" r.Data = make([]CoverageData, 1) for _, p := range profiles { fset := token.NewFileSet() // positions are relative to fset f, err := parser.ParseFile(fset, p.FileName, nil, 0) if err != nil { log.Printf("failed to parse go file: %v", err) continue } fileCov := CoverageFile{} fileCov.Filename = p.FileName ast.Inspect(f, func(n ast.Node) bool { switch x := n.(type) { case *ast.FuncLit: startf := fset.Position(x.Pos()) endf := fset.Position(x.End()) fileCov.Summary.Functions.Count++ if isFunctionCovered(startf, endf, p.Blocks) { fileCov.Summary.Functions.Covered++ } else { fileCov.Summary.Functions.Uncovered++ } case *ast.FuncDecl: startf := fset.Position(x.Pos()) endf := fset.Position(x.End()) fileCov.Summary.Functions.Count++ if isFunctionCovered(startf, endf, p.Blocks) { fileCov.Summary.Functions.Covered++ } else { fileCov.Summary.Functions.Uncovered++ } } return true }) for _, b := range p.Blocks { fileCov.Summary.Regions.Count++ if b.Count > 0 { fileCov.Summary.Regions.Covered++ } else { fileCov.Summary.Regions.Uncovered++ } fileCov.Summary.Lines.Count += b.NumStmt if b.Count > 0 { fileCov.Summary.Lines.Covered += b.NumStmt } else { fileCov.Summary.Lines.Uncovered += b.NumStmt } } r.Data[0].Totals.Regions.Count += fileCov.Summary.Regions.Count r.Data[0].Totals.Regions.Covered += fileCov.Summary.Regions.Covered r.Data[0].Totals.Regions.Uncovered += fileCov.Summary.Regions.Uncovered r.Data[0].Totals.Lines.Count += fileCov.Summary.Lines.Count r.Data[0].Totals.Lines.Covered += fileCov.Summary.Lines.Covered r.Data[0].Totals.Lines.Uncovered += fileCov.Summary.Lines.Uncovered r.Data[0].Totals.Functions.Count += fileCov.Summary.Functions.Count r.Data[0].Totals.Functions.Covered += fileCov.Summary.Functions.Covered r.Data[0].Totals.Functions.Uncovered += fileCov.Summary.Functions.Uncovered computePercent(&fileCov.Summary) r.Data[0].Files = append(r.Data[0].Files, fileCov) } computePercent(&r.Data[0].Totals) o, err := json.Marshal(r) if err != nil { log.Fatalf("failed to generate json: %v", err) } fmt.Printf(string(o)) } ================================================ FILE: infra/base-images/base-runner/gocoverage/pprof-merge/LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: infra/base-images/base-runner/gocoverage/pprof-merge/main.go ================================================ // Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "flag" "log" "os" "github.com/google/pprof/profile" ) var ( output string ) func main() { flag.StringVar(&output, "o", "merged.data", "") flag.Parse() files := os.Args[1:] if len(files) == 0 { log.Fatal("Give profiles files as arguments") } var profiles []*profile.Profile for _, fname := range files { f, err := os.Open(fname) if err != nil { log.Fatalf("Cannot open profile file at %q: %v", fname, err) } p, err := profile.Parse(f) if err != nil { log.Fatalf("Cannot parse profile at %q: %v", fname, err) } profiles = append(profiles, p) } merged, err := profile.Merge(profiles) if err != nil { log.Fatalf("Cannot merge profiles: %v", err) } out, err := os.OpenFile(output, os.O_RDWR|os.O_CREATE, 0755) if err != nil { log.Fatalf("Cannot open output to write: %v", err) } if err := merged.Write(out); err != nil { log.Fatalf("Cannot write merged profile to file: %v", err) } if err := out.Close(); err != nil { log.Printf("Error when closing the output file: %v", err) } } ================================================ FILE: infra/base-images/base-runner/install_deps.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies in a platform-aware way. apt-get update && apt-get install -y \ binutils \ file \ ca-certificates \ fonts-dejavu \ git \ libcap2 \ rsync \ unzip \ jq \ wget \ zip --no-install-recommends case $(uname -m) in x86_64) # We only need to worry about i386 if we are on x86_64. apt-get install -y lib32gcc1 libc6-i386 ;; esac ================================================ FILE: infra/base-images/base-runner/install_deps_ubuntu_20_04.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies in a platform-aware way. apt-get update && apt-get install -y \ binutils \ file \ ca-certificates \ fonts-dejavu \ git \ libcap2 \ rsync \ unzip \ jq \ wget \ zip --no-install-recommends case $(uname -m) in x86_64) # We only need to worry about i386 if we are on x86_64. apt-get install -y lib32gcc1 libc6-i386 ;; esac ================================================ FILE: infra/base-images/base-runner/install_deps_ubuntu_24_04.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies in a platform-aware way. apt-get update && apt-get install -y \ binutils \ file \ ca-certificates \ fonts-dejavu \ git \ libcap2 \ rsync \ unzip \ jq \ wget \ libunwind-dev \ libblocksruntime-dev \ zip --no-install-recommends # libunwind-dev libblocksruntime-dev are needed for Honggfuzz case $(uname -m) in x86_64) # We only need to worry about i386 if we are on x86_64. if grep -q '24.04' /etc/os-release; then apt-get install -y lib32gcc-s1 libc6-i386 else apt-get install -y lib32gcc1 libc6-i386 fi ;; esac ================================================ FILE: infra/base-images/base-runner/install_go.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install go on x86_64, don't do anything on ARM. case $(uname -m) in x86_64) # Download and install Go. export GOROOT=/root/.go wget https://go.dev/dl/go1.25.0.linux-amd64.tar.gz mkdir temp-go tar -C temp-go/ -xzf go1.25.0.linux-amd64.tar.gz mkdir $GOROOT mv temp-go/go/* /root/.go/ rm -rf temp-go echo 'Set "GOPATH=/root/go"' echo 'Set "PATH=$PATH:/root/.go/bin:$GOPATH/bin"' # Set up Golang coverage modules. printf $(find . -name gocoverage) cd $GOPATH/gocoverage && /root/.go/bin/go install ./... cd /root/.go/src/cmd/cover && /root/.go/bin/go build && mv cover $GOPATH/bin/gotoolcover pushd /tmp git clone --depth=1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=v2 cd go-118-fuzz-build/cmd/convertLibFuzzerTestcaseToStdLibGo /root/.go/bin/go build . mv convertLibFuzzerTestcaseToStdLibGo $GOPATH/bin/ popd ;; aarch64) # Don't install go because installer is not provided. echo "Not installing go: aarch64." ;; *) echo "Error: unsupported architecture: $(uname -m)" exit 1 ;; esac ================================================ FILE: infra/base-images/base-runner/install_java.sh ================================================ #!/bin/bash -eux # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install java in a platform-aware way. ARCHITECTURE= case $(uname -m) in x86_64) ARCHITECTURE=x64 ;; aarch64) ARCHITECTURE=aarch64 ;; *) echo "Error: unsupported architecture: $(uname -m)" exit 1 ;; esac wget -q https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16+8/OpenJDK17U-jdk_"$ARCHITECTURE"_linux_hotspot_17.0.16_8.tar.gz -O /tmp/openjdk-17.0.16_linux-"$ARCHITECTURE"_bin.tar.gz wget -q https://download.java.net/java/GA/jdk15.0.2/0d1cfde4252546c6931946de8db48ee2/7/GPL/openjdk-15.0.2_linux-"$ARCHITECTURE"_bin.tar.gz -O /tmp/openjdk-15.0.2_linux-"$ARCHITECTURE"_bin.tar.gz cd /tmp mkdir -p $JAVA_HOME tar -xz --strip-components=1 -f openjdk-17.0.16_linux-"$ARCHITECTURE"_bin.tar.gz --directory $JAVA_HOME rm -f openjdk-17.0.16_linux-"$ARCHITECTURE"_bin.tar.gz rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip # Install OpenJDK 15 and trim its size by removing unused components. Some projects only run with Java 15. mkdir -p $JAVA_15_HOME tar -xz --strip-components=1 -f openjdk-15.0.2_linux-"$ARCHITECTURE"_bin.tar.gz --directory $JAVA_15_HOME rm -f openjdk-15.0.2_linux-"$ARCHITECTURE"_bin.tar.gz rm -rf $JAVA_15_HOME/jmods $JAVA_15_HOME/lib/src.zip ================================================ FILE: infra/base-images/base-runner/install_javascript.sh ================================================ #!/bin/bash -eux # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # see installation instructions: https://github.com/nodesource/distributions#available-architectures apt-get update apt-get install -y ca-certificates curl gnupg mkdir -p /etc/apt/keyrings curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg NODE_MAJOR=20 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list apt-get update apt-get install nodejs -y # Install latest versions of nyc for source-based coverage reporting npm install --global nyc ================================================ FILE: infra/base-images/base-runner/jacoco_report_converter.py ================================================ #!/usr/bin/env python3 # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Helper script for creating an llvm-cov style JSON summary from a JaCoCo XML report.""" import json import os import sys import xml.etree.ElementTree as ET def convert(xml): """Turns a JaCoCo XML report into an llvm-cov JSON summary.""" summary = { 'type': 'oss-fuzz.java.coverage.json.export', 'version': '1.0.0', 'data': [{ 'totals': {}, 'files': [], }], } report = ET.fromstring(xml) totals = make_element_summary(report) summary['data'][0]['totals'] = totals # Since Java compilation does not track source file location, we match # coverage info to source files via the full class name, e.g. we search for # a path in /out/src ending in foo/bar/Baz.java for the class foo.bar.Baz. # Under the assumptions that a given project only ever contains a single # version of a class and that no class name appears as a suffix of another # class name, we can assign coverage info to every source file matched in that # way. src_files = list_src_files() for class_element in report.findall('./package/class'): # Skip fuzzer classes if is_fuzzer_class(class_element): continue # Skip non class elements if 'sourcefilename' not in class_element.attrib: continue class_name = class_element.attrib['name'] package_name = os.path.dirname(class_name) basename = class_element.attrib['sourcefilename'] # This path is 'foo/Bar.java' for the class element # . canonical_path = os.path.join(package_name, basename) class_summary = make_element_summary(class_element) for src_file in relative_to_src_path(src_files, canonical_path): summary['data'][0]['files'].append({ 'filename': src_file, 'summary': class_summary, }) return json.dumps(summary) def list_src_files(): """Returns a map from basename to full path for all files in $OUT/$SRC.""" filename_to_paths = {} out_path = os.environ['OUT'] + '/' src_path = os.environ['SRC'] src_in_out = out_path + src_path for dirpath, _, filenames in os.walk(src_in_out): for filename in filenames: full_path = dirpath + '/' + filename # Map /out//src/... to /src/... file_path = full_path[len(out_path):] filename_to_paths.setdefault(filename, []).append(file_path) return filename_to_paths def is_fuzzer_class(class_element): """Check if the class is fuzzer class.""" method_elements = class_element.find('./method[@name=\"fuzzerTestOneInput\"]') if method_elements: return True return False def relative_to_src_path(src_files, canonical_path): """Returns all paths in src_files ending in canonical_path.""" basename = os.path.basename(canonical_path) if basename not in src_files: return [] candidate_paths = src_files[basename] return [ path for path in candidate_paths if path.endswith("/" + canonical_path) ] def make_element_summary(element): """Returns a coverage summary for an element in the XML report.""" summary = {} function_counter = element.find('./counter[@type=\'METHOD\']') summary['functions'] = make_counter_summary(function_counter) line_counter = element.find('./counter[@type=\'LINE\']') summary['lines'] = make_counter_summary(line_counter) # JaCoCo tracks branch coverage, which counts the covered control-flow edges # between llvm-cov's regions instead of the covered regions themselves. For # non-trivial code parts, the difference is usually negligible. However, if # all methods of a class consist of a single region only (no branches), # JaCoCo does not report any branch coverage even if there is instruction # coverage. Since this would give incorrect results for CI Fuzz purposes, we # increase the regions counter by 1 if there is any amount of instruction # coverage. instruction_counter = element.find('./counter[@type=\'INSTRUCTION\']') has_some_coverage = instruction_counter is not None and int( instruction_counter.attrib["covered"]) > 0 branch_covered_adjustment = 1 if has_some_coverage else 0 region_counter = element.find('./counter[@type=\'BRANCH\']') summary['regions'] = make_counter_summary( region_counter, covered_adjustment=branch_covered_adjustment) return summary def make_counter_summary(counter_element, covered_adjustment=0): """Turns a JaCoCo element into an llvm-cov totals entry.""" summary = {} covered = covered_adjustment missed = 0 if counter_element is not None: covered += int(counter_element.attrib['covered']) missed += int(counter_element.attrib['missed']) summary['covered'] = covered summary['notcovered'] = missed summary['count'] = summary['covered'] + summary['notcovered'] if summary['count'] != 0: summary['percent'] = (100.0 * summary['covered']) / summary['count'] else: summary['percent'] = 0 return summary def main(): """Produces an llvm-cov style JSON summary from a JaCoCo XML report.""" if len(sys.argv) != 3: sys.stderr.write('Usage: %s \n' % sys.argv[0]) return 1 with open(sys.argv[1], 'r') as xml_file: xml_report = xml_file.read() json_summary = convert(xml_report) with open(sys.argv[2], 'w') as json_file: json_file.write(json_summary) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/nyc_report_converter.py ================================================ #!/usr/bin/env python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Helper script for creating a llvm-cov style JSON summary from a nyc JSON summary.""" import json import sys def convert(nyc_json_summary): """Turns a nyc JSON report into a llvm-cov JSON summary.""" summary = { 'type': 'oss-fuzz.javascript.coverage.json.export', 'version': '1.0.0', 'data': [{ 'totals': file_summary(nyc_json_summary['total']), 'files': [{ 'filename': src_file, 'summary': file_summary(nyc_json_summary[src_file]) } for src_file in nyc_json_summary if src_file != 'total'], }], } return json.dumps(summary) def file_summary(nyc_file_summary): """Returns a summary for a given file in the nyc JSON summary report.""" return { 'functions': element_summary(nyc_file_summary['functions']), 'lines': element_summary(nyc_file_summary['lines']), 'regions': element_summary(nyc_file_summary['branches']) } def element_summary(element): """Returns a summary of a coverage element in the nyc JSON summary of the file""" return { 'count': element['total'], 'covered': element['covered'], 'notcovered': element['total'] - element['covered'] - element['skipped'], 'percent': element['pct'] if element['pct'] != 'Unknown' else 0 } def main(): """Produces a llvm-cov style JSON summary from a nyc JSON summary.""" if len(sys.argv) != 3: sys.stderr.write('Usage: %s \n' % sys.argv[0]) return 1 with open(sys.argv[1], 'r') as nyc_json_summary_file: nyc_json_summary = json.load(nyc_json_summary_file) json_summary = convert(nyc_json_summary) with open(sys.argv[2], 'w') as json_output_file: json_output_file.write(json_summary) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/parse_options.py ================================================ #!/usr/bin/env python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Helper script for parsing custom fuzzing options.""" import configparser import sys def parse_options(options_file_path, options_section): """Parses the given file and returns options from the given section.""" parser = configparser.ConfigParser() parser.read(options_file_path) if not parser.has_section(options_section): return None options = parser[options_section] if options_section == 'libfuzzer': options_string = ' '.join( '-%s=%s' % (key, value) for key, value in options.items()) else: # Sanitizer options. options_string = ':'.join( '%s=%s' % (key, value) for key, value in options.items()) return options_string def main(): """Processes the arguments and prints the options in the correct format.""" if len(sys.argv) < 3: sys.stderr.write('Usage: %s \n' % sys.argv[0]) return 1 options = parse_options(sys.argv[1], sys.argv[2]) if options is not None: print(options) return 0 if __name__ == "__main__": sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/profraw_update.py ================================================ #!/usr/bin/env python3 # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Helper script for upgrading a profraw file to latest version.""" from collections import namedtuple import struct import subprocess import sys HeaderGeneric = namedtuple('HeaderGeneric', 'magic version') HeaderVersion9 = namedtuple( 'HeaderVersion9', 'BinaryIdsSize DataSize PaddingBytesBeforeCounters CountersSize \ PaddingBytesAfterCounters NumBitmapBytes PaddingBytesAfterBitmapBytes NamesSize CountersDelta BitmapDelta NamesDelta ValueKindLast' ) PROFRAW_MAGIC = 0xff6c70726f667281 def relativize_address(data, offset, databegin, sect_prf_cnts, sect_prf_data): """Turns an absolute offset into a relative one.""" value = struct.unpack('Q', data[offset:offset + 8])[0] if sect_prf_cnts <= value < sect_prf_data: # If the value is an address in the right section, make it relative. value = (value - databegin) & 0xffffffffffffffff value = struct.pack('Q', value) for i in range(8): data[offset + i] = value[i] # address was made relative return True # no changes done return False def upgrade(data, sect_prf_cnts, sect_prf_data): """Upgrades profraw data, knowing the sections addresses.""" generic_header = HeaderGeneric._make(struct.unpack('QQ', data[:16])) if generic_header.magic != PROFRAW_MAGIC: raise Exception('Bad magic.') base_version = generic_header.version if base_version >= 9: # Nothing to do. return data if base_version < 5 or base_version == 6: raise Exception('Unhandled version.') if generic_header.version == 5: generic_header = generic_header._replace(version=7) # Upgrade from version 5 to 7 by adding binaryids field. data = data[:8] + struct.pack('Q', generic_header.version) + struct.pack( 'Q', 0) + data[16:] if generic_header.version == 7: # cf https://reviews.llvm.org/D111123 generic_header = generic_header._replace(version=8) data = data[:8] + struct.pack('Q', generic_header.version) + data[16:] if generic_header.version == 8: # see https://reviews.llvm.org/D138846 generic_header = generic_header._replace(version=9) # Upgrade from version 8 to 9 by adding NumBitmapBytes, PaddingBytesAfterBitmapBytes and BitmapDelta fields. data = data[:8] + struct.pack( 'Q', generic_header.version) + data[16:56] + struct.pack( 'QQ', 0, 0) + data[56:72] + struct.pack('Q', 0) + data[72:] v9_header = HeaderVersion9._make(struct.unpack('QQQQQQQQQQQQ', data[16:112])) if base_version <= 8 and v9_header.BinaryIdsSize % 8 != 0: # Adds padding for binary ids. # cf commit b9f547e8e51182d32f1912f97a3e53f4899ea6be # cf https://reviews.llvm.org/D110365 padlen = 8 - (v9_header.BinaryIdsSize % 8) v7_header = v9_header._replace(BinaryIdsSize=v9_header.BinaryIdsSize + padlen) data = data[:16] + struct.pack('Q', v9_header.BinaryIdsSize) + data[24:] data = data[:112 + v9_header.BinaryIdsSize] + bytes( padlen) + data[112 + v9_header.BinaryIdsSize:] if base_version <= 8: offset = 112 + v9_header.BinaryIdsSize for d in range(v9_header.DataSize): # Add BitmapPtr and aligned u32(NumBitmapBytes) data = data[:offset + 3 * 8] + struct.pack( 'Q', 0) + data[offset + 3 * 8:offset + 6 * 8] + struct.pack( 'Q', 0) + data[offset + 6 * 8:] value = struct.unpack('Q', data[offset + 2 * 8:offset + 3 * 8])[0] - 16 * d data = data[:offset + 2 * 8] + struct.pack('Q', value) + data[offset + 3 * 8:] offset += 8 * 8 if base_version >= 8: # Nothing more to do. return data # Last changes are relaed to bump from 7 to version 8 making CountersPtr relative. dataref = sect_prf_data # 80 is offset of CountersDelta. if not relativize_address(data, 80, dataref, sect_prf_cnts, sect_prf_data): return data offset = 112 + v9_header.BinaryIdsSize # This also works for C+Rust binaries compiled with # clang-14/rust-nightly-clang-13. for _ in range(v9_header.DataSize): # 16 is the offset of CounterPtr in ProfrawData structure. relativize_address(data, offset + 16, dataref, sect_prf_cnts, sect_prf_data) # We need this because of CountersDelta -= sizeof(*SrcData); # seen in __llvm_profile_merge_from_buffer. dataref += 44 + 2 * (v9_header.ValueKindLast + 1) if was8: #profraw9 added RelativeBitmapPtr and NumBitmapBytes (8+4 rounded up to 16) dataref -= 16 # This is the size of one ProfrawData structure. offset += 44 + 2 * (v9_header.ValueKindLast + 1) return data def main(): """Helper script for upgrading a profraw file to latest version.""" if len(sys.argv) < 3: sys.stderr.write('Usage: %s options? ...\n' % sys.argv[0]) return 1 # First find llvm profile sections addresses in the elf, quick and dirty. process = subprocess.Popen(['readelf', '-S', sys.argv[1]], stdout=subprocess.PIPE) output, err = process.communicate() if err: print('readelf failed') return 2 for line in iter(output.split(b'\n')): if b'__llvm_prf_cnts' in line: sect_prf_cnts = int(line.split()[3], 16) elif b'__llvm_prf_data' in line: sect_prf_data = int(line.split()[3], 16) out_name = "default.profup" in_place = False start = 2 if sys.argv[2] == "-i": in_place = True start = start + 1 elif sys.argv[2] == "-o": out_name = sys.argv[3] start = 4 if len(sys.argv) < start: sys.stderr.write('Usage: %s options ...\n' % sys.argv[0]) return 1 for i in range(start, len(sys.argv)): # Then open and read the input profraw file. with open(sys.argv[i], 'rb') as input_file: profraw_base = bytearray(input_file.read()) # Do the upgrade, returning a bytes object. profraw_latest = upgrade(profraw_base, sect_prf_cnts, sect_prf_data) # Write the output to the file given to the command line. if in_place: out_name = sys.argv[i] with open(out_name, 'wb') as output_file: output_file.write(profraw_latest) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/python_coverage_runner_help.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Helper to manage coverage.py related operations. Does two main things: (1) pass commands into the coverage.py library and (2) translate .coverage created from a pyinstaller executable into paths that match local files. This is needed for html report creation. """ import os import re import json import sys from coverage.cmdline import main as coverage_main from coverage.data import CoverageData def should_exclude_file(filepath): """Returns whether the path should be excluded from the coverage report.""" # Skip all atheris code if "atheris" in filepath: return True # Filter out all standard python libraries if ('/usr/local/lib/python' in filepath and 'site-packages' not in filepath and 'dist-packages' not in filepath): return True # Avoid all PyInstaller modules. if 'PyInstaller' in filepath: return True return False def translate_lines(cov_data, new_cov_data, all_file_paths): """ Translate lines in a .coverage file created by coverage.py such that the file paths points to local files instead. This is needed when collecting coverage from executables created by pyinstaller. """ for pyinstaller_file_path in cov_data.measured_files(): stripped_py_file_path = pyinstaller_file_path if stripped_py_file_path.startswith('/tmp/_MEI'): stripped_py_file_path = '/'.join(stripped_py_file_path.split('/')[3:]) if stripped_py_file_path.startswith('/out/'): stripped_py_file_path = stripped_py_file_path.replace('/out/', '') # Check if this file exists in our file paths: for local_file_path in all_file_paths: if should_exclude_file(local_file_path): continue if local_file_path.endswith(stripped_py_file_path): print('Found matching: %s' % (local_file_path)) new_cov_data.add_lines( {local_file_path: cov_data.lines(pyinstaller_file_path)}) def translate_coverage(all_file_paths): """ Translate pyinstaller-generated file paths in .coverage (produced by coverage.py) into local file paths. Place result in .new_coverage. """ covdata_pre_translation = CoverageData('.coverage') covdata_post_translation = CoverageData('.new_coverage') covdata_pre_translation.read() translate_lines(covdata_pre_translation, covdata_post_translation, all_file_paths) covdata_post_translation.write() def convert_coveragepy_cov_to_summary_json(src, dst): """ Converts a json file produced by coveragepy into a summary.json file similary to llvm-cov output. `src` is the source coveragepy json file, `dst` is the destination json file, which will be overwritten. """ dst_dict = {'data': [{'files': {}}]} lines_covered = 0 lines_count = 0 with open(src, "r") as src_f: src_json = json.loads(src_f.read()) if 'files' in src_json: for elem in src_json.get('files'): if 'summary' not in src_json['files'][elem]: continue src_dict = src_json['files'][elem]['summary'] count = src_dict['covered_lines'] + src_dict['missing_lines'] covered = src_dict['covered_lines'] notcovered = src_dict['missing_lines'] percent = src_dict['percent_covered'] # Accumulate line coverage lines_covered += covered lines_count += count dst_dict['data'][0]['files'][elem] = { 'summary': { 'lines': { 'count': count, 'covered': covered, 'notcovered': notcovered, 'percent': percent } } } if lines_count > 0: lines_covered_percent = lines_covered / lines_count else: lines_covered_percent = 0.0 dst_dict['data'][0]['totals'] = { 'branches': { 'count': 0, 'covered': 0, 'notcovered': 0, 'percent': 0.0 }, 'functions': { 'count': 0, 'covered': 0, 'percent': 0.0 }, 'instantiations': { 'count': 0, 'covered': 0, 'percent': 0.0 }, 'lines': { 'count': lines_count, 'covered': lines_covered, 'percent': lines_covered_percent }, 'regions': { 'count': 0, 'covered': 0, 'notcovered': 0, 'percent': 0.0 } } with open(dst, 'w') as dst_f: dst_f.write(json.dumps(dst_dict)) def main(): """ Main handler. """ if sys.argv[1] == 'translate': print('Translating the coverage') files_path = sys.argv[2] all_file_paths = list() for root, _, files in os.walk(files_path): for relative_file_path in files: abs_file_path = os.path.abspath(os.path.join(root, relative_file_path)) all_file_paths.append(abs_file_path) print('Done with path walk') translate_coverage(all_file_paths) elif sys.argv[1] == 'convert-to-summary-json': src = sys.argv[2] dst = sys.argv[3] convert_coveragepy_cov_to_summary_json(src, dst) else: # Pass commands into coverage package sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(coverage_main()) if __name__ == '__main__': main() ================================================ FILE: infra/base-images/base-runner/rcfilt ================================================ #!/bin/bash -u # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Symbol demangling for both C++ and Rust # ################################################################################ # simply pipe rustfilt | c++filt -n ================================================ FILE: infra/base-images/base-runner/reproduce ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FUZZER=$1 shift if [ ! -v TESTCASE ]; then TESTCASE="/testcase" fi if [ ! -f $TESTCASE ]; then echo "Error: $TESTCASE not found, use: docker run -v :$TESTCASE ..." exit 1 fi export RUN_FUZZER_MODE="interactive" export FUZZING_ENGINE="libfuzzer" export SKIP_SEED_CORPUS="1" run_fuzzer $FUZZER $@ $TESTCASE ================================================ FILE: infra/base-images/base-runner/run_fuzzer ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Fuzzer runner. Appends .options arguments and seed corpus to users args. # Usage: $0 sysctl -w vm.mmap_rnd_bits=28 export PATH=$OUT:$PATH cd $OUT DEBUGGER=${DEBUGGER:-} FUZZER=$1 shift # This env var is set by CIFuzz. CIFuzz fills this directory with the corpus # from ClusterFuzz. CORPUS_DIR=${CORPUS_DIR:-} if [ -z "$CORPUS_DIR" ] then CORPUS_DIR="/tmp/${FUZZER}_corpus" rm -rf $CORPUS_DIR && mkdir -p $CORPUS_DIR fi SANITIZER=${SANITIZER:-} if [ -z $SANITIZER ]; then # If $SANITIZER is not specified (e.g. calling from `reproduce` command), it # is not important and can be set to any value. SANITIZER="default" fi if [[ "$RUN_FUZZER_MODE" = interactive ]]; then FUZZER_OUT="$OUT/${FUZZER}_${FUZZING_ENGINE}_${SANITIZER}_out" else FUZZER_OUT="/tmp/${FUZZER}_${FUZZING_ENGINE}_${SANITIZER}_out" fi function get_dictionary() { local options_file="$FUZZER.options" local dict_file="$FUZZER.dict" local dict="" if [[ -f "$options_file" ]]; then dict=$(sed -n 's/^\s*dict\s*=\s*\(.*\)/\1/p' "$options_file" | tail -1) fi if [[ -z "$dict" && -f "$dict_file" ]]; then dict="$dict_file" fi [[ -z "$dict" ]] && return if [[ "$FUZZING_ENGINE" = "libfuzzer" ]]; then printf -- "-dict=%s" "$dict" elif [[ "$FUZZING_ENGINE" = "afl" ]]; then printf -- "-x %s" "$dict" elif [[ "$FUZZING_ENGINE" = "honggfuzz" ]]; then printf -- "--dict %s" "$dict" elif [[ "$FUZZING_ENGINE" = "centipede" ]]; then printf -- "--dictionary %s" "$dict" else printf "Unexpected FUZZING_ENGINE: $FUZZING_ENGINE, ignoring\n" >&2 fi } function get_extra_binaries() { [[ "$FUZZING_ENGINE" != "centipede" ]] && return extra_binaries="$OUT/__centipede_${SANITIZER}/${FUZZER}" if compgen -G "$extra_binaries" >> /dev/null; then printf -- "--extra_binaries %s" \""$extra_binaries\"" fi } rm -rf $FUZZER_OUT && mkdir -p $FUZZER_OUT SEED_CORPUS="${FUZZER}_seed_corpus.zip" # TODO: Investigate why this code block is skipped # by all default fuzzers in bad_build_check. # They all set SKIP_SEED_CORPUS=1. if [ -f $SEED_CORPUS ] && [ -z ${SKIP_SEED_CORPUS:-} ]; then echo "Using seed corpus: $SEED_CORPUS" unzip -o -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null fi OPTIONS_FILE="${FUZZER}.options" CUSTOM_LIBFUZZER_OPTIONS="" if [ -f $OPTIONS_FILE ]; then custom_asan_options=$(parse_options.py $OPTIONS_FILE asan) if [ ! -z $custom_asan_options ]; then export ASAN_OPTIONS="$ASAN_OPTIONS:$custom_asan_options" fi custom_msan_options=$(parse_options.py $OPTIONS_FILE msan) if [ ! -z $custom_msan_options ]; then export MSAN_OPTIONS="$MSAN_OPTIONS:$custom_msan_options" fi custom_ubsan_options=$(parse_options.py $OPTIONS_FILE ubsan) if [ ! -z $custom_ubsan_options ]; then export UBSAN_OPTIONS="$UBSAN_OPTIONS:$custom_ubsan_options" fi CUSTOM_LIBFUZZER_OPTIONS=$(parse_options.py $OPTIONS_FILE libfuzzer) fi if [[ "$FUZZING_ENGINE" = afl ]]; then # Set afl++ environment options. export ASAN_OPTIONS="$ASAN_OPTIONS:abort_on_error=1:symbolize=0:detect_odr_violation=0:" export MSAN_OPTIONS="$MSAN_OPTIONS:exit_code=86:symbolize=0" export UBSAN_OPTIONS="$UBSAN_OPTIONS:symbolize=0" export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 export AFL_SKIP_CPUFREQ=1 export AFL_TRY_AFFINITY=1 export AFL_FAST_CAL=1 export AFL_CMPLOG_ONLY_NEW=1 export AFL_FORKSRV_INIT_TMOUT=30000 export AFL_IGNORE_PROBLEMS=1 export AFL_IGNORE_UNKNOWN_ENVS=1 # If $OUT/afl_cmplog.txt is present this means the target was compiled for # CMPLOG. So we have to add the proper parameters to afl-fuzz. test -e "$OUT/afl_cmplog.txt" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -c $OUT/$FUZZER" # If $OUT/afl++.dict we load it as a dictionary for afl-fuzz. test -e "$OUT/afl++.dict" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -x $OUT/afl++.dict" # Ensure timeout is a bit larger than 1sec as some of the OSS-Fuzz fuzzers # are slower than this. AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -t 5000+" # AFL expects at least 1 file in the input dir. echo input > ${CORPUS_DIR}/input CMD_LINE="$OUT/afl-fuzz $AFL_FUZZER_ARGS -i $CORPUS_DIR -o $FUZZER_OUT $(get_dictionary) $* -- $OUT/$FUZZER" echo afl++ setup: env|grep AFL_ cat "$OUT/afl_options.txt" elif [[ "$FUZZING_ENGINE" = honggfuzz ]]; then # Honggfuzz expects at least 1 file in the input dir. echo input > $CORPUS_DIR/input # --exit_upon_crash: exit whith a first crash seen # -V: verify crashes # -R (report): save report file to this location # -W (working dir): where the crashes go # -v (verbose): don't use VTE UI, just stderr # -z: use software-instrumentation of clang (trace-pc-guard....) # -P: use persistent mode of fuzzing (i.e. LLVMFuzzerTestOneInput) # -f: location of the initial (and destination) file corpus # -n: number of fuzzing threads (and processes) CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -V -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $* -- \"$OUT/$FUZZER\"" if [[ $(LC_ALL=C grep -P "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF" "$FUZZER" ) ]]; then # Honggfuzz Netdriver port. This must match the port in Clusterfuzz. export HFND_TCP_PORT=8666 fi elif [[ "$FUZZING_ENGINE" = centipede ]]; then # Create the work and corpus directory for Centipede. CENTIPEDE_WORKDIR="${CENTIPEDE_WORKDIR:-$OUT}" # Centipede only saves crashes to crashes/ in workdir. rm -rf $FUZZER_OUT # --workdir: Dir that stores corpus&features in Centipede's own format. # --corpus_dir: Location of the initial (and destination) file corpus. # --fork_server: Execute the target(s) via the fork server. # Run in fork mode to continue fuzzing indefinitely in case of # OOMs, timeouts, and crashes. # --exit_on_crash=0: Do not exit on crash. # --timeout=1200: The process that executes target binary will abort # if an input runs >= 1200s. # --rss_limit_mb=0: Disable RSS limit. # --address_space_limit_mb=0: No address space limit. # --binary: The target binary under test without sanitizer. # --extra_binary: The target binaries under test with sanitizers. CMD_LINE="$OUT/centipede --workdir=$CENTIPEDE_WORKDIR --corpus_dir=\"$CORPUS_DIR\" --fork_server=1 --exit_on_crash=1 --timeout=1200 --rss_limit_mb=4096 --address_space_limit_mb=5120 $(get_dictionary) --binary=\"$OUT/${FUZZER}\" $(get_extra_binaries) $*" else CMD_LINE="$OUT/$FUZZER -- $FUZZER_ARGS $*" if [ -z ${SKIP_SEED_CORPUS:-} ]; then CMD_LINE="$CMD_LINE $CORPUS_DIR" fi if [[ ! -z ${CUSTOM_LIBFUZZER_OPTIONS} ]]; then CMD_LINE="$CMD_LINE $CUSTOM_LIBFUZZER_OPTIONS" fi if [[ ! "$CMD_LINE" =~ "-dict=" ]]; then if [ -f "$FUZZER.dict" ]; then CMD_LINE="$CMD_LINE -dict=$FUZZER.dict" fi fi CMD_LINE="$CMD_LINE < /dev/null" fi echo $CMD_LINE # Unset OUT so the fuzz target can't rely on it. unset OUT if [ ! -z "$DEBUGGER" ]; then CMD_LINE="$DEBUGGER $CMD_LINE" fi bash -c "$CMD_LINE" ================================================ FILE: infra/base-images/base-runner/ruzzy ================================================ #!/usr/bin/env bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ASAN_OPTIONS="allocator_may_return_null=1:detect_leaks=0:use_sigaltstack=0" LD_PRELOAD=$(ruby -e 'require "ruzzy"; print Ruzzy::ASAN_PATH') \ ruby $@ ================================================ FILE: infra/base-images/base-runner/targets_list ================================================ #!/bin/bash for binary in $(find $OUT/ -executable -type f); do [[ "$binary" != *.so ]] || continue [[ $(basename "$binary") != jazzer_driver* ]] || continue file "$binary" | grep -e ELF -e "shell script" > /dev/null 2>&1 || continue grep "LLVMFuzzerTestOneInput" "$binary" > /dev/null 2>&1 || continue basename "$binary" done ================================================ FILE: infra/base-images/base-runner/test_all.py ================================================ #!/usr/bin/env python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Does bad_build_check on all fuzz targets in $OUT.""" import contextlib import multiprocessing import os import re import subprocess import stat import sys import tempfile BASE_TMP_FUZZER_DIR = '/tmp/not-out' EXECUTABLE = stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH IGNORED_TARGETS = [ r'do_stuff_fuzzer', r'checksum_fuzzer', r'fuzz_dump', r'fuzz_keyring', r'xmltest', r'fuzz_compression_sas_rle', r'ares_*_fuzzer' ] IGNORED_TARGETS_RE = re.compile('^' + r'$|^'.join(IGNORED_TARGETS) + '$') def move_directory_contents(src_directory, dst_directory): """Moves contents of |src_directory| to |dst_directory|.""" # Use mv because mv preserves file permissions. If we don't preserve file # permissions that can mess up CheckFuzzerBuildTest in cifuzz_test.py and # other cases where one is calling test_all on files not in OSS-Fuzz's real # out directory. src_contents = [ os.path.join(src_directory, filename) for filename in os.listdir(src_directory) ] command = ['mv'] + src_contents + [dst_directory] subprocess.check_call(command) def is_elf(filepath): """Returns True if |filepath| is an ELF file.""" result = subprocess.run(['file', filepath], stdout=subprocess.PIPE, check=False) return b'ELF' in result.stdout def is_shell_script(filepath): """Returns True if |filepath| is a shell script.""" result = subprocess.run(['file', filepath], stdout=subprocess.PIPE, check=False) return b'shell script' in result.stdout def find_fuzz_targets(directory): """Returns paths to fuzz targets in |directory|.""" # TODO(https://github.com/google/oss-fuzz/issues/4585): Use libClusterFuzz for # this. fuzz_targets = [] for filename in os.listdir(directory): path = os.path.join(directory, filename) if filename == 'llvm-symbolizer': continue if filename.startswith('afl-'): continue if filename.startswith('jazzer_'): continue if not os.path.isfile(path): continue if not os.stat(path).st_mode & EXECUTABLE: continue # Fuzz targets can either be ELF binaries or shell scripts (e.g. wrapper # scripts for Python and JVM targets or rules_fuzzing builds with runfiles # trees). if not is_elf(path) and not is_shell_script(path): continue if os.getenv('FUZZING_ENGINE') not in {'none', 'wycheproof'}: with open(path, 'rb') as file_handle: binary_contents = file_handle.read() if b'LLVMFuzzerTestOneInput' not in binary_contents: continue fuzz_targets.append(path) return fuzz_targets def do_bad_build_check(fuzz_target): """Runs bad_build_check on |fuzz_target|. Returns a Subprocess.ProcessResult.""" print('INFO: performing bad build checks for', fuzz_target) if centipede_needs_auxiliaries(): print('INFO: Finding Centipede\'s auxiliary for target', fuzz_target) auxiliary_path = find_centipede_auxiliary(fuzz_target) print('INFO: Using auxiliary binary:', auxiliary_path) auxiliary = [auxiliary_path] else: auxiliary = [] command = ['bad_build_check', fuzz_target] + auxiliary with tempfile.TemporaryDirectory() as temp_centipede_workdir: # Do this so that centipede doesn't fill up the disk during bad build check env = os.environ.copy() env['CENTIPEDE_WORKDIR'] = temp_centipede_workdir return subprocess.run(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=env, check=False) def get_broken_fuzz_targets(bad_build_results, fuzz_targets): """Returns a list of broken fuzz targets and their process results in |fuzz_targets| where each item in |bad_build_results| is the result of bad_build_check on the corresponding element in |fuzz_targets|.""" broken = [] for result, fuzz_target in zip(bad_build_results, fuzz_targets): if result.returncode != 0: broken.append((fuzz_target, result)) return broken def has_ignored_targets(out_dir): """Returns True if |out_dir| has any fuzz targets we are supposed to ignore bad build checks of.""" out_files = set(os.listdir(out_dir)) for filename in out_files: if re.match(IGNORED_TARGETS_RE, filename): return True return False @contextlib.contextmanager def use_different_out_dir(): """Context manager that moves OUT to subdirectory of BASE_TMP_FUZZER_DIR. This is useful for catching hardcoding. Note that this sets the environment variable OUT and therefore must be run before multiprocessing.Pool is created. Resets OUT at the end.""" # Use a fake OUT directory to catch path hardcoding that breaks on # ClusterFuzz. initial_out = os.getenv('OUT') os.makedirs(BASE_TMP_FUZZER_DIR, exist_ok=True) # Use a random subdirectory of BASE_TMP_FUZZER_DIR to allow running multiple # instances of test_all in parallel (useful for integration testing). with tempfile.TemporaryDirectory(dir=BASE_TMP_FUZZER_DIR) as out: # Set this so that run_fuzzer which is called by bad_build_check works # properly. os.environ['OUT'] = out # We move the contents of the directory because we can't move the # directory itself because it is a mount. move_directory_contents(initial_out, out) try: yield out finally: move_directory_contents(out, initial_out) os.environ['OUT'] = initial_out def test_all_outside_out(allowed_broken_targets_percentage): """Wrapper around test_all that changes OUT and returns the result.""" with use_different_out_dir() as out: return test_all(out, allowed_broken_targets_percentage) def centipede_needs_auxiliaries(): """Checks if auxiliaries are needed for Centipede.""" # Centipede always requires unsanitized binaries as the main fuzz targets, # and separate sanitized binaries as auxiliaries. # 1. Building sanitized binaries with helper.py (i.e., local or GitHub CI): # Unsanitized ones will be built automatically into the same docker container. # Script bad_build_check tests both # a) If main fuzz targets can run with the auxiliaries, and # b) If the auxiliaries are built with the correct sanitizers. # 2. In Trial build and production build: # Two kinds of binaries will be in separated buckets / docker containers. # Script bad_build_check tests either # a) If the unsanitized binaries can run without the sanitized ones, or # b) If the sanitized binaries are built with the correct sanitizers. return (os.getenv('FUZZING_ENGINE') == 'centipede' and os.getenv('SANITIZER') != 'none' and os.getenv('HELPER') == 'True') def find_centipede_auxiliary(main_fuzz_target_path): """Finds the sanitized binary path that corresponds to |main_fuzz_target| for bad_build_check.""" target_dir, target_name = os.path.split(main_fuzz_target_path) sanitized_binary_dir = os.path.join(target_dir, f'__centipede_{os.getenv("SANITIZER")}') sanitized_binary_path = os.path.join(sanitized_binary_dir, target_name) if os.path.isfile(sanitized_binary_path): return sanitized_binary_path # Neither of the following two should ever happen, returns None to indicate # an error. if os.path.isdir(sanitized_binary_dir): print('ERROR: Unable to identify Centipede\'s sanitized target' f'{sanitized_binary_path} in {os.listdir(sanitized_binary_dir)}') else: print('ERROR: Unable to identify Centipede\'s sanitized target directory' f'{sanitized_binary_dir} in {os.listdir(target_dir)}') return None def test_all(out, allowed_broken_targets_percentage): # pylint: disable=too-many-return-statements """Do bad_build_check on all fuzz targets.""" # TODO(metzman): Refactor so that we can convert test_one to python. fuzz_targets = find_fuzz_targets(out) if not fuzz_targets: print('ERROR: No fuzz targets found.') return False if centipede_needs_auxiliaries(): for fuzz_target in fuzz_targets: if not find_centipede_auxiliary(fuzz_target): print(f'ERROR: Couldn\'t find auxiliary for {fuzz_target}.') return False pool = multiprocessing.Pool() bad_build_results = pool.map(do_bad_build_check, fuzz_targets) pool.close() pool.join() broken_targets = get_broken_fuzz_targets(bad_build_results, fuzz_targets) broken_targets_count = len(broken_targets) if not broken_targets_count: return True print('Retrying failed fuzz targets sequentially', broken_targets_count) pool = multiprocessing.Pool(1) retry_targets = [] for broken_target, result in broken_targets: retry_targets.append(broken_target) bad_build_results = pool.map(do_bad_build_check, retry_targets) pool.close() pool.join() broken_targets = get_broken_fuzz_targets(bad_build_results, broken_targets) broken_targets_count = len(broken_targets) if not broken_targets_count: return True print('Broken fuzz targets', broken_targets_count) total_targets_count = len(fuzz_targets) broken_targets_percentage = 100 * broken_targets_count / total_targets_count for broken_target, result in broken_targets: print(broken_target) # Use write because we can't print binary strings. sys.stdout.buffer.write(result.stdout + result.stderr + b'\n') if broken_targets_percentage > allowed_broken_targets_percentage: print('ERROR: {broken_targets_percentage}% of fuzz targets seem to be ' 'broken. See the list above for a detailed information.'.format( broken_targets_percentage=broken_targets_percentage)) if has_ignored_targets(out): print('Build check automatically passing because of ignored targets.') return True return False print('{total_targets_count} fuzzers total, {broken_targets_count} ' 'seem to be broken ({broken_targets_percentage}%).'.format( total_targets_count=total_targets_count, broken_targets_count=broken_targets_count, broken_targets_percentage=broken_targets_percentage)) return True def get_allowed_broken_targets_percentage(): """Returns the value of the environment value 'ALLOWED_BROKEN_TARGETS_PERCENTAGE' as an int or returns a reasonable default.""" return int(os.getenv('ALLOWED_BROKEN_TARGETS_PERCENTAGE') or '10') def main(): """Does bad_build_check on all fuzz targets in parallel. Returns 0 on success. Returns 1 on failure.""" allowed_broken_targets_percentage = get_allowed_broken_targets_percentage() if not test_all_outside_out(allowed_broken_targets_percentage): return 1 return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/test_all_test.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests test_all.py""" import unittest from unittest import mock import test_all class TestTestAll(unittest.TestCase): """Tests for the test_all_function.""" @mock.patch('test_all.find_fuzz_targets', return_value=[]) @mock.patch('builtins.print') def test_test_all_no_fuzz_targets(self, mock_print, _): """Tests that test_all returns False when there are no fuzz targets.""" outdir = '/out' allowed_broken_targets_percentage = 0 self.assertFalse( test_all.test_all(outdir, allowed_broken_targets_percentage)) mock_print.assert_called_with('ERROR: No fuzz targets found.') if __name__ == '__main__': unittest.main() ================================================ FILE: infra/base-images/base-runner/test_one.py ================================================ #!/usr/bin/env python3 # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Does bad_build_check on a fuzz target in $OUT.""" import os import sys import test_all def test_one(fuzz_target): """Does bad_build_check on one fuzz target. Returns True on success.""" with test_all.use_different_out_dir(): fuzz_target_path = os.path.join(os.environ['OUT'], fuzz_target) result = test_all.do_bad_build_check(fuzz_target_path) if result.returncode != 0: sys.stdout.buffer.write(result.stdout + result.stderr + b'\n') return False return True def main(): """Does bad_build_check on one fuzz target. Returns 1 on failure, 0 on success.""" if len(sys.argv) != 2: print('Usage: %d ', sys.argv[0]) return 1 fuzz_target_binary = sys.argv[1] return 0 if test_one(fuzz_target_binary) else 1 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/base-images/base-runner/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build rust stuff in its own image. We only need the resulting binaries. # Keeping the rust toolchain in the image wastes 1 GB. FROM gcr.io/oss-fuzz-base/base-image:ubuntu-20-04 as temp-runner-binary-builder RUN apt-get update && apt-get install -y cargo libyaml-dev RUN cargo install rustfilt # Using multi-stage build to copy some LLVM binaries needed in the runner image. FROM gcr.io/oss-fuzz-base/base-clang:ubuntu-20-04 AS base-clang FROM gcr.io/oss-fuzz-base/base-builder-ruby:ubuntu-20-04 AS base-ruby # The base builder image compiles a specific Python version. Using a multi-stage build # to copy that same Python interpreter into the runner image saves build time and keeps # the Python versions in sync. FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-20-04 AS base-builder # Real image that will be used later. FROM gcr.io/oss-fuzz-base/base-image:ubuntu-20-04 COPY --from=temp-runner-binary-builder /root/.cargo/bin/rustfilt /usr/local/bin # Copy the binaries needed for code coverage and crash symbolization. COPY --from=base-clang /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/ # Copy the pre-compiled Python binaries and libraries COPY --from=base-builder /usr/local/bin/python3.11 /usr/local/bin/python3.11 COPY --from=base-builder /usr/local/lib/libpython3.11.so.1.0 /usr/local/lib/libpython3.11.so.1.0 COPY --from=base-builder /usr/local/include/python3.11 /usr/local/include/python3.11 COPY --from=base-builder /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=base-builder /usr/local/bin/pip3 /usr/local/bin/pip3 # Create symbolic links to ensure compatibility RUN ldconfig && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python3 && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python COPY install_deps_ubuntu_20_04.sh / RUN /install_deps_ubuntu_20_04.sh && rm /install_deps_ubuntu_20_04.sh ENV CODE_COVERAGE_SRC=/opt/code_coverage # Pin coverage to the same as in the base builder: # https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/install_python.sh#L22 RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage $CODE_COVERAGE_SRC && \ cd /opt/code_coverage && \ git checkout edba4873b5e8a390e977a64c522db2df18a8b27d && \ pip3 install wheel && \ # If version "Jinja2==2.10" is in requirements.txt, bump it to a patch version that # supports upgrading its MarkupSafe dependency to a Python 3.11 compatible release: sed -i 's/Jinja2==2.10/Jinja2==2.10.3/' requirements.txt && \ pip3 install -r requirements.txt && \ pip3 install MarkupSafe==2.0.1 && \ pip3 install coverage==6.3.2 # Default environment options for various sanitizers. # Note that these match the settings used in ClusterFuzz and # shouldn't be changed unless a corresponding change is made on # ClusterFuzz side as well. ENV ASAN_OPTIONS="alloc_dealloc_mismatch=0:allocator_may_return_null=1:allocator_release_to_os_interval_ms=500:check_malloc_usable_size=0:detect_container_overflow=1:detect_odr_violation=0:detect_leaks=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=0:handle_abort=1:handle_segv=1:handle_sigill=1:max_uar_stack_size_log=16:print_scariness=1:quarantine_size_mb=10:strict_memcmp=1:strip_path_prefix=/workspace/:symbolize=1:use_sigaltstack=1:dedup_token_length=3" ENV MSAN_OPTIONS="print_stats=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV UBSAN_OPTIONS="print_stacktrace=1:print_summary=1:silence_unsigned_overflow=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV FUZZER_ARGS="-rss_limit_mb=2560 -timeout=25" ENV AFL_FUZZER_ARGS="-m none" # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:$GOPATH/bin COPY gocoverage $GOPATH/gocoverage COPY install_go.sh / RUN /install_go.sh && rm -rf /install_go.sh /root/.go # Install OpenJDK 15 and trim its size by removing unused components. ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME=/usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server ENV PATH=$PATH:$JAVA_HOME/bin COPY install_java.sh / RUN /install_java.sh && rm /install_java.sh # Install JaCoCo for JVM coverage. RUN wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/0.8.7/org.jacoco.cli-0.8.7-nodeps.jar -O /opt/jacoco-cli.jar && \ wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar -O /opt/jacoco-agent.jar && \ echo "37df187b76888101ecd745282e9cd1ad4ea508d6 /opt/jacoco-agent.jar" | shasum --check && \ echo "c1814e7bba5fd8786224b09b43c84fd6156db690 /opt/jacoco-cli.jar" | shasum --check COPY install_javascript.sh / RUN /install_javascript.sh && rm /install_javascript.sh # Copy built ruby. It is up to the fuzzing harnesses # themselves to set GEM_HOME and GEM_PATH appropriately, as this depends # on how the harnesses are packaged. COPY --from=base-ruby /usr/local/bin/ruby /usr/local/bin/ruby COPY --from=base-ruby /usr/local/bin/gem /usr/local/bin/gem COPY --from=base-ruby /usr/local/lib/ruby /usr/local/lib/ruby COPY --from=base-ruby /usr/local/include/ruby-3.3.0 /usr/local/include/ruby-3.3.0 RUN apt-get update && apt-get install -y luarocks # Do this last to make developing these files easier/faster due to caching. COPY bad_build_check \ coverage \ coverage_helper \ download_corpus \ jacoco_report_converter.py \ nyc_report_converter.py \ rcfilt \ reproduce \ run_fuzzer \ parse_options.py \ generate_differential_cov_report.py \ profraw_update.py \ targets_list \ test_all.py \ test_one.py \ python_coverage_runner_help.py \ /usr/local/bin/ ================================================ FILE: infra/base-images/base-runner/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build rust stuff in its own image. We only need the resulting binaries. # Keeping the rust toolchain in the image wastes 1 GB. FROM gcr.io/oss-fuzz-base/base-image:ubuntu-24-04 as temp-runner-binary-builder RUN apt-get update && apt-get install -y cargo libyaml-dev RUN cargo install rustfilt # Using multi-stage build to copy some LLVM binaries needed in the runner image. FROM gcr.io/oss-fuzz-base/base-clang:ubuntu-24-04 AS base-clang FROM gcr.io/oss-fuzz-base/base-builder-ruby:ubuntu-24-04 AS base-ruby # The base builder image compiles a specific Python version. Using a multi-stage build # to copy that same Python interpreter into the runner image saves build time and keeps # the Python versions in sync. FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 AS base-builder # Real image that will be used later. FROM gcr.io/oss-fuzz-base/base-image:ubuntu-24-04 COPY --from=temp-runner-binary-builder /root/.cargo/bin/rustfilt /usr/local/bin # Copy the binaries needed for code coverage and crash symbolization. COPY --from=base-clang /usr/local/bin/llvm-cov \ /usr/local/bin/llvm-profdata \ /usr/local/bin/llvm-symbolizer \ /usr/local/bin/ # Copy the pre-compiled Python binaries and libraries COPY --from=base-builder /usr/local/bin/python3.11 /usr/local/bin/python3.11 COPY --from=base-builder /usr/local/lib/libpython3.11.so.1.0 /usr/local/lib/libpython3.11.so.1.0 COPY --from=base-builder /usr/local/include/python3.11 /usr/local/include/python3.11 COPY --from=base-builder /usr/local/lib/python3.11 /usr/local/lib/python3.11 COPY --from=base-builder /usr/local/bin/pip3 /usr/local/bin/pip3 # Create symbolic links to ensure compatibility RUN ldconfig && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python3 && \ ln -s /usr/local/bin/python3.11 /usr/local/bin/python COPY install_deps_ubuntu_24_04.sh / RUN /install_deps_ubuntu_24_04.sh && rm /install_deps_ubuntu_24_04.sh ENV CODE_COVERAGE_SRC=/opt/code_coverage # Pin coverage to the same as in the base builder: # https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/install_python.sh#L22 RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage $CODE_COVERAGE_SRC && \ cd /opt/code_coverage && \ git checkout edba4873b5e8a390e977a64c522db2df18a8b27d && \ pip3 install wheel && \ # If version "Jinja2==2.10" is in requirements.txt, bump it to a patch version that # supports upgrading its MarkupSafe dependency to a Python 3.11 compatible release: sed -i 's/Jinja2==2.10/Jinja2==2.10.3/' requirements.txt && \ pip3 install -r requirements.txt && \ pip3 install MarkupSafe==2.0.1 && \ pip3 install coverage==6.3.2 # Default environment options for various sanitizers. # Note that these match the settings used in ClusterFuzz and # shouldn't be changed unless a corresponding change is made on # ClusterFuzz side as well. ENV ASAN_OPTIONS="alloc_dealloc_mismatch=0:allocator_may_return_null=1:allocator_release_to_os_interval_ms=500:check_malloc_usable_size=0:detect_container_overflow=1:detect_odr_violation=0:detect_leaks=1:detect_stack_use_after_return=1:fast_unwind_on_fatal=0:handle_abort=1:handle_segv=1:handle_sigill=1:max_uar_stack_size_log=16:print_scariness=1:quarantine_size_mb=10:strict_memcmp=1:strip_path_prefix=/workspace/:symbolize=1:use_sigaltstack=1:dedup_token_length=3" ENV MSAN_OPTIONS="print_stats=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV UBSAN_OPTIONS="print_stacktrace=1:print_summary=1:silence_unsigned_overflow=1:strip_path_prefix=/workspace/:symbolize=1:dedup_token_length=3" ENV FUZZER_ARGS="-rss_limit_mb=2560 -timeout=25" ENV AFL_FUZZER_ARGS="-m none" # Set up Golang environment variables (copied from /root/.bash_profile). ENV GOPATH /root/go # /root/.go/bin is for the standard Go binaries (i.e. go, gofmt, etc). # $GOPATH/bin is for the binaries from the dependencies installed via "go get". ENV PATH $PATH:$GOPATH/bin COPY gocoverage $GOPATH/gocoverage COPY install_go.sh / RUN /install_go.sh && rm -rf /install_go.sh /root/.go # Install OpenJDK 15 and trim its size by removing unused components. ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 ENV JAVA_15_HOME=/usr/lib/jvm/java-15-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server ENV PATH=$PATH:$JAVA_HOME/bin COPY install_java.sh / RUN /install_java.sh && rm /install_java.sh # Install JaCoCo for JVM coverage. RUN wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/0.8.7/org.jacoco.cli-0.8.7-nodeps.jar -O /opt/jacoco-cli.jar && \ wget https://repo1.maven.org/maven2/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar -O /opt/jacoco-agent.jar && \ echo "37df187b76888101ecd745282e9cd1ad4ea508d6 /opt/jacoco-agent.jar" | shasum --check && \ echo "c1814e7bba5fd8786224b09b43c84fd6156db690 /opt/jacoco-cli.jar" | shasum --check COPY install_javascript.sh / RUN /install_javascript.sh && rm /install_javascript.sh # Copy built ruby. It is up to the fuzzing harnesses # themselves to set GEM_HOME and GEM_PATH appropriately, as this depends # on how the harnesses are packaged. COPY --from=base-ruby /usr/local/bin/ruby /usr/local/bin/ruby COPY --from=base-ruby /usr/local/bin/gem /usr/local/bin/gem COPY --from=base-ruby /usr/local/lib/ruby /usr/local/lib/ruby COPY --from=base-ruby /usr/local/include/ruby-3.3.0 /usr/local/include/ruby-3.3.0 RUN apt-get update && apt-get install -y luarocks # Do this last to make developing these files easier/faster due to caching. COPY bad_build_check \ coverage \ coverage_helper \ download_corpus \ jacoco_report_converter.py \ nyc_report_converter.py \ rcfilt \ reproduce \ run_fuzzer \ parse_options.py \ generate_differential_cov_report.py \ profraw_update.py \ targets_list \ test_all.py \ test_one.py \ python_coverage_runner_help.py \ /usr/local/bin/ ================================================ FILE: infra/base-images/base-runner-debug/CHANGELOG.md ================================================ # Docker Image Version Changelog: oss-fuzz/base-runner-debug ## Analysis Summary The `ubuntu-20-04` and `ubuntu-24-04` images for `oss-fuzz/base-runner-debug` were successfully built. These images are used for debugging fuzzers and contain tools like GDB and Valgrind. The Dockerfile structure was refactored to support multi-version builds by creating separate Dockerfiles for each Ubuntu version and updating the `FROM` instruction accordingly. ## Build Status | Image Tag | Dockerfile | Status | | --- | --- | --- | | `oss-fuzz/base-runner-debug:ubuntu-20-04` | `ubuntu-20-04.Dockerfile` | Success | | `oss-fuzz/base-runner-debug:ubuntu-24-04` | `ubuntu-24-04.Dockerfile` | Success | ## Package Comparison ### Key Differences (Ubuntu 20.04 vs. Ubuntu 24.04) The `ubuntu-24-04` image includes newer versions of GDB, Valgrind, and other debugging tools. ## Dockerfile Analysis The Dockerfiles for both versions have the following key differences: * **Base Image:** The `FROM` instruction in each Dockerfile points to the corresponding `oss-fuzz/base-runner` tag (`ubuntu-20-04` or `ubuntu-24-04`). * **GDB Installation:** Both versions download and build GDB from source. * **Refactoring:** The original `Dockerfile` was split into `ubuntu-20-04.Dockerfile` and `ubuntu-24-04.Dockerfile` to support the multi-version build strategy. ================================================ FILE: infra/base-images/base-runner-debug/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner RUN apt-get update && apt-get install -y valgrind zip # Installing GDB 12, re https://github.com/google/oss-fuzz/issues/7513. RUN apt-get install -y build-essential libgmp-dev && \ wget https://ftp.gnu.org/gnu/gdb/gdb-12.1.tar.xz && \ tar -xf gdb-12.1.tar.xz && cd gdb-12.1 && ./configure && \ make -j $(expr $(nproc) / 2) && make install && cd .. && \ rm -rf gdb-12.1* && apt-get remove --purge -y build-essential libgmp-dev ================================================ FILE: infra/base-images/base-runner-debug/ubuntu-20-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner:ubuntu-20-04 RUN apt-get update && apt-get install -y valgrind zip # Installing GDB 12, re https://github.com/google/oss-fuzz/issues/7513. RUN apt-get install -y build-essential libgmp-dev && \ wget https://ftp.gnu.org/gnu/gdb/gdb-12.1.tar.xz && \ tar -xf gdb-12.1.tar.xz && cd gdb-12.1 && ./configure && \ make -j $(expr $(nproc) / 2) && make install && cd .. && \ rm -rf gdb-12.1* && apt-get remove --purge -y build-essential libgmp-dev ================================================ FILE: infra/base-images/base-runner-debug/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04 RUN apt-get update && apt-get install -y valgrind zip # Installing GDB 12, re https://github.com/google/oss-fuzz/issues/7513. RUN apt-get install -y build-essential libgmp-dev && \ wget https://ftp.gnu.org/gnu/gdb/gdb-12.1.tar.xz && \ tar -xf gdb-12.1.tar.xz && cd gdb-12.1 && ./configure && \ make -j $(expr $(nproc) / 2) && make install && cd .. && \ rm -rf gdb-12.1* && apt-get remove --purge -y build-essential libgmp-dev ================================================ FILE: infra/base-images/list_images.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """ Helper script to print the official list of base images. This script serves as the single source of truth for shell scripts, avoiding logic duplication. """ import os import sys # Add the path to the `functions` directory to import the `base_images` module. FUNCTIONS_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', 'build', 'functions')) sys.path.append(FUNCTIONS_DIR) import base_images for image_config in base_images.BASE_IMAGE_DEFS: # Exclude 'base-clang-full' as it is a special case not intended for # the general build script. if image_config.get('name', '') != 'base-clang-full': print(image_config.get('name', '')) ================================================ FILE: infra/bisector.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Uses bisection to determine which commit a bug was introduced and fixed. This module takes a high and a low commit SHA, a repo name, and a bug. The module bisects the high and low commit SHA searching for the location where the bug was introduced. It also looks for where the bug was fixed. This is done with the following steps: NOTE: Needs to be run from root of the OSS-Fuzz source checkout. Typical usage example: python3 infra/bisector.py --old_commit 1e403e9259a1abedf108ab86f711ba52c907226d --new_commit f79be4f2330f4b89ea2f42e1c44ca998c59a0c0f --fuzz_target rules_fuzzer --project_name yara --testcase infra/yara_testcase --sanitizer address """ import argparse import collections import logging import os import sys import tempfile import build_specified_commit import helper import repo_manager import utils Result = collections.namedtuple('Result', ['repo_url', 'commit']) START_MARKERS = [ '==ERROR', '==WARNING', ] END_MARKERS = [ 'SUMMARY:', ] DEDUP_TOKEN_MARKER = 'DEDUP_TOKEN:' class BisectError(Exception): """Bisection error.""" def __init__(self, message, repo_url): super().__init__(message) self.repo_url = repo_url def main(): """Finds the commit SHA where an error was initally introduced.""" logging.getLogger().setLevel(logging.INFO) utils.chdir_to_root() parser = argparse.ArgumentParser( description='git bisection for finding introduction of bugs') parser.add_argument('--project_name', help='The name of the project where the bug occurred.', required=True) parser.add_argument('--new_commit', help='The newest commit SHA to be bisected.', required=True) parser.add_argument('--old_commit', help='The oldest commit SHA to be bisected.', required=True) parser.add_argument('--fuzz_target', help='The name of the fuzzer to be built.', required=True) parser.add_argument('--test_case_path', help='The path to test case.', required=True) parser.add_argument('--engine', help='The default is "libfuzzer".', default='libfuzzer') parser.add_argument('--sanitizer', default='address', help='The default is "address".') parser.add_argument('--type', choices=['regressed', 'fixed'], help='The bisection type.', required=True) parser.add_argument('--architecture', default='x86_64') args = parser.parse_args() build_data = build_specified_commit.BuildData(project_name=args.project_name, engine=args.engine, sanitizer=args.sanitizer, architecture=args.architecture) result = bisect(args.type, args.old_commit, args.new_commit, args.test_case_path, args.fuzz_target, build_data) if not result.commit: logging.error('No error was found in commit range %s:%s', args.old_commit, args.new_commit) return 1 if result.commit == args.old_commit: logging.error( 'Bisection Error: Both the first and the last commits in' 'the given range have the same behavior, bisection is not possible. ') return 1 if args.type == 'regressed': print('Error was introduced at commit %s' % result.commit) elif args.type == 'fixed': print('Error was fixed at commit %s' % result.commit) return 0 def _get_dedup_token(output): """Get dedup token.""" for line in output.splitlines(): token_location = line.find(DEDUP_TOKEN_MARKER) if token_location == -1: continue return line[token_location + len(DEDUP_TOKEN_MARKER):].strip() return None def _check_for_crash(project_name, fuzz_target, testcase_path): """Check for crash.""" def docker_run(args, **kwargs): del kwargs command = ['docker', 'run', '--rm', '--privileged'] if sys.stdin.isatty(): command.append('-i') return utils.execute(command + args) logging.info('Checking for crash') out, err, return_code = helper.reproduce_impl( project=helper.Project(project_name), fuzzer_name=fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=testcase_path, run_function=docker_run, err_result=(None, None, None)) if return_code is None: return None logging.info('stdout =\n%s', out) logging.info('stderr =\n%s', err) # pylint: disable=unsupported-membership-test has_start_marker = any( marker in out or marker in err for marker in START_MARKERS) has_end_marker = any(marker in out or marker in err for marker in END_MARKERS) if not has_start_marker or not has_end_marker: return None return _get_dedup_token(out + err) # pylint: disable=too-many-locals # pylint: disable=too-many-arguments # pylint: disable=too-many-statements def _bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target, build_data): """Perform the bisect.""" # pylint: disable=too-many-branches base_builder_repo = build_specified_commit.load_base_builder_repo() with tempfile.TemporaryDirectory() as tmp_dir: repo_url, repo_path = build_specified_commit.detect_main_repo( build_data.project_name, commit=new_commit) if not repo_url or not repo_path: raise ValueError('Main git repo can not be determined.') if old_commit == new_commit: raise BisectError('old_commit is the same as new_commit', repo_url) # Copy /src from the built Docker container to ensure all dependencies # exist. This will be mounted when running them. host_src_dir = build_specified_commit.copy_src_from_docker( build_data.project_name, tmp_dir) bisect_repo_manager = repo_manager.RepoManager( os.path.join(host_src_dir, os.path.basename(repo_path))) bisect_repo_manager.fetch_all_remotes() commit_list = bisect_repo_manager.get_commit_list(new_commit, old_commit) old_idx = len(commit_list) - 1 new_idx = 0 logging.info('Testing against new_commit (%s)', commit_list[new_idx]) if not build_specified_commit.build_fuzzers_from_commit( commit_list[new_idx], bisect_repo_manager, host_src_dir, build_data, base_builder_repo=base_builder_repo): raise BisectError('Failed to build new_commit', repo_url) if bisect_type == 'fixed': should_crash = False elif bisect_type == 'regressed': should_crash = True else: raise BisectError('Invalid bisect type ' + bisect_type, repo_url) expected_error = _check_for_crash(build_data.project_name, fuzz_target, testcase_path) logging.info('new_commit result = %s', expected_error) if not should_crash and expected_error: logging.warning('new_commit crashed but not shouldn\'t. ' 'Continuing to see if stack changes.') range_valid = False for _ in range(2): logging.info('Testing against old_commit (%s)', commit_list[old_idx]) if not build_specified_commit.build_fuzzers_from_commit( commit_list[old_idx], bisect_repo_manager, host_src_dir, build_data, base_builder_repo=base_builder_repo): raise BisectError('Failed to build old_commit', repo_url) if _check_for_crash(build_data.project_name, fuzz_target, testcase_path) == expected_error: logging.warning('old_commit %s had same result as new_commit %s', old_commit, new_commit) # Try again on an slightly older commit. old_commit = bisect_repo_manager.get_parent(old_commit, 64) if not old_commit: break commit_list = bisect_repo_manager.get_commit_list( new_commit, old_commit) old_idx = len(commit_list) - 1 continue range_valid = True break if not range_valid: raise BisectError('old_commit had same result as new_commit', repo_url) while old_idx - new_idx > 1: curr_idx = (old_idx + new_idx) // 2 logging.info('Testing against %s (idx=%d)', commit_list[curr_idx], curr_idx) if not build_specified_commit.build_fuzzers_from_commit( commit_list[curr_idx], bisect_repo_manager, host_src_dir, build_data, base_builder_repo=base_builder_repo): # Treat build failures as if we couldn't repo. # TODO(ochang): retry nearby commits? old_idx = curr_idx continue current_error = _check_for_crash(build_data.project_name, fuzz_target, testcase_path) logging.info('Current result = %s', current_error) if expected_error == current_error: new_idx = curr_idx else: old_idx = curr_idx return Result(repo_url, commit_list[new_idx]) # pylint: disable=too-many-locals # pylint: disable=too-many-arguments def bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target, build_data): """From a commit range, this function caluclates which introduced a specific error from a fuzz testcase_path. Args: bisect_type: The type of the bisect ('regressed' or 'fixed'). old_commit: The oldest commit in the error regression range. new_commit: The newest commit in the error regression range. testcase_path: The file path of the test case that triggers the error fuzz_target: The name of the fuzzer to be tested. build_data: a class holding all of the input parameters for bisection. Returns: The commit SHA that introduced the error or None. Raises: ValueError: when a repo url can't be determine from the project. """ try: return _bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target, build_data) finally: # Clean up projects/ as _bisect may have modified it. oss_fuzz_repo_manager = repo_manager.RepoManager(helper.OSS_FUZZ_DIR) oss_fuzz_repo_manager.git(['reset', 'projects']) oss_fuzz_repo_manager.git(['checkout', 'projects']) oss_fuzz_repo_manager.git(['clean', '-fxd', 'projects']) if __name__ == '__main__': main() ================================================ FILE: infra/bisector_test.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing perepo_managerissions and # limitations under the License. """Test the functionality of bisection module: 1) Test a known case where an error appears in a regression range. 2) Bisect can handle incorrect inputs. IMPORTANT: This test needs to be run with root privileges. """ import os import unittest import bisector import build_specified_commit import test_repos # Necessary because __file__ changes with os.chdir TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) @unittest.skip('Test is too long to be run with presubmit.') class BisectIntegrationTests(unittest.TestCase): """Class to test the functionality of bisection method.""" BISECT_TYPE = 'regressed' def test_bisect_invalid_repo(self): """Test the bisection method on a project that does not exist.""" test_repo = test_repos.INVALID_REPO build_data = build_specified_commit.BuildData( project_name=test_repo.project_name, engine='libfuzzer', sanitizer='address', architecture='x86_64') with self.assertRaises(ValueError): bisector.bisect(self.BISECT_TYPE, test_repo.old_commit, test_repo.new_commit, test_repo.testcase_path, test_repo.fuzz_target, build_data) def test_bisect(self): """Test the bisect method on example projects.""" for test_repo in test_repos.TEST_REPOS: if test_repo.new_commit: build_data = build_specified_commit.BuildData( project_name=test_repo.project_name, engine='libfuzzer', sanitizer='address', architecture='x86_64') result = bisector.bisect(self.BISECT_TYPE, test_repo.old_commit, test_repo.new_commit, test_repo.testcase_path, test_repo.fuzz_target, build_data) self.assertEqual(result.commit, test_repo.intro_commit) if __name__ == '__main__': # Change to oss-fuzz main directory so helper.py runs correctly. if os.getcwd() != os.path.dirname(TEST_DIR_PATH): os.chdir(os.path.dirname(TEST_DIR_PATH)) unittest.main() ================================================ FILE: infra/build/blog/.gitignore ================================================ oss-fuzz-blog hugo-coder ================================================ FILE: infra/build/blog/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM python:3.11-bullseye # Allow statements and log messages to immediately appear in the Knative logs ENV PYTHONUNBUFFERED True RUN mkdir -p hugo-bin && \ cd hugo-bin && \ wget https://github.com/gohugoio/hugo/releases/download/v0.126.1/hugo_extended_0.126.1_linux-amd64.tar.gz && \ tar -xzf hugo_extended_0.126.1_linux-amd64.tar.gz ENV PATH="${PATH}:/hugo-bin/" RUN git clone https://github.com/luizdepra/hugo-coder hugo-coder && \ cd hugo-coder && \ git checkout 759cc945636473d251a28597e2007cbb7d11631d # 17th May 2024 COPY content /content COPY hugo.toml /hugo.toml COPY build_blog.sh /build_blog.sh RUN /build_blog.sh CMD exec python3 -m http.server 8011 -d /oss-fuzz-blog/page/public ================================================ FILE: infra/build/blog/build_blog.sh ================================================ #!/bin/bash -eux # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ BASE=$PWD if [ -d "${BASE}/hugo-coder" ] then echo "Local version of hugo exists. Using this." else # When writing the blog outeside of docker we clone Hugo here. git clone https://github.com/luizdepra/hugo-coder hugo-coder cd hugo-coder git checkout 759cc945636473d251a28597e2007cbb7d11631d # 17th May 2024 cd ../ fi # Build the site if [ -d "${BASE}/oss-fuzz-blog" ] then rm -rf ${BASE}/oss-fuzz-blog fi mkdir oss-fuzz-blog cd oss-fuzz-blog hugo new site page cd page git init # Copy over our content cp -rf ${BASE}/hugo-coder themes/hugo-coder cp $BASE/hugo.toml . rm -rf ./content cp -rf $BASE/content . # Build the site hugo -D # Uncomment the following to launch site automatically #python3 -m http.server 8011 -d ./oss-fuzz-blog/page/public ================================================ FILE: infra/build/blog/content/about.md ================================================ +++ title = "About" description = "OSS-Fuzz's blog" date = "2024-05-20" aliases = ["about-us", "about-oss-fuzz", "contact"] author = "OSS-Fuzz maintainers" +++ This is a blog for updates, research and initiatives of the OSS-Fuzz project. OSS-Fuzz is an open source fuzzing framework focused on large scale fuzzing of open source projects. The efforts described in this blog focuses on this domain and includes both feature updates to OSS-Fuzz itself as well as insights into research and development efforts of OSS-Fuzz. ================================================ FILE: infra/build/blog/content/posts/introducing-java-auto-harnessing.md ================================================ +++ authors = ["OSS-Fuzz Maintainers"] title = "Introducing Java fuzz harness synthesis using LLMs" date = "2024-09-05" description = "Introducing LLM-based harness generation for Java OSS-Fuzz projects." categories = [ "Fuzzing", "Fuzzing synthesis", "LLM", "Automated fuzzing", "Java", "Java automatic fuzzing", ] +++ # Introduction The primary objective of OSS-Fuzz-gen is to automate the fuzzing process for open-source software. In our previous blog posts ([1](https://security.googleblog.com/2023/08/ai-powered-fuzzing-breaking-bug-hunting.html),[2](https://blog.oss-fuzz.com/posts/introducing-llm-based-harness-synthesis-for-unfuzzed-projects/)), we've demonstrated promising results using large language models (LLMs) to enhance existing C/C++ OSS-Fuzz projects and explored the potential of leveraging LLMs for initial OSS-Fuzz integrations. In this blog post, we explore how we can extend this work to another language (Java), and the unique challenges we encountered while building Java-specific capabilities into our existing OSS-Fuzz-Gen workflow: 1. Extracting program analysis data from Java projects. 2. Generate LLM prompts based on program analysis targeted Java projects. # Java fuzz harness sample and outline To illustrate the typical structure of a Java fuzz harness, consider the following example targeting the [Jettison](https://github.com/google/oss-fuzz/tree/master/projects/jettison) project, specifically the constructor of the `MappedXMLStreamReader` class. This constructor requires a `JSONObject` as an argument, which the harness instantiates using fuzz data provided by the `FuzzedDataProvider` object. Moreover, since `MappedXMLStreamReader` is a resource class implementing the `AutoCloseable` interface, the harness must invoke the close method on the instantiated object to prevent memory exhaustion. Failure to do so would result in memory leaks during each fuzz iteration. The harness also needs to handle `JSONException` and `XMLStreamException` exceptions, as these are valid exceptions that the target class may throw. If these exceptions are not appropriately caught, they would be incorrectly reported as issues, leading to false positives. It is also important to note that the methods targeted by the harness are publicly accessible, as otherwise the harness wouldn’t build successfully. ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.codehaus.jettison.mapped.MappedXMLStreamReader; import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONException; import javax.xml.stream.XMLStreamException; public class JsonFuzzer { public static void fuzzerInitialize() { } public static void fuzzerTearDown() { } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JSONObject jsonObject = new JSONObject(); for (int i = 0; i < 10; ++i) { try { jsonObject.put(data.consumeString(10), data.consumeString(10)); } catch (JSONException e) { // handle exception } } MappedXMLStreamReader reader = new MappedXMLStreamReader(jsonObject); reader.close(); } catch (JSONException | XMLStreamException e) { // handle exception } } } ``` These aspects are central in the generation of Java fuzzing harnesses, and, we may see similar code structures in a C++ harness, one of the observations that we have made during our Java fuzzing automation efforts is that without contextual information regarding the aforementioned parts the LLMs are likely to generate harnesses that can’t build or produce false positives. To this end, a significant part of enabling Java fuzzing harness synthesis by way of LLMs has been to provide enough context to the LLM so it is aware of these constraints. # Challenges faced integrating Java into OSS-Fuzz-gen The above example highlights several common characteristics of Java harnesses, and throughout our efforts we identified the need for specific handling of these within our prompt. This includes specific considerations to the following attributes: ## 1. Object creation and constructors Fuzzing Java targets almost always requires creating and managing objects, and this involves calling constructors, managing object lifecycles, and ensuring objects are in valid states before invoking methods. Because precise object management is crucial, it is important to provide context about object creation to LLMs so they can generate fuzzing harnesses that use the correct constructors or static methods. For example, our auto-generation capabilities support generating harnesses targeting both static methods and object instance methods. Whenever the target is an instance method we provide details about the constructors associated with a given class, and further descriptions about the types of the arguments to the construct. This constructor section that we add to the LLM prompt, provides details such as a list of constructors, methods and guidelines in the target code that create and initialize objects of the type that the target method is attached to. A sample of this section is shown below, where the goal of the constructor section is to provide context for the LLM on how to instantiate a `DiffRowGenerator` object. ```sh DiffRowGenerator.Builder.build() You MUST call the STATIC method DiffRowGenerator.create() to retrieve an instance of DiffRowGenerator.Builder before invoking DiffRowGenerator.Builder.build() to generate a com.github.difflib.text.DiffRowGenerator instance. ``` For the full prompt and the harness generated by the prompt, please see the following [Gist](https://gist.github.com/DavidKorczynski/d16bf21a433931d6c8be9f5a4048f48e). ## 2. Exception handling Exceptions are prevalent in Java and although they are also prevalent in C++, we found a need for adding further handling of exceptions when auto generating Java harnesses. We anticipate that this is, to some extent, due to Java fuzzing often revolving around generating harnesses that are meant to flag any uncaught exceptions in the target code, whereas the predominant goal of C++ fuzzing is to capture memory corruption issues. To this end, we added a specific guide on which exceptions a Java harness needs to catch as displayed in the prompt snippet below: ```sh The tag contains a list of exceptions thrown by the target method that you MUST catch. ... jakarta.mail.internet.AddressException ``` In order to extract the exceptions that a harness should catch, we rely on reachability analysis from Fuzz Introspector, that extracts the exceptions a given function can throw explicitly. The primary objective of including this section is to minimize the number of false positives arising from expected exceptions and to catch all checked exceptions, thereby preventing compilation errors in the generated harness. ## 3. Resources object closing In Java fuzzing we must manage and close resources for classes that implement `AutoCloseable` to prevent memory leaks and resource exhaustion. Java relies on the garbage collector for memory management so a harness generally doesn’t need to worry about out-of-memory issues or memory leaks. However, for classes that implement the `AutoCloseable` interface, such as file streams, network connections, or database handles, the garbage collector won’t free up its allocated memory. To this end, in order to avoid memory leaks and out-of-memory issues, we need to provide context for the LLM whenever `AutoCloseable` objects are and guidance for closing the objects correctly. To address this, we add to the LLM prompt general guidance on the need for closing `AutoCloseable` interfaces, as well as specific guidance whenever we incur objects that implements this interface, as shown by the snippet of a prompt below: ```sh ... You MUST invoke the close method of the org.codehaus.jettison.mapped.MappedXMLStreamReader objects in the finally block after the target method is invoked. You MUST invoke the close method of any resource class objects that implements the java.lang.AutoCloseable interface in the finally block after the target method is invoked. ... ``` ## 4. Choosing suitable targets A central theme when auto-generating fuzzing harnesses is to identify entry points in the target code that are relevant fuzz targets. In general, OSS-Fuzz-gen does this by identifying target functions that exhibit a lot of complexity, but has zero or low code coverage from the existing OSS-Fuzz harnesses. This works well in terms of identifying targets that if fuzzed correctly will yield a lot of code coverage. This idea translates well into Java as well, in that we are interested in fuzzing targets that are high in the function call tree of the target codebase. However, we found that we need additional filtering mechanisms when choosing target method candidates, due to the language features of Java such as polymorphism, method scope and more. In addition to this, because Java targets often have several thousand methods that are potential candidates, we found a stronger need for more carefully choosing which candidates may be viable targets. For example, in addition to the existing candidate choosing mechanisms we have in OSS-Fuzz-gen, we added filtering logic for Java methods that only includes methods if they: - Are publicly accessible. - Are not part of the JVM library. - Are not part of an enum class. - Are not called by any existing fuzzing harnesses - Are not part of any exception or testing class or contain the words “test”, “exception” or “error in the function name. ## 5. Random objects and primitive data Java harnesses often have to generate complex types as input to the target methods, and these types themselves are often generated either through creation of a sequence of different objects or using helper methods provided by helper classes exposed by the Jazzer fuzzing framework. We found the need to provide further guidance on how to instantiate the arguments of a given function, as well provide guidance on generating simple types such as strings seeded with fuzz data. To this end, we include in each prompt a section on how to instantiate the arguments of a target method, as shown by the below snippet: ```sh 1. Argument #0 requires a java.util.List instance with a generic type of String. You MUST create an empty java.util.List instance, then fill the list with multiple DIFFERENT String objects generated by FuzzedDataProvider::consumeString(int) or FuzzedDataProvider::consumeAsciiString(int) or FuzzedDataProvider::consumeRemainingAsString() or FuzzedDataProvider::consumeRemainingAsAsciiString() or FuzzedDataProvider::pickValue(String[]) methods. 2. Argument #1 requires a com.github.difflib.patch.Patch instance with a generic type of String. You MUST create two empty java.util.List instance, then fill the two lists with multiple DIFFERENT String objects generated by FuzzedDataProvider::consumeString(int) or FuzzedDataProvider::consumeAsciiString(int) or FuzzedDataProvider::consumeRemainingAsString() or FuzzedDataProvider::consumeRemainingAsAsciiString() or FuzzedDataProvider::pickValue(String[]) methods. After the two lists creation, use these newly created lists to invoke the STATIC method com.github.difflib.DiffUtils.diff(java.util.List,java.util.List) to generate a com.github.difflib.patch.Patch instance with generic type of String. ``` The section outlines both how to create primitive types using the `FuzzedDataProvider` exposed by the fuzzing engine, as well as guidelines on how to create higher-level types such as the `difflib.patch.Patch` as shown in the second argument in the above snippet. ## 6. General Java fuzzing requirements There are several fuzzing engines for Java, such as JQF, Jazzer, and JavaFuzz, each with its own unique structure and methodology, unlike the more standardized engines used for C/C++ fuzzing. Currently, OSS-Fuzz supports Java fuzzing exclusively through the Jazzer engine, so it is essential for OSS-Fuzz-Gen to provide guidelines that enable LLMs to generate harnesses following Jazzer's specific structure for direct use in OSS-Fuzz. We found a need to guide the LLM towards generating Jazzer-friendly harnesses by providing a Java-specific introduction section in the LLM, as well as a section on general Java fuzzing guidelines. An example snippet of the general guidelines are shown in the snippet below: ```sh ... The generated fuzzing harness should be wrapped with the tag. NEVER use any methods from the java.lang.Random class in the generated code. NEVER use any classes or methods in the java.lang.reflect package in the generated code. NEVER use the @FuzzTest annotation for specifying the fuzzing method. Please avoid using any multithreading or multi-processing approach. Please add import statements for necessary classes, except for classes in the java.lang package. You MUST create the object before calling the target method. You MUST catch java.lang.RuntimeException. Please use HeaderTokenizerFuzzer as the Java class name. ``` # Results The Java harness generation logic is built into OSS-Fuzz-gen which means we can run the logic at scale. To test our approach we ran the harness generation on a total of 106 existing Java project integrations in OSS-Fuzz. An overview of the results are shown in the below table. In total we tried to synthesize harnesses for 592 targets, which means that we identified 592 interesting Java methods to fuzz. In total, 280 of the harnesses synthesized were able to build and of these 280 harnesses a total of 102 harnesses had an edge-coverage delta of more than zero. This means that 102 harnesses had code exploration, where the remaining 178 harnesses either ran into an exception in the first iteration or failed to explore code incrementally. | Total number of projects | Total harnesses synthesized | Harnesses successfully built | harness build success rate | Harnesses with edge coverage delta above 0 | |--------------------------|----------------------------|--------------------|-----------------|----------------| | 106 | 592 | 280 | 47.30% | 102 | During our evaluation, several of the harnesses reported bugs which we triaged. We found that two issues were deemed to be security issues (awaiting response) and also triaged four issues that were considered reliability bugs. All issues were reported to the upstream maintainers. In the following we’ll go through the four harnesses that found reliability bugs (uncaught exceptions). ## Reliability bug 1: uncaught exception in jakarta.mail Reported [here](https://github.com/jakartaee/mail-api/issues/734) Generated harness: ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; import jakarta.mail.internet.ParameterList; import jakarta.mail.internet.ParseException; public class HeaderTokenizerFuzzer { public static void fuzzerInitialize() { } public static void fuzzerTearDown() { } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { for (int i = 0; i < 10; i++) { String var_0 = data.consumeRemainingAsString(); ParameterList parameterList = new ParameterList(var_0); } } catch (ParseException e) { } } } ``` Execution log and bug trace: ```sh #2 INITED cov: 34 ft: 34 corp: 1/1b exec/s: 0 rss: 911Mb #6 NEW cov: 51 ft: 69 corp: 2/3b lim: 4 exec/s: 0 rss: 911Mb L: 2/2 MS: 8 ChangeByte-Custom-ChangeBit-Custom-CopyPart-Custom-InsertByte-Custom- #12 NEW cov: 60 ft: 79 corp: 3/5b lim: 4 exec/s: 0 rss: 911Mb L: 2/2 MS: 2 InsertByte-Custom- #14 NEW cov: 62 ft: 82 corp: 4/8b lim: 4 exec/s: 0 rss: 911Mb L: 3/3 MS: 4 ShuffleBytes-Custom-InsertByte-Custom- #15 NEW cov: 63 ft: 83 corp: 5/10b lim: 4 exec/s: 0 rss: 911Mb L: 2/3 MS: 2 ChangeByte-Custom- #16 REDUCE cov: 63 ft: 83 corp: 5/9b lim: 4 exec/s: 0 rss: 911Mb L: 2/2 MS: 2 EraseBytes-Custom- #25 NEW cov: 64 ft: 84 corp: 6/11b lim: 4 exec/s: 0 rss: 911Mb L: 2/2 MS: 8 ShuffleBytes-Custom-ChangeByte-Custom-ChangeByte-Custom-CopyPart-Custom- #54 NEW cov: 71 ft: 91 corp: 7/14b lim: 4 exec/s: 0 rss: 911Mb L: 3/3 MS: 8 ChangeBinInt-Custom-CrossOver-Custom-InsertByte-Custom-ChangeBit-Custom- #60 NEW cov: 73 ft: 95 corp: 8/16b lim: 4 exec/s: 0 rss: 911Mb L: 2/3 MS: 2 CopyPart-Custom- … #232899 REDUCE cov: 247 ft: 1033 corp: 288/8318b lim: 493 exec/s: 116449 rss: 936Mb L: 14/260 MS: 2 EraseBytes-Custom- #234061 REDUCE cov: 247 ft: 1033 corp: 288/8317b lim: 501 exec/s: 117030 rss: 936Mb L: 13/260 MS: 4 ChangeBit-Custom-EraseBytes-Custom- #234662 REDUCE cov: 247 ft: 1033 corp: 288/8309b lim: 501 exec/s: 117331 rss: 936Mb L: 33/260 MS: 2 EraseBytes-Custom- #236110 REDUCE cov: 247 ft: 1033 corp: 288/8305b lim: 509 exec/s: 118055 rss: 936Mb L: 25/260 MS: 6 ShuffleBytes-Custom-CMP-Custom-EraseBytes-Custom- DE: "*0*"- #236377 REDUCE cov: 247 ft: 1033 corp: 288/8304b lim: 509 exec/s: 118188 rss: 936Mb L: 42/260 MS: 4 ChangeBit-Custom-EraseBytes-Custom- #236528 REDUCE cov: 247 ft: 1033 corp: 288/8303b lim: 509 exec/s: 118264 rss: 936Mb L: 8/260 MS: 2 EraseBytes-Custom- #238094 NEW cov: 247 ft: 1037 corp: 289/8336b lim: 517 exec/s: 119047 rss: 936Mb L: 33/260 MS: 2 CopyPart-Custom- == Java Exception: java.util.ConcurrentModificationException at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1584) at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1607) at jakarta.mail.internet.ParameterList.combineMultisegmentNames(ParameterList.java:408) at jakarta.mail.internet.ParameterList.(ParameterList.java:309) at HeaderTokenizerFuzzer.fuzzerTestOneInput(HeaderTokenizerFuzzer.java:16) ``` ## Reliability bug 2: uncaught exception in jettison.json Reported [here](https://github.com/jettison-json/jettison/issues/96) Generated harness: ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONTokener; public class JsonFuzzer { public static void fuzzerInitialize() { } public static void fuzzerTearDown() { } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JSONTokener jSONTokener = new JSONTokener(data.consumeRemainingAsString()); JSONArray jSONArray = new JSONArray(jSONTokener); } catch (JSONException e) { } } } ``` Execution log and bug trace: ```sh #1729 INITED cov: 88 ft: 341 corp: 67/2733b exec/s: 0 rss: 954Mb #1731 NEW cov: 90 ft: 343 corp: 68/2742b lim: 567 exec/s: 0 rss: 954Mb L: 9/558 MS: 4 CopyPart-Custom-ManualDict-Custom- DE: "}="- #1758 NEW cov: 92 ft: 345 corp: 69/2747b lim: 567 exec/s: 0 rss: 954Mb L: 5/558 MS: 4 PersAutoDict-Custom-CrossOver-Custom- DE: "}="- #1759 REDUCE cov: 92 ft: 345 corp: 69/2745b lim: 567 exec/s: 0 rss: 954Mb L: 9/558 MS: 2 EraseBytes-Custom- #1763 NEW cov: 94 ft: 347 corp: 70/2820b lim: 567 exec/s: 0 rss: 954Mb L: 75/558 MS: 8 ChangeASCIIInt-Custom-EraseBytes-Custom-ShuffleBytes-Custom-CopyPart-Custom- #1779 NEW cov: 96 ft: 349 corp: 71/2853b lim: 567 exec/s: 0 rss: 954Mb L: 33/558 MS: 2 ManualDict-Custom- DE: "\""- #1804 NEW cov: 98 ft: 351 corp: 72/2864b lim: 567 exec/s: 0 rss: 954Mb L: 11/558 MS: 10 CMP-Custom-ChangeBit-Custom-ChangeBinInt-Custom-InsertByte-Custom-ChangeByte-Custom- DE: "(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at org.codehaus.jettison.json.JSONTokener.newJSONArray(JSONTokener.java:436) at org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:342) at org.codehaus.jettison.json.JSONArray.(JSONArray.java:145) at JsonFuzzer.fuzzerTestOneInput(JsonFuzzer.java:17) ``` ## Reliability bug 3: Uncaught exception in sqlite-jdbc Reported [here](https://github.com/xerial/sqlite-jdbc/issues/1141) Generated harness: ```java import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.sqlite.ExtendedCommand; public class SqliteConnectionFuzzer { public static void fuzzerInitialize() { // Initializing objects for fuzzing } public static void fuzzerTearDown() { // Tear down objects after fuzzing } public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Use the FuzzedDataProvider object to generate random data for fuzzing String string0 = data.consumeRemainingAsString(); for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { // Fuzz by invoking the target method with random parameters / objects generated above. ExtendedCommand.removeQuotation(string0); } } } } ``` Execution log and bug trace: ```sh #2 INITED cov: 9 ft: 9 corp: 1/1b exec/s: 0 rss: 942Mb #486 NEW cov: 10 ft: 10 corp: 2/3b lim: 8 exec/s: 486 rss: 1042Mb L: 2/2 MS: 8 ChangeByte-Custom-ChangeBit-Custom-CopyPart-Custom-ChangeBit-Custom- == Java Exception: java.lang.StringIndexOutOfBoundsException: begin 1, end 0, length 1 at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3734) at java.base/java.lang.String.substring(String.java:1903) at org.sqlite.ExtendedCommand.removeQuotation(ExtendedCommand.java:57) at SqliteConnectionFuzzer.fuzzerTestOneInput(SqliteConnectionFuzzer.java:19) ``` ## Reliability bug 4: uncaught exception in jolt Reported [here](https://github.com/bazaarvoice/jolt/issues/1268) Generated harness: ```java import com.bazaarvoice.jolt.removr.spec.RemovrCompositeSpec; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.Map; import java.util.HashMap; public class JsonUtilsFuzzer { public static void fuzzerInitialize() { } public static void fuzzerTearDown() { } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { String var_0 = data.consumeString(1024); Map var_1 = new HashMap(); for (int i = 0; i < data.consumeInt(0, 10); i++) { var_1.put(data.consumeString(1024), data.consumeString(1024)); } RemovrCompositeSpec target = new RemovrCompositeSpec(var_0, var_1); } catch (java.lang.UnsupportedOperationException e) { } } } ``` Execution log and bug trace: ```sh #358 NEW cov: 52 ft: 67 corp: 12/35b lim: 4 exec/s: 0 rss: 990Mb L: 4/4 MS: 6 ChangeBinInt-Custom-PersAutoDict-Custom-CopyPart-Custom- DE: "\000\000"- #411 NEW cov: 54 ft: 70 corp: 13/39b lim: 4 exec/s: 0 rss: 990Mb L: 4/4 MS: 6 CrossOver-Custom-ShuffleBytes-Custom-CopyPart-Custom- #468 REDUCE cov: 54 ft: 70 corp: 13/38b lim: 4 exec/s: 0 rss: 990Mb L: 2/4 MS: 4 ChangeBit-Custom-CrossOver-Custom- #469 REDUCE cov: 54 ft: 70 corp: 13/37b lim: 4 exec/s: 0 rss: 990Mb L: 2/4 MS: 2 CrossOver-Custom- == Java Exception: java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1 at com.bazaarvoice.jolt.common.pathelement.StarDoublePathElement.(StarDoublePathElement.java:54) at com.bazaarvoice.jolt.removr.spec.RemovrSpec.parse(RemovrSpec.java:55) at com.bazaarvoice.jolt.removr.spec.RemovrSpec.(RemovrSpec.java:36) at com.bazaarvoice.jolt.removr.spec.RemovrCompositeSpec.(RemovrCompositeSpec.java:59) at JsonUtilsFuzzer.fuzzerTestOneInput(JsonUtilsFuzzer.java:20) ``` # Conclusions and future work In this blog post we have introduced our initial efforts toward automated java fuzzing. We described the challenges we faced during integration of Java support to OSS-Fuzz-gen, including how we pick interesting candidates and how we provide Java-specific context in the LLM prompts. The approach is built into our existing pipelines in OSS-Fuzz-gen, which enables us to do harness generation at scale for all OSS-Fuzz Java projects. The approach has shown interesting elements including code coverage gains across a large part of the Java projects as well as reporting security and reliability issues. We will continue our efforts in automated Java fuzzer generation and are actively exploring new avenues for prompt generation. The goal is to provide reliable and clear harness suggestions to OSS-Fuzz users. We are also exploring combining our Java efforts with approaches for generating OSS-Fuzz integrations from scratch, as described in a previous [blog post](https://blog.oss-fuzz.com/posts/introducing-llm-based-harness-synthesis-for-unfuzzed-projects/). The efforts described in this blog post are available in our OSS-Fuzz-gen repository [https://github.com/google/oss-fuzz-gen](https://github.com/google/oss-fuzz-gen) and we invite contributions from the community to further the Java harness automation generation. ================================================ FILE: infra/build/blog/content/posts/introducing-llm-based-harness-synthesis-for-unfuzzed-projects.md ================================================ +++ authors = ["OSS-Fuzz Maintainers"] title = "Introducing LLM-based harness synthesis for unfuzzed projects" date = "2024-05-27" description = "Introducing LLM-based harness generation for unfuzzed projects." categories = [ "Fuzzing", "Fuzzing synthesis", "LLM", "Automated fuzzing", ] +++ # Introduction As part of the OSS-Fuzz-Gen project, we’ve been working on generating fuzzing harnesses for OSS-Fuzz projects with the goal of improving fuzzing coverage and unearthing more vulnerabilities. Results previously published from our ongoing work described in our [blog post](https://security.googleblog.com/2023/08/ai-powered-fuzzing-breaking-bug-hunting.html) showed promising results, with absolute coverage increases of up to 35% across over 160 OSS-Fuzz projects, and [6 new vulnerabilities](https://github.com/google/oss-fuzz-gen/?tab=readme-ov-file#bugs-discovered) discovered. However, this work only applied to projects already integrated into OSS-Fuzz as it uses the existing fuzzing build setups scripts in the given OSS-Fuzz project. Recently, we experimented with generating fuzzing harnesses for arbitrary C/C++ software projects, using the same LLM techniques. The primary goal of our efforts are to take as input a GitHub repository and output an OSS-Fuzz project as well as a ClusterFuzzLite project with a meaningful fuzz harness. In this blog post we will describe how we automatically build projects, how we generate fuzzing harnesses using LLMs, how these are evaluated and list a selection of 15 projects that we generated OSS-Fuzz/ClusterFuzzLite integrations for and have upstreamed the results. # Generating OSS-Fuzz integrations with LLM harness synthesis The high-level process for generating fuzzing harnesses from scratch takes as input a URL to a GitHub project and then follows a four step approach: 1. Build generator: Try building the project using a set of pre-defined auto-build heuristics and capture the output of the build heuristics. If no build succeeds, do not continue. 2. Fuzz Introspector build: For each successful build, rebuild the project under analysis of [Fuzz Introspector](https://github.com/ossf/fuzz-introspector) in order to extract a myriad of program analysis data as output in a Fuzz Introspector report. 3. LLM-based harness generation: Synthesize harnesses by way of LLMs where the prompts are based on the program analysis data from Fuzz Introspector report. 4. Harness Building: For each generated harness, build it using the build scripts generated from step (1) and run each harness for a number of seconds to evaluate its runtime performance. Log results from runtime for later inspection. For each harness wrap it in an appropriate OSS-Fuzz and ClusterFuzzLite project. The output of the above is a set of OSS-Fuzz/ClusterFuzzLite projects with LLM-generated harnesses, build scripts, Dockerfiles and output from runtime evaluations. The following figure visualizes the approach, and we will now go into further details with each of the above steps. ![image](/images/llm-from-scratch-overview.png) ## Step 1: Auto-build target project The first step intends to build the target project. In the case of C/C++ projects this is a non-trivial problem because, in comparison to several managed languages, there is limited consensus on how to build projects. There are multiple build systems, e.g. Make, CMake, Bazel, Ninja and so on, some projects rely on third-party dependencies to be installed on the system that builds the project, and some projects may rely on multiple commands to create the build artifacts. In addition to this, in order to build the code in a fuzzer-friendly manner we need to ensure certain compiler flags, e.g. to enable sanitizers, and compilers are used for the compilation. The strategy we have opted for auto-building projects for a fuzzer-friendly build is creating a set of generalized build scripts by abstracting the existing build scripts in OSS-Fuzz. These generalized build scripts are template-like and include, for example, general build approaches based on Make, CMake and also compiling source files directly. We call these generalized build scripts for “build heuristics”. The build heuristics also include features for building the target code statically, since this is a requirement by OSS-Fuzz, and techniques for disabling certain options there may be available in the target projects’ build set up. We added these options because we observed several libraries where default options may not be fuzz-compatible and disabling these would successfully build the target projects. Upon successful execution of a build template, we search for the binary artifacts created by the build. Specifically, we are interested in the static archives produced by the build since to run on OSS-Fuzz it is preferred to link harnesses statically. We consider each build that produces at least one static archive to be a successful build, and each successful build is used for further processing in the next steps. The output of this step is a bash build script for each successful build template. To provide intuition for how the build scripts look, consider the following two examples. Example 1, lorawan-parser build script ([PR](https://github.com/JiapengLi/lorawan-parser/pull/17)): ```sh autoreconf -fi ./configure make $CC $CFLAGS $LIB_FUZZING_ENGINE $SRC/fuzzer.c -Wl,--whole-archive $SRC/lorawan-parser/lw/.libs/liblorawan.a -Wl,--whole-archive $SRC/lorawan-parser/lib/libloragw$SRC/.libs/libloragw.a -Wl,--whole-archive $SRC/lorawan-parser/lib/.libs/lib.a -Wl,--allow-multiple-definition -I$SRC/lorawan-parser/util/parser -I$SRC/lorawan-parser/lib/libloragw/inc -I$SRC/lorawan-parser/lib -I$SRC/lorawan-parser/lw -o $OUT/fuzzer ``` Example 2, simpleson build script ([PR](https://github.com/gregjesl/simpleson/pull/40)): ```sh mkdir fuzz-build cd fuzz-build cmake -DCMAKE_VERBOSE_MAKEFILE=ON ../ make V=1 || true $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/fuzzer.cpp -Wl,--whole-archive $SRC/simpleson/fuzz-build/libsimpleson.a -Wl,--allow-multiple-definition -I$SRC/simpleson/ -o $OUT/fuzzer ``` ## Step 2: Extract program analysis data using Fuzz Introspector The next step is to extract data about the program under analysis so that we can use it in a programmatic manner. We need this for two reasons. First, in order to select functions that are good candidates for fuzzing in the target project. Second, we need to be able to programmatically describe the program under analysis in a way that allows us to generate LLM prompts that describe the source code in a human-readable manner. To achieve this we build the target under analysis, using the build scripts from the previous step, in combination with Fuzz Introspector. Fuzz Introspector is an LLVM-based program analysis tool that extracts a lot of data useful for fuzz introspection and also program analysis in general. For example, for each function in the target project Fuzz Introspector provides data such as function signature, cross-reference information, source code, cyclomatic complexity, call tree and more. This is all useful for our LLM-based harness generation since the goal is to present the LLM with a prompt that gives a precise technical description of the target under analysis.The output of this step is an introspector report for each build script. The json snippet below is a sample subset of the data that Fuzz Introspector provides for the [json_validate](https://github.com/JiapengLi/lorawan-parser/blob/010a8f16074fb9a004b812e0289c5bc527e548ba/lib/json.c#L433) function in the [lorawan-parser](https://github.com/JiapengLi/lorawan-parser) project. The full data is available in this [Gist](https://gist.github.com/DavidKorczynski/f573d074d7745f351f76fcecd4a51930) and this type of data is provided to each function in a target codebase. We have stripped the sample for a number of keys in the json output to focus primarily on the data that we use in OSS-Fuzz-gen. Specifically, during OSS-Fuzz-gen harness synthesis we use of the data below: 1. Cyclomatic complexity data to highlight functions of interest. 2. Callsite to identify sample locations a given function is used. 3. Debug information to present to the prompt with program context about the target function. 4. Source code location to extract source. This is a target function that our approach successfully generated an OSS-Fuzz integration for. ```json { "Func name": "json_validate", "Functions filename": "/src/test-fuzz-build-2/./lib/json.c", "Function call depth": 7, "Cyclomatic complexity": 4, "Functions reached": 45, "Reached by functions": 0, "Accumulated cyclomatic complexity": 212, "ArgNames": [ "json" ], "callsites": { "skip_space": [ "./lib/json.c#json_validate:437", "./lib/json.c#json_validate:441" ], "parse_value": [ "./lib/json.c#json_validate:438" ] }, "source_line_begin": 434, "source_line_end": 446, "function_signature": "bool json_validate(const char *)", "debug_function_info": { "name": "json_validate", "is_public": 0, "is_private": 0, "func_signature_elems": { "return_type": [ "DW_TAG_base_type", "bool" ], "params": [ [ "DW_TAG_pointer_type", "DW_TAG_const_type", "char" ] ] }, "source": { "source_file": "/src/test-fuzz-build-2/lib/json.c", "source_line": "433" }, "return_type": "bool", "args": [ "const char *" ] } }, ``` ## Step 3: LLM-based harness synthesis The next step is to use LLMs to generate fuzzing harnesses. To do this, we have implemented several “harness-generators” that take as input the introspector reports and use this to create human-readable (LLM-readable) prompts which direct the LLM towards creating fuzz harnesses. The high-level idea is to generate textual descriptions of the target functions that are likely to produce a good harness by the LLM. To this end, for each function we consider a likely good candidate for fuzzing we have features for including in the prompts: - Description of the target function’s signature, with complete types, of the target program - Description of specifically which header files are available in the target project. - Examples of cross-references that use the target function to present sample code patterns involving the target function. - The actual source code of the target function. - Provide basic guidance to the LLM, such as the need for wrapping it in `LLVMFuzzerTestOneInput`. The output of this step is a set of fuzzing harnesses produced by LLMs. Specifically, we generate Y amounts of harnesses, where Y is the number of functions to target in the program under analysis. The harnesses that perform the best for each project are in general those that target high-level functions in the target project where the given function accepts fairly raw input data and does not rely on a complex initialization set up. This includes top level functions to, e.g. parse a given string, read a certain file and similar. The interesting parts of the LLM harness synthesi is that the LLM generates the correct initialization logic, provides the correct data types seeded with fuzz data and also provides correct cleaning up logic. To this end, we consider our approach to likely be useful for a lot of open source projects that are by nature fuzzing-friendly targets. The following GitHub [Gist](https://gist.github.com/DavidKorczynski/bc386b88eab43931338971cff4d4655b) contains three sample prompts generated by the prompt-generation logic, and also the corresponding harness as output by the LLM. These are all prompts that generated successful harnesses in that the harnesses exercised a meaningful portion of code in the target as well as based on human investigation were determined to be good harnesses. The following examples show fuzzing harnesses generated by our approach. Example 1, nanosvg harness ([PR](https://github.com/google/oss-fuzz/pull/11944)): ```c #include #include #include #include #include "nanosvgrast.h" #include "nanosvg.h" #include "stb_image_write.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Ensure null-terminated string char* data_copy = (char*)malloc(size + 1); memcpy(data_copy, data, size); data_copy[size] = '\0'; // Dummy arguments const char* dummy_filename = "dummy.svg"; float dummy_value = 1.0f; // Call the target function NSVGimage* result = nsvgParse(data_copy, dummy_filename, dummy_value); // Free memory if (result) { nsvgDelete(result); } free(data_copy); return 0; } ``` Example 2, tinyexpr harness ([PR](https://github.com/google/oss-fuzz/pull/11944)): ```c #include #include #include #include #include "minctest.h" #include "tinyexpr.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) { return 0; } char *input = (char*)malloc(size + 1); if (!input) { return 0; } memcpy(input, data, size); input[size] = '\0'; te_variable vars[] = {{ "x", 0 }}; int error; te_expr *result = te_compile(input, vars, 1, &error); free(input); te_free(result); return 0; } ``` Example 3, Simpleson harness ([PR](https://github.com/gregjesl/simpleson/pull/40)) ```c #include #include #include #include #include "json.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) { return 0; } // Copy input data to a null-terminated string char* input = new char[size + 1]; memcpy(input, data, size); input[size] = '\0'; try { json::jobject::parse(input); } catch (...) { // Catch all exceptions thrown by the target code } delete[] input; return 0; } ``` ## Step 4: Build and run each generated project The final step is to verify that the build scripts combined with the fuzzing harnesses can build actual executables, and for each successfully built executable to verify that the harness is meaningful. Specifically, from step (1) we have a set of build scripts that successfully build the project under analysis and from step (3) we have a set of harnesses, for each successful build script, that targets the project under analysis. We now combine these by running the build script and creating a command for building a given harness against the output static libraries. For each successfully built harness we run the given harness for a set period of time (40 seconds) in order to collect runtime logs, and for each successfully built harness we wrap the relevant artifacts in an OSS-Fuzz project as well as CluserFuzzLite project that can be run directly using the OSS-Fuzz infrastructure. The logs from runtime are then used for later inspection to determine if a harness was good, using factors such as edge coverage and how long the harness ran without running into any issues. At this stage, this is then verified by a human to determine if the integration is considered to the standard of an OSS-Fuzz/ClusterFuzzLite integration. # Results The goal of our efforts is to enable continuous fuzzing for arbitrary open source projects. We ran our approach on a benchmark of C/C++ projects and have captured a subset of the successful integrations in order to integrate them to OSS-Fuzz or upstream ClusterFuzzLite. During the initial runs of the fuzz harnesses three memory corruption issues were reported and also a couple of memory leakages. We manually debugged the issues to create fixes and report the issues upstream. The memory corruption issues were all heap-based read buffer overflows, where the heap-aspect comes from the harnesses allocating data on the heap. An interesting aspect for one of the discovered issues is that the project already had CodeQL running as part of its continuous integration workflow, however, CodeQL did not find the issue as reported by the automatically generated fuzzing set up. In addition to the issues reported we also collected code coverage for the projects based on the coverage achieved from a 40 second run. The below table contains references to the 15 projects that we upstream for continuous fuzzing. These project integrations were all fully automatically generated, with the caveat that for some of the pull requests we made follow-up commits that only addressed cosmetic changes, such as beautifying the code and making the build scripts more lean. | Target GitHub repository | Integration PR | Code coverage | Issues found and fixed | | ------------- | ------- | ------- | ------- | | https://github.com/memononen/nanosvg | [PR](https://github.com/google/oss-fuzz/pull/11944) | 41% | | | https://github.com/skeeto/pdjson | [PR](https://github.com/skeeto/pdjson/pull/33) | 78% | | | https://github.com/gregjesl/simpleson | [PR](https://github.com/gregjesl/simpleson/pull/40) | 35% | [PR](https://github.com/gregjesl/simpleson/pull/39) | | https://github.com/kgabis/parson | [PR](https://github.com/kgabis/parson/pull/214) | 42% | | | https://github.com/rafagafe/tiny-json | [PR](https://github.com/rafagafe/tiny-json/pull/18) | 85% | | | https://github.com/kosma/minmea | [PR](https://github.com/kosma/minmea/pull/79) | 37% | | | https://github.com/marcobambini/sqlite-createtable-parser | [PR](https://github.com/marcobambini/sqlite-createtable-parser/pull/5) | 14% | [PR](https://github.com/marcobambini/sqlite-createtable-parser/pull/6 ) | | https://github.com/benoitc/http-parser | [PR](https://github.com/benoitc/http-parser/pull/102) | 1.5% | [PR](https://github.com/benoitc/http-parser/pull/103 ) | | https://github.com/orangeduck/mpc | [PR](https://github.com/orangeduck/mpc/pull/169) | 49% | | | https://github.com/JiapengLi/lorawan-parser | [PR](https://github.com/JiapengLi/lorawan-parser/pull/17) | 11% | | | https://github.com/argtable/argtable3 | [PR](https://github.com/argtable/argtable3/pull/96) | 0.8% | | | https://github.com/h2o/picohttpparser | [PR](https://github.com/h2o/picohttpparser/pull/83) | 41% | | | https://github.com/ndevilla/iniparser | [PR](https://github.com/ndevilla/iniparser/pull/161) | 46% | | | https://github.com/codeplea/tinyexpr | [PR](https://github.com/codeplea/tinyexpr/pull/114) | 34% | | | https://github.com/vincenthz/libjson | [PR](https://github.com/vincenthz/libjson/pull/28) | 10% | | # Continuing the LLM harness synthesis loop The LLM-based synthesis generation does not stop once a target project has integrated into OSS-Fuzz. In fact, at this point, the existing capabilities of OSS-Fuzz-gen will come into play and continuously, on a weekly basis, experiment with new harnesses for the target project that takes into account the project’s current coverage status on OSS-Fuzz. In particular, OSS-Fuzz-gen will analyze which are the most promising new targets for a given OSS-Fuzz project and use our extensive LLM-based harness synthesis to evaluate, test and run new harnesses for a given project. To this end, the synthesis will continue and improve as a given project is continuously fuzzed. The [overall goal we’re working towards](https://security.googleblog.com/2023/08/ai-powered-fuzzing-breaking-bug-hunting.html) is to provide a fully automated solution to improve the security of projects with fuzzing, from the initial build integration, continuous fuzz harness generation, bug reporting and triage, and automatic patching. ## Contribute to the efforts The efforts described in this blog post are open sourced in [OSS-Fuzz-gen](https://github.com/google/oss-fuzz-gen/tree/main/experimental/c-cpp). We invite contributions, and would like to highlight specific efforts that will have a positive impact on our OSS-Fuzz from scratch generation: - Adding new build heuristics to enable compilation and fuzz introspector analysis of new projects. The key here is that any improvements in this context will open up analysis of new open source projects, and will ultimately be a positive sum outcome. - Adding additional prompt generators with a given example of success. The approach described in this blog runs each prompt generator without affecting the other prompt generation approaches, and because of this there is no need to worry of causing regressions in our existing prompt generators. As such, contributions are welcome for any new prompt generation approach that successfully creates harnesses for a project where the existing prompt generation approaches come short. We encourage the use of program analysis data from Fuzz Introspector in order to provide source code context. ================================================ FILE: infra/build/blog/content/posts/oss-fuzz-hello-world.md ================================================ +++ authors = ["OSS-Fuzz Maintainers"] title = "OSS-Fuzz blog" date = "2024-05-20" description = "Introduction to the OSS-Fuzz blog" tags = [ "fuzzing", "blogging", ] categories = [ "introduction", ] +++ Welcome to the new OSS-Fuzz blog! In this place we will publish feature updates, research efforts and all-things OSS-Fuzz related. ================================================ FILE: infra/build/blog/content/posts/oss-fuzz-integrations-via-agent-based-build-generation.md ================================================ +++ authors = ["OSS-Fuzz Maintainers"] title = "OSS-Fuzz integrations via agent-based build generation" date = "2025-05-25" description = "OSS-Fuzz integrations via agent-based build generation." categories = [ "Fuzzing", "Fuzzing synthesis", "LLM", "Automated fuzzing", "Automated build script generation", ] +++ # Introduction As part of the [OSS-Fuzz-Gen](https://github.com/google/oss-fuzz-gen) project we have been working on making it easier for maintainers to integrate projects into OSS-Fuzz. Since OSS-Fuzz requires a specific build script in a format that uses the OSS-Fuzz build environment, the problem of automating OSS-Fuzz integrations is largely split in two parts: (1) creating a script for building the target project and relevant fuzzing harnesses and (2) creating the actual fuzzing harness. As such, any solution looking to automate OSS-Fuzz integrations must be able to solve both of these problems for a diverse set of open source projects. The key goal for automating OSS-Fuzz integration is to support a full workflow that takes as input a project, e.g. GitHub repository, that is not integrated into OSS-Fuzz and outputs a generated OSS-Fuzz project with a working build script and one or more fuzzing harnesses. Furthermore, this workflow should be easily accessible and deployable, so open source maintainers can quickly leverage its features. The primary focus of OSS-Fuzz-Gen has so far been on generating fuzzing harnesses for existing OSS-Fuzz projects. In a previous [blog post](https://blog.oss-fuzz.com/posts/introducing-llm-based-harness-synthesis-for-unfuzzed-projects/) we documented an end-to-end approach for OSS-Fuzz integrations, however, there were several significant limitations to this approach that meant it did not sufficiently solve the problems described above. Specifically, the build script generation was based on a template-based strategy and this had limitations in terms of being able to create build scripts for a diverse set of projects. In this blog post, we present two improvements towards an end-to-end OSS-Fuzz integration workflow: 1) An agentic LLM-based approach for build script generation. 2) A CLI tool making this easy to access and run. # Overview and sample run The main goal of our approach is to automate the full end-to-end generation of an OSS-Fuzz project, by simply providing as input one or more Git repositories and then outputting a list of one or more OSS-Fuzz integrations. We expose these capabilities as a CLI in a Python package which makes it easy to install and run. To demonstrate the capabilities and give an intuition for the workflow, consider the below sample which generates an OSS-Fuzz project, including fuzzing harnesses, for [https://github.com/zserge/jsmn](https://github.com/zserge/jsmn). ```sh # Prepare virtual environment python3.11 -m virtualenv .venv . .venv/bin/activate # Clone OSS-Fuzz-gen git clone https://github.com/google/oss-fuzz-gen cd oss-fuzz-gen # Install OSS-Fuzz-gen python3 -m pip install . # Generate fuzzers for https://github.com/zserge/jsmn echo "https://github.com/zserge/jsmn" > input.txt # Run the generation # Setup Vertex AI access: https://github.com/google/oss-fuzz-gen/blob/main/USAGE.md#llm-access oss-fuzz-generator generate-full -i input.txt -m vertex_ai_gemini-2-flash-chat --agent -w work-1 # List the files of generated project $ ls final-oss-fuzz-projects/jsmn-agent/ build.sh Dockerfile empty-fuzzer.0.c empty-fuzzer.1.c project.yaml ``` The first step is to install the Python package, which is currently done by cloning OSS-Fuzz-Gen and then installing it using `python -m pip install .`. The installed package includes a CLI tool `oss-fuzz-generator` which exposes the OSS-Fuzz project generation capabilities. The only step following this is to set up your LLM environment and use the `generate-full` command. This command will generate a build script as well as fuzzing harnesses, and also merge all successful fuzzing harness into one single OSS-Fuzz project. More specifically, `oss-fuzz-generator generate-full` will perform three main steps for each of the repositories in the `input.txt` file: 1) Generate a build script that will compile fuzzers of a given project 2) If step 1 was successful, generate fuzzing harnesses for the project 3) Merge successful fuzzing harnesses into a single OSS-Fuzz project In this blog post, we will focus on step 1 above. # Agent-based build generation The agent-based approach to generating build scripts rely on three central components. First, an initial prompt that outlines the overall task and constraints for creating build scripts for a given arbitrary repository. Second, an agent that communicates with the LLM and executes arbitrary commands, provided by the LLM, within the environment where the build script will be run, allowing the LLM to explore the runtime environment. Third, a process for running generated build scripts as well as executing generated fuzzers to guide the output from the LLM. The overall algorithm for the agentic build generation workflow is as follows: ``` initial_prompt = prepare_initial_prompt(target_repository) prompt = prepare_initial_prompt(target_repository) llm_client = llm_start_chat() while should_keep_going(): llm_response = llm_client.chat(prompt) res = parse_llm_response(llm_response) if res.is_commands() { output = execute_commands(res.get_commands()); } else if (res.has_build_script()) { output = build_and_run_fuzzer(res.get_build_script(), res.get_fuzz_harness()); if (output.has_successful_build_script()) { // Success in harness generation return output } } else { // Failure happened in parsing LLM output exit() } // Prepare a next prompt for the LLM to chat. prompt = prepare_next_prompt(output); ``` The algorithm returns a successful build script if the `return output` line is reached. Specifically, this line is reached when the LLM has created a build script with an accompanying fuzz harness that can successfully build and link against the code of the target repository. There are four key functions in the build generation algorithm: - *parse_llm_response*: takes as input the raw text returned by the LLM and converts it into either (1) a list of commands to execute in the runtime environment where the fuzzers are build or (2) a build script with supplied fuzzing harness source code. The LLM is initially instructed in the prepare_initial_prompt to generate text that conforms to a given standard, such as by wrapping output in XML tags. - *execute_commands*: if the LLM returns a list of commands as determined by `parse_llm_response`, then this function executes these commands in the runtime environment in which the build script is to be run. The main point of this is that it enables the LLM to explore, understand and test the runtime environment. Results from running the commands are returned to the LLM and since the agent runs in a loop, the LLM can continuously issue commands, interpret the output and act accordingly. - *build_and_run_fuzzer*: if the LLM returns a build script and potentially a fuzzing harness (it may be empty) as determined by the `parse_llm_response`, then this function will build these artifacts in the runtime environment. The output of the build will be analysed, and, if a successful harness was built then the process is considered completed. In case the build was not successful, then the output of executing the build script is saved and will eventually be passed back to the LLM. - *prepare_next_prompt*: in the event that the iteration did not result in a successful build script, which can happen either if the LLM had returned a set of commands or the returned build script failed, the output of this will be used to construct a next prompt for the LLM. Specifically, we use the output from `execute_commands` and `build_and_run_fuzzer` as input to the next prompt. The prompt itself wraps around the output with a lightweight textual description. This prompt will then be used in the next agent iteration and passed to `llm_client.chat`. The output of the above algorithm is upon success a build script that can produce a successful fuzzing harness. The next step is then to use this build script as the foundation of an OSS-Fuzz project, and use OSS-Fuzz-Gen’s core capabilities of generating fuzzing harnesses for an OSS-Fuzz project. # Empirical evaluation To test our approach, we ran this on a set of GitHub repositories written in C/C++. In total we analysed 225 repositories which generated a total of 88 OSS-Fuzz integrations with valid build scripts. We furthermore ran the harness generation capabilities of OSS-Fuzz-Gen on these projects to confirm the validity of the build scripts. In this blog post we will focus on the results of the build generation and discuss bug-finding capabilities in a future blog post. We found that the approach has many strengths in that it overcame hurdles posed by many of the projects, and that it’s able to create build scripts our template-based approach is not. In this section we will go through a few samples of the build scripts to highlight the capabilities and limitations of the approach. ### Libcypher-parser Target: [https://github.com/cleishm/libcypher-parser](https://github.com/cleishm/libcypher-parser) The build script generated for this project is: ```sh # Build script for libcypher-parser with fuzzing harness # Install necessary dependencies apt-get update && apt-get install -y make autoconf automake libtool curl # Install autoconf 2.71 cd /tmp curl -O http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz tar -xzf autoconf-2.71.tar.gz cd autoconf-2.71 ./configure make make install # Install leg tool cd /tmp curl -L -O https://www.piumarta.com/software/peg/peg-0.1.18.tar.gz tar -xzf peg-0.1.18.tar.gz cd peg-0.1.18 make make install # Build libcypher-parser cd $SRC/libcypher-parser ./autogen.sh ./configure --enable-static --disable-shared make # Copy the static library to the output directory cp lib/src/.libs/libcypher-parser.a $OUT/ # Compile the fuzzing harness for fuzzer in $(find $SRC -maxdepth 1 -name 'empty-fuzzer.*'); do fuzzer_basename=$(basename $fuzzer .c) $CC $CFLAGS -I$SRC/libcypher-parser/lib/src $fuzzer -o $OUT/${fuzzer_basename} \ -L$OUT -lcypher-parser -Wl,--whole-archive $LIB_FUZZING_ENGINE -Wl,--no-whole-archive done ``` Overall, this is a fairly complex build in that it installs a version of autoconf different to what is already in the runtime environment and also a tool “peg”. In order to identify that the “leg”/”peg” tool is needed, the agent had to interpret the output of the building the project without this tool, as doing so leads to the following issue when configuring libcypher-parser: ```sh ... checking for leg... no configure: error: leg is required: please install http://piumarta.com/software/peg/ ERROR:__main__:Building fuzzers failed. ``` ### Yams Target: [https://github.com/jpsim/Yams](https://github.com/jpsim/Yams) The build script produced in this case is as follows: ```sh #!/bin/bash # Set up build environment cd $SRC/Yams/Sources/CYaml mkdir -p build cd build cmake .. -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX make # Compile the fuzzing harness $CC $CFLAGS -I$SRC/Yams/Sources/CYaml/include -I$SRC $SRC/empty-fuzzer.c -o $OUT/empty-fuzzer -L. -Wl,--whole-archive libCYaml.a -Wl,--no-whole-archive $LIB_FUZZING_ENGINE ``` The build script is a simple cmake build script, but it passes arguments to the cmake command to ensure the target builds with the commands as specified by the OSS-Fuzz runtime environment. Interestingly, the building and linking of the fuzz harness in this context is not done in a loop. This works in principle, in that the project is able to build and link a fuzzing harness, but is limited in that it is unable to build and link and arbitrary number of fuzzing harnesses. ### Moment Target: [https://github.com/kmussel/Moment](https://github.com/kmussel/Moment) This is a library that has not been active for 10 years, so a particular challenge of this project is building a potentially old project. The build script generated is the following: ```sh #!/bin/bash # Install necessary tools apt-get update && apt-get install -y bison flex # Set source and output directories SRC_DIR="$SRC/Moment" OUT_DIR="$OUT" # Preprocess parseIt.ym to remove the Foundation import sed '/#import /d' $SRC_DIR/parseIt.ym > $SRC_DIR/parseIt_preprocessed.ym # Use bison to generate parseIt.c and y.tab.h bison -d -o $SRC_DIR/parseIt.c $SRC_DIR/parseIt_preprocessed.ym # Rename the generated header to y.tab.h mv $SRC_DIR/parseIt.h $SRC_DIR/y.tab.h # Use flex to generate tokeIt.c flex -o $SRC_DIR/tokeIt.c $SRC_DIR/tokeIt.l # Compile the source files into object files $CC $CFLAGS -c $SRC_DIR/TimeParser.c -o TimeParser.o $CC $CFLAGS -c $SRC_DIR/parseIt.c -o parseIt.o $CC $CFLAGS -I$SRC_DIR -c $SRC_DIR/tokeIt.c -o tokeIt.o # Archive the object files into a static library llvm-ar rcs libmoment.a TimeParser.o parseIt.o tokeIt.o # Compile the fuzzing harness and link with the static library $CC $CFLAGS -I$SRC_DIR $SRC/empty-fuzzer.c -o $OUT_DIR/empty-fuzzer -L. libmoment.a $LIB_FUZZING_ENGINE ``` Similar to libcypher-parser above, the impressive parts of this build script is the complexity of it, and the ability to download and install custom packages, and using the tools of these packages as part of the build script process. The build script adjusts a file in the target project using `sed` and runs several tools, bison and flex, to generate code needed for the compilation. Furthermore, the project itself does not have any build system files, e.g. `Makefile` and consequently the build agent reverts to compiling the source files directly. # Limitations and future work During our empirical evaluation we observed several limitations and possible improvements. ### Build scripts that succeed but avoid target source code We observed several cases where the agent produces build scripts that simply avoid building the target source code and just end up building an empty fuzzing harness. The problem is that the approach currently does not do post-processing analysis on the generated harness in terms of validating that the target source code is part of the resulting binary. The problem in this case is that when the process moves on to harness generation, then the build script is not able to support the workflow because no building of the target source code is involved. Although this was a rare occurrence, a required solution is to have more rigorous post processing to validate the completeness of the build script generated, or the ability to adjust later in the end-to-end workflow. ### Build scripts that can only build a single fuzzing harness The approach instructs the LLMs to generate build scripts that can build an arbitrary number of fuzzing harnesses. This is to make it possible to use the build script for building and linking any number of fuzzing harnesses that the harness-generation part of OSS-Fuzz-gen produces. It is likely OSS-Fuzz-gen will end up producing more than one valuable fuzzing harness, and the build script should be able to build them all at the same time. We observed that this constraint is not always accepted and some build scripts end up with the capability of only building a single fuzzing harness, e.g. due to lack of a loop in the build instructions. The problem in this case is that the user of the tool will have to adjust the build script such that it can build an arbitrary number of fuzzing harnesses, assuming that two or more fuzzing harnesses are needed for the final OSS-Fuzz integration. ### Integrating into target codebase’s build configurations The current approach often yields build scripts that explicitly link fuzzing harnesses using CXX or CC environment variables to link against static libraries built earlier in the build script. As such, the build scripts are composed of a set of commands as well as a fuzzing harness source code. Another approach would be to integrate the building of the fuzzers into the build system of the target repository, such as by extending Makefiles and alike. Although this won’t have any practical difference as such, it may make the approach more friendly towards developers. ### Diagnosis and conclusions on failed generation In the case where the build script generation failed, there is at the moment no real explanation as to why it failed. An extension to the workflow is to have another agent or similar, that analyse the reason why the build failed. For example, it is valuable to know if the reason for failing is a hard reason such as the code cannot be compiled in the relevant build runtime, or whether the LLM simply wasn’t capable of finding a proper solution. In case the reason is a hard reason, that is in a sense a positive conclusion since it can explicitly tell the user that the target project is not compatible with OSS-Fuzz (such as, if it’s a Windows-only project). # Conclusion In this blog post we have introduced a new capability of [OSS-Fuzz-Gen](https://github.com/google/oss-fuzz-gen) for producing OSS-Fuzz project integrations from scratch via an agent-based approach to build script generation. This is available through a CLI tool and only a single command is required for generating an OSS-Fuzz project. We ran the approach against a set of 225 projects which resulted in 88 OSS-Fuzz build scripts, and to highlight the capabilities we went through a set of these as well as identified limitations and future work. The tooling is available on GitHub at [https://github.com/google/oss-fuzz-gen/tree/main/experimental/end_to_end](https://github.com/google/oss-fuzz-gen/tree/main/experimental/end_to_end) and we encourage users to try and run the tooling on their projects of interest. We are always happy to hear about projects where the build generation is not working and welcome users to submit this information as GitHub issues in the above repository. ================================================ FILE: infra/build/blog/hugo.toml ================================================ seURL = '' languageCode = 'en-us' title = 'OSS-Fuzz blog' theme = 'hugo-coder' languagecode = "en" defaultcontentlanguage = "en" paginate = 20 [markup.highlight] style = "github-dark" [params] info = "Fuzzing Open Source Software at Scale" description = "OSS-Fuzz fuzzing blog" keywords = "fuzzing, vulnerability research, open source, security" avatarurl = "images/oss-fuzz-logo.png" faviconSVG = "/img/favicon.svg" favicon_32 = "/img/favicon-32x32.png" favicon_16 = "/img/favicon-16x16.png" since = 2024 enableTwemoji = true colorScheme = "auto" hidecolorschemetoggle = false [taxonomies] category = "categories" series = "series" tag = "tags" author = "authors" # Social links [[params.social]] name = "Github" icon = "fa-brands fa-github fa-2x" weight = 1 url = "https://github.com/google/oss-fuzz" # Menu links [[menu.main]] name = "Blog" weight = 1 url = "posts/" [[menu.main]] name = "About" weight = 2 url = "about/" ================================================ FILE: infra/build/build_status/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner RUN mkdir -p /opt/oss-fuzz/infra/build_status COPY infra/build/functions/* /opt/oss-fuzz/infra/build_status/ COPY infra/build/build_status/* /opt/oss-fuzz/infra/build_status/ RUN pip3 install -r /opt/oss-fuzz/infra/build_status/requirements.txt ENTRYPOINT [ "python3", "/opt/oss-fuzz/infra/build_status/update_build_status.py" ] ================================================ FILE: infra/build/build_status/cloudbuild.yaml ================================================ steps: - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/build-status - '-f' - infra/build/build_status/Dockerfile - . - name: 'gcr.io/oss-fuzz-base/build-status' args: [] timeout: 14400s options: logging: CLOUD_LOGGING_ONLY timeout: 14400s ================================================ FILE: infra/build/build_status/fuzz_introspector_page_gen.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Logic to create Fuzz Introspector overview page.""" import json from urllib.request import urlopen from bs4 import BeautifulSoup TABLE_HEAD = """""" TABLE_END = """
Project Report Fuzz target count Code statically reached Code covered at runtime
""" FUZZ_INTROSPECTOR_HTML_TOP = """
Fuzzer introspection of OSS-Fuzz projects
Fuzz Introspector documentation:https://fuzz-introspector.readthedocs.io/en/latest/
Fuzz Introspector repository:https://github.com/ossf/fuzz-introspector
""" FUZZ_INTROSPECTOR_HTML_BOTTOM = """
""" def refine_percentage_string(percentage_string): """Shortens a srting to 4 characters and prepends zeros if necessary. We need to prepend the zero to make sorting in the final table accurrate. """ percentage_string = percentage_string.replace("%", "") if len(percentage_string.split(".")[0]) == 1: percentage_string = "0" + percentage_string if len(percentage_string) > 5: percentage_string = percentage_string[:5] # Check if the percentage is withing range of [0.0 : 100.0] # Some old reports from 2022 have deprecated data, which we do not want to # display. float_val = float(percentage_string) if float_val < 0.0 or float_val > 100.0: # Raise exception to make the code display '-' elements. raise Exception('Out of range numbers') return percentage_string + "%" def fetch_fuzz_introspector_summary(report_url): """Given a URL to an introspector report, returns a dictionary with data from the report. This includes, fuzzer count, reachability and code coverage. """ # Extract json summary file. summary_url = report_url.replace('fuzz_report.html', 'summary.json') response = urlopen(summary_url) json_data = json.loads(response.read()) # 1) Extract fuzzer count. This corresponds to all but two elements at the # top level of the dictionary. fuzzer_count = len(json_data) - 2 # 2) Extract reachability count. reached_stats = "0.0%" if 'MergedProjectProfile' in json_data: if 'stats' in json_data['MergedProjectProfile']: merged_profile = json_data['MergedProjectProfile'] reached_stats = merged_profile['stats']['reached-complexity-percentage'] reached_stats = refine_percentage_string(str(reached_stats)) # Extract code coverage stats. # Momentarily, we will get this from the HTML page because it's not yet # in the summary.json. This will change in the near future, but in the # spirit of time we keep it like this for now. fuzz_report_html = urlopen(report_url).read() soup = BeautifulSoup(fuzz_report_html, 'html.parser') target_divs = soup.findAll('text', {'class': 'percentage'}) # The code coverage is the third instance of this text class. raw_code_coverage = target_divs[2].string.strip() code_coverage = refine_percentage_string(raw_code_coverage) return { 'fuzzer_count': fuzzer_count, 'project_complexity_reached': reached_stats, 'code_coverage': code_coverage } def get_fuzzer_introspector_project_summary(report_url): """Return dictionary containing summary of fuzz introspector project.""" try: results_dict = fetch_fuzz_introspector_summary(report_url) except Exception: # pylint: disable=broad-except results_dict = { 'fuzzer_count': '-', 'project_complexity_reached': '-', 'code_coverage': '-' } return results_dict def get_fuzz_introspector_row(project, report_url): """Creates a single row in the Fuzz Introspector HTML table.""" project_summary = get_fuzzer_introspector_project_summary(report_url) return ("" f"{project}" f"{project_summary['fuzzer_count']}" f"{project_summary['project_complexity_reached']}" f"{project_summary['code_coverage']}" "\n") def create_introspector_overview_table(fuzz_introspector_index): """Creates a HTML table with Fuzz Introspector summary for each project.""" all_rows = "" for project_name in fuzz_introspector_index: report_url = fuzz_introspector_index[project_name] all_rows += get_fuzz_introspector_row(project_name, report_url) return TABLE_HEAD + all_rows + TABLE_END def get_fuzz_introspector_html_page(fuzz_introspector_index): """Creates a HTML page as a string displaying Fuzz Introspector overview.""" html_table = create_introspector_overview_table(fuzz_introspector_index) return (FUZZ_INTROSPECTOR_HTML_TOP + html_table + FUZZ_INTROSPECTOR_HTML_BOTTOM) ================================================ FILE: infra/build/build_status/update_build_status.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud function to request builds.""" import concurrent.futures import logging import json import sys import os import google.auth from googleapiclient.discovery import build import googleapiclient.errors from google.cloud import ndb from google.cloud import storage import yaml import build_and_run_coverage import build_lib import build_project import datastore_entities import fuzz_introspector_page_gen BADGE_DIR = 'badge_images' BADGE_IMAGE_TYPES = {'svg': 'image/svg+xml', 'png': 'image/png'} DESTINATION_BADGE_DIR = 'badges' MAX_BUILD_LOGS = 7 STATUS_BUCKET = 'oss-fuzz-build-logs' INTROSPECTOR_BUCKET = 'oss-fuzz-introspector' INTROSPECTOR_BUCKET_URL = 'https://storage.googleapis.com/oss-fuzz-introspector' INTROSPECTOR_DOC_URL = 'https://fuzz-introspector.readthedocs.io/en/latest/' INTROSPECTOR_INDEX_JSON = 'build_status.json' INTROSPECTOR_INDEX_HTML = 'index.html' FUZZING_STATUS_FILENAME = 'status.json' COVERAGE_STATUS_FILENAME = 'status-coverage.json' INTROSPECTOR_STATUS_FILENAME = 'status-introspector.json' # pylint: disable=invalid-name _client = None logging.basicConfig(level=logging.INFO) # pylint: disable=global-statement def get_storage_client(): """Return storage client.""" global _client if not _client: _client = storage.Client() return _client def is_build_successful(build_obj): """Check build success.""" return build_obj['status'] == 'SUCCESS' def upload_status(data, status_filename): """Upload json file to cloud storage.""" bucket = get_storage_client().get_bucket(STATUS_BUCKET) blob = bucket.blob(status_filename) blob.cache_control = 'no-cache' blob.upload_from_string(json.dumps(data), content_type='application/json') def sort_projects(projects): """Sort projects in order Failures, Successes, Not yet built.""" def key_func(project): if not project['history']: return 2 # Order projects without history last. if project['history'][0]['success']: # Successful builds come second. return 1 # Build failures come first. return 0 projects.sort(key=key_func) def update_last_successful_build(project, build_tag): """Update last successful build.""" last_successful_build = ndb.Key(datastore_entities.LastSuccessfulBuild, project['name'] + '-' + build_tag).get() if not last_successful_build and 'last_successful_build' not in project: return if 'last_successful_build' not in project: project['last_successful_build'] = { 'build_id': last_successful_build.build_id, 'finish_time': last_successful_build.finish_time } else: if last_successful_build: last_successful_build.build_id = project['last_successful_build'][ 'build_id'] last_successful_build.finish_time = project['last_successful_build'][ 'finish_time'] else: last_successful_build = datastore_entities.LastSuccessfulBuild( id=project['name'] + '-' + build_tag, project=project['name'], build_id=project['last_successful_build']['build_id'], finish_time=project['last_successful_build']['finish_time']) last_successful_build.put() class BuildGetter: # pylint: disable=too-few-public-methods """Class for getting builds. This is a hack because builds were previously run in the global region while builds going forward have been run in us-central1. This class will try looking for the build from the global region, until that fails, at which point it will look for builds in the us-central1 region.""" def __init__(self): self._credentials, self._image_project = google.auth.default() self._global_cloudbuild = build('cloudbuild', 'v1', credentials=self._credentials, cache_discovery=False) self._central_cloudbuild = build( 'cloudbuild', 'v1', credentials=self._credentials, cache_discovery=False, client_options=build_lib.REGIONAL_CLIENT_OPTIONS) self._cloudbuilds = [self._global_cloudbuild, self._central_cloudbuild] self._swapped = False def _swap_cloudbuild_order_once(self): """Swap the region order after one failure since the global build region was first used before being switched to us-central1.""" if self._swapped: return new_last, new_first = self._cloudbuilds self._cloudbuilds = [new_first, new_last] self._swapped = True def get_build(self, build_id): """Get the build from global or us-central1 region.""" for cloudbuild in self._cloudbuilds[:]: try: return cloudbuild.projects().builds().get(projectId=self._image_project, id=build_id).execute() except googleapiclient.errors.HttpError: self._swap_cloudbuild_order_once() continue assert None # pylint: disable=no-member def get_build_history(build_ids): """Returns build object for the last finished build of project.""" build_getter = BuildGetter() history = [] last_successful_build = None for build_id in reversed(build_ids): project_build = build_getter.get_build(build_id) if project_build['status'] not in ('SUCCESS', 'FAILURE', 'TIMEOUT'): continue if (not last_successful_build and is_build_successful(project_build)): last_successful_build = { 'build_id': build_id, 'finish_time': project_build['finishTime'], } if not upload_log(build_id): log_name = f'log-{build_id}' logging.error('Missing build log file %s', log_name) continue history.append({ 'build_id': build_id, 'finish_time': project_build['finishTime'], 'success': is_build_successful(project_build) }) if len(history) == MAX_BUILD_LOGS: break project = {'history': history} if last_successful_build: project['last_successful_build'] = last_successful_build return project def _get_main_repo(project_name): """Get the main repo for a project.""" project = datastore_entities.Project.query( datastore_entities.Project.name == project_name).get() if not project: return None project_yaml = yaml.safe_load(project.project_yaml_contents) return project_yaml.get('main_repo') # pylint: disable=too-many-locals def update_build_status(build_tag, status_filename): """Update build statuses.""" projects = [] def process_project(project_build): """Process a project.""" # We need a new context for every thread. with ndb.Client().context(): project = get_build_history(project_build.build_ids) project['name'] = project_build.project project['main_repo'] = _get_main_repo(project_build.project) print('Processing project', project['name']) return project with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor: futures = [] for project_build in datastore_entities.BuildsHistory.query( datastore_entities.BuildsHistory.build_tag == build_tag).order( 'project'): futures.append(executor.submit(process_project, project_build)) for future in concurrent.futures.as_completed(futures): project = future.result() update_last_successful_build(project, build_tag) projects.append(project) sort_projects(projects) data = {'projects': projects} upload_status(data, status_filename) def update_build_badges(project, last_build_successful, last_coverage_build_successful): """Upload badges of given project.""" badge = 'building' # last_coverage_build_successful is False if there was an unsuccessful build # and None if the target does not support coverage (e.g. Python or Java # targets). if last_coverage_build_successful is False: badge = 'coverage_failing' if not last_build_successful: badge = 'failing' print(f'[badge] {project}: {badge}') for extension in BADGE_IMAGE_TYPES: badge_name = f'{badge}.{extension}' # Copy blob from badge_images/badge_name to badges/project/ blob_name = f'{BADGE_DIR}/{badge_name}' destination_blob_name = f'{DESTINATION_BADGE_DIR}/{project}.{extension}' status_bucket = get_storage_client().get_bucket(STATUS_BUCKET) badge_blob = status_bucket.blob(blob_name) status_bucket.copy_blob(badge_blob, status_bucket, new_name=destination_blob_name) def upload_log(build_id): """Upload log file to GCS.""" status_bucket = get_storage_client().get_bucket(STATUS_BUCKET) gcb_bucket = get_storage_client().get_bucket(build_project.GCB_LOGS_BUCKET) log_name = f'log-{build_id}.txt' log = gcb_bucket.blob(log_name) dest_log = status_bucket.blob(log_name) if not log.exists(): print('Failed to find build log', log_name, file=sys.stderr) return False if dest_log.exists(): return True gcb_bucket.copy_blob(log, status_bucket) return True def load_status_from_gcs(filename): """Load statuses from bucket.""" status_bucket = get_storage_client().get_bucket(STATUS_BUCKET) status = json.loads(status_bucket.blob(filename).download_as_string()) result = {} for project in status['projects']: if project['history']: result[project['name']] = project['history'][0]['success'] return result def update_badges(): """Update badges.""" project_build_statuses = load_status_from_gcs(FUZZING_STATUS_FILENAME) coverage_build_statuses = load_status_from_gcs(COVERAGE_STATUS_FILENAME) with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor: futures = [] for project in datastore_entities.Project.query(): if project.name not in project_build_statuses: continue # Certain projects (e.g. JVM and Python) do not have any coverage # builds, but should still receive a badge. coverage_build_status = None if project.name in coverage_build_statuses: coverage_build_status = coverage_build_statuses[project.name] futures.append( executor.submit(update_build_badges, project.name, project_build_statuses[project.name], coverage_build_status)) concurrent.futures.wait(futures) def upload_index(json_index, html_string): """Upload json and html file to introspector bucket.""" introspector_bucket = get_storage_client().get_bucket(INTROSPECTOR_BUCKET) json_blob = introspector_bucket.blob(INTROSPECTOR_INDEX_JSON) html_blob = introspector_bucket.blob(INTROSPECTOR_INDEX_HTML) json_blob.cache_control = 'no-cache' json_blob.upload_from_string(json.dumps(json_index), content_type='application/json') html_blob.cache_control = 'no-cache' html_blob.upload_from_string(html_string, content_type='text/html') def generate_introspector_index(): """Generate index.html for successful Fuzz Introspector projects""" status_bucket = get_storage_client().get_bucket(STATUS_BUCKET) status = json.loads( status_bucket.blob(INTROSPECTOR_STATUS_FILENAME).download_as_string()) introspector_bucket = get_storage_client().get_bucket(INTROSPECTOR_BUCKET) index_blob = introspector_bucket.blob(INTROSPECTOR_INDEX_JSON) if index_blob.exists(): introspector_index = json.loads(index_blob.download_as_string()) else: introspector_index = {} for project in status['projects']: if project['history'] and project['history'][0]['success']: project_name = project['name'] build_date = project['history'][0]['finish_time'].split('T')[0].replace( '-', '') introspector_index[project_name] = os.path.join(INTROSPECTOR_BUCKET_URL, project_name, 'inspector-report', build_date, 'fuzz_report.html') html_string = fuzz_introspector_page_gen.get_fuzz_introspector_html_page( introspector_index) upload_index(introspector_index, html_string) def main(): """Entry point for cloudbuild""" with ndb.Client().context(): configs = ((build_project.FUZZING_BUILD_TYPE, FUZZING_STATUS_FILENAME), (build_and_run_coverage.COVERAGE_BUILD_TYPE, COVERAGE_STATUS_FILENAME), (build_and_run_coverage.INTROSPECTOR_BUILD_TYPE, INTROSPECTOR_STATUS_FILENAME)) for tag, filename in configs: update_build_status(tag, filename) update_badges() generate_introspector_index() if __name__ == '__main__': main() ================================================ FILE: infra/build/build_status/update_build_status_test.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for Cloud Function update builds status.""" import os import sys import unittest from unittest import mock from google.cloud import ndb sys.path.append(os.path.dirname(__file__)) # pylint: disable=wrong-import-position import datastore_entities import test_utils import update_build_status # pylint: disable=no-member # pylint: disable=too-few-public-methods class MockGetBuild: """Spoofing get_builds function.""" def __init__(self, builds): self.builds = builds def get_build(self, build_id): """Mimic build object retrieval.""" for build in self.builds: if build['build_id'] == build_id: return build return None @mock.patch('google.auth.default', return_value=['temp', 'temp']) @mock.patch('update_build_status.build', return_value='cloudbuild') @mock.patch('update_build_status.upload_log') class TestGetBuildHistory(unittest.TestCase): """Unit tests for get_build_history.""" def test_get_build_history(self, mock_upload_log, mock_cloud_build, mock_google_auth): """Test for get_build_steps.""" del mock_cloud_build, mock_google_auth mock_upload_log.return_value = True builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS'}] mock_get_build = MockGetBuild(builds) update_build_status.BuildGetter.get_build = mock_get_build.get_build expected_projects = { 'history': [{ 'build_id': '1', 'finish_time': 'test_time', 'success': True }], 'last_successful_build': { 'build_id': '1', 'finish_time': 'test_time' } } self.assertDictEqual(update_build_status.get_build_history(['1']), expected_projects) def test_get_build_history_no_last_success(self, mock_upload_log, mock_cloud_build, mock_google_auth): """Test when there is no last successful build.""" del mock_cloud_build, mock_google_auth builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'FAILURE'}] mock_get_build = MockGetBuild(builds) update_build_status.BuildGetter.get_build = mock_get_build.get_build mock_upload_log.return_value = True expected_projects = { 'history': [{ 'build_id': '1', 'finish_time': 'test_time', 'success': False }] } self.assertDictEqual(update_build_status.get_build_history(['1']), expected_projects) class TestSortProjects(unittest.TestCase): """Unit tests for testing sorting functionality.""" def test_sort_projects(self): """Test sorting functionality.""" projects = [{ 'name': '1', 'history': [] }, { 'name': '2', 'history': [{ 'success': True }] }, { 'name': '3', 'history': [{ 'success': False }] }] expected_order = ['3', '2', '1'] update_build_status.sort_projects(projects) self.assertEqual(expected_order, [project['name'] for project in projects]) class TestUpdateLastSuccessfulBuild(unittest.TestCase): """Unit tests for updating last successful build.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() def test_update_last_successful_build_new(self): """When last successful build isn't available in datastore.""" with ndb.Client().context(): project = { 'name': 'test-project', 'last_successful_build': { 'build_id': '1', 'finish_time': 'test_time' } } update_build_status.update_last_successful_build(project, 'fuzzing') expected_build_id = '1' self.assertEqual( expected_build_id, ndb.Key(datastore_entities.LastSuccessfulBuild, 'test-project-fuzzing').get().build_id) def test_update_last_successful_build_datastore(self): """When last successful build is only available in datastore.""" with ndb.Client().context(): project = {'name': 'test-project'} datastore_entities.LastSuccessfulBuild(id='test-project-fuzzing', build_tag='fuzzing', project='test-project', build_id='1', finish_time='test_time').put() update_build_status.update_last_successful_build(project, 'fuzzing') expected_project = { 'name': 'test-project', 'last_successful_build': { 'build_id': '1', 'finish_time': 'test_time' } } self.assertDictEqual(project, expected_project) def test_update_last_successful_build(self): """When last successful build is available at both places.""" with ndb.Client().context(): project = { 'name': 'test-project', 'last_successful_build': { 'build_id': '2', 'finish_time': 'test_time' } } datastore_entities.LastSuccessfulBuild(id='test-project-fuzzing', build_tag='fuzzing', project='test-project', build_id='1', finish_time='test_time').put() update_build_status.update_last_successful_build(project, 'fuzzing') expected_build_id = '2' self.assertEqual( expected_build_id, ndb.Key(datastore_entities.LastSuccessfulBuild, 'test-project-fuzzing').get().build_id) @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) class TestUpdateBuildStatus(unittest.TestCase): """Unit test for update build status.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() # pylint: disable=no-self-use @mock.patch('google.auth.default', return_value=['temp', 'temp']) @mock.patch('update_build_status.build', return_value='cloudbuild') @mock.patch('update_build_status.upload_log') def test_update_build_status(self, mock_upload_log, mock_cloud_build, mock_google_auth): """Testing update build status as a whole.""" del self, mock_cloud_build, mock_google_auth update_build_status.upload_status = mock.MagicMock() mock_upload_log.return_value = True status_filename = 'status.json' with ndb.Client().context(): datastore_entities.Project( name='test-project-1', project_yaml_contents=( 'main_repo: "https://github/com/main/repo1"')).put() datastore_entities.Project( name='test-project-2', project_yaml_contents=( 'main_repo: "https://github/com/main/repo2"')).put() datastore_entities.Project( name='test-project-3', project_yaml_contents=( 'main_repo: "https://github/com/main/repo3"')).put() datastore_entities.BuildsHistory(id='test-project-1-fuzzing', build_tag='fuzzing', project='test-project-1', build_ids=['1']).put() datastore_entities.BuildsHistory(id='test-project-2-fuzzing', build_tag='fuzzing', project='test-project-2', build_ids=['2']).put() datastore_entities.BuildsHistory(id='test-project-3-fuzzing', build_tag='fuzzing', project='test-project-3', build_ids=['3']).put() builds = [{ 'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS' }, { 'build_id': '2', 'finishTime': 'test_time', 'status': 'FAILURE' }, { 'build_id': '3', 'status': 'WORKING' }] mock_get_build = MockGetBuild(builds) update_build_status.BuildGetter.get_build = mock_get_build.get_build expected_data = { 'projects': [{ 'history': [{ 'build_id': '2', 'finish_time': 'test_time', 'success': False }], 'name': 'test-project-2', 'main_repo': 'https://github/com/main/repo2', }, { 'history': [{ 'build_id': '1', 'finish_time': 'test_time', 'success': True }], 'last_successful_build': { 'build_id': '1', 'finish_time': 'test_time' }, 'name': 'test-project-1', 'main_repo': 'https://github/com/main/repo1', }, { 'history': [], 'name': 'test-project-3', 'main_repo': 'https://github/com/main/repo3', }] } update_build_status.update_build_status('fuzzing', 'status.json') update_build_status.upload_status.assert_called_with( expected_data, status_filename) @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/__init__.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ================================================ FILE: infra/build/functions/base_images.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud function to build base images on Google Cloud Builder. This script can be run locally for testing or deployment purposes. By default, it performs a real build. To perform a dry run, use the '--dry-run' flag. To prevent images from being pushed to the registry, use '--no-push'. Example: python3 infra/build/functions/base_images.py --dry-run """ from collections.abc import Sequence import logging import os import sys import google.auth import build_lib BASE_PROJECT = 'oss-fuzz-base' IMAGE_NAME_PREFIX = f'gcr.io/{BASE_PROJECT}/' MAJOR_TAG = 'v1' TIMEOUT = '21600' # 6 hours # Defines the Ubuntu versions supported by the build infrastructure. # 'legacy' refers to the unversioned, default image. # Note: This list indicates build capability, not production readiness. # A version is only ready for general use after being fully enabled in # ClusterFuzz. SUPPORTED_VERSIONS = ('legacy', 'ubuntu-20-04', 'ubuntu-24-04') # Define which of the supported versions is considered the default. # This version will receive the ':v1' tag. DEFAULT_VERSION = 'legacy' # Defines the dependency graph for base images. IMAGE_DEPENDENCIES = { 'base-clang': ['base-image'], 'base-clang-full': ['base-clang'], 'base-builder': ['base-clang'], 'base-builder-go': ['base-builder'], 'base-builder-javascript': ['base-builder'], 'base-builder-jvm': ['base-builder'], 'base-builder-python': ['base-builder'], 'base-builder-ruby': ['base-builder'], 'base-builder-rust': ['base-builder'], 'base-builder-swift': ['base-builder'], 'base-runner': ['base-image', 'base-builder', 'base-builder-ruby'], 'base-runner-debug': ['base-runner'], 'indexer': ['base-clang-full'], } class ImageConfig: """Configuration for a specific base image version.""" name: str version: str path: str dockerfile_path: str build_args: Sequence[str] | None def __init__(self, name: str, version: str, path: str | None = None, build_args: Sequence[str] | None = None): self.name = name self.version = version self.path = path if path else self._get_default_path() self.dockerfile_path = self._resolve_dockerfile() self.build_args = build_args def _get_default_path(self) -> str: """Returns the default path to the image's build directory.""" if self.name == 'indexer': return os.path.join('infra', 'indexer') return os.path.join('infra', 'base-images', self.name) def _resolve_dockerfile(self) -> str: """Resolves the path to the Dockerfile. Prefers a version-specific one if it exists, otherwise falling back to the legacy Dockerfile. """ if self.version != 'legacy': versioned_dockerfile = os.path.join(self.path, f'{self.version}.Dockerfile') logging.info('Using versioned Dockerfile: %s', versioned_dockerfile) return versioned_dockerfile legacy_dockerfile = os.path.join(self.path, 'Dockerfile') logging.info('Using legacy Dockerfile: %s', legacy_dockerfile) return legacy_dockerfile @property def final_tag(self) -> str: """ Returns the final tag for the image, using ':v1' for the default version and the version name for others. """ return MAJOR_TAG if self.version == DEFAULT_VERSION else self.version @property def full_image_name_with_tag(self) -> str: """Returns the full GCR image name with the final tag.""" return f'{IMAGE_NAME_PREFIX}{self.name}:{self.final_tag}' # Definitions of the base images to be built. BASE_IMAGE_DEFS = [ { 'name': 'base-image' }, { 'name': 'base-clang' }, { 'name': 'base-clang-full', 'path': 'infra/base-images/base-clang', 'build_args': ('FULL_LLVM_BUILD=1',) }, { 'name': 'indexer' }, { 'name': 'base-builder' }, { 'name': 'base-builder-go' }, { 'name': 'base-builder-javascript' }, { 'name': 'base-builder-jvm' }, { 'name': 'base-builder-python' }, { 'name': 'base-builder-ruby' }, { 'name': 'base-builder-rust' }, { 'name': 'base-builder-swift' }, { 'name': 'base-runner' }, { 'name': 'base-runner-debug' }, ] def get_base_image_steps(images: Sequence[ImageConfig]) -> list[dict]: """Returns build steps for a given list of image configurations.""" steps = [build_lib.get_git_clone_step()] build_ids = {} for image_config in images: # The final tag is ':v1' for the default version, or the version name # (e.g., ':ubuntu-24-04') for others. tags = [image_config.full_image_name_with_tag] # The 'legacy' build is also tagged as 'latest' for use by subsequent # build steps within the same pipeline. if image_config.version == 'legacy': tags.append(f'{IMAGE_NAME_PREFIX}{image_config.name}:latest') dockerfile_path = os.path.join('oss-fuzz', image_config.dockerfile_path) step = build_lib.get_docker_build_step(tags, image_config.path, dockerfile_path=dockerfile_path, build_args=image_config.build_args) # Check for dependencies and add 'waitFor' if necessary. dependencies = IMAGE_DEPENDENCIES.get(image_config.name, []) wait_for = [build_ids[dep] for dep in dependencies if dep in build_ids] if wait_for: step['waitFor'] = wait_for build_ids[image_config.name] = step['id'] steps.append(step) return steps def run_build(steps: list[dict], images_to_push: list[str], build_version: str, tags: list[str] | None = None, dry_run: bool = False, no_push: bool = False): """Executes a build in GCB and pushes the resulting images. Alternatively, prints the configuration if in dry_run mode. """ if dry_run: print( '--------------------------------------------------------------------') print(f'DRY RUN FOR VERSION: {build_version}') print( '--------------------------------------------------------------------') print(f'Images to push: {images_to_push}') print(f'Push enabled: {not no_push}') print('Build steps:') for step in steps: print(f" - {step['name']}: {' '.join(step['args'])}") print( '--------------------------------------------------------------------\n' ) return images_for_gcb = images_to_push if no_push: logging.info('"--no-push" flag detected. Skipping push to registry.') images_for_gcb = [] credentials, _ = google.auth.default() body_overrides = { 'images': images_for_gcb, 'options': { 'machineType': 'E2_HIGHCPU_32' }, } build_tags = ['base-image-build', f'version-{build_version}'] if tags: build_tags.extend(tags) build_info = build_lib.run_build('', steps, credentials, BASE_PROJECT, TIMEOUT, body_overrides, build_tags, use_build_pool=False) if build_info: build_id = build_info.get('id') log_url = build_info.get('logUrl') logging.info('Successfully triggered build %s for version %s.', build_id, build_version) logging.info('Build logs are available at: %s', log_url) else: logging.error('Failed to trigger build for version %s.', build_version) def get_images_architecture_manifest_steps(target_tag: str) -> list[dict]: """Returns steps for creating and pushing a multi-architecture manifest. The manifest is for the base-builder and base-runner images with a specific tag. """ images = [ f'{IMAGE_NAME_PREFIX}base-builder', f'{IMAGE_NAME_PREFIX}base-runner' ] steps = [] for image in images: steps.extend(get_image_push_architecture_manifest_steps(image, target_tag)) return steps def get_image_push_architecture_manifest_steps(image: str, target_tag: str) -> list[dict]: """Returns steps for pushing a manifest pointing to ARM64/AMD64 versions.""" # The AMD64 image is the one we just built. amd64_source_image = f'{image}:{target_tag}' # The ARM64 image is a pre-built generic testing image. arm64_source_image = f'{image}-testing-arm' # The final manifest will point to this tag. manifest_tag = f'{image}:{target_tag}' # Intermediate tags for pushing architecture-specific images. amd64_manifest_image = f'{image}:{target_tag}-manifest-amd64' arm64_manifest_image = f'{image}:{target_tag}-manifest-arm64v8' steps = [ # Tag and push the AMD64 image. { 'name': 'gcr.io/cloud-builders/docker', 'args': ['tag', amd64_source_image, amd64_manifest_image], }, { 'name': 'gcr.io/cloud-builders/docker', 'args': ['push', amd64_manifest_image], }, # Pull and tag the ARM64 image. { 'name': 'gcr.io/cloud-builders/docker', 'args': ['pull', arm64_source_image], }, { 'name': 'gcr.io/cloud-builders/docker', 'args': ['tag', arm64_source_image, arm64_manifest_image], }, { 'name': 'gcr.io/cloud-builders/docker', 'args': ['push', arm64_manifest_image], }, # Create and push the manifest. { 'name': 'gcr.io/cloud-builders/docker', 'args': [ 'manifest', 'create', manifest_tag, '--amend', arm64_manifest_image, '--amend', amd64_manifest_image ], }, { 'name': 'gcr.io/cloud-builders/docker', 'args': ['manifest', 'push', manifest_tag] } ] return steps def base_builder(event, context, dry_run: bool = False, no_push: bool = False): """Cloud function entry point. Triggers parallel base image builds for each supported Ubuntu version. """ del event, context logging.basicConfig(level=logging.INFO) for version in SUPPORTED_VERSIONS: logging.info('Starting build for version: %s', version) version_images = [ ImageConfig(version=version, **def_args) for def_args in BASE_IMAGE_DEFS ] steps = get_base_image_steps(version_images) images_to_push = [img.full_image_name_with_tag for img in version_images] # Also push the 'latest' tag for the default build. if version == DEFAULT_VERSION: images_to_push.extend( [f'{IMAGE_NAME_PREFIX}{img.name}:latest' for img in version_images]) # Determine the final tag for this build. target_tag = MAJOR_TAG if version == DEFAULT_VERSION else version # Create a multi-architecture manifest for this version's final tag. logging.info('Adding multi-architecture manifest steps for tag: %s', target_tag) steps.extend(get_images_architecture_manifest_steps(target_tag)) images_to_push.extend([ f'{IMAGE_NAME_PREFIX}base-builder:{target_tag}', f'{IMAGE_NAME_PREFIX}base-runner:{target_tag}' ]) logging.info('Triggering GCB build for version: %s', version) run_build(steps, images_to_push, build_version=version, dry_run=dry_run, no_push=no_push) if __name__ == '__main__': is_dry_run = '--dry-run' in sys.argv no_push = '--no-push' in sys.argv base_builder(None, None, dry_run=is_dry_run, no_push=no_push) ================================================ FILE: infra/build/functions/build_and_push_test_images.py ================================================ #! /usr/bin/env python3 # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for building and pushing base-images to gcr.io/oss-fuzz-base/ with "-test" suffix. This is useful for using the build infra to test image changes.""" import logging import multiprocessing import os import re import subprocess import sys import time import google.auth import yaml from googleapiclient.discovery import build as cloud_build import base_images import build_lib CLOUD_PROJECT = 'oss-fuzz-base' INFRA_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) IMAGES_DIR = os.path.join(INFRA_DIR, 'base-images') OSS_FUZZ_ROOT = os.path.dirname(INFRA_DIR) GCB_BUILD_TAGS = ['trial-build'] # Add the new Ubuntu versions to the list of versions to build. BASE_IMAGE_VERSIONS = ['legacy', 'ubuntu-20-04', 'ubuntu-24-04'] def push_image(tag): """Pushes image with |tag| to docker registry.""" logging.info('Pushing: %s', tag) command = ['docker', 'push', tag] subprocess.run(command, check=True) logging.info('Pushed: %s', tag) def build_and_push_image(image, test_image_tag, version='legacy'): """Builds and pushes |image| to docker registry with "-testing" suffix.""" main_image_name, test_image_name = get_image_tags(image, test_image_tag, version) build_image(image, [main_image_name, test_image_name], main_image_name, version) push_image(test_image_name) def build_image(image, tags, cache_from_tag, version='latest'): """Builds |image| and tags it with |tags|.""" logging.info('Building: %s', image) command = ['docker', 'build'] for tag in tags: command.extend(['--tag', tag]) path = os.path.join(IMAGES_DIR, image) if version != 'legacy': command.extend(['-f', os.path.join(path, f'{version}.Dockerfile')]) command.extend([ '--build-arg', 'BUILDKIT_INLINE_CACHE=1', '--cache-from', cache_from_tag ]) command.append(path) subprocess.run(command, check=True) logging.info('Built: %s', image) def _run_cloudbuild(build_body): """Runs a cloud build and returns the build ID.""" yaml_file = os.path.join(OSS_FUZZ_ROOT, 'cloudbuild.yaml') with open(yaml_file, 'w') as yaml_file_handle: yaml.dump(build_body, yaml_file_handle) # Use --async to not wait on the build. result = subprocess.run([ 'gcloud', 'builds', 'submit', '--project=oss-fuzz-base', f'--config={yaml_file}', '--async', '--format=value(id)' ], cwd=OSS_FUZZ_ROOT, check=True, capture_output=True, text=True) return result.stdout.strip() def wait_for_build_and_report_summary(build_id, cloud_project='oss-fuzz-base'): """Waits for a GCB build to complete and reports a detailed summary.""" logs_url = build_lib.get_logs_url(build_id) credentials, _ = google.auth.default() cloudbuild = cloud_build('cloudbuild', 'v1', credentials=credentials, cache_discovery=False, client_options=build_lib.REGIONAL_CLIENT_OPTIONS) cloudbuild_api = cloudbuild.projects().builds() logging.info( '================================================================') logging.info(' PHASE 1: STARTED BASE IMAGE BUILD') logging.info( '----------------------------------------------------------------') for line in build_lib.get_build_info_lines(build_id, cloud_project): logging.info(line) logging.info( '================================================================') logging.info('Waiting for base image build to complete...') build_result = None while True: try: build_result = cloudbuild_api.get(projectId=cloud_project, id=build_id).execute() status = build_result['status'] if status in ('SUCCESS', 'FAILURE', 'TIMEOUT', 'CANCELLED', 'EXPIRED'): break except Exception as e: logging.error('Error checking build status: %s', e) time.sleep(15) logging.info( '================================================================') logging.info(' PHASE 1: BASE IMAGE BUILD REPORT') logging.info( '----------------------------------------------------------------') for line in build_lib.get_build_info_lines(build_id, cloud_project): logging.info(line) logging.info( '================================================================') if not build_result or 'steps' not in build_result: logging.error('Could not retrieve build steps. See logs for details: %s', logs_url) return False # Detailed step-by-step report succeeded_steps = 0 failed_steps = [] for step in build_result['steps']: step_id = step.get('id', step.get('name', 'Unnamed Step')) step_status = step.get('status', 'UNKNOWN') if step_status == 'SUCCESS': logging.info(' - %s: %s', step_id, step_status) succeeded_steps += 1 else: logging.error(' - %s: %s', step_id, step_status) failed_steps.append(step_id) logging.info( '----------------------------------------------------------------') logging.info('Summary: %d succeeded, %d failed.', succeeded_steps, len(failed_steps)) logging.info( '================================================================') if failed_steps: logging.error('The following images failed to build: %s', ', '.join(failed_steps)) logging.error('See full logs for details: %s', logs_url) return False logging.info('All base images built successfully.') return True def get_image_tags(image: str, test_image_tag: str | None = None, version: str = 'legacy'): """Returns tags for image build.""" if version == 'legacy': main_image_name = f'{base_images.IMAGE_NAME_PREFIX}{image}' else: main_image_name = f'{base_images.IMAGE_NAME_PREFIX}{image}:{version}' test_image_name = None if test_image_tag: test_image_name = ( f'{base_images.IMAGE_NAME_PREFIX}{image}-{test_image_tag}') return main_image_name, test_image_name def gcb_build_and_push_images(test_image_tag: str, version_tag: str = None): """Build and push test versions of base images using GCB.""" # Define the dependency hierarchy for base images. IMAGE_DEPENDENCIES = { 'base-clang': ['base-image'], 'base-clang-full': ['base-clang'], 'base-builder': ['base-clang'], 'base-runner': [ 'base-image', 'base-clang', 'base-builder', 'base-builder-ruby' ], 'base-builder-go': ['base-builder'], 'base-builder-javascript': ['base-builder'], 'base-builder-jvm': ['base-builder'], 'base-builder-python': ['base-builder'], 'base-builder-ruby': ['base-builder'], 'base-builder-rust': ['base-builder'], 'base-builder-swift': ['base-builder'], 'base-runner-debug': ['base-runner'], 'indexer': ['base-clang-full'], } steps = [] added_step_ids = set() test_image_names = [] versions = [version_tag] if version_tag else BASE_IMAGE_VERSIONS for version in versions: for base_image_def in base_images.BASE_IMAGE_DEFS: base_image = base_images.ImageConfig(version=version, **base_image_def) main_image_name, test_image_name = get_image_tags(base_image.name, test_image_tag, version) test_image_names.append(test_image_name) if version == 'legacy': dockerfile = os.path.join(base_image.path, 'Dockerfile') else: dockerfile = os.path.join(base_image.path, f'{version}.Dockerfile') # Skip building if the Dockerfile does not exist. if not os.path.exists(os.path.join(OSS_FUZZ_ROOT, dockerfile)): logging.info('Skipping %s for version %s as it does not exist.', dockerfile, version) continue intermediate_tag = base_images.IMAGE_NAME_PREFIX + base_image.name tags_for_build = sorted( list(set([main_image_name, test_image_name, intermediate_tag]))) # Get dependency tags for caching. dependencies = IMAGE_DEPENDENCIES.get(base_image.name, []) if not isinstance(dependencies, list): dependencies = [dependencies] cache_tags = [] for dep_name in dependencies: dep_main_tag, _ = get_image_tags(dep_name, None, version) cache_tags.append(dep_main_tag) step = build_lib.get_docker_build_step( tags_for_build, base_image.path, use_buildkit_cache=True, src_root='.', build_args=base_image.build_args, dockerfile_path=dockerfile, additional_cache_from_tags=cache_tags) # Add a unique ID to each step for dependency tracking. step_id = f'build-{base_image.name}-{version}' step['id'] = step_id # Add 'waitFor' if the image has dependencies that have been added. wait_for_ids = [] for dependency in dependencies: dependency_id = f'build-{dependency}-{version}' if dependency_id in added_step_ids: wait_for_ids.append(dependency_id) if wait_for_ids: step['waitFor'] = wait_for_ids steps.append(step) added_step_ids.add(step_id) build_body = build_lib.get_build_body(steps, base_images.TIMEOUT, {'images': test_image_names}, GCB_BUILD_TAGS + [test_image_tag]) build_id = _run_cloudbuild(build_body) return wait_for_build_and_report_summary(build_id) def build_and_push_images(test_image_tag, version_tag=None): """Builds and pushes base-images.""" images = [ ['base-image'], ['base-clang'], ['base-clang-full'], ['indexer'], ['base-builder'], [ 'base-builder-swift', 'base-builder-ruby', 'base-builder-rust', 'base-builder-go', 'base-builder-javascript', 'base-builder-jvm', 'base-builder-python', ], ['base-runner'], ['base-runner-debug'], ] os.environ['DOCKER_BUILDKIT'] = '1' max_parallelization = max([len(image_list) for image_list in images]) proc_count = min(multiprocessing.cpu_count(), max_parallelization) logging.info('Using %d parallel processes.', proc_count) with multiprocessing.Pool(proc_count) as pool: for image_list in images: args_list = [] for image in image_list: versions = [version_tag] if version_tag else BASE_IMAGE_VERSIONS for version in versions: # Check if the specific versioned Dockerfile exists before adding. if version == 'legacy': dockerfile_path = os.path.join(IMAGES_DIR, image, 'Dockerfile') else: dockerfile_path = os.path.join(IMAGES_DIR, image, f'{version}.Dockerfile') if os.path.exists(dockerfile_path): args_list.append((image, test_image_tag, version)) pool.starmap(build_and_push_image, args_list) def main(): """Builds base-images tags them with "-testing" suffix (in addition to normal tag) and pushes testing suffixed images to docker registry.""" test_image_tag = sys.argv[1] logging.basicConfig(level=logging.DEBUG) logging.info('Doing simple gcloud command to ensure 2FA passes.') subprocess.run(['gcloud', 'projects', 'list', '--limit=1'], check=True) build_and_push_images(test_image_tag) if __name__ == '__main__': main() ================================================ FILE: infra/build/functions/build_and_run_coverage.py ================================================ #!/usr/bin/env python3 # # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Starts and runs coverage build on Google Cloud Builder. Usage: build_and_run_coverage.py . """ import json import logging import os import sys import posixpath import build_lib import build_project SANITIZER = 'coverage' FUZZING_ENGINE = 'libfuzzer' ARCHITECTURE = 'x86_64' PLATFORM = 'linux' COVERAGE_BUILD_TYPE = 'coverage' INTROSPECTOR_BUILD_TYPE = 'introspector' # This is needed for ClusterFuzz to pick up the most recent reports data. LATEST_REPORT_INFO_CONTENT_TYPE = 'application/json' # Languages from project.yaml that have code coverage support. LANGUAGES_WITH_COVERAGE_SUPPORT = [ 'c', 'c++', 'go', 'jvm', 'rust', 'swift', 'python' ] LANGUAGES_WITH_INTROSPECTOR_SUPPORT = ['c', 'c++', 'python', 'jvm', 'rust'] class Bucket: # pylint: disable=too-few-public-methods """Class representing the GCS bucket.""" BUCKET_NAME = None def __init__(self, project, date, platform, testing): self.bucket_name = self.BUCKET_NAME if testing: self.bucket_name += '-testing' self.date = date self.project = project self.html_report_url = ( f'{build_lib.GCS_URL_BASENAME}{self.bucket_name}/{project}' f'/reports/{date}/{platform}') self.latest_report_info_url = (f'/{self.bucket_name}' f'/latest_report_info/{project}.json') def get_upload_url(self, upload_type): """Returns an upload url for |upload_type|.""" return (f'gs://{self.bucket_name}/{self.project}' f'/{upload_type}/{self.date}') class CoverageBucket(Bucket): # pylint: disable=too-few-public-methods """Class representing the coverage GCS bucket.""" BUCKET_NAME = 'oss-fuzz-coverage' class IntrospectorBucket(Bucket): # pylint: disable=too-few-public-methods """Class representing the introspector GCS bucket.""" BUCKET_NAME = 'oss-fuzz-introspector' def get_build_steps( # pylint: disable=too-many-locals, too-many-arguments project_name, project_yaml, dockerfile_lines, config): """Returns build steps for project.""" project = build_project.Project(project_name, project_yaml, dockerfile_lines) if project.disabled: return [], f'Project "{project.name}" is disabled.' if project.fuzzing_language not in LANGUAGES_WITH_COVERAGE_SUPPORT: return [], (f'Project "{project.name}" is written in ' f'"{project.fuzzing_language}", coverage is not supported yet.') report_date = build_project.get_datetime_now().strftime('%Y%m%d') bucket = CoverageBucket(project.name, report_date, PLATFORM, config.testing) build_steps = build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config) build = build_project.Build(FUZZING_ENGINE, 'coverage', ARCHITECTURE) env = build_project.get_env(project.fuzzing_language, build) build_steps.append( build_project.get_compile_step(project, build, env, config.parallel)) download_corpora_steps = build_lib.download_corpora_steps( project.name, test_image_suffix=config.test_image_suffix) if not download_corpora_steps: return [], f'Failed to get corpora for project "{project.name}".' build_steps.extend(download_corpora_steps) failure_msg = ('*' * 80 + '\nCode coverage report generation failed.\n' 'To reproduce, run:\n' f'python infra/helper.py build_image {project.name}\n' 'python infra/helper.py build_fuzzers --sanitizer coverage ' f'{project.name}\n' f'python infra/helper.py coverage {project.name}\n' + '*' * 80) # Unpack the corpus and run coverage script. coverage_env = env + [ 'HTTP_PORT=', f'COVERAGE_EXTRA_ARGS={project.coverage_extra_args.strip()}', ] build_steps.append({ 'name': build_lib.get_runner_image_name(config.test_image_suffix, config.base_image_tag), 'env': coverage_env, 'args': [ 'bash', '-c', ('for f in /corpus/*.zip; do unzip -q $f -d ${f%.*} || (' 'echo "Failed to unpack the corpus for $(basename ${f%.*}). ' 'This usually means that corpus backup for a particular fuzz ' 'target does not exist. If a fuzz target was added in the last ' '24 hours, please wait one more day. Otherwise, something is ' 'wrong with the fuzz target or the infrastructure, and corpus ' 'pruning task does not finish successfully." && exit 1' '); done && coverage || (echo "' + failure_msg + '" && false)') ], 'volumes': [{ 'name': 'corpus', 'path': '/corpus' }], }) # Upload the report. upload_report_url = bucket.get_upload_url('reports') upload_report_by_target_url = bucket.get_upload_url('reports-by-target') # Delete the existing report as gsutil cannot overwrite it in a useful way due # to the lack of `-T` option (it creates a subdir in the destination dir). build_steps.append(build_lib.gsutil_rm_rf_step(upload_report_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'report'), upload_report_url, ], }) # TODO(navidem): # Currently python and jvm coverage does not produce per_target reports. # Skipping python for now to avoid breakage. if (project.fuzzing_language not in ['python', 'jvm'] and project.fuzzing_language in LANGUAGES_WITH_INTROSPECTOR_SUPPORT): build_steps.append(build_lib.gsutil_rm_rf_step(upload_report_by_target_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'report_target'), upload_report_by_target_url, ], }) # Upload the fuzzer stats. Delete the old ones just in case. upload_fuzzer_stats_url = bucket.get_upload_url('fuzzer_stats') build_steps.append(build_lib.gsutil_rm_rf_step(upload_fuzzer_stats_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'fuzzer_stats'), upload_fuzzer_stats_url, ], }) if project.fuzzing_language in LANGUAGES_WITH_INTROSPECTOR_SUPPORT: # Upload the text coverage reports. Delete the old ones just in case. upload_textcov_reports_url = bucket.get_upload_url('textcov_reports') build_steps.append(build_lib.gsutil_rm_rf_step(upload_textcov_reports_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'textcov_reports'), upload_textcov_reports_url, ], }) # Upload the fuzzer logs. Delete the old ones just in case upload_fuzzer_logs_url = bucket.get_upload_url('logs') build_steps.append(build_lib.gsutil_rm_rf_step(upload_fuzzer_logs_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'logs'), upload_fuzzer_logs_url, ], }) # Upload srcmap. srcmap_upload_url = bucket.get_upload_url('srcmap') srcmap_upload_url = srcmap_upload_url.rstrip('/') + '.json' build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ 'cp', '/workspace/srcmap.json', srcmap_upload_url, ], }) # Update the latest report information file for ClusterFuzz. latest_report_info_url = build_lib.get_signed_url( bucket.latest_report_info_url, content_type=LATEST_REPORT_INFO_CONTENT_TYPE) latest_report_info_body = json.dumps({ 'fuzzer_stats_dir': upload_fuzzer_stats_url, 'html_report_url': posixpath.join(bucket.html_report_url, 'index.html'), 'report_date': report_date, 'report_summary_path': os.path.join(upload_report_url, PLATFORM, 'summary.json'), }) build_steps.append( build_lib.http_upload_step(latest_report_info_body, latest_report_info_url, LATEST_REPORT_INFO_CONTENT_TYPE)) return build_steps, None def get_fuzz_introspector_steps( # pylint: disable=too-many-locals, too-many-arguments, unused-argument project_name, project_yaml, dockerfile_lines, config): """Returns build steps of fuzz introspector for project""" project = build_project.Project(project_name, project_yaml, dockerfile_lines) if project.disabled: return [], f'Project "{project.name}" is disabled.' if project.fuzzing_language not in LANGUAGES_WITH_INTROSPECTOR_SUPPORT: return [], (f'Project "{project.name}" is written in ' f'"{project.fuzzing_language}", Fuzz Introspector is not ' 'supported yet.') build_steps = [] build = build_project.Build(FUZZING_ENGINE, 'introspector', ARCHITECTURE) report_date = build_project.get_datetime_now().strftime('%Y%m%d') bucket = IntrospectorBucket(project.name, report_date, PLATFORM, config.testing) # TODO (navidem): find the latest coverage report. coverage_report_latest = report_date bucket_name = 'oss-fuzz-coverage' coverage_url = (f'{build_lib.GCS_URL_BASENAME}{bucket_name}/{project.name}' f'/reports/{coverage_report_latest}/linux') download_coverage_steps = build_lib.download_coverage_data_steps( project.name, coverage_report_latest, bucket_name, build.out, config.base_image_tag) if not download_coverage_steps: return [], f'Skipping introspector build for {project.name}. No coverage data found.' build_steps.extend(download_coverage_steps) build_steps.extend( build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config)) env = build_project.get_env(project.fuzzing_language, build) env.append(f'GIT_REPO={project.main_repo}') env.append(f'COVERAGE_URL={coverage_url}') env.append(f'PROJECT_NAME={project.name}') build_steps.append( build_project.get_compile_step(project, build, env, config.parallel, allow_failure=True)) # Upload the report. upload_report_url = bucket.get_upload_url('inspector-report') # Delete the existing report as gsutil cannot overwrite it in a useful way due # to the lack of `-T` option (it creates a subdir in the destination dir). build_steps.append(build_lib.gsutil_rm_rf_step(upload_report_url)) build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'inspector'), upload_report_url, ], }) return build_steps, None def main(): """Build and run coverage for projects.""" coverage_status = build_project.build_script_main( 'Generates coverage report for project.', get_build_steps, COVERAGE_BUILD_TYPE) if coverage_status != 0: return coverage_status return build_project.build_script_main( 'Generates introspector report for project.', get_fuzz_introspector_steps, INTROSPECTOR_BUILD_TYPE) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/build_and_run_coverage_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for build_and_run_coverage.""" import json import os import sys import unittest from unittest import mock from pyfakefs import fake_filesystem_unittest FUNCTIONS_DIR = os.path.dirname(__file__) sys.path.append(FUNCTIONS_DIR) # pylint: disable=wrong-import-position import build_and_run_coverage import build_project import test_utils # pylint: disable=no-member class TestRequestCoverageBuilds(fake_filesystem_unittest.TestCase): """Unit tests for sync.""" def setUp(self): self.maxDiff = None # pylint: disable=invalid-name self.setUpPyfakefs() @mock.patch('build_lib.get_signed_url', return_value='test_url') @mock.patch('build_lib.download_corpora_steps', return_value=[{ 'url': 'test_download' }]) @mock.patch('build_project.get_datetime_now', return_value=test_utils.FAKE_DATETIME) @mock.patch('build_lib.get_unique_build_step_image_id', return_value='UNIQUE_ID') def test_get_coverage_build_steps(self, mock_url, mock_corpora_steps, mock_get_datetime_now, mock_get_id): """Test for get_build_steps.""" del mock_url, mock_corpora_steps, mock_get_datetime_now project_yaml_contents = ( 'language: c++\n' 'sanitizers:\n' ' - address\n' 'architectures:\n' ' - x86_64\n' 'main_repo: https://github.com/google/oss-fuzz.git\n') self.fs.create_dir(test_utils.PROJECT_DIR) test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents) expected_build_steps_file_path = test_utils.get_test_data_file_path( 'expected_coverage_build_steps.json') self.fs.add_real_file(expected_build_steps_file_path) with open(expected_build_steps_file_path) as expected_build_steps_file: expected_coverage_build_steps = json.load(expected_build_steps_file) config = build_project.Config(upload=False) project_yaml, dockerfile = build_project.get_project_data( test_utils.PROJECT) build_steps, _ = build_and_run_coverage.get_build_steps( test_utils.PROJECT, project_yaml, dockerfile, config) self.assertEqual(build_steps, expected_coverage_build_steps) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/build_lib.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Utility module for Google Cloud Build scripts.""" import base64 import binascii import collections from collections.abc import Sequence import dataclasses import datetime import json import logging import os import re import six.moves.urllib.parse as urlparse import sys import time import tarfile import tempfile import uuid from googleapiclient.discovery import build as cloud_build import googleapiclient.discovery import google.api_core.client_options import google.auth from google.cloud import storage from oauth2client import service_account as service_account_lib import requests import yaml BASE_IMAGES_PROJECT = 'oss-fuzz-base' IMAGE_PROJECT = 'oss-fuzz' BUILD_TIMEOUT = 20 * 60 * 60 # Needed for reading public target.list.* files. GCS_URL_BASENAME = 'https://storage.googleapis.com/' GCS_UPLOAD_URL_FORMAT = '/{0}/{1}/{2}' # Where corpus backups can be downloaded from. CORPUS_BACKUP_URL = ('/{project}-backup.clusterfuzz-external.appspot.com/' 'corpus/libFuzzer/{fuzzer}/latest.zip') # Regex to match special chars in project name. SPECIAL_CHARS_REGEX = re.compile('[^a-zA-Z0-9_-]') # Cloud Builder has a limit of 100 build steps and 100 arguments for each step. CORPUS_DOWNLOAD_BATCH_SIZE = 100 TARGETS_LIST_BASENAME = 'targets.list' EngineInfo = collections.namedtuple( 'EngineInfo', ['upload_bucket', 'supported_sanitizers', 'supported_architectures']) @dataclasses.dataclass class SignedPolicyDocument: """Signed policy document""" bucket: str policy: str x_goog_algorithm: str x_goog_date: str x_goog_credential: str x_goog_signature: str ENGINE_INFO = { 'libfuzzer': EngineInfo(upload_bucket='clusterfuzz-builds', supported_sanitizers=['address', 'memory', 'undefined'], supported_architectures=['x86_64', 'i386', 'aarch64']), 'afl': EngineInfo(upload_bucket='clusterfuzz-builds-afl', supported_sanitizers=['address'], supported_architectures=['x86_64']), 'honggfuzz': EngineInfo(upload_bucket='clusterfuzz-builds-honggfuzz', supported_sanitizers=['address'], supported_architectures=['x86_64']), 'none': EngineInfo(upload_bucket='clusterfuzz-builds-no-engine', supported_sanitizers=['address'], supported_architectures=['x86_64']), 'centipede': EngineInfo(upload_bucket='clusterfuzz-builds-centipede', supported_sanitizers=['address', 'none'], supported_architectures=['x86_64']), } OSS_FUZZ_BUILDPOOL_NAME = os.getenv( 'GCB_BUILDPOOL_NAME', 'projects/oss-fuzz/locations/us-central1/' 'workerPools/buildpool') OSS_FUZZ_INDEXER_BUILDPOOL_NAME = os.getenv( 'GCB_BUILDPOOL_NAME', 'projects/oss-fuzz/locations/us-central1/' 'workerPools/indexer-buildpool') OSS_FUZZ_EXPERIMENTS_BUILDPOOL_NAME = os.getenv( 'GCB_BUILDPOOL_NAME', 'projects/oss-fuzz/locations/us-central1/' 'workerPools/buildpool-experiments') CLOUD_BUILD_LOCATION = os.getenv('CLOUD_BUILD_LOCATION', 'us-central1') REGIONAL_CLIENT_OPTIONS = google.api_core.client_options.ClientOptions( api_endpoint=f'https://{CLOUD_BUILD_LOCATION}-cloudbuild.googleapis.com/') DOCKER_TOOL_IMAGE = 'gcr.io/cloud-builders/docker' _ARM64 = 'aarch64' OSS_FUZZ_ROOT = os.path.abspath(os.path.join(__file__, '..', '..', '..', '..')) def get_targets_list_filename(sanitizer): """Returns target list filename.""" return TARGETS_LIST_BASENAME + '.' + sanitizer def get_targets_list_url(bucket, project, sanitizer): """Returns target list url.""" filename = get_targets_list_filename(sanitizer) url = GCS_UPLOAD_URL_FORMAT.format(bucket, project, filename) return url def dockerify_run_step(step, build, use_architecture_image_name=False, container_name=None): """Modify a docker run step to run using gcr.io/cloud-builders/docker. This allows us to specify which architecture to run the image on.""" image = step['name'] if use_architecture_image_name: image = _make_image_name_architecture_specific(image, build.architecture) step['name'] = DOCKER_TOOL_IMAGE if build.is_arm: platform = 'linux/arm64' else: platform = 'linux/amd64' new_args = [ 'run', '--platform', platform, '-v', '/workspace:/workspace', '--privileged', '--cap-add=all' ] if container_name: new_args.extend(['--name', container_name]) if 'env' in step: for env_var in step.get('env', {}): new_args.extend(['-e', env_var]) new_args += ['-t', image] new_args += step['args'] step['args'] = new_args return step def get_upload_bucket(engine, architecture, testing): """Returns the upload bucket for |engine| and architecture. Returns the testing bucket if |testing|.""" bucket = ENGINE_INFO[engine].upload_bucket if architecture != 'x86_64': bucket += '-' + architecture if testing: bucket += '-testing' return bucket def _get_targets_list(project_name): """Returns target list.""" # libFuzzer ASan 'x86_84' is the default configuration, get list of targets # from it. # We never want the target list from the testing bucket, the testing bucket is # only for uploading. bucket = get_upload_bucket('libfuzzer', 'x86_64', testing=None) url = get_targets_list_url(bucket, project_name, 'address') url = urlparse.urljoin(GCS_URL_BASENAME, url) response = requests.get(url) if not response.status_code == 200: sys.stderr.write('Failed to get list of targets from "%s".\n' % url) sys.stderr.write('Status code: %d \t\tText:\n%s\n' % (response.status_code, response.text)) return None return response.text.split() def _sign_client_id(): service_account_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS') if service_account_path: creds = ( service_account_lib.ServiceAccountCredentials.from_json_keyfile_name( os.environ['GOOGLE_APPLICATION_CREDENTIALS'])) return creds.service_account_email else: _, project = google.auth.default() return project + '@appspot.gserviceaccount.com' def _sign_blob(blob): service_account_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS') if service_account_path: creds = ( service_account_lib.ServiceAccountCredentials.from_json_keyfile_name( os.environ['GOOGLE_APPLICATION_CREDENTIALS'])) client_id = creds.service_account_email signature = base64.b64encode(creds.sign_blob(blob)[1]) else: credentials, project = google.auth.default() iam = googleapiclient.discovery.build('iamcredentials', 'v1', credentials=credentials, cache_discovery=False) client_id = project + '@appspot.gserviceaccount.com' service_account = f'projects/-/serviceAccounts/{client_id}' response = iam.projects().serviceAccounts().signBlob( name=service_account, body={ 'delegates': [], 'payload': base64.b64encode(blob.encode('utf-8')).decode('utf-8'), }).execute() signature = response['signedBlob'] return client_id, signature # TODO(ochang): Migrate older signed URLs to V4 signatures. def get_signed_policy_document_upload_prefix(bucket, path_prefix): now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None) timestamp = now.strftime('%Y%m%dT%H%M%SZ') datestamp = now.date().strftime('%Y%m%d') expiry = now + datetime.timedelta(hours=24) client_id = _sign_client_id() x_goog_credential = f'{client_id}/{datestamp}/auto/storage/goog4_request' doc = { 'expiration': expiry.isoformat() + 'Z', 'conditions': [[ 'starts-with', '$key', path_prefix, ], { 'bucket': bucket, }, { 'x-goog-algorithm': 'GOOG4-RSA-SHA256' }, { 'x-goog-credential': x_goog_credential }, { 'x-goog-date': timestamp }] } encoded = base64.b64encode(json.dumps(doc).encode()).decode() client_id, signature = _sign_blob(encoded) return SignedPolicyDocument( bucket=bucket, policy=encoded, x_goog_algorithm='GOOG4-RSA-SHA256', x_goog_credential=x_goog_credential, x_goog_date=timestamp, x_goog_signature=binascii.hexlify(base64.b64decode(signature)).decode(), ) # pylint: disable=no-member def get_signed_url(path, method='PUT', content_type=''): """Returns signed url.""" timestamp = int(time.time() + BUILD_TIMEOUT) blob = f'{method}\n\n{content_type}\n{timestamp}\n{path}' client_id, signature = _sign_blob(blob) values = { 'GoogleAccessId': client_id, 'Expires': timestamp, 'Signature': signature, } return f'https://storage.googleapis.com{path}?{urlparse.urlencode(values)}' def _normalized_name(name): """Return normalized name with special chars like slash, colon, etc normalized to hyphen(-). This is important as otherwise these chars break local and cloud storage paths.""" return SPECIAL_CHARS_REGEX.sub('-', name).strip('-') def download_corpora_steps(project_name, test_image_suffix): """Returns GCB steps for downloading corpora backups for the given project. """ fuzz_targets = _get_targets_list(project_name) if not fuzz_targets: return None, f'No fuzz targets found for project "{project_name}".' steps = [] # Split fuzz targets into batches of CORPUS_DOWNLOAD_BATCH_SIZE. for i in range(0, len(fuzz_targets), CORPUS_DOWNLOAD_BATCH_SIZE): download_corpus_args = [] for binary_name in fuzz_targets[i:i + CORPUS_DOWNLOAD_BATCH_SIZE]: qualified_name = binary_name qualified_name_prefix = '%s_' % project_name if not binary_name.startswith(qualified_name_prefix): qualified_name = qualified_name_prefix + binary_name # Normalize qualified_name name. qualified_name = _normalized_name(qualified_name) url = get_signed_url(CORPUS_BACKUP_URL.format(project=project_name, fuzzer=qualified_name), method='GET') corpus_archive_path = os.path.join('/corpus', binary_name + '.zip') download_corpus_args.append('%s %s' % (corpus_archive_path, url)) steps.append({ 'name': get_runner_image_name(test_image_suffix), 'entrypoint': 'download_corpus', 'args': download_corpus_args, 'volumes': [{ 'name': 'corpus', 'path': '/corpus' }], }) return steps, None def download_coverage_data_steps(project_name, latest, bucket_name, out_dir, base_image_tag=None): """Returns GCB steps to download coverage data for the given project""" steps = [] fuzz_targets = _get_targets_list(project_name) if not fuzz_targets: sys.stderr.write('No fuzz targets found for project "%s".\n' % project_name) return None runner_image_name = get_runner_image_name(base_image_tag=base_image_tag) steps.append({ 'name': runner_image_name, 'args': ['bash', '-c', (f'mkdir -p {out_dir}/textcov_reports')] }) coverage_data_path = os.path.join(f'{out_dir}/textcov_reports/') bucket_url = f'gs://{bucket_name}/{project_name}/textcov_reports/{latest}/*' steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': ['-m', 'cp', '-r', bucket_url, coverage_data_path], 'allowFailure': True }) steps.append({ 'name': runner_image_name, 'args': ['bash', '-c', f'ls -lrt {out_dir}/textcov_reports'], 'allowFailure': True }) return steps def http_upload_step(data, signed_url, content_type): """Returns a GCB step to upload data to the given URL via GCS HTTP API.""" step = { 'name': 'gcr.io/cloud-builders/curl', 'args': [ '-H', 'Content-Type: ' + content_type, '-X', 'PUT', '-d', data, signed_url, ], } return step def signed_policy_document_curl_args(doc: SignedPolicyDocument): """Signed policy document curl args.""" return [ '-F', 'policy=' + doc.policy, '-F', 'x-goog-algorithm=' + doc.x_goog_algorithm, '-F', 'x-goog-date=' + doc.x_goog_date, '-F', 'x-goog-credential=' + doc.x_goog_credential, '-F', 'x-goog-signature=' + doc.x_goog_signature, ] def upload_using_signed_policy_document(file_path, upload_path, doc: SignedPolicyDocument): """Upload using signed policy document.""" step = { 'name': 'gcr.io/cloud-builders/curl', 'args': signed_policy_document_curl_args(doc) + [ '-F', f'key={upload_path}', '-F', f'file=@{file_path}', f'https://{doc.bucket}.storage.googleapis.com', ] } return step def gsutil_rm_rf_step(url): """Returns a GCB step to recursively delete the object with given GCS url.""" step = { 'name': 'gcr.io/cloud-builders/gsutil', 'entrypoint': 'sh', 'args': [ '-c', 'gsutil -m rm -rf %s || exit 0' % url, ], } return step def get_pull_test_images_steps(test_image_suffix): """Returns steps to pull testing versions of base-images and tag them so that they are used in builds.""" images = [ 'gcr.io/oss-fuzz-base/base-builder', 'gcr.io/oss-fuzz-base/base-builder-swift', 'gcr.io/oss-fuzz-base/base-builder-javascript', 'gcr.io/oss-fuzz-base/base-builder-jvm', 'gcr.io/oss-fuzz-base/base-builder-go', 'gcr.io/oss-fuzz-base/base-builder-python', 'gcr.io/oss-fuzz-base/base-builder-ruby', 'gcr.io/oss-fuzz-base/base-builder-rust', 'gcr.io/oss-fuzz-base/base-runner', ] steps = [] for image in images: test_image = image + '-' + test_image_suffix steps.append({ 'name': DOCKER_TOOL_IMAGE, 'args': [ 'pull', test_image, ], 'waitFor': '-' # Start this immediately, don't wait for previous step. }) # This step is hacky but gives us great flexibility. OSS-Fuzz has hardcoded # references to gcr.io/oss-fuzz-base/base-builder (in dockerfiles, for # example) and gcr.io/oss-fuzz-base-runner (in this build code). But the # testing versions of those images are called e.g. # gcr.io/oss-fuzz-base/base-builder-testing and # gcr.io/oss-fuzz-base/base-runner-testing. How can we get the build to use # the testing images instead of the real ones? By doing this step: tagging # the test image with the non-test version, so that the test version is used # instead of pulling the real one. steps.append({ 'name': DOCKER_TOOL_IMAGE, 'args': ['tag', test_image, image], }) return steps def get_srcmap_step_id(): """Returns the id for the srcmap step.""" return 'srcmap' def get_git_clone_step(repo_url='https://github.com/google/oss-fuzz.git', branch=None): """Returns the git clone step.""" clone_step = { 'args': ['clone', repo_url, '--depth', '1'], 'name': 'gcr.io/cloud-builders/git', } if branch: # Do this to support testing other branches. clone_step['args'].extend(['--branch', branch]) return clone_step def _make_image_name_architecture_specific(image_name, architecture): """Returns an architecture-specific name for |image_name|, based on |build|""" return f'{image_name}-{architecture.lower()}' def get_unique_build_step_image_id(): return uuid.uuid4() def get_docker_build_step(image_names, directory, use_buildkit_cache=False, src_root='oss-fuzz', architecture='x86_64', cache_image='', build_args: Sequence[str] | None = None, dockerfile_path: str | None = None, additional_cache_from_tags: list | None = None): """Returns the docker build step.""" assert len(image_names) >= 1 directory = os.path.join(src_root, directory) if architecture != _ARM64: args = ['build'] else: args = [ 'buildx', 'build', '--platform', 'linux/arm64', '--progress', 'plain', '--load' ] # TODO(metzman): This wont work when we want to build the base-images. image_names = [ _make_image_name_architecture_specific(image_name, architecture) for image_name in image_names ] if cache_image: args.extend(['--build-arg', f'CACHE_IMAGE={cache_image}']) for image_name in sorted(image_names): args.extend(['--tag', image_name]) if build_args: for build_arg in build_args: args.extend(['--build-arg', build_arg]) if dockerfile_path: args.extend(['-f', dockerfile_path]) step = { 'name': DOCKER_TOOL_IMAGE, 'args': args, 'id': f'build-{get_unique_build_step_image_id()}', } # Handle buildkit args # Note that we mutate "args" after making it a value in step. if use_buildkit_cache: env = ['DOCKER_BUILDKIT=1'] step['env'] = env args.extend(['--build-arg', 'BUILDKIT_INLINE_CACHE=1']) all_cache_tags = set(image_names) if additional_cache_from_tags: all_cache_tags.update(additional_cache_from_tags) for image in sorted(list(all_cache_tags)): args.extend(['--cache-from', image]) args.append(directory) return step def has_arm_build(architectures): """Returns True if project has an ARM build.""" return 'aarch64' in architectures def get_srcmap_steps(image, language, directory='/workspace'): srcmap_step_id = get_srcmap_step_id() return [{ 'name': image, 'args': [ 'bash', '-c', f'srcmap > {directory}/srcmap.json && cat {directory}/srcmap.json' ], 'env': [ 'OSSFUZZ_REVISION=$REVISION_ID', f'FUZZING_LANGUAGE={language}', ], 'id': srcmap_step_id }] def get_project_image_steps( # pylint: disable=too-many-arguments name, image, language, config, architectures=None, experiment=False, cache_image=None, srcmap=True): """Returns GCB steps to build OSS-Fuzz project image.""" if architectures is None: architectures = [] # TODO(metzman): Pass the URL to clone. clone_step = get_git_clone_step(repo_url=config.repo, branch=config.branch) if experiment: # Skip cloning if we're in an experiment. The source is submitted to GCB # via gcloud builds submit. steps = [] else: steps = [clone_step] if config.test_image_suffix: steps.extend(get_pull_test_images_steps(config.test_image_suffix)) src_root = 'oss-fuzz' if not experiment else '.' docker_build_step = get_docker_build_step( [image, _get_unsafe_name(name)], os.path.join('projects', name), src_root=src_root, cache_image=cache_image) steps.append(docker_build_step) if srcmap: steps.extend(get_srcmap_steps(image, language)) if has_arm_build(architectures): builder_name = 'buildxbuilder' steps.extend([ { 'name': 'gcr.io/cloud-builders/docker', 'args': ['run', '--privileged', 'linuxkit/binfmt:v0.8'] }, { 'name': DOCKER_TOOL_IMAGE, 'args': ['buildx', 'create', '--name', builder_name] }, { 'name': DOCKER_TOOL_IMAGE, 'args': ['buildx', 'use', builder_name] }, ]) docker_build_arm_step = get_docker_build_step( [image, _get_unsafe_name(name)], os.path.join('projects', name), architecture=_ARM64) steps.append(docker_build_arm_step) if (config.build_type == 'fuzzing' and language in ('c', 'c++') and not not config.testing and not config.experiment and config.upload): logging.info('Pushing.') # Push so that historical bugs are reproducible. push_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': ['push', _get_unsafe_name(name)], 'id': 'push-image', 'waitFor': [docker_build_step['id']], 'allowFailure': True } steps.append(push_step) return steps def _get_unsafe_name(name): return f'us-central1-docker.pkg.dev/oss-fuzz/unsafe/{name}' def get_logs_url(build_id): """Returns url that displays the build logs.""" return ( f'https://oss-fuzz-gcb-logs.storage.googleapis.com/log-{build_id}.txt') def get_gcb_url(build_id, cloud_project='oss-fuzz'): """Returns url where logs are displayed for the build.""" return ( 'https://console.cloud.google.com/cloud-build/builds;region=us-central1/' f'{build_id}?project={cloud_project}') def get_build_info_lines(build_id, cloud_project='oss-fuzz'): """Returns a list of strings with build information.""" gcb_url = get_gcb_url(build_id, cloud_project) log_url = get_logs_url(build_id) return [ f'GCB Build ID: {build_id}', f'GCB Build URL: {gcb_url}', f'Log URL: {log_url}', ] def get_runner_image_name(test_image_suffix=None, base_image_tag=None): """Returns the runner image that should be used. Returns the testing image if |test_image_suffix|. """ image = f'gcr.io/{BASE_IMAGES_PROJECT}/base-runner' # For trial builds, the version is embedded in the suffix. if test_image_suffix: image += '-' + test_image_suffix return image # For local/manual runs, the version is passed as a tag. # Only add a tag if it's specified and not 'legacy', as 'legacy' implies # 'latest', which is the default behavior. if base_image_tag and base_image_tag != 'legacy': image += f":{base_image_tag}" return image def get_build_body( # pylint: disable=too-many-arguments steps, timeout, body_overrides, tags, use_build_pool=True, experiment=False): """Helper function to create a build from |steps|.""" if 'GCB_OPTIONS' in os.environ: options = yaml.safe_load(os.environ['GCB_OPTIONS']) else: options = {} if use_build_pool: if experiment: options['pool'] = {'name': OSS_FUZZ_EXPERIMENTS_BUILDPOOL_NAME} # TODO: refactor all of this to make this less ugly. elif 'indexer' in tags: options['pool'] = {'name': OSS_FUZZ_INDEXER_BUILDPOOL_NAME} else: options['pool'] = {'name': OSS_FUZZ_BUILDPOOL_NAME} build_body = { 'steps': steps, 'timeout': str(timeout) + 's', 'options': options, 'logsBucket': 'gs://oss-fuzz-gcb-logs', } if tags: build_body['tags'] = tags if body_overrides is None: body_overrides = {} for key, value in body_overrides.items(): build_body[key] = value return build_body def _tgz_local_build(oss_fuzz_project, temp_tgz_path): """Prepare a .tgz containing the files required to build `oss_fuzz_project`.""" # Just the projects/ dir should be sufficient. project_rel_path = os.path.join('projects', oss_fuzz_project) with tarfile.open(temp_tgz_path, 'w:gz') as tar: tar.add(os.path.join(OSS_FUZZ_ROOT, project_rel_path), arcname=project_rel_path) def run_build( # pylint: disable=too-many-arguments, too-many-locals oss_fuzz_project, steps, credentials, cloud_project, timeout, body_overrides=None, tags=None, use_build_pool=True, experiment=False): """Runs the build.""" build_body = get_build_body(steps, timeout, body_overrides, tags, use_build_pool=use_build_pool, experiment=experiment) if experiment: with tempfile.NamedTemporaryFile(suffix='source.tgz') as tgz_file: # Archive the necessary files for the build. _tgz_local_build(oss_fuzz_project, tgz_file.name) gcs_client = storage.Client() # This is the automatically created Cloud Build bucket for Cloud Build. bucket_name = gcs_client.project + '_cloudbuild' bucket = gcs_client.bucket(bucket_name) blob_name = f'source/{str(uuid.uuid4())}.tgz' blob = bucket.blob(blob_name) logging.info(f'Uploading project to {bucket_name}/{blob_name}') blob.upload_from_filename(tgz_file.name) build_body['source'] = { 'storageSource': { 'bucket': bucket_name, 'object': blob_name, } } cloudbuild = cloud_build('cloudbuild', 'v1', credentials=credentials, cache_discovery=False, client_options=REGIONAL_CLIENT_OPTIONS) build_info = cloudbuild.projects().builds().create(projectId=cloud_project, body=build_body).execute() return build_info['metadata']['build'] def wait_for_build(build_id, credentials, cloud_project): """Wait for a GCB build.""" cloudbuild = cloud_build('cloudbuild', 'v1', credentials=credentials, cache_discovery=False, client_options=REGIONAL_CLIENT_OPTIONS) while True: try: status = cloudbuild.projects().builds().get(projectId=cloud_project, id=build_id).execute() if status.get('status') in ('SUCCESS', 'FAILURE', 'TIMEOUT', 'INTERNAL_ERROR', 'EXPIRED', 'CANCELLED'): # Build done. return except (googleapiclient.errors.HttpError, BrokenPipeError): pass time.sleep(15) # Avoid rate limiting. def cancel_build(build_id, credentials, cloud_project): """Cancel a GCB build""" cloudbuild = cloud_build('cloudbuild', 'v1', credentials=credentials, cache_discovery=False, client_options=REGIONAL_CLIENT_OPTIONS) cloudbuild.projects().builds().cancel(projectId=cloud_project, id=build_id).execute() ================================================ FILE: infra/build/functions/build_project.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #!/usr/bin/env python3 """Starts project build on Google Cloud Builder. Usage: build_project.py """ import argparse from dataclasses import dataclass import datetime import json import logging import os import posixpath import re import shlex import sys from typing import Optional import oauth2client.client import six import yaml import build_lib FUZZING_BUILD_TYPE = 'fuzzing' INDEXER_BUILD_TYPE = 'indexer' GCB_LOGS_BUCKET = 'oss-fuzz-gcb-logs' GCB_EXPERIMENT_LOGS_BUCKET = 'oss-fuzz-gcb-experiment-logs' DEFAULT_ARCHITECTURES = ['x86_64'] DEFAULT_ENGINES = ['libfuzzer', 'afl', 'honggfuzz', 'centipede'] DEFAULT_SANITIZERS = ['address', 'undefined'] LATEST_VERSION_FILENAME = 'latest.version' LATEST_VERSION_CONTENT_TYPE = 'text/plain' QUEUE_TTL_SECONDS = 60 * 60 * 24 # 24 hours. PROJECTS_DIR = os.path.abspath( os.path.join(__file__, os.path.pardir, os.path.pardir, os.path.pardir, os.path.pardir, 'projects')) DEFAULT_OSS_FUZZ_REPO = 'https://github.com/google/oss-fuzz.git' # Used if build logs are uploaded to a separate place. LOCAL_BUILD_LOG_PATH = '/workspace/build.log' BUILD_SUCCESS_MARKER = '/workspace/build.succeeded' _CACHED_IMAGE = ('us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/' '{name}-ofg-cached-{sanitizer}') _CACHED_SANITIZERS = ('address', 'coverage') _INDEXED_CONTAINER_NAME = 'indexed-container' _TRACING_CONTAINER_NAME = 'tracing-container' @dataclass class Config: testing: bool = False test_image_suffix: Optional[str] = None base_image_tag: Optional[str] = None repo: Optional[str] = DEFAULT_OSS_FUZZ_REPO branch: Optional[str] = None parallel: bool = False upload: bool = True experiment: bool = False # TODO(ochang): This should be different per engine+sanitizer combination. upload_build_logs: Optional[str] = None build_type: Optional[str] = None fuzzing_engine: Optional[str] = None fuzz_target: Optional[str] = None # Allow the WORKDIR to be commented out for OSS-Fuzz-Gen, which creates new # Dockerfiles that inherit from cached verisons of the project images. # e.g. # FROM us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/proj-ofg-cached-address # # WORKDIR foo # COPY new_target.c /src/proj/ # # Because the WORKDIR is already set in the parent image and can be a relative # path, we can't set it again in the new Dockerfile. # However, we still need to know what the value is (for GCB), so we leave it # commented. WORKDIR_REGEX = re.compile(r'\s*#?\s*WORKDIR\s*([^\s]+)') class Build: # pylint: disable=too-few-public-methods """Class representing the configuration for a build.""" def __init__(self, fuzzing_engine, sanitizer, architecture): self.fuzzing_engine = fuzzing_engine self.sanitizer = sanitizer self.architecture = architecture self.targets_list_filename = build_lib.get_targets_list_filename( self.sanitizer) @property def is_arm(self): """Returns True if CPU architecture is ARM-based.""" return self.architecture == 'aarch64' @property def out(self): """Returns the out directory for the build.""" return posixpath.join( '/workspace/out/', f'{self.fuzzing_engine}-{self.sanitizer}-{self.architecture}') def get_project_data(project_name): """(Local only) Returns a tuple containing the contents of the project.yaml and Dockerfile of |project_name|. Raises a FileNotFoundError if there is no Dockerfile for |project_name|.""" project_dir = os.path.join(PROJECTS_DIR, project_name) dockerfile_path = os.path.join(project_dir, 'Dockerfile') try: with open(dockerfile_path) as dockerfile: dockerfile = dockerfile.read() except FileNotFoundError: raise project_yaml_path = os.path.join(project_dir, 'project.yaml') with open(project_yaml_path, 'r') as project_yaml_file_handle: project_yaml_contents = project_yaml_file_handle.read() project_yaml = yaml.safe_load(project_yaml_contents) return project_yaml, dockerfile def get_sanitizer_strings(sanitizers): """Accepts the sanitizers field from project.yaml where some sanitizers can be defined as experimental. Returns a list of sanitizers.""" processed_sanitizers = [] for sanitizer in sanitizers: if isinstance(sanitizer, six.string_types): processed_sanitizers.append(sanitizer) elif isinstance(sanitizer, dict): processed_sanitizers.extend(sanitizer.keys()) return processed_sanitizers def set_default_sanitizer_for_centipede(project_yaml): """Adds none as a sanitizer for centipede in yaml if it does not exist yet.""" # Centipede requires a separate unsanitized binary to use sanitized ones. if ('centipede' in project_yaml['fuzzing_engines'] and project_yaml['sanitizers'] and 'none' not in project_yaml['sanitizers']): project_yaml['sanitizers'].append('none') class Project: # pylint: disable=too-many-instance-attributes """Class representing an OSS-Fuzz project.""" def __init__(self, name, project_yaml, dockerfile): project_yaml = project_yaml.copy() set_yaml_defaults(project_yaml) self.name = name self.workdir = workdir_from_dockerfile(dockerfile) self._sanitizers = project_yaml['sanitizers'] self.disabled = project_yaml['disabled'] self.architectures = project_yaml['architectures'] self.fuzzing_engines = project_yaml['fuzzing_engines'] self.coverage_extra_args = project_yaml['coverage_extra_args'] self.labels = project_yaml['labels'] self.fuzzing_language = project_yaml['language'] self.run_tests = project_yaml['run_tests'] self.base_os_version = project_yaml.get('base_os_version', 'legacy') if 'main_repo' in project_yaml: self.main_repo = project_yaml['main_repo'] else: self.main_repo = '' self.indexer_targets = project_yaml.get('indexer', {}).get('targets', []) # This is set to enable build infra to use cached images (which are # specific to a sanitizer). # TODO: find a better way to handle this. self.cached_sanitizer = None # This is used by OSS-Fuzz-Gen, which generates fake project names for each # benchmark. We still need access to the real project name in some cases. self.real_name = self.name @property def sanitizers(self): """Returns processed sanitizers.""" assert isinstance(self._sanitizers, list) return get_sanitizer_strings(self._sanitizers) @property def image(self): """Returns the docker image for the project.""" return f'gcr.io/{build_lib.IMAGE_PROJECT}/{self.name}' @property def cached_image(self): return _CACHED_IMAGE.format(name=self.real_name, sanitizer=self.cached_sanitizer) def get_last_step_id(steps): """Returns the id of the last step in |steps|.""" return steps[-1]['id'] def set_yaml_defaults(project_yaml): """Sets project.yaml's default parameters.""" project_yaml.setdefault('disabled', False) project_yaml.setdefault('architectures', DEFAULT_ARCHITECTURES) project_yaml.setdefault('sanitizers', DEFAULT_SANITIZERS) project_yaml.setdefault('fuzzing_engines', DEFAULT_ENGINES) project_yaml.setdefault('run_tests', True) project_yaml.setdefault('coverage_extra_args', '') project_yaml.setdefault('labels', {}) # Adds 'none' as a sanitizer for centipede to the project yaml by default, # because Centipede always requires a separate build of unsanitized binary. set_default_sanitizer_for_centipede(project_yaml) def is_supported_configuration(build): """Check if the given configuration is supported.""" fuzzing_engine_info = build_lib.ENGINE_INFO[build.fuzzing_engine] if build.architecture == 'i386' and build.sanitizer != 'address': return False # TODO(jonathanmetzman): UBSan should be easy to support. if build.architecture == 'aarch64' and (build.sanitizer not in {'address', 'hwaddress'}): return False return (build.sanitizer in fuzzing_engine_info.supported_sanitizers and build.architecture in fuzzing_engine_info.supported_architectures) def workdir_from_dockerfile(dockerfile): """Parses WORKDIR from the Dockerfile.""" dockerfile_lines = dockerfile.split('\n') for line in dockerfile_lines: match = re.match(WORKDIR_REGEX, line) if match: # We need to escape '$' since they're used for subsitutions in Container # Builer builds. return match.group(1).replace('$', '$$') return '/src' def get_datetime_now(): """Returns datetime.datetime.now(). Used for mocking.""" return datetime.datetime.now() def get_env(fuzzing_language, build, project_name=None): """Returns an environment for building. The environment is returned as a list and is suitable for use as the "env" parameter in a GCB build step. The environment variables are based on the values of |fuzzing_language| and |build.""" env_dict = { 'FUZZING_LANGUAGE': fuzzing_language, 'FUZZING_ENGINE': build.fuzzing_engine, 'SANITIZER': build.sanitizer, 'ARCHITECTURE': build.architecture, # Set HOME so that it doesn't point to a persisted volume (see # https://github.com/google/oss-fuzz/issues/6035). 'HOME': '/root', 'OUT': build.out, } if project_name is not None: env_dict['PROJECT_NAME'] = project_name return list(sorted([f'{key}={value}' for key, value in env_dict.items()])) def get_compile_step(project, build, env, parallel, upload_build_logs=None, allow_failure=False): """Returns the GCB step for compiling |projects| fuzzers using |env|. The type of build is specified by |build|.""" failure_msg = ( '*' * 80 + '\\nFailed to build.\\nTo reproduce, run:\\n' f'python infra/helper.py build_image {project.name}\\n' 'python infra/helper.py build_fuzzers --sanitizer ' f'{build.sanitizer} --engine {build.fuzzing_engine} --architecture ' f'{build.architecture} {project.name}\\n' + '*' * 80) compile_output_redirect = '' if upload_build_logs: # Also write a build success marker because this step needs to succeed first # for a subsequent step to upload the log. compile_output_redirect = ( f'&> {LOCAL_BUILD_LOG_PATH} && touch {BUILD_SUCCESS_MARKER}') compile_step = { 'name': project.image, 'env': env, 'args': [ 'bash', '-c', # Remove /out to make sure there are non instrumented binaries. # `cd /src && cd {workdir}` (where {workdir} is parsed from the # Dockerfile). Container Builder overrides our workdir so we need # to add this step to set it back. (f'rm -r /out && cd /src && cd {project.workdir} && ' f'mkdir -p {build.out} && compile {compile_output_redirect}|| ' f'(echo "{failure_msg}" && false)'), ], 'id': get_id('compile', build), } if upload_build_logs or allow_failure: # The failure will be reported in a subsequent step. compile_step['allowFailure'] = True build_lib.dockerify_run_step(compile_step, build, use_architecture_image_name=build.is_arm) maybe_add_parallel(compile_step, build_lib.get_srcmap_step_id(), parallel) return compile_step def maybe_add_parallel(step, wait_for_id, parallel): """Makes |step| run immediately after |wait_for_id| if |parallel|. Mutates |step|.""" if not parallel: return step['waitFor'] = wait_for_id def get_id(step_type, build): """Returns a unique step id based on |step_type| and |build|. Useful for parallelizing builds.""" return (f'{step_type}-{build.fuzzing_engine}-{build.sanitizer}' f'-{build.architecture}') def get_build_steps( # pylint: disable=too-many-locals, too-many-statements, too-many-branches, too-many-arguments project_name, project_yaml, dockerfile, config, additional_env=None, use_caching=False, timestamp=None): """Returns build steps for project.""" project = Project(project_name, project_yaml, dockerfile) return get_build_steps_for_project(project, config, additional_env=additional_env, use_caching=use_caching, timestamp=timestamp), None def get_build_steps_for_project(project, config, additional_env=None, use_caching=False, timestamp=None): """Returns build steps for project.""" if not timestamp: timestamp = get_datetime_now() timestamp = timestamp.strftime('%Y%m%d%H%M') if use_caching: # For cached builds: the cache images are sanitizer-specific, so we need to # do a rebuild prior to each compile. build_steps = [] else: # Non-cached builds just use a single builder image to build all sanitizers. build_steps = build_lib.get_project_image_steps( project.name, project.image, project.fuzzing_language, config=config, architectures=project.architectures, experiment=config.experiment) # Sort engines to make AFL first to test if libFuzzer has an advantage in # finding bugs first since it is generally built first. for fuzzing_engine in sorted(project.fuzzing_engines): # Sort sanitizers and architectures so order is determinisitic (good for # tests). for sanitizer in sorted(project.sanitizers): if use_caching and sanitizer in _CACHED_SANITIZERS: project.cached_sanitizer = sanitizer build_steps.extend( build_lib.get_project_image_steps( project.name, project.image, project.fuzzing_language, config=config, architectures=project.architectures, experiment=config.experiment, cache_image=project.cached_image)) # Build x86_64 before i386. for architecture in reversed(sorted(project.architectures)): build = Build(fuzzing_engine, sanitizer, architecture) if not is_supported_configuration(build): continue env = get_env(project.fuzzing_language, build) if additional_env: env.extend(additional_env) compile_step = get_compile_step(project, build, env, config.parallel, config.upload_build_logs) build_steps.append(compile_step) if config.upload_build_logs: build_steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', LOCAL_BUILD_LOG_PATH, config.upload_build_logs ], }) # Report the build failure if it happened. build_steps.append({ 'name': project.image, 'args': [ 'bash', '-c', f'cat {LOCAL_BUILD_LOG_PATH} && test -f {BUILD_SUCCESS_MARKER}' ], }) if project.run_tests: failure_msg = ( '*' * 80 + '\\nBuild checks failed.\\n' 'To reproduce, run:\\n' f'python infra/helper.py build_image {project.name}\\n' 'python infra/helper.py build_fuzzers --sanitizer ' f'{build.sanitizer} --engine {build.fuzzing_engine} ' f'--architecture {build.architecture} {project.name}\\n' 'python infra/helper.py check_build --sanitizer ' f'{build.sanitizer} --engine {build.fuzzing_engine} ' f'--architecture {build.architecture} {project.name}\\n' + '*' * 80) # Test fuzz targets. runner_image_name = build_lib.get_runner_image_name( config.test_image_suffix, config.base_image_tag) test_step = { 'name': runner_image_name, 'env': env, 'args': [ 'bash', '-c', f'test_all.py || (echo "{failure_msg}" && false)' ], 'id': get_id('build-check', build) } build_lib.dockerify_run_step(test_step, build) maybe_add_parallel(test_step, get_last_step_id(build_steps), config.parallel) build_steps.append(test_step) if project.labels: # Write target labels. build_steps.append({ 'name': project.image, 'env': env, 'args': [ '/usr/local/bin/write_labels.py', json.dumps(project.labels), build.out, ], }) build_steps.extend([ # Generate targets list. { 'name': build_lib.get_runner_image_name(config.test_image_suffix, config.base_image_tag), 'env': env, 'args': [ 'bash', '-c', f'targets_list > /workspace/{build.targets_list_filename}' ], } ]) if config.upload: upload_steps = get_upload_steps(project, build, timestamp, config.testing) build_steps.extend(upload_steps) return build_steps def _indexer_built_image_name(name: str): # TODO(ochang): Write this to a tar (via docker image save) and upload this to # GCS. return f'us-docker.pkg.dev/oss-fuzz/indexer/{name}' def _tracer_built_image_name(name: str): # TODO(ochang): Write this to a tar (via docker image save) and upload this to # GCS. return f'us-docker.pkg.dev/oss-fuzz/tracer/{name}' def _create_indexed_build_steps(project, build, timestamp, env, indexer_targets, build_type='indexer'): """Creates the build steps for a specific indexer type.""" if build_type == 'indexer': container_name = _INDEXED_CONTAINER_NAME image_name = _indexer_built_image_name(project.name) build_script_command = '/opt/indexer/index_build.py' elif build_type == 'tracer': container_name = _TRACING_CONTAINER_NAME image_name = _tracer_built_image_name(project.name) build_script_command = ( '/opt/indexer/index_build.py --tracing-instrumentation') else: raise ValueError(f'Unknown build_type: {build_type}') if indexer_targets: build_script_command += ' -t ' + ','.join(indexer_targets) command_sequence = [ 'cd /src', f'cd {project.workdir}', f'mkdir -p {build.out}', build_script_command, # Enable re-building both the project and the indexes. 'cp -n /usr/local/bin/replay_build.sh $$SRC/', # The following complicated dance is so that the resulting image works # in a standalone way without the mount paths GCB installs by default # (/workspace). # First we save the $OUT contents into /outbak. 'mkdir -p /outbak && cp -a $$OUT/* /outbak/ && ' # Create a link from /out to the actual $OUT. 'rm -rf /out && ln -s $$OUT /out && ' # Unmount GCB's mount paths. 'umount /workspace && mkdir -p $$OUT && ' # Restore the actual contents into $OUT after unmounting. 'mv -T /outbak $$OUT && ' # Unshallow the main repository so we have easy access to the git history. f'/usr/local/bin/unshallow_repos.py {project.main_repo}', ] build_step = { 'name': project.image, 'args': ['bash', '-c', ' && '.join(command_sequence)], 'env': env, } build_lib.dockerify_run_step(build_step, build, use_architecture_image_name=build.is_arm, container_name=container_name) upload_steps = [] # TODO: Don't upload anything if we're in trial build. if build_type == 'indexer': prefix = f'indexer_indexes/{project.name}/{timestamp}/' signed_policy_document = build_lib.get_signed_policy_document_upload_prefix( 'clusterfuzz-builds', prefix) curl_signed_args = shlex.join( build_lib.signed_policy_document_curl_args(signed_policy_document)) upload_steps = [ { # TODO(metzman): Make sure not to include other tars, and support # .tar.gz 'name': get_uploader_image(), 'args': [ '-c', f'for tar in {build.out}/*.tar; ' f'do curl {curl_signed_args} -F key="{prefix}$(basename $tar)" ' f'-F file="@$tar" https://{signed_policy_document.bucket}' '.storage.googleapis.com; ' 'done' ], 'entrypoint': 'bash', 'allowFailure': True, }, build_lib.upload_using_signed_policy_document('/workspace/srcmap.json', f'{prefix}srcmap.json', signed_policy_document) ] push_image_steps = [ { 'name': build_lib.DOCKER_TOOL_IMAGE, 'args': [ 'container', 'commit', '-c', 'ENV REPLAY_ENABLED 1', container_name, image_name + f':{timestamp}' ], }, { 'name': build_lib.DOCKER_TOOL_IMAGE, 'args': ['tag', image_name + f':{timestamp}', image_name], }, { 'name': build_lib.DOCKER_TOOL_IMAGE, 'args': ['push', '--all-tags', image_name], }, ] return [build_step] + upload_steps + push_image_steps def get_indexer_build_steps(project_name, project_yaml, dockerfile, config, additional_env=None, use_caching=False, timestamp=None): """Get indexer build steps.""" project = Project(project_name, project_yaml, dockerfile) if project.fuzzing_language not in {'c', 'c++'}: return [], f'Project "{project.name}" is written in "{project.fuzzing_language}", indexer is not supported yet.' if not timestamp: timestamp = get_datetime_now() timestamp = timestamp.strftime('%Y%m%d%H%M') build_steps = build_lib.get_project_image_steps( project.name, project.image, project.fuzzing_language, config=config, architectures=project.architectures, experiment=config.experiment) build = Build('none', 'address', 'x86_64') env = get_env(project.fuzzing_language, build, project.name) env.append('INDEXER_BUILD=1') env.append('CAPTURE_REPLAY_SCRIPT=1') indexer_steps = _create_indexed_build_steps(project, build, timestamp, env, project.indexer_targets, build_type='indexer') tracer_steps = _create_indexed_build_steps(project, build, timestamp, env, project.indexer_targets, build_type='tracer') return build_steps + indexer_steps + tracer_steps, None def get_targets_list_upload_step(bucket, project, build, uploader_image): """Returns the step to upload targets_list for |build| of |project| to |bucket|.""" targets_list_url = build_lib.get_signed_url( build_lib.get_targets_list_url(bucket, project.name, build.sanitizer)) return { 'name': uploader_image, 'args': [ f'/workspace/{build.targets_list_filename}', targets_list_url, ], } def get_uploader_image(): """Returns the uploader base image in |base_images_project|.""" return f'gcr.io/{build_lib.BASE_IMAGES_PROJECT}/uploader' def get_upload_steps(project, build, timestamp, testing): """Returns the steps for uploading the fuzzer build specified by |project| and |build|. Uses |timestamp| for naming the uploads. Uses |testing| for determining which image to use for the upload.""" bucket = build_lib.get_upload_bucket(build.fuzzing_engine, build.architecture, testing) stamped_name = '-'.join([project.name, build.sanitizer, timestamp]) zip_file = stamped_name + '.zip' upload_url = build_lib.get_signed_url( build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, project.name, zip_file)) stamped_srcmap_file = stamped_name + '.srcmap.json' srcmap_url = build_lib.get_signed_url( build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, project.name, stamped_srcmap_file)) latest_version_file = '-'.join( [project.name, build.sanitizer, LATEST_VERSION_FILENAME]) latest_version_url = build_lib.GCS_UPLOAD_URL_FORMAT.format( bucket, project.name, latest_version_file) latest_version_url = build_lib.get_signed_url( latest_version_url, content_type=LATEST_VERSION_CONTENT_TYPE) uploader_image = get_uploader_image() upload_steps = [ # Zip binaries. { 'name': project.image, 'args': ['bash', '-c', f'cd {build.out} && zip -r {zip_file} *'], }, # Upload srcmap. { 'name': uploader_image, 'args': [ '/workspace/srcmap.json', srcmap_url, ], }, # Upload binaries. { 'name': uploader_image, 'args': [ os.path.join(build.out, zip_file), upload_url, ], }, # Upload targets list. get_targets_list_upload_step(bucket, project, build, uploader_image), # Upload the latest.version file. build_lib.http_upload_step(zip_file, latest_version_url, LATEST_VERSION_CONTENT_TYPE), # Cleanup. get_cleanup_step(project, build), ] return upload_steps def get_cleanup_step(project, build): """Returns the step for cleaning up after doing |build| of |project|.""" return { 'name': project.image, 'args': [ 'bash', '-c', 'rm -r ' + build.out, ], } # pylint: disable=no-member,too-many-arguments def run_build(oss_fuzz_project, build_steps, credentials, build_type, cloud_project='oss-fuzz', extra_tags=None, experiment=False, timeout=None): """Run the build for given steps on cloud build. |build_steps| are the steps to run. |credentials| are are used to authenticate to GCB and build in |cloud_project|. |oss_fuzz_project| and |build_type| are used to tag the build in GCB so the build can be queried for debugging purposes.""" if extra_tags is None: extra_tags = [] tags = [oss_fuzz_project + '-' + build_type, build_type, oss_fuzz_project] tags.extend(extra_tags) if timeout is None: timeout = build_lib.BUILD_TIMEOUT bucket = GCB_LOGS_BUCKET if not experiment else GCB_EXPERIMENT_LOGS_BUCKET body_overrides = { 'logsBucket': bucket, 'queueTtl': str(QUEUE_TTL_SECONDS) + 's', } return build_lib.run_build(oss_fuzz_project, build_steps, credentials, cloud_project, timeout, body_overrides=body_overrides, tags=tags, experiment=experiment) def parse_args(description, args): """Parses command line arguments (or args if it is not None) and returns them. Suitable for a build script.""" parser = argparse.ArgumentParser(sys.argv[0], description=description) parser.add_argument('projects', help='Projects.', nargs='+') parser.add_argument('--testing', action='store_true', required=False, default=False, help='Upload to testing buckets.') parser.add_argument('--test-image-suffix', required=False, default=None, help='Use testing base-images.') parser.add_argument('--repo', required=False, default=DEFAULT_OSS_FUZZ_REPO, help='Use specified OSS-Fuzz repo.') parser.add_argument('--branch', required=False, default=None, help='Use specified OSS-Fuzz branch.') parser.add_argument('--parallel', action='store_true', required=False, default=False, help='Do builds in parallel.') parser.add_argument('--experiment', action='store_true', required=False, default=False, help='Configuration for experiments.') parser.add_argument('--fuzzing-engine', required=False, default='libfuzzer', help='Fuzzing engine name.') parser.add_argument('--fuzz-target', required=False, default='', help='Fuzz target name.') return parser.parse_args(args) def create_config(args, build_type, base_image_tag=None): """Create a Config object from parsed command line |args|.""" upload = not args.experiment return Config(testing=args.testing, test_image_suffix=args.test_image_suffix, base_image_tag=base_image_tag, branch=args.branch, parallel=args.parallel, upload=upload, experiment=args.experiment, build_type=build_type, fuzzing_engine=args.fuzzing_engine, fuzz_target=args.fuzz_target) def build_script_main(script_description, get_build_steps_func, build_type, args=None): """Gets arguments from command line using |script_description| as helpstring description or from args. Gets build_steps using |get_build_steps_func| and then runs those steps on GCB, tagging the builds with |build_type|. Returns 0 on success, 1 on failure.""" args = parse_args(script_description, args) logging.basicConfig(level=logging.INFO) credentials = oauth2client.client.GoogleCredentials.get_application_default() error = False for project_name in args.projects: try: project_yaml, dockerfile_contents = get_project_data(project_name) except FileNotFoundError: logging.error('Couldn\'t get project data. Skipping %s.', project_name) error = True continue base_image_tag = project_yaml.get('base_os_version', 'legacy') if base_image_tag == 'legacy': base_image_tag = None config = create_config(args, build_type, base_image_tag=base_image_tag) steps, _ = get_build_steps_func(project_name, project_yaml, dockerfile_contents, config) if not steps: logging.error('No steps. Skipping %s.', project_name) error = True continue run_build(project_name, steps, credentials, build_type, experiment=args.experiment) return 0 if not error else 1 def main(): """Build and run projects.""" return build_script_main('Builds a project on GCB.', get_build_steps, FUZZING_BUILD_TYPE) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/build_project_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for build_project.""" import json import os import sys import unittest from unittest import mock from pyfakefs import fake_filesystem_unittest FUNCTIONS_DIR = os.path.dirname(__file__) sys.path.append(FUNCTIONS_DIR) # pylint: disable=wrong-import-position import build_project import test_utils # pylint: disable=no-member class TestRequestCoverageBuilds(fake_filesystem_unittest.TestCase): """Unit tests for sync.""" def setUp(self): self.maxDiff = None # pylint: disable=invalid-name self.setUpPyfakefs() @mock.patch('build_lib.get_signed_url', return_value='test_url') @mock.patch('build_project.get_datetime_now', return_value=test_utils.FAKE_DATETIME) @mock.patch('build_lib.get_unique_build_step_image_id', return_value='UNIQUE_ID') def test_get_build_steps(self, mock_url, mock_get_datetime_now, mock_get_id): """Test for get_build_steps.""" del mock_url, mock_get_datetime_now project_yaml_contents = ( 'language: c++\n' 'sanitizers:\n' ' - address\n' ' - memory\n' ' - undefined\n' 'architectures:\n' ' - x86_64\n' ' - i386\n' ' - aarch64\n' 'main_repo: https://github.com/google/oss-fuzz.git\n') self.fs.create_dir(test_utils.PROJECT_DIR) test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents) expected_build_steps_file_path = test_utils.get_test_data_file_path( 'expected_build_steps.json') self.fs.add_real_file(expected_build_steps_file_path) with open(expected_build_steps_file_path) as expected_build_steps_file: expected_build_steps = json.load(expected_build_steps_file) config = build_project.Config(upload=True) project_yaml, dockerfile = build_project.get_project_data( test_utils.PROJECT) build_steps, _ = build_project.get_build_steps(test_utils.PROJECT, project_yaml, dockerfile, config) self.assertEqual(build_steps, expected_build_steps) @mock.patch('build_lib.get_signed_url', return_value='test_url') @mock.patch('build_project.get_datetime_now', return_value=test_utils.FAKE_DATETIME) @mock.patch('build_lib.get_unique_build_step_image_id', return_value='UNIQUE_ID') def test_get_centipede_build_steps(self, mock_url, mock_get_datetime_now, mock_get_id): """Test for get_build_steps of centipede.""" del mock_url, mock_get_datetime_now # The none sanitizer should be added automatically when other sanitizers are # specified by the users. project_yaml_contents = ( 'language: c++\n' 'fuzzing_engines:\n' ' - centipede\n' 'sanitizers:\n' ' - address\n' 'architectures:\n' ' - x86_64\n' 'main_repo: https://github.com/google/centipede.git\n') self.fs.create_dir(test_utils.PROJECT_DIR) test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents) expected_build_steps_file_path = test_utils.get_test_data_file_path( 'expected_centipede_build_steps.json') self.fs.add_real_file(expected_build_steps_file_path) with open(expected_build_steps_file_path) as expected_build_steps_file: expected_build_steps = json.load(expected_build_steps_file) config = build_project.Config(upload=True) project_yaml, dockerfile = build_project.get_project_data( test_utils.PROJECT) build_steps, _ = build_project.get_build_steps(test_utils.PROJECT, project_yaml, dockerfile, config) self.assertEqual(build_steps, expected_build_steps) @mock.patch('build_lib.get_signed_url', return_value='test_url') @mock.patch('build_project.get_datetime_now', return_value=test_utils.FAKE_DATETIME) @mock.patch('build_lib.get_unique_build_step_image_id', return_value='UNIQUE_ID') def test_get_build_steps_ubuntu_24_04(self, mock_url, mock_get_datetime_now, mock_get_id): """Test for get_build_steps with ubuntu-24-04.""" del mock_url, mock_get_datetime_now project_yaml_contents = ( 'language: c++\n' 'base_os_version: ubuntu-24-04\n' 'sanitizers:\n' ' - address\n' ' - memory\n' ' - undefined\n' 'architectures:\n' ' - x86_64\n' ' - i386\n' ' - aarch64\n' 'main_repo: https://github.com/google/oss-fuzz.git\n') self.fs.create_dir(test_utils.PROJECT_DIR) test_utils.create_project_data(test_utils.PROJECT, project_yaml_contents) expected_build_steps_file_path = test_utils.get_test_data_file_path( 'expected_build_steps_ubuntu_24_04.json') self.fs.add_real_file(expected_build_steps_file_path) with open(expected_build_steps_file_path) as expected_build_steps_file: expected_build_steps = json.load(expected_build_steps_file) config = build_project.Config(upload=True) project_yaml, dockerfile = build_project.get_project_data( test_utils.PROJECT) config.base_image_tag = project_yaml.get('base_os_version') build_steps, _ = build_project.get_build_steps(test_utils.PROJECT, project_yaml, dockerfile, config) self.assertEqual(build_steps, expected_build_steps) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/datastore_entities.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud datastore entity classes.""" from google.cloud import ndb # pylint: disable=too-few-public-methods class Project(ndb.Model): """Represents an integrated OSS-Fuzz project.""" name = ndb.StringProperty() schedule = ndb.StringProperty() project_yaml_contents = ndb.TextProperty() dockerfile_contents = ndb.TextProperty() # pylint: disable=too-few-public-methods class GithubCreds(ndb.Model): """Represents GitHub credentials.""" client_id = ndb.StringProperty() client_secret = ndb.StringProperty() # pylint: disable=too-few-public-methods class BuildsHistory(ndb.Model): """Container for build history of projects.""" build_tag = ndb.StringProperty() project = ndb.StringProperty() build_ids = ndb.StringProperty(repeated=True) class LastSuccessfulBuild(ndb.Model): """Container for storing last successful build of project.""" build_tag = ndb.StringProperty() project = ndb.StringProperty() build_id = ndb.StringProperty() finish_time = ndb.StringProperty() ================================================ FILE: infra/build/functions/deploy.sh ================================================ #!/bin/bash -ex # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ BASE_IMAGE_JOB_TOPIC=schedule-base-image-build BASE_IMAGE_SCHEDULER_JOB=base-image-scheduler BASE_IMAGE_SCHEDULE="0 3 * * *" BASE_IMAGE_MESSAGE="Start base image build" BUILD_JOB_TOPIC=request-build COVERAGE_BUILD_JOB_TOPIC=request-coverage-build INTROSPECTOR_BUILD_JOB_TOPIC=request-introspector-build SYNC_JOB_TOPIC=schedule-project-sync SYNC_SCHEDULER_JOB=sync-scheduler SYNC_JOB_SCHEDULE="*/30 * * * *" SYNC_MESSAGE="Start Sync" function deploy_pubsub_topic { topic=$1 project=$2 if ! gcloud pubsub topics describe $topic --project $project ; then gcloud pubsub topics create $topic \ --project $project fi } function deploy_scheduler { scheduler_name=$1 schedule="$2" topic=$3 message="$4" project=$5 if gcloud scheduler jobs describe $scheduler_name --project $project ; then gcloud scheduler jobs update pubsub $scheduler_name \ --project $project \ --schedule "$schedule" \ --topic $topic \ --message-body "$message" else gcloud scheduler jobs create pubsub $scheduler_name \ --project $project \ --schedule "$schedule" \ --topic $topic \ --message-body "$message" fi } function deploy_cloud_function { name=$1 entry_point=$2 topic=$3 project=$4 gcloud functions deploy $name \ --entry-point $entry_point \ --trigger-topic $topic \ --runtime python311 \ --project $project \ --timeout 540 \ --region us-central1 \ --set-env-vars GCP_PROJECT=$project,FUNCTION_REGION=us-central1 \ --max-instances 1 \ --memory 4096MB } if [ $# == 1 ]; then PROJECT_ID=$1 else echo -e "\n Usage ./deploy.sh "; exit; fi deploy_pubsub_topic $BUILD_JOB_TOPIC $PROJECT_ID deploy_pubsub_topic $SYNC_JOB_TOPIC $PROJECT_ID deploy_pubsub_topic $BASE_IMAGE_JOB_TOPIC $PROJECT_ID deploy_pubsub_topic $COVERAGE_BUILD_JOB_TOPIC $PROJECT_ID deploy_pubsub_topic $INTROSPECTOR_BUILD_JOB_TOPIC $PROJECT_ID deploy_scheduler $SYNC_SCHEDULER_JOB \ "$SYNC_JOB_SCHEDULE" \ $SYNC_JOB_TOPIC \ "$SYNC_MESSAGE" \ $PROJECT_ID deploy_scheduler $BASE_IMAGE_SCHEDULER_JOB \ "$BASE_IMAGE_SCHEDULE" \ $BASE_IMAGE_JOB_TOPIC \ "$BASE_IMAGE_MESSAGE" \ $PROJECT_ID deploy_cloud_function sync \ sync \ $SYNC_JOB_TOPIC \ $PROJECT_ID deploy_cloud_function base-image-build \ build_base_images \ $BASE_IMAGE_JOB_TOPIC \ $PROJECT_ID deploy_cloud_function request-build \ build_project \ $BUILD_JOB_TOPIC \ $PROJECT_ID deploy_cloud_function request-coverage-build \ coverage_build \ $COVERAGE_BUILD_JOB_TOPIC \ $PROJECT_ID deploy_cloud_function request-introspector-build \ introspector_build \ $INTROSPECTOR_BUILD_JOB_TOPIC \ $PROJECT_ID gcloud datastore indexes create index.yaml --project $PROJECT_ID ================================================ FILE: infra/build/functions/fuzzbench.py ================================================ #!/usr/bin/env python3 # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Does fuzzbench runs on Google Cloud Build.""" import json import logging import os import random import requests import sys import build_lib import build_project import ood_upload_corpus INFRA_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(os.path.join(INFRA_DIR, 'cifuzz')) import clusterfuzz_deployment import config_utils FUZZBENCH_BUILD_TYPE = 'coverage' FUZZBENCH_PATH = '/fuzzbench' GCB_WORKSPACE_DIR = '/workspace' MAX_FUZZING_DURATION = 1800 OOD_OUTPUT_CORPUS_DIR = f'{GCB_WORKSPACE_DIR}/ood_output_corpus' OOD_CRASHES_DIR = f'{GCB_WORKSPACE_DIR}/crashes' def get_engine_project_image_name(fuzzing_engine, project): """Returns the name of an image used to build |project| with |fuzzing_engine|.""" return f'gcr.io/oss-fuzz-base/{fuzzing_engine}/{project.name}' def get_ood_image_name(fuzzing_engine, project): """Returns the name of an OSS-Fuzz on Demand image.""" # TODO(andrenribeiro): Abstract the OOD image name generation to a separate # location. return f'us-central1-docker.pkg.dev/oss-fuzz/unsafe/ood/{fuzzing_engine}/{project.name}' def get_gcs_public_corpus_url(project, fuzz_target_name): """Returns the url of a public gcs seed corpus.""" return ( f'https://storage.googleapis.com/{project.name}-backup.clusterfuzz-' f'external.appspot.com/corpus/libFuzzer/{project.name}_{fuzz_target_name}' f'/public.zip') def get_latest_libfuzzer_build(project_name): """Returns the latest LibFuzzer build gsutil URI and the build file name.""" # Mandatory environment variables required to obtain the latest build name os.environ['CIFUZZ_TEST'] = 'True' os.environ['OSS_FUZZ_PROJECT_NAME'] = project_name config = config_utils.RunFuzzersConfig() deployment = clusterfuzz_deployment.OSSFuzz(config, None) latest_build_filename = deployment.get_latest_build_name() build_uri = f'gs://clusterfuzz-builds/{project_name}/{latest_build_filename}' return build_uri, latest_build_filename def get_fuzz_target_name(project_name): """Use Fuzz Introspector Web API to choose a random fuzz target for |project_name|""" header = {'accept': 'application/json'} url = f'https://introspector.oss-fuzz.com/api/harness-source-and-executable?project={project_name}' resp = requests.get(url, headers=header) resp.raise_for_status() resp_json = resp.json() if resp_json['result'] == 'error' or len(resp_json['pairs']) < 1: logging.info(f'There are no fuzz targets available for {project_name}') return None idx = random.randint(0, len(resp_json['pairs']) - 1) fuzz_target_name = resp_json['pairs'][idx]['executable'] logging.info(f'Using fuzz target: {fuzz_target_name}') return fuzz_target_name def get_env(project, build, fuzz_target_name): """Gets the environment for fuzzbench/oss-fuzz-on-demand.""" env = build_project.get_env(project.fuzzing_language, build) env.append(f'FUZZBENCH_PATH={FUZZBENCH_PATH}') env.append('FORCE_LOCAL=1') env.append(f'PROJECT={project.name}') env.append('OSS_FUZZ_ON_DEMAND=1') env.extend([ f'FUZZ_TARGET={fuzz_target_name}', f'BENCHMARK={project.name}', 'EXPERIMENT_TYPE=bug' ]) return env def get_fuzzbench_setup_steps(): """Returns the build steps required to set up fuzzbench on oss-fuzz-on-demand build.""" fuzzbench_setup_steps = [ { 'args': [ 'clone', 'https://github.com/google/fuzzbench', '--depth', '1', FUZZBENCH_PATH ], 'name': 'gcr.io/cloud-builders/git', 'volumes': [{ 'name': 'fuzzbench_path', 'path': FUZZBENCH_PATH, }], }, { 'name': 'gcr.io/cloud-builders/docker', 'args': ['pull', 'gcr.io/oss-fuzz-base/base-builder-fuzzbench'] }, { # TODO(metzman): Don't overwrite base-builder 'name': 'gcr.io/cloud-builders/docker', 'args': [ 'tag', 'gcr.io/oss-fuzz-base/base-builder-fuzzbench', 'gcr.io/oss-fuzz-base/base-builder' ] }, ] return fuzzbench_setup_steps def get_build_fuzzers_steps(fuzzing_engine, project, env): """Returns the build_fuzzers step to build |project| with |fuzzing_engine|, for fuzzbench/oss-fuzz-on-demand.""" steps = [] engine_dockerfile_path = os.path.join(FUZZBENCH_PATH, 'fuzzers', fuzzing_engine, 'builder.Dockerfile') build_args = [ 'build', '--build-arg', f'parent_image=gcr.io/oss-fuzz/{project.name}', '--tag', get_engine_project_image_name(fuzzing_engine, project), '--file', engine_dockerfile_path, os.path.join(FUZZBENCH_PATH, 'fuzzers') ] engine_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': build_args, 'volumes': [{ 'name': 'fuzzbench_path', 'path': FUZZBENCH_PATH, }], } steps.append(engine_step) project_yaml_path = f'{GCB_WORKSPACE_DIR}/oss-fuzz/projects/{project.name}/project.yaml' benchmark_yaml_path = '/benchmark.yaml' compile_project_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'env': env, 'volumes': [{ 'name': 'fuzzbench_path', 'path': FUZZBENCH_PATH, }], 'args': [ 'bash', '-c', # Remove /out to make sure there are non instrumented binaries. # `cd /src && cd {workdir}` (where {workdir} is parsed from the # Dockerfile). Container Builder overrides our workdir so we need # to add this step to set it back. (f'cp {project_yaml_path} {benchmark_yaml_path} && ' f'rm -r /out && cd /src && cd {project.workdir} && ' 'mkdir -p $$OUT && compile'), ], } steps.append(compile_project_step) return steps def get_gcs_corpus_steps(fuzzing_engine, project, env_dict): """Returns the build steps to download corpus from GCS (if it exists) and use it on oss-fuzz-on-demand.""" steps = [] corpus_path = f'{GCB_WORKSPACE_DIR}/gcs_corpus' corpus_filename = 'public.zip' fuzz_target_name = env_dict["FUZZ_TARGET"] corpus_url = get_gcs_public_corpus_url(project, fuzz_target_name) download_and_use_corpus_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'args': [ 'bash', '-c', f'if wget --spider --quiet {corpus_url}; then ' f' echo "URL exists. Downloading..." && mkdir -p {corpus_path} && ' f' cd {corpus_path} && wget -O {corpus_filename} {corpus_url};' f'else ' f' echo "URL does not exist. Skipping download."; ' f'fi' ], } steps.append(download_and_use_corpus_step) seed_corpus_path = f'{env_dict["OUT"]}/{fuzz_target_name}_seed_corpus.zip' gcs_corpus_path = f'{corpus_path}/{corpus_filename}' update_corpus_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'args': [ 'bash', '-c', f'if test -f "{gcs_corpus_path}"; then ' f' mv {gcs_corpus_path} {seed_corpus_path} && ' f' rm -r {corpus_path};' f'else ' f' echo "There is no corpus to update."; ' f'fi' ], } steps.append(update_corpus_step) return steps def get_build_ood_image_steps(fuzzing_engine, project, env_dict): """Returns the build steps to create the oss-fuzz-on-demand self-contained image. Executing docker run on this image starts the fuzzing process.""" steps = [] fuzzbench_run_fuzzer_path = f'{GCB_WORKSPACE_DIR}/oss-fuzz/infra/base-images/base-builder-fuzzbench/fuzzbench_run_fuzzer' copy_runtime_essential_files_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'volumes': [{ 'name': 'fuzzbench_path', 'path': FUZZBENCH_PATH, }], 'args': [ 'bash', '-c', f'cp {fuzzbench_run_fuzzer_path} ' f'{GCB_WORKSPACE_DIR}/fuzzbench_run_fuzzer.sh && ' f'cp -r {FUZZBENCH_PATH} {GCB_WORKSPACE_DIR} && ' f'ls {GCB_WORKSPACE_DIR}' ], } steps.append(copy_runtime_essential_files_step) ood_image = get_ood_image_name(fuzzing_engine, project) fuzzer_runtime_dockerfile_path = os.path.join( GCB_WORKSPACE_DIR + FUZZBENCH_PATH, 'fuzzers', fuzzing_engine, 'runner.Dockerfile') build_runtime_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': [ 'build', '--tag', ood_image, '--file', fuzzer_runtime_dockerfile_path, os.path.join(GCB_WORKSPACE_DIR + FUZZBENCH_PATH, 'fuzzers') ] } steps.append(build_runtime_step) oss_fuzz_on_demand_dockerfile_path = f'{GCB_WORKSPACE_DIR}/oss-fuzz/infra/build/functions/ood.Dockerfile' build_out_path_without_workspace = env_dict["OUT"][10:] build_ood_image_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': [ 'build', '--tag', ood_image, '--file', oss_fuzz_on_demand_dockerfile_path, '--build-arg', f'BENCHMARK={env_dict["BENCHMARK"]}', '--build-arg', f'BUILD_OUT_PATH={build_out_path_without_workspace}', '--build-arg', f'FUZZBENCH_PATH={FUZZBENCH_PATH}', '--build-arg', f'FUZZING_ENGINE={env_dict["FUZZING_ENGINE"]}', '--build-arg', f'FUZZ_TARGET={env_dict["FUZZ_TARGET"]}', '--build-arg', f'MAX_TOTAL_TIME={MAX_FUZZING_DURATION}', '--build-arg', f'OOD_OUTPUT_CORPUS_DIR={OOD_OUTPUT_CORPUS_DIR}', '--build-arg', f'runtime_image={ood_image}', GCB_WORKSPACE_DIR ] } steps.append(build_ood_image_step) return steps def get_push_and_run_ood_image_steps(fuzzing_engine, project, env_dict): """Returns the build steps to push and run the oss-fuzz-on-demand self-contained image.""" steps = [] ood_image = get_ood_image_name(fuzzing_engine, project) push_ood_image_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': ['push', ood_image] } steps.append(push_ood_image_step) # This step also copies fuzzing output corpus to $OOD_OUTPUT_CORPUS_DIR run_ood_image_step = { 'name': 'gcr.io/cloud-builders/docker', 'args': [ 'run', '-v', f'{GCB_WORKSPACE_DIR}:{GCB_WORKSPACE_DIR}', ood_image ] } steps.append(run_ood_image_step) return steps def get_extract_crashes_steps(fuzzing_engine, project, env_dict): """Returns the build steps to download a LibFuzzer build and use it to extract crashes from the fuzzing output.""" steps = [] libfuzzer_build_dir = f'{GCB_WORKSPACE_DIR}/libfuzzer_build/' create_libfuzzer_build_dir_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'args': ['bash', '-c', f'mkdir -p {libfuzzer_build_dir}'] } steps.append(create_libfuzzer_build_dir_step) build_uri, build_filename = get_latest_libfuzzer_build(project.name) download_libfuzzer_build_step = { 'name': 'gcr.io/cloud-builders/gsutil', 'args': ['-m', 'cp', '-r', build_uri, libfuzzer_build_dir] } steps.append(download_libfuzzer_build_step) extract_crashes_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'args': [ 'bash', '-c', f'unzip {libfuzzer_build_dir}{build_filename} ' f'-d {libfuzzer_build_dir} && mkdir -p {OOD_CRASHES_DIR} && ' f'{libfuzzer_build_dir}{env_dict["FUZZ_TARGET"]} {OOD_OUTPUT_CORPUS_DIR} ' f'-runs=0 -artifact_prefix={OOD_CRASHES_DIR}/; ' f'echo "\nCrashes found by OOD:" && ls {OOD_CRASHES_DIR} ' ], } steps.append(extract_crashes_step) return steps def get_upload_testcase_steps(project, env_dict): """Returns the build steps to upload a testcase in the ClusterFuzz External upload testcase endpoint.""" steps = [] access_token_file_path = f'{GCB_WORKSPACE_DIR}/at.txt' get_access_token_step = { 'name': 'google/cloud-sdk', 'args': [ 'bash', '-c', f'gcloud auth print-access-token > {access_token_file_path}' ] } steps.append(get_access_token_step) upload_testcase_script_path = f'{GCB_WORKSPACE_DIR}/oss-fuzz/infra/build/functions/ood_upload_testcase.py' job_name = f'libfuzzer_asan_{project.name}' target_name = f'{project.name}_{env_dict["FUZZ_TARGET"]}' upload_testcase_step = { 'name': 'python:3.8', 'args': [ 'python3', upload_testcase_script_path, OOD_CRASHES_DIR, job_name, target_name, access_token_file_path ] } steps.append(upload_testcase_step) return steps def get_upload_corpus_steps(fuzzing_engine, project, env_dict): """Returns the build steps to upload corpus elements to GCS.""" steps = [] upload_corpus_script_path = f'{GCB_WORKSPACE_DIR}/oss-fuzz/infra/build/functions/ood_upload_corpus.py' doc, path_prefix = ood_upload_corpus.get_corpus_signed_policy_document( project.name, env_dict['FUZZ_TARGET']) doc_str = json.dumps(doc.__dict__) num_uploads = '1000' upload_corpus_step = { 'name': get_engine_project_image_name(fuzzing_engine, project), 'args': [ 'python3', upload_corpus_script_path, doc_str, path_prefix, OOD_OUTPUT_CORPUS_DIR, num_uploads ] } steps.append(upload_corpus_step) return steps def get_build_steps( # pylint: disable=too-many-locals, too-many-arguments project_name, project_yaml, dockerfile_lines, config): """Returns build steps for project.""" project = build_project.Project(project_name, project_yaml, dockerfile_lines) if project.disabled: logging.info('Project "%s" is disabled.', project.name) return [] fuzz_target_name = config.fuzz_target if not fuzz_target_name: fuzz_target_name = get_fuzz_target_name(project.name) if not fuzz_target_name: return None steps = get_fuzzbench_setup_steps() steps += build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config) build = build_project.Build(config.fuzzing_engine, 'address', 'x86_64') env = get_env(project, build, fuzz_target_name) steps += get_build_fuzzers_steps(config.fuzzing_engine, project, env) env_dict = {string.split('=')[0]: string.split('=')[1] for string in env} steps += get_gcs_corpus_steps(config.fuzzing_engine, project, env_dict) steps += get_build_ood_image_steps(config.fuzzing_engine, project, env_dict) steps += get_push_and_run_ood_image_steps(config.fuzzing_engine, project, env_dict) steps += get_extract_crashes_steps(config.fuzzing_engine, project, env_dict) steps += get_upload_testcase_steps(project, env_dict) steps += get_upload_corpus_steps(config.fuzzing_engine, project, env_dict) return steps def main(): """Build and run fuzzbench for OSS-Fuzz projects.""" return build_project.build_script_main('Does a FuzzBench run.', get_build_steps, FUZZBENCH_BUILD_TYPE) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/fuzzbench_local_run.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Does fuzzbench runs locally.""" # TODO It is worth checking https://github.com/google/oss-fuzz/pull/12833 for # insights on making this code less specific for OSS-Fuzz on Demand. import os import re import shutil import subprocess import sys import tempfile import time import build_lib import build_project import fuzzbench GCB_WORKSPACE_DIR = fuzzbench.GCB_WORKSPACE_DIR FUZZBENCH_PATH = fuzzbench.FUZZBENCH_PATH DOCKER_BUILDER_IMAGE = 'gcr.io/cloud-builders/docker' LOG_FILE_PATH = os.path.join(os.path.dirname(__file__), 'fuzzbench_local_run_log.txt') def run_step_locally(temp_dir, local_fuzzbench_path, step, i, log_file): """Run a build step locally.""" log_file.write(f'--- Step {i}: ---\n') log_file.write(f'Step_details:\n{step}\n') log_file.write('------\n') image_name = step.get('name') args = step.get('args', []) env_list = step.get('env', []) volumes = step.get('volumes', []) if not image_name: raise Exception(f'Error: Step {i} has no "name" field.\n') if not args: raise Exception(f'Error: Step {i} has no "args" field.\n') if args[0] == 'push': log_file.write(f'Skipping step {i} because it is a push step.\n') return step_container_work_dir = os.path.join(GCB_WORKSPACE_DIR, step.get('dir', '')) # This is needed because when running a container inside of a container, the # mount point of the second container is also in the host machine and not in # the first container if args[0] == 'run' and args[1] == '-v' and GCB_WORKSPACE_DIR in args[2]: args[2] = args[2].replace(GCB_WORKSPACE_DIR, temp_dir, 1) docker_command = ['docker', 'run', '--rm', '--cpus=0.5'] docker_command.extend(['-w', step_container_work_dir]) docker_command.extend(['-v', f'{temp_dir}:{GCB_WORKSPACE_DIR}']) mount_fuzzbench = any(vol.get('path') == FUZZBENCH_PATH for vol in volumes) if mount_fuzzbench: docker_command.extend(['-v', f'{local_fuzzbench_path}:{FUZZBENCH_PATH}']) if image_name == DOCKER_BUILDER_IMAGE: docker_command.extend(['-v', '/var/run/docker.sock:/var/run/docker.sock']) for env_var in env_list: docker_command.extend(['-e', env_var]) docker_command.append(image_name) docker_command.extend(args) # Local runs use local changes if 'https://github.com/google/oss-fuzz.git' in docker_command: oss_fuzz_dir = os.path.dirname( os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) docker_command = ['cp', '-r', f'{oss_fuzz_dir}', f'{temp_dir}'] if '$$' in docker_command[-1]: docker_command[-1] = re.sub(r'\$\$([a-zA-Z0-9_]+)', r'"$\1"', docker_command[-1]) log_file.write(f'Executing Docker Command:\n') log_file.write( ' '.join(map(lambda x: f'"{x}"' if ' ' in x else x, docker_command)) + '\n') log_file.flush() try: start_time = time.time() result = subprocess.run(docker_command, check=True, capture_output=True, text=True) end_time = time.time() log_file.write( f'--- Container STDOUT ---\n' f'{result.stdout}' f'--- Container STDERR ---\n' f'{result.stderr}' f'--- Step {i} completed successfully --- Took {end_time - start_time}s\n\n' ) except subprocess.CalledProcessError as e: if e.returncode == 124: end_time = time.time() log_file.write( f'Caught timeout: {e}\n' f'--- Step {i} completed with a timeout --- Took {end_time - start_time}s\n\n' ) else: log_file.write('--- DOCKER RUN ERROR ---\n' f'Docker command failed with exit code {e.returncode}\n' '--- Container STDOUT ---\n' f'{e.stdout}' '--- Container STDERR ---\n' f'{e.stderr}' f'Failed Step Details: {step}\n' f'Failed Docker Command: {" ".join(docker_command)}\n' f'Execution failed at step {i}\n') sys.exit() except Exception as e: log_file.write('--- UNEXPECTED ERROR ---\n' f'An unexpected error occurred during step {i}: {e}\n' f'Failed Step Details: {step}\n' f'Failed Docker Command: {" ".join(docker_command)}\n' f'Execution failed at step {i}\n') sys.exit() def remove_temp_dir_content(temp_dir, i, log_file): """Remove temporary directory using Docker to avoid permission issues.""" remove_temp_dir_step = { 'name': 'bash', 'args': ['sh', '-c', f'rm -rf {GCB_WORKSPACE_DIR}/*'] } run_step_locally(temp_dir, '', remove_temp_dir_step, i, log_file) def run_steps_locally(steps, temp_dir=None, log_file_path=LOG_FILE_PATH, testing=False): """Executes Cloud Build steps locally by running each step's command inside the specified container using 'docker run'. Log is written in to |log_file_path|""" with open(log_file_path, 'w') as log_file: if not steps: log_file.write('No steps provided to run.\n') return log_file.write(f'--- Starting Local Execution with Docker ---\n') log_file.flush() if not temp_dir: temp_dir = tempfile.mkdtemp() local_fuzzbench_path = os.path.join(temp_dir, 'fuzzbench_vol') os.makedirs(local_fuzzbench_path, exist_ok=True) for i, step in enumerate(steps): run_step_locally(temp_dir, local_fuzzbench_path, step, i, log_file) log_file.flush() log_file.write(f'--- Local Execution Finished ---\n') if not testing: log_file.write(f'--- Starting temporary directory removal ---\n') remove_temp_dir_content(temp_dir, i + 1, log_file) shutil.rmtree(temp_dir) log_file.write(f'--- Removed temporary directory ---\n') def main(): """Local fuzzbench build and run for OSS-Fuzz projects. Excludes steps on which non local storage is written.""" args = build_project.parse_args('local_fuzzbench_run', None) project_name = args.projects[0] project_yaml, dockerfile_lines = build_project.get_project_data(project_name) config = build_project.create_config(args, fuzzbench.FUZZBENCH_BUILD_TYPE) project = build_project.Project(project_name, project_yaml, dockerfile_lines) fuzz_target_name = config.fuzz_target if not fuzz_target_name: fuzz_target_name = fuzzbench.get_fuzz_target_name(project.name) if not fuzz_target_name: raise Exception( 'Fuzz Introspector Web API did not find a fuzz target. Provide one') steps = fuzzbench.get_fuzzbench_setup_steps() steps += build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config) build = build_project.Build(config.fuzzing_engine, 'address', 'x86_64') env = fuzzbench.get_env(project, build, fuzz_target_name) steps += fuzzbench.get_build_fuzzers_steps(config.fuzzing_engine, project, env) env_dict = {string.split('=')[0]: string.split('=')[1] for string in env} steps += fuzzbench.get_gcs_corpus_steps(config.fuzzing_engine, project, env_dict) steps += fuzzbench.get_build_ood_image_steps(config.fuzzing_engine, project, env_dict) steps += fuzzbench.get_push_and_run_ood_image_steps(config.fuzzing_engine, project, env_dict) steps += fuzzbench.get_extract_crashes_steps(config.fuzzing_engine, project, env_dict) run_steps_locally(steps) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/fuzzbench_test.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for fuzzbench.py.""" import logging import os import requests import sys import shutil import tempfile import unittest from unittest import mock import build_lib import build_project import fuzzbench import fuzzbench_local_run LOG_FILE_PATH = os.path.join(os.path.dirname(__file__), 'fuzzbench_test_log.txt') class GetFuzzTargetName(unittest.TestCase): """Tests for get_fuzz_target_name.""" @mock.patch('requests.get') @mock.patch('random.randint') @mock.patch('logging.info') def test_successful_retrieval(self, mock_logging_info, mock_randint, mock_get): """Tests successful retrieval and random selection of a fuzz target.""" mock_response = mock.MagicMock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = { 'result': 'success', 'pairs': [{ 'executable': 'target1' }, { 'executable': 'target2' }, { 'executable': 'target3' }] } mock_get.return_value = mock_response mock_randint.return_value = 1 project_name = 'test_project' fuzz_target = fuzzbench.get_fuzz_target_name(project_name) self.assertEqual(fuzz_target, 'target2') mock_get.assert_called_once_with( f'https://introspector.oss-fuzz.com/api/harness-source-and-executable?project={project_name}', headers={'accept': 'application/json'}) mock_randint.assert_called_once_with(0, 2) mock_logging_info.assert_called_with('Using fuzz target: target2') @mock.patch('requests.get') @mock.patch('logging.info') def test_api_error(self, mock_logging_info, mock_get): """Tests handling of API errors during the request.""" mock_response = mock.MagicMock() mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError( 'API Error') mock_get.return_value = mock_response project_name = 'error_project' with self.assertRaises(requests.exceptions.HTTPError): fuzzbench.get_fuzz_target_name(project_name) mock_get.assert_called_once_with( f'https://introspector.oss-fuzz.com/api/harness-source-and-executable?project={project_name}', headers={'accept': 'application/json'}) mock_logging_info.assert_not_called() @mock.patch('requests.get') @mock.patch('logging.info') def test_no_fuzz_targets(self, mock_logging_info, mock_get): """Tests the case where the API returns an error indicating no fuzz targets.""" mock_response = mock.MagicMock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = {'result': 'error'} mock_get.return_value = mock_response project_name = 'empty_project' fuzz_target = fuzzbench.get_fuzz_target_name(project_name) self.assertIsNone(fuzz_target) mock_get.assert_called_once_with( f'https://introspector.oss-fuzz.com/api/harness-source-and-executable?project={project_name}', headers={'accept': 'application/json'}) mock_logging_info.assert_called_once_with( f'There are no fuzz targets available for {project_name}') @mock.patch('requests.get') @mock.patch('logging.info') def test_empty_pairs(self, mock_logging_info, mock_get): """Tests the case where the API returns an empty list of fuzz target pairs.""" mock_response = mock.MagicMock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = {'result': 'success', 'pairs': []} mock_get.return_value = mock_response project_name = 'empty_pairs_project' fuzz_target = fuzzbench.get_fuzz_target_name(project_name) self.assertIsNone(fuzz_target) mock_get.assert_called_once_with( f'https://introspector.oss-fuzz.com/api/harness-source-and-executable?project={project_name}', headers={'accept': 'application/json'}) mock_logging_info.assert_called_once_with( f'There are no fuzz targets available for {project_name}') class FuzzbenchRunsTest(unittest.TestCase): """Tests for fuzzbench runs.""" def setUp(self): """Creates a temporary directory for fuzzbench runs tests.""" self.temp_dir = tempfile.mkdtemp() def tearDown(self): """Removes temporary directory.""" with open(LOG_FILE_PATH, 'w', encoding='utf-8') as log_file: fuzzbench_local_run.remove_temp_dir_content(self.temp_dir, -1, log_file) shutil.rmtree(self.temp_dir) os.remove(LOG_FILE_PATH) def _fuzzbench_test_setup(self): """Returns necessary variables for fuzzbench runs setup.""" project_name = 'example' fuzz_target_name = 'do_stuff_fuzzer' project_yaml, dockerfile_lines = build_project.get_project_data( project_name) project = build_project.Project(project_name, project_yaml, dockerfile_lines) fuzzing_engine = 'mopt' build = build_project.Build(fuzzing_engine, 'address', 'x86_64') env = fuzzbench.get_env(project, build, fuzz_target_name) return fuzzing_engine, project, env def _assert_log_content(self, frequency): """Asserts the frequency of 'successfully' in the log content.""" with open(LOG_FILE_PATH, 'r', encoding='utf-8') as log_file: log_content = log_file.read() count = log_content.count('successfully') self.assertGreaterEqual(count, frequency) def _fuzzbench_setup_steps_test(self, fuzzing_engine, project, env): """Test for fuzzbench setup steps.""" steps = fuzzbench.get_fuzzbench_setup_steps() fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(3) def _get_project_image_steps_test(self, fuzzing_engine, project, env_dict): """Test for project image steps.""" config = build_project.Config(build_type=fuzzbench.FUZZBENCH_BUILD_TYPE, fuzzing_engine=fuzzing_engine, fuzz_target=env_dict['FUZZ_TARGET']) steps = build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config) fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(3) def _build_fuzzers_steps_test(self, fuzzing_engine, project, env): """Test for build fuzzers steps.""" steps = fuzzbench.get_build_fuzzers_steps(fuzzing_engine, project, env) fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(2) def _corpus_steps_test(self, fuzzing_engine, project, env_dict): """Test for corpus steps.""" steps = fuzzbench.get_gcs_corpus_steps(fuzzing_engine, project, env_dict) fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(2) def _build_ood_image_steps_test(self, fuzzing_engine, project, env_dict): """Test for build ood image steps.""" steps = fuzzbench.get_build_ood_image_steps(fuzzing_engine, project, env_dict) # Limit fuzzing time for testing build_ood_image_args = steps[2]['args'] for i in range(len(build_ood_image_args)): if 'MAX_TOTAL_TIME' in build_ood_image_args[i]: build_ood_image_args[i] = 'MAX_TOTAL_TIME=5' fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(3) def _run_ood_image_step_test(self, fuzzing_engine, project, env_dict): """Test for run ood image step.""" steps = fuzzbench.get_push_and_run_ood_image_steps(fuzzing_engine, project, env_dict) test_steps = [] for step in steps: if step['args'][0] != 'push': test_steps.append(step) fuzzbench_local_run.run_steps_locally(test_steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(1) def _extract_crashes_steps_test(self, fuzzing_engine, project, env_dict): """Test for extract crashes steps.""" steps = fuzzbench.get_extract_crashes_steps(fuzzing_engine, project, env_dict) for step in steps: if '-runs=0 -artifact_prefix=' in step['args'][-1]: step['args'] = ['timeout', '10'] + step['args'] fuzzbench_local_run.run_steps_locally(steps, self.temp_dir, LOG_FILE_PATH, testing=True) self._assert_log_content(3) def test_fuzzbench_runs(self): """Test for fuzzbench runs.""" fuzzing_engine, project, env = self._fuzzbench_test_setup() env_dict = {string.split('=')[0]: string.split('=')[1] for string in env} self._fuzzbench_setup_steps_test(fuzzing_engine, project, env) self._get_project_image_steps_test(fuzzing_engine, project, env_dict) self._build_fuzzers_steps_test(fuzzing_engine, project, env) self._corpus_steps_test(fuzzing_engine, project, env_dict) # Disable OOD test as it seems broken # TODO(Jonathan) (David) fix this test. # self._build_ood_image_steps_test(fuzzing_engine, project, env_dict) # self._run_ood_image_step_test(fuzzing_engine, project, env_dict) self._extract_crashes_steps_test(fuzzing_engine, project, env_dict) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/build/functions/gcb.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Entrypoint for CI into trial_build or oss_fuzz_on_demand. This script will get the command from the last PR comment containing "/gcbrun" and pass it to trial_build.py or oss_fuzz_on_demand. On trial_build.py it will build test versions of base-images, push them and then do test builds using those images. """ import logging import os import sys import github import trial_build import oss_fuzz_on_demand TRIGGER_COMMAND = '/gcbrun' TRIAL_BUILD_COMMAND_STR = f'{TRIGGER_COMMAND} trial_build.py ' OSS_FUZZ_ON_DEMAND_COMMAND_STR = f'{TRIGGER_COMMAND} oss_fuzz_on_demand.py ' SKIP_COMMAND_STR = f'{TRIGGER_COMMAND} skip' def get_comments(pull_request_number): """Returns comments on the GitHub Pull request referenced by |pull_request_number|.""" github_obj = github.Github() repo = github_obj.get_repo('google/oss-fuzz') pull = repo.get_pull(pull_request_number) pull_comments = list(pull.get_comments()) issue = repo.get_issue(pull_request_number) issue_comments = list(issue.get_comments()) # Github only returns comments if from the pull object when a pull request is # open. If it is a draft, it will only return comments from the issue object. return pull_comments + issue_comments def get_latest_gcbrun_command(comments): """Gets the last /gcbrun comment from comments.""" for comment in reversed(comments): # This seems to get comments on code too. body = comment.body if body.startswith(SKIP_COMMAND_STR): return None if not body.startswith(TRIAL_BUILD_COMMAND_STR) and ( not body.startswith(OSS_FUZZ_ON_DEMAND_COMMAND_STR)): continue if len(body) == len(TRIAL_BUILD_COMMAND_STR) or ( len(body) == len(OSS_FUZZ_ON_DEMAND_COMMAND_STR)): return None return body[len(TRIGGER_COMMAND):].strip().split(' ') return None def exec_command_from_github(args): """Executes the gcbrun command for trial_build.py or oss_fuzz_on_demand.py in the most recent command on |pull_request_number|. Returns True on success, False on failure.""" pull_request_number = int(os.environ['PULL_REQUEST_NUMBER']) branch = os.environ['BRANCH'] repo = os.environ['REPO'] comments = get_comments(pull_request_number) full_command = get_latest_gcbrun_command(comments) if full_command is None: logging.info('Trial build not requested.') # Create a flag file to indicate that the build was skipped. with open('trial_build_skipped.flag', 'w') as f: pass return None command_file = full_command[0] command = full_command[1:] command.extend(['--repo', repo]) # Set the branch so that the trial_build builds the projects from the PR # branch. command.extend(['--branch', branch]) command.extend(args) logging.info('Executing command: %s.', command) if command_file == OSS_FUZZ_ON_DEMAND_COMMAND_STR.split(' ')[1]: return oss_fuzz_on_demand.oss_fuzz_on_demand_main(command) == 0 return trial_build.trial_build_main(command, local_base_build=False) def main(): """Entrypoint for GitHub CI into trial_build.py""" logging.basicConfig(level=logging.INFO) logging.getLogger('oauth2client').setLevel(logging.WARNING) args = sys.argv[1:] result = exec_command_from_github(args) if result or result is None: return 0 return 1 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/gcb_test.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for gcb.py.""" import unittest from unittest import mock import gcb class GetLatestGCBrunCommandTest(unittest.TestCase): """Tests for get_latest_gcbrun_command.""" def test_command_parsing(self): """Tests that commands from GitHub comments are parsed properly.""" mock_comment = mock.MagicMock() mock_comment.body = ('/gcbrun trial_build.py aiohttp --sanitizer ' 'coverage address --fuzzing-engine libfuzzer') comments = [mock_comment] expected_command = [ 'trial_build.py', 'aiohttp', '--sanitizer', 'coverage', 'address', '--fuzzing-engine', 'libfuzzer' ] actual_command = gcb.get_latest_gcbrun_command(comments) self.assertEqual(expected_command, actual_command) def test_last_comment(self): """Tests that the last comment from the GitHub PR is considered the command.""" mock_comment_1 = mock.MagicMock() mock_comment_1.body = ('/gcbrun trial_build.py aiohttp --sanitizer ' 'coverage address --fuzzing-engine libfuzzer') mock_comment_2 = mock.MagicMock() mock_comment_2.body = ('/gcbrun trial_build.py skcms --sanitizer ' 'coverage address --fuzzing-engine libfuzzer') comments = [mock_comment_1, mock_comment_2] expected_command = [ 'trial_build.py', 'skcms', '--sanitizer', 'coverage', 'address', '--fuzzing-engine', 'libfuzzer' ] actual_command = gcb.get_latest_gcbrun_command(comments) self.assertEqual(expected_command, actual_command) def test_oss_fuzz_on_demand_command_parsing(self): """Tests that the OSS-Fuzz on demand commands from GitHub comments are parsed properly.""" mock_comment = mock.MagicMock() mock_comment.body = ('/gcbrun oss_fuzz_on_demand.py aiohttp --sanitizer ' 'coverage address --fuzzing-engine libfuzzer') comments = [mock_comment] expected_command = [ 'oss_fuzz_on_demand.py', 'aiohttp', '--sanitizer', 'coverage', 'address', '--fuzzing-engine', 'libfuzzer' ] actual_command = gcb.get_latest_gcbrun_command(comments) self.assertEqual(expected_command, actual_command) class ExecCommandFromGithubTest(unittest.TestCase): """Tests for exec_command_from_github.""" @mock.patch('os.environ', { 'PULL_REQUEST_NUMBER': '0', 'BRANCH': 'test_branch', 'REPO': 'test_repo' }) def test_exec_command(self): """Tests if exec_command_from_github is generating the correct command.""" test_cases = [ { "comments": [('/gcbrun oss_fuzz_on_demand.py aiohttp --sanitizer' 'coverage address --fuzzing-engine libfuzzer')], "latest_command": [ 'oss_fuzz_on_demand.py', 'aiohttp', '--sanitizer', 'coverage', 'address', '--fuzzing-engine', 'libfuzzer' ], "expected_command": [ 'aiohttp', '--sanitizer', 'coverage', 'address', '--fuzzing-engine', 'libfuzzer', '--repo', 'test_repo', '--branch', 'test_branch', '--version-tag', 'latest' ], "trial_build_called": False, }, { "comments": ['/gcbrun trial_build.py my_project'], "latest_command": ['trial_build.py', 'my_project'], "expected_command": [ 'my_project', '--repo', 'test_repo', '--branch', 'test_branch', '--version-tag', 'latest' ], "trial_build_called": True, }, { "comments": ['/gcbrun trial_build.py my_project'], "latest_command": None, "expected_command": [ 'my_project', '--repo', 'test_repo', '--branch', 'test_branch', '--version-tag', 'latest' ], "trial_build_called": True, }, ] for i, test_case in enumerate(test_cases): with self.subTest(i=i): with mock.patch( 'gcb.get_comments', return_value=test_case["comments"]), mock.patch( 'gcb.get_latest_gcbrun_command', return_value=test_case["latest_command"]), mock.patch( 'oss_fuzz_on_demand.oss_fuzz_on_demand_main') as ( mock_oss_fuzz_on_demand ), mock.patch('trial_build.trial_build_main') as ( mock_trial_build_trial_build_main): gcb.exec_command_from_github(['--version-tag', 'latest']) if test_case["latest_command"] == None: mock_trial_build_trial_build_main.assert_not_called() mock_oss_fuzz_on_demand.assert_not_called() else: if test_case["trial_build_called"]: mock_trial_build_trial_build_main.assert_called_once_with( test_case["expected_command"], local_base_build=False) mock_oss_fuzz_on_demand.assert_not_called() else: mock_trial_build_trial_build_main.assert_not_called() mock_oss_fuzz_on_demand.assert_called_once_with( test_case["expected_command"]) @mock.patch('os.environ', { 'PULL_REQUEST_NUMBER': '0', 'BRANCH': 'test_branch', 'REPO': 'test_repo' }) @mock.patch('gcb.get_comments', return_value=[('/gcbrun oss_fuzz_on_demand.py aiohttp --sanitizer' 'coverage address --fuzzing-engine libfuzzer')]) @mock.patch('gcb.get_latest_gcbrun_command', return_value=[ 'oss_fuzz_on_demand.py', 'aiohttp', '--fuzzing-engine', 'libfuzzer' ]) @mock.patch('trial_build.trial_build_main') @mock.patch('oss_fuzz_on_demand.oss_fuzz_on_demand_main') def test_build_script_main_args(self, mock_oss_fuzz_on_demand_main, mock_trial_build_main, mock_get_latest_gcbrun_command, mock_gcb_get_comments): """Tests for build_script_main args on oss_fuzz_on_demmand call.""" gcb.exec_command_from_github([]) mock_trial_build_main.assert_not_called() build_script_main_args = [ 'aiohttp', '--fuzzing-engine', 'libfuzzer', '--repo', 'test_repo', '--branch', 'test_branch' ] mock_oss_fuzz_on_demand_main.assert_called_once_with(build_script_main_args) ================================================ FILE: infra/build/functions/index.yaml ================================================ indexes: - kind: BuildsHistory properties: - name: build_tag - name: project ================================================ FILE: infra/build/functions/indexer_build_test.py ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unittests for indexer build steps.""" import sys import os import unittest from unittest import mock from pyfakefs import fake_filesystem_unittest FUNCTIONS_DIR = os.path.dirname(__file__) sys.path.append(FUNCTIONS_DIR) import build_project import build_lib class TestIndexerBuildSteps(fake_filesystem_unittest.TestCase): """Unittests for indexer build.""" def setUp(self): self.setUpPyfakefs() @mock.patch('build_lib.get_signed_policy_document_upload_prefix') @mock.patch('build_lib.signed_policy_document_curl_args') @mock.patch('build_lib.upload_using_signed_policy_document') @mock.patch('build_lib.get_project_image_steps') def test_get_indexer_build_steps(self, mock_get_project_image_steps, mock_upload_using_policy, mock_signed_policy_args, mock_get_policy_doc): """Test get_indexer_build_steps.""" mock_get_project_image_steps.return_value = [] mock_policy_doc = mock.Mock() mock_policy_doc.bucket = 'test-bucket' mock_get_policy_doc.return_value = mock_policy_doc mock_signed_policy_args.return_value = ['-F', 'policy=foo'] mock_upload_using_policy.return_value = {'name': 'upload_srcmap'} project_name = 'test-project' project_yaml = { 'language': 'c++', 'sanitizers': ['address'], 'architectures': ['x86_64'], 'main_repo': 'https://github.com/test/repo.git', 'indexer': { 'targets': ['target1'] } } dockerfile = '''FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get install -y make''' config = build_project.Config(upload=True, experiment=False) steps, reason = build_project.get_indexer_build_steps( project_name, project_yaml, dockerfile, config) indexer_step = None for step in steps: if 'args' in step and ('--name' in step['args'] and 'indexed-container' in step['args']): indexer_step = step break self.assertIsNotNone(indexer_step, "Indexer build step not found") bash_command = indexer_step['args'][-1] self.assertIn('unshallow_repos.py', bash_command) upload_step = None for step in steps: if 'args' in step and len(step['args']) >= 2 and isinstance( step['args'][1], str) and 'for tar in' in step['args'][1]: upload_step = step break self.assertIsNotNone(upload_step, "Upload step not found") upload_command = upload_step['args'][1] self.assertIn('for tar in /workspace/out/none-address-x86_64/*.tar', upload_command) self.assertIn('curl -F policy=foo', upload_command) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/build/functions/main.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud functions for build infrastructure.""" import base_images import project_sync import request_build import request_coverage_build import request_introspector_build def build_project(event, context): """Entry point for cloud function to requesting project builds.""" request_build.request_build(event, context) def sync(event, context): """Entry point for cloud function that syncs projects from github.""" project_sync.sync(event, context) def build_base_images(event, context): """Entry point for cloud function that builds base images.""" base_images.base_builder(event, context) def coverage_build(event, context): """Entry point for cloud function to build coverage reports.""" request_coverage_build.request_coverage_build(event, context) def introspector_build(event, context): """Entry point for cloud function to build introspector reports.""" request_introspector_build.request_introspector_build(event, context) ================================================ FILE: infra/build/functions/ood.Dockerfile ================================================ #!/usr/bin/env python3 # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ARG runtime_image FROM $runtime_image ARG BUILD_OUT_PATH ARG FUZZING_ENGINE ARG FUZZ_TARGET ARG FUZZBENCH_PATH ARG BENCHMARK ARG MAX_TOTAL_TIME ARG OOD_OUTPUT_CORPUS_DIR RUN mkdir -p /ood RUN mkdir -p /ood$FUZZBENCH_PATH COPY ./fuzzbench_run_fuzzer.sh /ood COPY .$BUILD_OUT_PATH /ood COPY .$FUZZBENCH_PATH /ood$FUZZBENCH_PATH ENV OUT=/ood ENV FUZZING_ENGINE=$FUZZING_ENGINE ENV FUZZ_TARGET=$FUZZ_TARGET ENV FUZZBENCH_PATH=/ood$FUZZBENCH_PATH ENV BENCHMARK=$BENCHMARK ENV MAX_TOTAL_TIME=$MAX_TOTAL_TIME ENV OOD_OUTPUT_CORPUS_DIR=$OOD_OUTPUT_CORPUS_DIR CMD ["bash", "-c", "source /ood/fuzzbench_run_fuzzer.sh && \ mkdir -p $OOD_OUTPUT_CORPUS_DIR && \ cp -r $OUTPUT_CORPUS_DIR $OOD_OUTPUT_CORPUS_DIR"] ================================================ FILE: infra/build/functions/ood_upload_corpus.py ================================================ #!/usr/bin/env python3 # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Upload OSS-Fuzz on Demand output corpus to GCS.""" import argparse import base64 import json import logging import os import pickle import requests import subprocess import sys import uuid import build_lib def get_corpus_signed_policy_document(project_name, fuzz_target_name): """Returns a signed policy document and a path prefix to upload corpus to GCS.""" bucket = f'{project_name}-corpus.clusterfuzz-external.appspot.com' path_prefix = f'libFuzzer/{fuzz_target_name}/' signed_policy_document = build_lib.get_signed_policy_document_upload_prefix( bucket, path_prefix) return signed_policy_document, path_prefix def upload_corpus_file(file_path, upload_path, doc): """Make a request to upload a corpus file to GCS.""" url = f'https://storage.googleapis.com/{doc.bucket}' print(f'Upload url: {url}') data = { 'key': upload_path, 'policy': doc.policy, 'x-goog-algorithm': doc.x_goog_algorithm, 'x-goog-date': doc.x_goog_date, 'x-goog-credential': doc.x_goog_credential, 'x-goog-signature': doc.x_goog_signature, } files = { 'file': open(file_path, 'rb'), } try: response = requests.post(url, data=data, files=files) response.raise_for_status() print(f'File uploaded successfully to {url}/{upload_path}') except requests.exceptions.RequestException as e: print(f'Error uploading file: {e}') if response is not None: print(f'Response status code: {response.status_code}') print(f'Response text: {response.text}') def get_files_path(directory_path, num_files): """Returns the path for |num_files| corpus files.""" file_paths = [] for root, _, files in os.walk(directory_path): for name in files: file_path = os.path.join(root, name) file_paths.append(file_path) if len(file_paths) >= num_files: return file_paths return file_paths def upload_corpus(doc_str, path_prefix, output_corpus_directory, num_uploads): """Uploads |num_uploads| corpus files using |doc_str| signed document policy. It uses |path_prefix| to get the upload path.""" doc_data = json.loads(doc_str) doc = build_lib.SignedPolicyDocument(**doc_data) file_paths = get_files_path(output_corpus_directory, num_uploads) for file_path in file_paths: suffix = uuid.uuid4().hex upload_path = path_prefix + suffix upload_corpus_file(file_path, upload_path, doc) def get_args(): """Parses command line arguments and returns them.""" parser = argparse.ArgumentParser( description="Script to upload corpus elements to GCS.") parser.add_argument("doc_str", type=str, help="The signed document policy string.") parser.add_argument("path_prefix", type=str, help="The prefix to get the corpus upload path.") parser.add_argument( "output_corpus_directory", type=str, help="The directory where the fuzzing output corpus is stored.") parser.add_argument("num_uploads", type=int, help="The number of elements which will be uploaded.") args = parser.parse_args() return args def main(): """Upload OSS-Fuzz on Demand output corpus to GCS.""" args = get_args() upload_corpus(args.doc_str, args.path_prefix, args.output_corpus_directory, args.num_uploads) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/ood_upload_corpus_test.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for ood_upload_corpus_test.py.""" import json import os import shutil import tempfile import unittest from unittest.mock import patch, MagicMock, call import build_lib import ood_upload_corpus class GetFilePathTest(unittest.TestCase): """Tests for get_files_path function.""" def setUp(self): """Set tem_dir attribute""" self.temp_dir = tempfile.mkdtemp() def tearDown(self): """Remove temp_dir after tests""" shutil.rmtree(self.temp_dir) def test_no_files(self): """Test for empty directory""" self.assertEqual(ood_upload_corpus.get_files_path(self.temp_dir, 10), []) def test_single_file(self): """Test for single file""" file_name = 'test_file.txt' file_path = os.path.join(self.temp_dir, file_name) open(file_path, 'w').close() self.assertEqual(ood_upload_corpus.get_files_path(self.temp_dir, 10), [file_path]) def test_multiple_files(self): """Test for multiple files""" file_names = ['file1.txt', 'file2.csv', 'data.json'] for name in file_names: file_path = os.path.join(self.temp_dir, name) open(file_path, 'w').close() files_path_set = set(ood_upload_corpus.get_files_path(self.temp_dir, 2)) self.assertTrue(len(files_path_set) == 2) self.assertTrue( files_path_set.issubset( set([ f'{self.temp_dir}/file1.txt', f'{self.temp_dir}/file2.csv', f'{self.temp_dir}/data.json' ]))) def test_with_subdirectory(self): """Test for directory with subdirectory""" os.makedirs(os.path.join(self.temp_dir, 'subdir')) self.assertEqual(ood_upload_corpus.get_files_path(self.temp_dir, 10), []) file_name = 'test_file.txt' file_path = os.path.join(self.temp_dir, file_name) open(file_path, 'w').close() self.assertEqual(ood_upload_corpus.get_files_path(self.temp_dir, 10), [file_path]) class TestUploadCorpus(unittest.TestCase): """Tests for upload_corpus function.""" @patch('uuid.uuid4') @patch('ood_upload_corpus.upload_corpus_file') @patch('ood_upload_corpus.get_files_path') def test_upload_multiple_files(self, mock_get_files_path, mock_upload_corpus_file, mock_uuid): """Tests uploading multiple corpus files with the given document policy.""" output_dir = 'test_corpus_dir' path_prefix = 'gs://test_bucket/corpus/' num_uploads = 3 doc = build_lib.SignedPolicyDocument(bucket='bucket', policy='test_policy', x_goog_algorithm='x', x_goog_credential='x', x_goog_date='00000000', x_goog_signature='x') doc_str = json.dumps(doc.__dict__) mock_get_files_path.return_value = [ os.path.join(output_dir, 'file_0.txt'), os.path.join(output_dir, 'file_1.txt'), os.path.join(output_dir, 'file_2.txt'), ] mock_uuid.side_effect = [ MagicMock(hex='suffix1'), MagicMock(hex='suffix2'), MagicMock(hex='suffix3') ] ood_upload_corpus.upload_corpus(doc_str, path_prefix, output_dir, num_uploads) mock_get_files_path.assert_called_once_with(output_dir, num_uploads) mock_upload_corpus_file.assert_has_calls([ call(os.path.join(output_dir, 'file_0.txt'), 'gs://test_bucket/corpus/suffix1', doc), call(os.path.join(output_dir, 'file_1.txt'), 'gs://test_bucket/corpus/suffix2', doc), call(os.path.join(output_dir, 'file_2.txt'), 'gs://test_bucket/corpus/suffix3', doc), ]) self.assertEqual(mock_uuid.call_count, num_uploads) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/build/functions/ood_upload_testcase.py ================================================ #!/usr/bin/env python3 # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Upload OSS-Fuzz on Demand testcases.""" import json import logging import os import sys import subprocess try: import requests except ImportError: print("requests library not found. Installing...") subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"]) import requests POST_URL = 'https://oss-fuzz.com/upload-testcase/upload-oauth' def get_access_token(access_token_path): """Returns the ACCESS_TOKEN for upload testcase requests""" with open(access_token_path, 'r') as f: line = f.readline() return line.strip() def get_headers(access_token_path): """Returns the headers required to upload testcase requests""" access_token = get_access_token(access_token_path) return { 'Authorization': 'Bearer ' + access_token, } def upload_testcase(upload_url, testcase_path, job, target, access_token_path): """Make an upload testcase request.""" files = { 'file': open(testcase_path, 'rb'), } data = { 'job': job, 'target': target, } try: resp = requests.post(upload_url, files=files, data=data, headers=get_headers(access_token_path)) resp.raise_for_status() result = json.loads(resp.text) print('Upload succeeded. Testcase ID is', result['id']) except: print('Failed to upload with status', resp.status_code) print(resp.text) def get_crash_file_path(dir_path): """Returns the path of a crash file (except from out of memory, timeout and slow units crashes) inside 'dir_path'. Returns None if there are no files inside the the given directory.""" excluded_prefixes = ('oom', 'timeout', 'slow-unit') for entry in os.scandir(dir_path): if entry.is_file() and not entry.name.startswith(excluded_prefixes): return f'{dir_path}/{entry.name}' return None def main(): """Upload an OSS-Fuzz on Demand testcase.""" testcase_dir_path = sys.argv[1] job = sys.argv[2] target = sys.argv[3] access_token_path = sys.argv[4] testcase_path = get_crash_file_path(testcase_dir_path) if not testcase_path: print('OSS-Fuzz on Demand did not find any relevant crashes.') else: upload_testcase(POST_URL, testcase_path, job, target, access_token_path) return 0 if __name__ == '__main__': main() ================================================ FILE: infra/build/functions/ood_upload_testcase_test.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for ood_upload_testcase_test.py.""" import os import shutil import tempfile import unittest from unittest import mock import ood_upload_testcase class GetCrashFilePathTest(unittest.TestCase): """Tests for get_crash_file_path.""" def setUp(self): """Set tem_dir attribute""" self.temp_dir = tempfile.mkdtemp() def tearDown(self): """Remove temp_dir after tests""" shutil.rmtree(self.temp_dir) def test_no_files(self): """Test for empty directory""" self.assertIsNone(ood_upload_testcase.get_crash_file_path(self.temp_dir)) def test_single_file(self): """Test for single file""" file_name = 'test_file.txt' file_path = os.path.join(self.temp_dir, file_name) open(file_path, 'w').close() self.assertEqual(ood_upload_testcase.get_crash_file_path(self.temp_dir), file_path) def test_multiple_files(self): """Test for multiple files""" file_names = ['file1.txt', 'file2.csv', 'data.json'] file_paths = [] for name in file_names: file_path = os.path.join(self.temp_dir, name) file_paths.append(file_path) open(file_path, 'w').close() self.assertIn(ood_upload_testcase.get_crash_file_path(self.temp_dir), file_paths) def test_with_subdirectory(self): """Test for directory with subdirectory""" os.makedirs(os.path.join(self.temp_dir, 'subdir')) self.assertIsNone(ood_upload_testcase.get_crash_file_path(self.temp_dir)) file_name = 'test_file.txt' file_path = os.path.join(self.temp_dir, file_name) open(file_path, 'w').close() self.assertEqual(ood_upload_testcase.get_crash_file_path(self.temp_dir), file_path) def test_oom_file(self): """Test for crash file starting with 'oom'""" file_name = 'oom-test_file.txt' file_path = os.path.join(self.temp_dir, file_name) open(file_path, 'w').close() self.assertIsNone(ood_upload_testcase.get_crash_file_path(self.temp_dir)) ================================================ FILE: infra/build/functions/oss_fuzz_on_demand.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """OSS-Fuzz on demand.""" import sys import logging import fuzzbench import build_project def oss_fuzz_on_demand_main(args=None): """Main function for OSS-Fuzz on demand. Returns 0 on success, 1 on failure.""" return build_project.build_script_main('Does a FuzzBench run.', fuzzbench.get_build_steps, fuzzbench.FUZZBENCH_BUILD_TYPE, args) def main(): """Build OSS-Fuzz projects with FuzzBench fuzzing engines.""" logging.basicConfig(level=logging.INFO) return 0 if oss_fuzz_on_demand_main() else 1 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/build/functions/project_experiment.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script to run target experiments on GCB.""" import argparse import logging import sys import google.auth import build_lib import build_project def run_experiment(project_name, command, output_path, experiment_name): """Runs the experiment specified on GCB.""" config = build_project.Config(testing=True, test_image_suffix='', repo=build_project.DEFAULT_OSS_FUZZ_REPO, branch=None, parallel=False, upload=False, experiment=True, upload_build_logs=None) try: project_yaml, dockerfile_contents = ( build_project.get_project_data(project_name)) except FileNotFoundError: logging.error('Couldn\'t get project data. Skipping %s.', project_name) return None project = build_project.Project(project_name, project_yaml, dockerfile_contents) # Override sanitizers and engine because we only care about libFuzzer+ASan # for benchmarking purposes. build_project.set_yaml_defaults(project_yaml) project_yaml['sanitizers'] = ['address'] project_yaml['fuzzing_engines'] = ['libfuzzer'] project_yaml['architectures'] = ['x86_64'] # Don't do bad build checks. project_yaml['run_tests'] = False steps = build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config, architectures=project.architectures, experiment=config.experiment) steps.extend([ { 'name': project.image, 'args': [ 'bash', '-c', 'mkdir /workspace/out', ] }, { 'name': project.image, 'args': [ 'bash', '-c', f'(cd "/src"; cd {project.workdir}; {command})', ] }, { 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', '/workspace/out/*', output_path, ] }, ]) credentials, _ = google.auth.default() return build_project.run_build(project_name, steps, credentials, 'experiment', experiment=True, extra_tags=[f'experiment-{experiment_name}']) def main(): """Runs run target experiments on GCB.""" parser = argparse.ArgumentParser(sys.argv[0], description='Test projects') parser.add_argument('--project', required=True, help='Project name') parser.add_argument('--command', required=True, help='Command to run inside the project image.') parser.add_argument('--upload_output', required=True, help='GCS bucket location to upload output to.') parser.add_argument('--experiment_name', required=True, help='Experiment name.') args = parser.parse_args() run_experiment(args.project, args.command, args.upload_output, args.experiment_name) if __name__ == '__main__': main() ================================================ FILE: infra/build/functions/project_sync.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud functions for build scheduling.""" from collections import namedtuple import io import logging import os import re import tempfile import urllib.request import zipfile from google.api_core import exceptions from google.cloud import ndb from google.cloud import scheduler_v1 import yaml import build_and_run_coverage import build_project from datastore_entities import Project VALID_PROJECT_NAME = re.compile(r'^[a-zA-Z0-9_-]+$') DEFAULT_BUILDS_PER_DAY = 1 MAX_BUILDS_PER_DAY = 4 COVERAGE_SCHEDULE = '0 6 * * *' INTROSPECTOR_SCHEDULE = '0 10 * * *' FUZZING_BUILD_TOPIC = 'request-build' COVERAGE_BUILD_TOPIC = 'request-coverage-build' INTROSPECTOR_BUILD_TOPIC = 'request-introspector-build' ProjectMetadata = namedtuple( 'ProjectMetadata', 'schedule project_yaml_contents dockerfile_contents') Content = namedtuple('Content', 'type path name decoded_content') logging.basicConfig(level=logging.INFO) # pylint: disable=too-few-public-methods class OssFuzzRepo: """OSS-Fuzz repo.""" _MASTER_ZIP_LINK = ( 'https://github.com/google/oss-fuzz/archive/refs/heads/master.zip') def __init__(self, out_dir): with urllib.request.urlopen(self._MASTER_ZIP_LINK) as response: zip_contents = response.read() with zipfile.ZipFile(io.BytesIO(zip_contents)) as zip_file: zip_file.extractall(out_dir) self._out_dir = out_dir @property def _repo_dir(self): return os.path.join(self._out_dir, 'oss-fuzz-master') def get_contents(self, path): """Gets contents of path.""" contents = [] list_path = os.path.join(self._repo_dir, path) for item in os.listdir(list_path): full_path = os.path.join(list_path, item) rel_path = os.path.relpath(full_path, self._repo_dir) if os.path.isdir(full_path): file_type = 'dir' decoded_content = None else: file_type = 'file' with open(full_path, mode='rb') as file: decoded_content = file.read() contents.append( Content(file_type, rel_path, os.path.basename(rel_path), decoded_content)) return contents class ProjectYamlError(Exception): """Error in project.yaml format.""" def create_scheduler(cloud_scheduler_client, project_name, schedule, tag, topic): """Creates schedulers for new projects.""" project_id = os.environ.get('GCP_PROJECT') location_id = os.environ.get('FUNCTION_REGION') parent = cloud_scheduler_client.location_path(project_id, location_id) job = { 'name': parent + '/jobs/' + project_name + '-scheduler-' + tag, 'pubsub_target': { 'topic_name': 'projects/' + project_id + '/topics/' + topic, 'data': project_name.encode() }, 'schedule': schedule } try: existing_job = cloud_scheduler_client.get_job(job['name']) except exceptions.NotFound: existing_job = None if existing_job: if existing_job.schedule != schedule: update_mask = {'paths': ['schedule']} cloud_scheduler_client.update_job(job, update_mask) else: cloud_scheduler_client.create_job(parent, job) def delete_scheduler(cloud_scheduler_client, project_name, tag): """Deletes schedulers for projects that were removed.""" project_id = os.environ.get('GCP_PROJECT') location_id = os.environ.get('FUNCTION_REGION') name = cloud_scheduler_client.job_path(project_id, location_id, project_name + '-scheduler-' + tag) cloud_scheduler_client.delete_job(name) def delete_project(cloud_scheduler_client, project): """Delete the given project.""" logging.info('Deleting project %s', project.name) for tag in (build_project.FUZZING_BUILD_TYPE, build_and_run_coverage.COVERAGE_BUILD_TYPE, build_and_run_coverage.INTROSPECTOR_BUILD_TYPE): try: delete_scheduler(cloud_scheduler_client, project.name, tag) except exceptions.NotFound: # Already deleted. continue except exceptions.GoogleAPICallError as error: logging.error('Scheduler deletion for %s failed with %s', project.name, error) return project.key.delete() # pylint: disable=too-many-branches def sync_projects(cloud_scheduler_client, projects): """Sync projects with cloud datastore.""" for project in Project.query(): if project.name not in projects: delete_project(cloud_scheduler_client, project) existing_projects = {project.name for project in Project.query()} for project_name in projects: try: create_scheduler(cloud_scheduler_client, project_name, projects[project_name].schedule, build_project.FUZZING_BUILD_TYPE, FUZZING_BUILD_TOPIC) create_scheduler(cloud_scheduler_client, project_name, COVERAGE_SCHEDULE, build_and_run_coverage.COVERAGE_BUILD_TYPE, COVERAGE_BUILD_TOPIC) create_scheduler(cloud_scheduler_client, project_name, INTROSPECTOR_SCHEDULE, build_and_run_coverage.INTROSPECTOR_BUILD_TYPE, INTROSPECTOR_BUILD_TOPIC) except exceptions.GoogleAPICallError as error: logging.error('Scheduler creation for %s failed with %s', project_name, error) continue if project_name in existing_projects: continue project_metadata = projects[project_name] Project(name=project_name, schedule=project_metadata.schedule, project_yaml_contents=project_metadata.project_yaml_contents, dockerfile_contents=project_metadata.dockerfile_contents).put() for project in Project.query(): if project.name not in projects: continue logging.info('Setting up project %s', project.name) project_metadata = projects[project.name] project_changed = False if project.schedule != project_metadata.schedule: try: logging.info('Schedule changed.') project.schedule = project_metadata.schedule project_changed = True except exceptions.GoogleAPICallError as error: logging.error('Updating scheduler for %s failed with %s', project.name, error) if project.project_yaml_contents != project_metadata.project_yaml_contents: project.project_yaml_contents = project_metadata.project_yaml_contents project_changed = True if project.dockerfile_contents != project_metadata.dockerfile_contents: project.dockerfile_contents = project_metadata.dockerfile_contents project_changed = True if project_changed: project.put() def _has_docker_file(project_contents): """Checks if project has a Dockerfile.""" return any( content_file.name == 'Dockerfile' for content_file in project_contents) def get_project_metadata(project_contents): """Checks for schedule parameter in yaml file else uses DEFAULT_SCHEDULE.""" for content_file in project_contents: if content_file.name == 'project.yaml': project_yaml_contents = content_file.decoded_content.decode('utf-8') if content_file.name == 'Dockerfile': dockerfile_contents = content_file.decoded_content.decode('utf-8') project_yaml = yaml.safe_load(project_yaml_contents) builds_per_day = project_yaml.get('builds_per_day', DEFAULT_BUILDS_PER_DAY) if not isinstance(builds_per_day, int) or builds_per_day not in range( 1, MAX_BUILDS_PER_DAY + 1): raise ProjectYamlError('Parameter is not an integer in range [1-4]') # Starting at 6:00 am, next build schedules are added at 'interval' slots # Example for interval 2, hours = [6, 18] and schedule = '0 6,18 * * *' interval = 24 // builds_per_day hours = [] for hour in range(6, 30, interval): hours.append(hour % 24) schedule = '0 ' + ','.join(str(hour) for hour in hours) + ' * * *' return ProjectMetadata(schedule, project_yaml_contents, dockerfile_contents) def get_projects(repo): """Get project list from git repository.""" projects = {} contents = repo.get_contents('projects') for content_file in contents: if content_file.type != 'dir' or not VALID_PROJECT_NAME.match( content_file.name): continue project_contents = repo.get_contents(content_file.path) if not _has_docker_file(project_contents): continue try: projects[content_file.name] = get_project_metadata(project_contents) except ProjectYamlError as error: logging.error( 'Incorrect format for project.yaml file of %s with error %s', content_file.name, error) return projects def sync(event, context): """Sync projects with cloud datastore.""" del event, context # Unused. with ndb.Client().context(): with tempfile.TemporaryDirectory() as temp_dir: repo = OssFuzzRepo(temp_dir) projects = get_projects(repo) cloud_scheduler_client = scheduler_v1.CloudSchedulerClient() sync_projects(cloud_scheduler_client, projects) ================================================ FILE: infra/build/functions/project_sync_test.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for Cloud Function sync, which syncs the list of github projects and uploads them to the Cloud Datastore.""" import os import sys import unittest from google.cloud import ndb sys.path.append(os.path.dirname(__file__)) # pylint: disable=wrong-import-position import datastore_entities import project_sync import test_utils # pylint: disable=no-member # pylint: disable=too-few-public-methods class Repository: """Mocking Github Repository.""" def __init__(self, name, file_type, path, contents=None): self.contents = contents or [] self.name = name self.type = file_type self.path = path self.decoded_content = b"name: test" def get_contents(self, path): """"Get contents of repository.""" if self.path == path: return self.contents for content_file in self.contents: if content_file.path == path: return content_file.contents return None def set_yaml_contents(self, decoded_content): """Set yaml_contents.""" self.decoded_content = decoded_content class CloudSchedulerClient: """Mocking cloud scheduler client.""" def __init__(self): self.schedulers = [] # pylint: disable=no-self-use def location_path(self, project_id, location_id): """Return project path.""" return f'projects/{project_id}/location/{location_id}' def create_job(self, parent, job): """Simulate create job.""" del parent self.schedulers.append(job) def get_job(self, name): """Simulate get_job.""" for scheduler in self.schedulers: if scheduler['name'] == name: return scheduler return None # pylint: disable=no-self-use def job_path(self, project_id, location_id, name): """Return job path.""" return f'projects/{project_id}/location/{location_id}/jobs/{name}' def delete_job(self, name): """Simulate delete jobs.""" for job in self.schedulers: if job['name'] == name: self.schedulers.remove(job) break def update_job(self, job, update_mask): """Simulate update jobs.""" for existing_job in self.schedulers: if existing_job == job and 'schedule' in update_mask: job['schedule'] = update_mask['schedule'] class TestDataSync(unittest.TestCase): """Unit tests for sync.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() def test_sync_projects_update(self): """Testing sync_projects() updating a schedule.""" cloud_scheduler_client = CloudSchedulerClient() with ndb.Client().context(): datastore_entities.Project(name='test1', schedule='0 8 * * *', project_yaml_contents='', dockerfile_contents='').put() datastore_entities.Project(name='test2', schedule='0 9 * * *', project_yaml_contents='', dockerfile_contents='').put() projects = { 'test1': project_sync.ProjectMetadata('0 8 * * *', '', ''), 'test2': project_sync.ProjectMetadata('0 7 * * *', '', '') } project_sync.sync_projects(cloud_scheduler_client, projects) projects_query = datastore_entities.Project.query() self.assertEqual({ 'test1': '0 8 * * *', 'test2': '0 7 * * *' }, {project.name: project.schedule for project in projects_query}) def test_sync_projects_create(self): """"Testing sync_projects() creating new schedule.""" cloud_scheduler_client = CloudSchedulerClient() with ndb.Client().context(): datastore_entities.Project(name='test1', schedule='0 8 * * *', project_yaml_contents='', dockerfile_contents='').put() projects = { 'test1': project_sync.ProjectMetadata('0 8 * * *', '', ''), 'test2': project_sync.ProjectMetadata('0 7 * * *', '', '') } project_sync.sync_projects(cloud_scheduler_client, projects) projects_query = datastore_entities.Project.query() self.assertEqual({ 'test1': '0 8 * * *', 'test2': '0 7 * * *' }, {project.name: project.schedule for project in projects_query}) self.assertCountEqual([ { 'name': 'projects/test-project/location/us-central1/jobs/' 'test1-scheduler-fuzzing', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-build', 'data': b'test1' }, 'schedule': '0 8 * * *' }, { 'name': 'projects/test-project/location/us-central1/jobs/' 'test1-scheduler-coverage', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-coverage-build', 'data': b'test1' }, 'schedule': '0 6 * * *' }, { 'name': 'projects/test-project/location/us-central1/jobs/' 'test1-scheduler-introspector', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-introspector-build', 'data': b'test1' }, 'schedule': '0 10 * * *' }, { 'name': 'projects/test-project/location/us-central1/jobs/' 'test2-scheduler-fuzzing', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-build', 'data': b'test2' }, 'schedule': '0 7 * * *' }, { 'name': 'projects/test-project/location/us-central1/jobs/' 'test2-scheduler-coverage', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-coverage-build', 'data': b'test2' }, 'schedule': '0 6 * * *' }, { 'name': 'projects/test-project/location/us-central1/jobs/' 'test2-scheduler-introspector', 'pubsub_target': { 'topic_name': 'projects/test-project/topics/request-introspector-build', 'data': b'test2' }, 'schedule': '0 10 * * *' }, ], cloud_scheduler_client.schedulers) def test_sync_projects_delete(self): """Testing sync_projects() deleting.""" cloud_scheduler_client = CloudSchedulerClient() with ndb.Client().context(): datastore_entities.Project(name='test1', schedule='0 8 * * *', project_yaml_contents='', dockerfile_contents='').put() datastore_entities.Project(name='test2', schedule='0 9 * * *', project_yaml_contents='', dockerfile_contents='').put() projects = {'test1': project_sync.ProjectMetadata('0 8 * * *', '', '')} project_sync.sync_projects(cloud_scheduler_client, projects) projects_query = datastore_entities.Project.query() self.assertEqual( {'test1': '0 8 * * *'}, {project.name: project.schedule for project in projects_query}) def test_get_projects_yaml(self): """Testing get_projects() yaml get_schedule().""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]), Repository('test1', 'dir', 'projects/test1', [ Repository('Dockerfile', 'file', 'projects/test1/Dockerfile'), Repository('project.yaml', 'file', 'projects/test1/project.yaml') ]) ]) repo.contents[0].contents[1].set_yaml_contents(b'builds_per_day: 2') repo.contents[1].contents[1].set_yaml_contents(b'builds_per_day: 3') self.assertEqual( project_sync.get_projects(repo), { 'test0': project_sync.ProjectMetadata('0 6,18 * * *', 'builds_per_day: 2', 'name: test'), 'test1': project_sync.ProjectMetadata('0 6,14,22 * * *', 'builds_per_day: 3', 'name: test') }) def test_get_projects_no_docker_file(self): """Testing get_projects() with missing dockerfile""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]), Repository('test1', 'dir', 'projects/test1') ]) self.assertEqual( project_sync.get_projects(repo), { 'test0': project_sync.ProjectMetadata('0 6 * * *', 'name: test', 'name: test') }) def test_get_projects_invalid_project_name(self): """Testing get_projects() with invalid project name""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]), Repository('test1@', 'dir', 'projects/test1', [ Repository('Dockerfile', 'file', 'projects/test1/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]) ]) self.assertEqual( project_sync.get_projects(repo), { 'test0': project_sync.ProjectMetadata('0 6 * * *', 'name: test', 'name: test') }) def test_get_projects_non_directory_type_project(self): """Testing get_projects() when a file in projects/ is not of type 'dir'.""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]), Repository('test1', 'file', 'projects/test1') ]) self.assertEqual( project_sync.get_projects(repo), { 'test0': project_sync.ProjectMetadata('0 6 * * *', 'name: test', 'name: test') }) def test_invalid_yaml_format(self): """Testing invalid yaml schedule parameter argument.""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]) ]) repo.contents[0].contents[1].set_yaml_contents( b'builds_per_day: some-string') self.assertEqual(project_sync.get_projects(repo), {}) def test_yaml_out_of_range(self): """Testing invalid yaml schedule parameter argument.""" repo = Repository('oss-fuzz', 'dir', 'projects', [ Repository('test0', 'dir', 'projects/test0', [ Repository('Dockerfile', 'file', 'projects/test0/Dockerfile'), Repository('project.yaml', 'file', 'projects/test0/project.yaml') ]) ]) repo.contents[0].contents[1].set_yaml_contents(b'builds_per_day: 5') self.assertEqual(project_sync.get_projects(repo), {}) @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/report_generator.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Generates a comparative report of trial build results and determines the final status of the pipeline.""" import json import os import sys # Define the expected result files for each build version. RESULT_FILES = { 'Legacy': 'legacy-results.json', 'Ubuntu 20.04': 'ubuntu-20-04-results.json', 'Ubuntu 24.04': 'ubuntu-24-04-results.json', } def _print_box(title, lines): """Prints a formatted box with a title and lines.""" box_width = 92 title_line = f'| {title.center(box_width - 4)} |' summary_lines = [ '+' + '-' * (box_width - 2) + '+', title_line, '+' + '-' * (box_width - 2) + '+', ] for line in lines: padding = box_width - 4 - len(line) summary_lines.append(f'| {line}{" " * padding} |') summary_lines.append('+' + '-' * (box_width - 2) + '+') print('\n'.join(summary_lines)) def generate_final_summary(all_results): """Prints a summary of all build versions.""" box_width = 92 summary_lines = [] total_unique_projects = set() for version, data in all_results.items(): if data: total_unique_projects.update(data.get('all_projects', [])) passed = str(data.get('successful_builds', 0)) failed = str(data.get('failed_builds', 0)) skipped = str(data.get('skipped_builds', 0)) total_builds = str( data.get('successful_builds', 0) + data.get('failed_builds', 0) + data.get('skipped_builds', 0)) line = ( f" {version.ljust(15)} -> {'Passed:'.ljust(8)} {passed.ljust(6)} | " f"{'Failed:'.ljust(8)} {failed.ljust(6)} | {'Skipped:'.ljust(8)} {skipped.ljust(6)} | " f"{'Total:'.ljust(7)} {total_builds.ljust(6)}") summary_lines.append(line) if summary_lines: separator = '-' * (box_width - 4) summary_lines.append(separator) project_summary_line = ( f" Total Projects Analyzed: {len(total_unique_projects)}") summary_lines.append(project_summary_line) _print_box('FINAL BUILD REPORT', summary_lines) def generate_comparison_table(all_results): """Prints a table comparing failures across versions.""" all_projects = set() for data in all_results.values(): if data and 'all_projects' in data: all_projects.update(data['all_projects']) if not all_projects: print('\nNo projects were run.') return project_col_width = 30 header = ' Project | Legacy | Ubuntu 20.04 | Ubuntu 24.04' separator = '-------------------------------+------------------+------------------+------------------' table_lines = [header, separator] for project in sorted(list(all_projects)): project_name = project if len(project_name) > project_col_width: project_name = project_name[:project_col_width - 3] + '...' row = f' {project_name.ljust(project_col_width)}|' for version in RESULT_FILES: status_icon = ' ' if all_results.get(version): if project in all_results[version].get('failed_projects', []): status_icon = 'FAIL' elif project in all_results[version].get('skipped_projects', []): status_icon = 'SKIP' else: status_icon = 'PASS' row += f' {status_icon.center(15)} |' row = row[:-1] table_lines.append(row) _print_box('FAILURE COMPARISON TABLE', table_lines) def main(): """Main function to generate report and determine pipeline status.""" if os.path.exists('trial_build_skipped.flag'): print('Skipping report generation because trial build was not invoked.') sys.exit(0) all_results = {} any_failures = False any_results_found = False total_unique_projects = set() print('Generating final build report...') for version, filename in RESULT_FILES.items(): if not os.path.exists(filename): print(f'Warning: Result file "{filename}" not found.') all_results[version] = None continue with open(filename, 'r') as f: data = json.load(f) all_results[version] = data any_results_found = True if data.get('failed_builds', 0) > 0: any_failures = True total_unique_projects.update(data.get('all_projects', [])) if not any_results_found: error_lines = [ 'No result files found. This typically means that all upstream builds', 'either timed out or failed catastrophically.', ] _print_box('FINAL BUILD REPORT', error_lines) print('\nPipeline finished with failures.') sys.exit(1) generate_comparison_table(all_results) generate_final_summary(all_results) has_explicit_failures = any_failures no_projects_were_run = any_results_found and not total_unique_projects if has_explicit_failures or no_projects_were_run: if no_projects_were_run and not has_explicit_failures: print( '\nWarning: No projects were run. This may indicate an upstream issue.' ) print('\nPipeline finished with failures.') sys.exit(1) print('\nPipeline finished successfully.') sys.exit(0) if __name__ == '__main__': main() ================================================ FILE: infra/build/functions/request_build.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud function to request builds.""" import base64 import google.auth from google.cloud import ndb import yaml import build_project import datastore_entities BASE_PROJECT = 'oss-fuzz-base' MAX_BUILD_HISTORY_LENGTH = 64 QUEUE_TTL_SECONDS = 60 * 60 * 24 # 24 hours. def update_build_history(project_name, build_id, build_tag): """Update build history of project.""" project_key = ndb.Key(datastore_entities.BuildsHistory, project_name + '-' + build_tag) project = project_key.get() if not project: project = datastore_entities.BuildsHistory(id=project_name + '-' + build_tag, build_tag=build_tag, project=project_name, build_ids=[]) if len(project.build_ids) >= MAX_BUILD_HISTORY_LENGTH: project.build_ids.pop(0) project.build_ids.append(build_id) project.put() def get_project_data(project_name): """Retrieve project metadata from datastore.""" query = datastore_entities.Project.query( datastore_entities.Project.name == project_name) project = query.get() if not project: raise RuntimeError( f'Project {project_name} not available in cloud datastore') project_yaml = yaml.safe_load(project.project_yaml_contents) return project_yaml, project.dockerfile_contents def get_empty_config(): """Returns an empty build config.""" return build_project.Config() def get_build_steps(project_name, timestamp=None): """Retrieve build steps.""" project_yaml, dockerfile_lines = get_project_data(project_name) build_config = build_project.Config( build_type=build_project.FUZZING_BUILD_TYPE, base_image_tag=project_yaml.get('base_os_version', None)) return build_project.get_build_steps(project_name, project_yaml, dockerfile_lines, build_config, timestamp=timestamp) def get_indexer_build_steps(project_name, timestamp=None): """Retrieve build steps.""" project_yaml, dockerfile_lines = get_project_data(project_name) build_config = build_project.Config( build_type=build_project.INDEXER_BUILD_TYPE) return build_project.get_indexer_build_steps(project_name, project_yaml, dockerfile_lines, build_config, timestamp=timestamp) def run_build(oss_fuzz_project, build_steps, credentials, build_type, cloud_project, update_history=True): """Execute build on cloud build. Wrapper around build_project.py that also updates the db.""" build = build_project.run_build(oss_fuzz_project, build_steps, credentials, build_type, cloud_project) if update_history: update_build_history(oss_fuzz_project, build['id'], build_type) # pylint: disable=no-member def request_build(event, context): """Entry point for cloud function to request builds.""" del context #unused if 'data' in event: project_name = base64.b64decode(event['data']).decode('utf-8') else: raise RuntimeError('Project name missing from payload') timestamp = build_project.get_datetime_now() with ndb.Client().context(): credentials, cloud_project = google.auth.default() build_steps = get_build_steps(project_name, timestamp) if not build_steps: return run_build( project_name, build_steps, credentials, build_project.FUZZING_BUILD_TYPE, cloud_project=cloud_project, ) indexer_build_steps = get_indexer_build_steps(project_name, timestamp) if not indexer_build_steps: return run_build( project_name, indexer_build_steps, credentials, build_project.INDEXER_BUILD_TYPE, cloud_project=cloud_project, update_history=False, ) ================================================ FILE: infra/build/functions/request_build_test.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for Cloud Function request builds which builds projects.""" import base64 import json import os import sys import unittest from unittest import mock from google.cloud import ndb # pylint: disable=wrong-import-position import datastore_entities import request_build import test_utils import build_project import build_lib # pylint: disable=no-member class TestRequestBuilds(unittest.TestCase): """Unit tests for sync.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() self.maxDiff = None # pylint: disable=invalid-name self.mock_get_signed_url = mock.patch( 'build_lib.get_signed_url', return_value='https://example.com/signed-url').start() self.mock_get_signed_policy = mock.patch( 'build_lib.get_signed_policy_document_upload_prefix', return_value=mock.MagicMock()).start() self.mock_curl_args = mock.patch( 'build_lib.signed_policy_document_curl_args', return_value=[]).start() def tearDown(self): mock.patch.stopall() def test_get_build_steps_no_project(self): """Test for when project isn't available in datastore.""" with ndb.Client().context(): self.assertRaises(RuntimeError, request_build.get_build_steps, 'test-project') @mock.patch('build_project.run_build', return_value={'id': 'mock-build-id'}) def test_get_build_steps_with_base_os_version(self, mock_run_build): """Test that get_build_steps uses the base_os_version.""" project_name = 'example' base_os_version = 'ubuntu-24-04' project_yaml_contents = """ homepage: https://my-api.example.com main_repo: https://github.com/example/my-api language: c++ vendor_ccs: [] fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: ubuntu-24-04 """ dockerfile_contents = """ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make # Get *your* source code here. RUN git clone https://github.com/google/oss-fuzz.git my-git-repo WORKDIR my-git-repo COPY build.sh $SRC/ """ with ndb.Client().context(): datastore_entities.Project(name=project_name, project_yaml_contents=project_yaml_contents, dockerfile_contents=dockerfile_contents).put() event = {'data': base64.b64encode(project_name.encode('utf-8'))} with mock.patch('google.auth.default', return_value=(None, 'oss-fuzz')): request_build.request_build(event, None) self.assertTrue(mock_run_build.called) self.assertEqual(2, mock_run_build.call_count) build_steps = mock_run_build.call_args_list[0][0][1] found_build_check_step = False for inner_step in build_steps[0]: if isinstance( inner_step, dict) and inner_step.get('id') and 'build-check' in inner_step['id']: found_build_check_step = True expected_image = f'gcr.io/oss-fuzz-base/base-runner:{base_os_version}' self.assertIn(expected_image, inner_step['args']) break self.assertTrue(found_build_check_step, 'Build check step not found.') def test_build_history(self): """Testing build history.""" with ndb.Client().context(): datastore_entities.BuildsHistory(id='test-project-fuzzing', build_tag='fuzzing', project='test-project', build_ids=[str(i) for i in range(1, 65) ]).put() request_build.update_build_history('test-project', '65', 'fuzzing') expected_build_ids = [str(i) for i in range(2, 66)] self.assertEqual(datastore_entities.BuildsHistory.query().get().build_ids, expected_build_ids) def test_build_history_no_existing_project(self): """Testing build history when build history object is missing.""" with ndb.Client().context(): request_build.update_build_history('test-project', '1', 'fuzzing') expected_build_ids = ['1'] self.assertEqual(datastore_entities.BuildsHistory.query().get().build_ids, expected_build_ids) def test_get_project_data(self): """Testing get project data.""" with ndb.Client().context(): self.assertRaises(RuntimeError, request_build.get_project_data, 'test-project') @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/request_coverage_build.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud function that requests coverage builds.""" import base64 import google.auth from google.cloud import ndb import build_and_run_coverage import request_build import build_project BASE_PROJECT = 'oss-fuzz-base' def get_build_steps(project_name): """Retrieve build steps.""" project_yaml, dockerfile_lines = request_build.get_project_data(project_name) build_config = build_project.Config( base_image_tag=project_yaml.get('base_os_version', None)) return build_and_run_coverage.get_build_steps(project_name, project_yaml, dockerfile_lines, build_config) def request_coverage_build(event, context): """Entry point for coverage build cloud function.""" del context # Unused. if 'data' in event: project_name = base64.b64decode(event['data']).decode('utf-8') else: raise RuntimeError('Project name missing from payload') with ndb.Client().context(): credentials, cloud_project = google.auth.default() build_steps = get_build_steps(project_name) if not build_steps: return request_build.run_build(project_name, build_steps, credentials, build_and_run_coverage.COVERAGE_BUILD_TYPE, cloud_project=cloud_project) ================================================ FILE: infra/build/functions/request_coverage_build_test.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for Cloud Function request_coverage_build.""" import base64 import os import sys import unittest from unittest import mock from google.cloud import ndb # pylint: disable=wrong-import-position import datastore_entities import request_coverage_build import test_utils import yaml # pylint: disable=no-member class TestRequestCoverageBuild(unittest.TestCase): """Unit tests for sync.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() self.maxDiff = None @mock.patch('request_build.run_build', return_value={'id': 'mock-build-id'}) @mock.patch('build_lib.get_signed_url', return_value='https://mocked-signed-url.com') def test_get_build_steps_with_base_os_version(self, mock_get_signed_url, mock_run_build): """Test that get_build_steps uses the base_os_version for coverage builds.""" project_name = 'example' base_os_version = 'ubuntu-24-04' project_yaml_contents = f""" homepage: https://my-api.example.com main_repo: https://github.com/example/my-api language: c++ fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: {base_os_version} """ dockerfile_contents = "FROM gcr.io/oss-fuzz-base/base-builder" with mock.patch('request_build.get_project_data') as mock_get_project_data: mock_get_project_data.return_value = ( yaml.safe_load(project_yaml_contents), dockerfile_contents) event = {'data': base64.b64encode(project_name.encode('utf-8'))} with mock.patch('google.auth.default', return_value=(None, 'oss-fuzz')): request_coverage_build.request_coverage_build(event, None) self.assertTrue(mock_run_build.called) build_steps = mock_run_build.call_args[0][1] for inner_list in build_steps: for step in inner_list: if isinstance( step, dict ) and 'name' in step and 'gcr.io/oss-fuzz-base/base-runner' in step[ 'name']: found_build_check_step = True expected_image = f'gcr.io/oss-fuzz-base/base-runner:{base_os_version}' self.assertEqual(step['name'], expected_image) break if found_build_check_step: break self.assertTrue(found_build_check_step, 'Coverage build step not found.') @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/request_introspector_build.py ================================================ # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Cloud function that requests fuzz introspector builds.""" import base64 import google.auth from google.cloud import ndb import build_and_run_coverage import request_build import build_project BASE_PROJECT = 'oss-fuzz-base' # TODO (navidem): write test, currently tested manually. def get_build_steps(project_name, image_project, base_images_project): """Retrieve build steps.""" project_yaml, dockerfile_lines = request_build.get_project_data(project_name) build_config = build_project.Config( base_image_tag=project_yaml.get('base_os_version', None)) build_config.base_image_tag = project_yaml.get('base_os_version', None) return build_and_run_coverage.get_fuzz_introspector_steps( project_name, project_yaml, dockerfile_lines, build_config) def request_introspector_build(event, context): """Entry point for fuzz introspector build cloud function.""" del context # Unused. if 'data' in event: project_name = base64.b64decode(event['data']).decode('utf-8') else: raise RuntimeError('Project name missing from payload') with ndb.Client().context(): credentials, cloud_project = google.auth.default() build_steps = get_build_steps(project_name, cloud_project, BASE_PROJECT) if not build_steps: return request_build.run_build(project_name, build_steps, credentials, build_and_run_coverage.INTROSPECTOR_BUILD_TYPE, cloud_project=cloud_project) ================================================ FILE: infra/build/functions/request_introspector_build_test.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Unit tests for Cloud Function request_introspector_build.""" import base64 import os import sys import unittest from unittest import mock from google.cloud import ndb # pylint: disable=wrong-import-position import datastore_entities import request_introspector_build import test_utils import yaml # pylint: disable=no-member class TestRequestIntrospectorBuild(unittest.TestCase): """Unit tests for sync.""" @classmethod def setUpClass(cls): cls.ds_emulator = test_utils.start_datastore_emulator() test_utils.wait_for_emulator_ready(cls.ds_emulator, 'datastore', test_utils.DATASTORE_READY_INDICATOR) test_utils.set_gcp_environment() def setUp(self): test_utils.reset_ds_emulator() self.maxDiff = None @mock.patch('request_build.run_build', return_value={'id': 'mock-build-id'}) def test_get_build_steps_with_base_os_version(self, mock_run_build): """Test that get_build_steps uses the base_os_version for introspector builds.""" project_name = 'example' base_os_version = 'ubuntu-24-04' project_yaml_contents = f""" homepage: https://my-api.example.com main_repo: https://github.com/example/my-api language: c++ fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: {base_os_version} """ dockerfile_contents = "FROM gcr.io/oss-fuzz-base/base-builder" with mock.patch('request_build.get_project_data') as mock_get_project_data: mock_get_project_data.return_value = ( yaml.safe_load(project_yaml_contents), dockerfile_contents) event = {'data': base64.b64encode(project_name.encode('utf-8'))} with mock.patch('google.auth.default', return_value=(None, 'oss-fuzz')): request_introspector_build.request_introspector_build(event, None) self.assertTrue(mock_run_build.called) build_steps = mock_run_build.call_args[0][1] for inner_list in build_steps: for step in inner_list: if isinstance( step, dict ) and 'name' in step and 'gcr.io/oss-fuzz-base/base-runner' in step[ 'name']: found_build_check_step = True expected_image = f'gcr.io/oss-fuzz-base/base-runner:{base_os_version}' self.assertEqual(step['name'], expected_image) break if found_build_check_step: break self.assertTrue(found_build_check_step, 'Introspector build step not found.') @classmethod def tearDownClass(cls): test_utils.cleanup_emulator(cls.ds_emulator) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/functions/requirements.txt ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ Brotli==1.0.9 hiredis==3.0.0 PyYaml==6.0.2 PyGithub==2.6.1 grpcio==1.71.0 google-auth==1.21.1 google-cloud-datastore<2.0 google-cloud-ndb==1.7.1 google-cloud-scheduler==1.3.0 google-cloud-storage==1.29.0 google-api-core==1.22.2 google-api-python-client==1.9.3 oauth2client==4.1.3 python-dateutil==2.8.1 protobuf==3.20.2 beautifulsoup4==4.11.1 wrapt==1.17.2 ================================================ FILE: infra/build/functions/target_experiment.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script to run target experiments on GCB.""" import argparse import logging import os import sys import google.auth import build_lib import build_project # 12 hours, allowing more than enough waiting time before cloud build starts. build_lib.BUILD_TIMEOUT = 12 * 60 * 60 def run_experiment(project_name, target_name, args, output_path, build_output_path, upload_corpus_path, upload_coverage_path, experiment_name, upload_reproducer_path, tags, use_cached_image, real_project_name=None): config = build_project.Config(testing=True, test_image_suffix='', repo=build_project.DEFAULT_OSS_FUZZ_REPO, branch=None, parallel=False, upload=False, experiment=True, upload_build_logs=build_output_path) try: project_yaml, dockerfile_contents = ( build_project.get_project_data(project_name)) except FileNotFoundError: logging.error('Couldn\'t get project data. Skipping %s.', project_name) return # Override sanitizers and engine because we only care about libFuzzer+ASan # for benchmarking purposes. build_project.set_yaml_defaults(project_yaml) project_yaml['sanitizers'] = ['address'] project_yaml['fuzzing_engines'] = ['libfuzzer'] project_yaml['architectures'] = ['x86_64'] # Don't do bad build checks. project_yaml['run_tests'] = False project = build_project.Project(project_name, project_yaml, dockerfile_contents) if real_project_name: # If the passed project name is not the actual OSS-Fuzz project name (e.g. # OSS-Fuzz-Gen generated benchmark), record the real one here. project.real_name = real_project_name steps = build_project.get_build_steps_for_project( project, config, use_caching=use_cached_image) build = build_project.Build('libfuzzer', 'address', 'x86_64') local_output_path = '/workspace/output.log' local_corpus_path_base = '/workspace/corpus' local_corpus_path = os.path.join(local_corpus_path_base, target_name) default_target_path = os.path.join(build.out, target_name) local_target_dir = os.path.join(build.out, 'target') local_corpus_zip_path = '/workspace/corpus/corpus.zip' local_artifact_path = os.path.join(build.out, 'artifacts/') local_stacktrace_path = os.path.join(build.out, 'stacktrace/') fuzzer_args = ' '.join(args + [f'-artifact_prefix={local_artifact_path}']) env = build_project.get_env(project_yaml['language'], build) env.append('RUN_FUZZER_MODE=batch') env.append('CORPUS_DIR=' + local_corpus_path) run_step = { 'name': 'gcr.io/oss-fuzz-base/base-runner', 'env': env, 'args': [ 'bash', '-c', (f'mkdir -p {local_corpus_path} && ' f'mkdir -p {local_target_dir} && ' f'mkdir -p {local_artifact_path} && ' f'mkdir -p {local_stacktrace_path} && ' f'run_fuzzer {target_name} {fuzzer_args} ' f'|& tee {local_output_path} || true'), ] } steps.append(build_lib.dockerify_run_step(run_step, build)) steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': ['-m', 'cp', local_output_path, output_path] }) # Upload corpus. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'entrypoint': '/bin/bash', 'args': [ '-c', (f'cd {local_corpus_path} && ' f'zip -r {local_corpus_zip_path} * && ' f'gsutil -m cp {local_corpus_zip_path} {upload_corpus_path} || ' f'rm -f {local_corpus_zip_path}'), ], }) if upload_reproducer_path: # Upload binary. First copy the binary directly from default_target_path, # if that fails, find it under build out dir and copy to local_target_dir. # If either succeeds, then upload it to bucket. # If multiple files are found, suffix them and upload them all. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'entrypoint': '/bin/bash', 'args': [ '-c', (f'cp {default_target_path} {local_target_dir} 2>/dev/null || ' f'find {build.out} -type f -name {target_name} -exec bash -c ' f'\'cp "$0" "{local_target_dir}/$(echo "$0" | sed "s@/@_@g")"\' ' f'{{}} \\; && gsutil cp -r {local_target_dir} ' f'{upload_reproducer_path}/target_binary || true'), ], }) # Upload reproducer. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'entrypoint': '/bin/bash', 'args': [ '-c', (f'gsutil -m cp -r {local_artifact_path} {upload_reproducer_path} ' '|| true'), ], }) # Upload stacktrace. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'entrypoint': '/bin/bash', 'args': [ '-c', (f'if [ -f {local_target_dir}/{target_name} ]; then ' f'{local_target_dir}/{target_name} {local_artifact_path}/* > ' f'{local_stacktrace_path}/{target_name}.st 2>&1; ' 'else ' f'for target in {local_target_dir}/*; do ' f'"$target" {local_artifact_path}/* > ' f'"{local_stacktrace_path}/$target.st" 2>&1; ' 'done; fi; ' f'gsutil -m cp -r {local_stacktrace_path} {upload_reproducer_path}' ' || true'), ], }) # Build for coverage. build = build_project.Build('libfuzzer', 'coverage', 'x86_64') env = build_project.get_env(project_yaml['language'], build) if use_cached_image: project.cached_sanitizer = 'coverage' steps.extend( build_lib.get_project_image_steps(project.name, project.image, project.fuzzing_language, config=config, architectures=project.architectures, experiment=config.experiment, cache_image=project.cached_image, srcmap=False)) steps.append( build_project.get_compile_step(project, build, env, config.parallel)) # Generate coverage report. env.extend([ # The coverage script automatically adds the target name to this. 'CORPUS_DIR=' + local_corpus_path_base, 'HTTP_PORT=', f'COVERAGE_EXTRA_ARGS={project.coverage_extra_args.strip()}', ]) steps.append({ 'name': build_lib.get_runner_image_name(''), 'env': env, 'entrypoint': '/bin/bash', 'args': [ '-c', ( f'timeout 30m coverage {target_name}; ret=$?; ' '[ $ret -eq 124 ] ' # Exit code 124 indicates a time out. f'&& echo "coverage {target_name} timed out after 30 minutes" ' f'|| echo "coverage {target_name} completed with exit code $ret"' ), ], }) # Upload raw coverage data. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'dumps'), os.path.join(upload_coverage_path, 'dumps'), ], }) # Upload coverage report. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'report'), os.path.join(upload_coverage_path, 'report'), ], }) # Upload textcovs. steps.append({ 'name': 'gcr.io/cloud-builders/gsutil', 'args': [ '-m', 'cp', '-r', os.path.join(build.out, 'textcov_reports'), os.path.join(upload_coverage_path, 'textcov_reports'), ], }) credentials, _ = google.auth.default() build = build_project.run_build(project_name, steps, credentials, 'experiment', experiment=True, extra_tags=[experiment_name, project_name] + tags) build_id = build['id'] print('Waiting for build', build_id) try: build_lib.wait_for_build(build_id, credentials, 'oss-fuzz') except (KeyboardInterrupt, SystemExit): # Cancel the build on exit, to avoid dangling builds. build_lib.cancel_build(build_id, credentials, 'oss-fuzz') def main(): """Runs a target experiment on GCB.""" parser = argparse.ArgumentParser(sys.argv[0], description='Test projects') parser.add_argument('--project', required=True, help='Project name') parser.add_argument('--target', required=True, help='Target name') parser.add_argument('args', nargs='+', help='Additional arguments to pass to the target') parser.add_argument('--upload_build_log', required=True, help='GCS build log location.') parser.add_argument('--upload_output_log', required=True, help='GCS log location.') parser.add_argument('--upload_corpus', required=True, help='GCS location to upload corpus.') parser.add_argument('--upload_reproducer', required=False, default='', help='GCS location to upload reproducer.') parser.add_argument('--upload_coverage', required=True, help='GCS location to upload coverage data.') parser.add_argument('--experiment_name', required=True, help='Experiment name.') parser.add_argument('--tags', nargs='*', help='Tags for cloud build.', default=[]) parser.add_argument('--use_cached_image', action='store_true', help='Use cached images post build.') parser.add_argument( '--real_project', required=False, default='', help=('The real OSS-Fuzz project name (e.g. if `--project` ' 'is an autogenerated project name).')) args = parser.parse_args() run_experiment(args.project, args.target, args.args, args.upload_output_log, args.upload_build_log, args.upload_corpus, args.upload_coverage, args.experiment_name, args.upload_reproducer, args.tags, args.use_cached_image, args.real_project) if __name__ == '__main__': main() ================================================ FILE: infra/build/functions/test_data/expected_build_steps.json ================================================ [ { "args": [ "clone", "https://github.com/google/oss-fuzz.git", "--depth", "1" ], "name": "gcr.io/cloud-builders/git" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "--tag", "gcr.io/oss-fuzz/test-project", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json" ], "env": [ "OSSFUZZ_REVISION=$REVISION_ID", "FUZZING_LANGUAGE=c++" ], "id": "srcmap" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "run", "--privileged", "linuxkit/binfmt:v0.8" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "create", "--name", "buildxbuilder" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "use", "buildxbuilder" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "build", "--platform", "linux/arm64", "--progress", "plain", "--load", "--tag", "gcr.io/oss-fuzz/test-project-aarch64", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project-aarch64", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/afl-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-afl-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine afl --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-afl-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/afl-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/afl-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/afl-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-none-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-none-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-none-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.none" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-none-x86_64 && zip -r test-project-none-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-none-x86_64/test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.none", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-none-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=honggfuzz", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/honggfuzz-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/honggfuzz-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-honggfuzz-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=honggfuzz", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/honggfuzz-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-honggfuzz-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/honggfuzz-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/honggfuzz-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/honggfuzz-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-i386 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-i386" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture i386 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-i386" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-i386 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-i386/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-i386" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/arm64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=aarch64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-aarch64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project-aarch64", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-aarch64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-aarch64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/arm64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=aarch64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-aarch64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-aarch64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-aarch64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-aarch64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-aarch64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-memory-x86_64", "-e", "SANITIZER=memory", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-memory-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-memory-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-memory-x86_64", "-e", "SANITIZER=memory", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-memory-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.memory" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-memory-x86_64 && zip -r test-project-memory-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-memory-x86_64/test-project-memory-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.memory", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-memory-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-memory-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-undefined-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.undefined" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-undefined-x86_64 && zip -r test-project-undefined-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-undefined-x86_64/test-project-undefined-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.undefined", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-undefined-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-undefined-x86_64" ] } ] ================================================ FILE: infra/build/functions/test_data/expected_build_steps_ubuntu_24_04.json ================================================ [ { "args": [ "clone", "https://github.com/google/oss-fuzz.git", "--depth", "1" ], "name": "gcr.io/cloud-builders/git" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "--tag", "gcr.io/oss-fuzz/test-project", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json" ], "env": [ "OSSFUZZ_REVISION=$REVISION_ID", "FUZZING_LANGUAGE=c++" ], "id": "srcmap" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "run", "--privileged", "linuxkit/binfmt:v0.8" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "create", "--name", "buildxbuilder" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "use", "buildxbuilder" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "buildx", "build", "--platform", "linux/arm64", "--progress", "plain", "--load", "--tag", "gcr.io/oss-fuzz/test-project-aarch64", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project-aarch64", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/afl-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-afl-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine afl --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-afl-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/afl-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/afl-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/afl-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-none-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-none-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-none-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.none" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-none-x86_64 && zip -r test-project-none-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-none-x86_64/test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.none", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-none-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=honggfuzz", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/honggfuzz-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/honggfuzz-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-honggfuzz-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=honggfuzz", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/honggfuzz-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine honggfuzz --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-honggfuzz-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=honggfuzz", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/honggfuzz-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/honggfuzz-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/honggfuzz-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/honggfuzz-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-i386 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-i386" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture i386 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-i386" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-i386 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-i386/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-i386" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/arm64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=aarch64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-aarch64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project-aarch64", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-address-aarch64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-aarch64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/arm64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=aarch64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-aarch64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture aarch64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-aarch64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=aarch64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-aarch64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-address-aarch64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-address-aarch64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-address-aarch64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-memory-x86_64", "-e", "SANITIZER=memory", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-memory-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-memory-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-memory-x86_64", "-e", "SANITIZER=memory", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer memory --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-memory-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-memory-x86_64", "SANITIZER=memory" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.memory" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-memory-x86_64 && zip -r test-project-memory-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-memory-x86_64/test-project-memory-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.memory", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-memory-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-memory-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-undefined-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer undefined --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.undefined" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/libfuzzer-undefined-x86_64 && zip -r test-project-undefined-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/libfuzzer-undefined-x86_64/test-project-undefined-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.undefined", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-undefined-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/libfuzzer-undefined-x86_64" ] } ] ================================================ FILE: infra/build/functions/test_data/expected_centipede_build_steps.json ================================================ [ { "args": [ "clone", "https://github.com/google/oss-fuzz.git", "--depth", "1" ], "name": "gcr.io/cloud-builders/git" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "--tag", "gcr.io/oss-fuzz/test-project", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json" ], "env": [ "OSSFUZZ_REVISION=$REVISION_ID", "FUZZING_LANGUAGE=c++" ], "id": "srcmap" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer address --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer address --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-address-x86_64 && zip -r test-project-address-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-address-x86_64/test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.address", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-address-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-address-x86_64" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/centipede-none-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-centipede-none-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=centipede", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/centipede-none-x86_64", "-e", "SANITIZER=none", "-t", "gcr.io/oss-fuzz-base/base-runner", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer none --engine centipede --architecture x86_64 test-project\\npython infra/helper.py check_build --sanitizer none --engine centipede --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "build-check-centipede-none-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=centipede", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/centipede-none-x86_64", "SANITIZER=none" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.none" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "cd /workspace/out/centipede-none-x86_64 && zip -r test-project-none-202001010000.zip *" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/srcmap.json", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/out/centipede-none-x86_64/test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz-base/uploader", "args": [ "/workspace/targets.list.none", "test_url" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: text/plain", "-X", "PUT", "-d", "test-project-none-202001010000.zip", "test_url" ] }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "rm -r /workspace/out/centipede-none-x86_64" ] } ] ================================================ FILE: infra/build/functions/test_data/expected_coverage_build_steps.json ================================================ [ { "args": [ "clone", "https://github.com/google/oss-fuzz.git", "--depth", "1" ], "name": "gcr.io/cloud-builders/git" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "--tag", "gcr.io/oss-fuzz/test-project", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/test-project", "oss-fuzz/projects/test-project" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/oss-fuzz/test-project", "args": [ "bash", "-c", "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json" ], "env": [ "OSSFUZZ_REVISION=$REVISION_ID", "FUZZING_LANGUAGE=c++" ], "id": "srcmap" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-coverage-x86_64", "SANITIZER=coverage" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-coverage-x86_64", "-e", "SANITIZER=coverage", "-t", "gcr.io/oss-fuzz/test-project", "bash", "-c", "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/libfuzzer-coverage-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image test-project\\npython infra/helper.py build_fuzzers --sanitizer coverage --engine libfuzzer --architecture x86_64 test-project\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-coverage-x86_64" }, { "url": "test_download" }, { "name": "gcr.io/oss-fuzz-base/base-runner", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-coverage-x86_64", "SANITIZER=coverage", "HTTP_PORT=", "COVERAGE_EXTRA_ARGS=" ], "args": [ "bash", "-c", "for f in /corpus/*.zip; do unzip -q $f -d ${f%.*} || (echo \"Failed to unpack the corpus for $(basename ${f%.*}). This usually means that corpus backup for a particular fuzz target does not exist. If a fuzz target was added in the last 24 hours, please wait one more day. Otherwise, something is wrong with the fuzz target or the infrastructure, and corpus pruning task does not finish successfully.\" && exit 1); done && coverage || (echo \"********************************************************************************\nCode coverage report generation failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage test-project\npython infra/helper.py coverage test-project\n********************************************************************************\" && false)" ], "volumes": [ { "name": "corpus", "path": "/corpus" } ] }, { "name": "gcr.io/cloud-builders/gsutil", "entrypoint": "sh", "args": [ "-c", "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/reports/20200101 || exit 0" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "-m", "cp", "-r", "/workspace/out/libfuzzer-coverage-x86_64/report", "gs://oss-fuzz-coverage/test-project/reports/20200101" ] }, { "name": "gcr.io/cloud-builders/gsutil", "entrypoint": "sh", "args": [ "-c", "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/reports-by-target/20200101 || exit 0" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "-m", "cp", "-r", "/workspace/out/libfuzzer-coverage-x86_64/report_target", "gs://oss-fuzz-coverage/test-project/reports-by-target/20200101" ] }, { "name": "gcr.io/cloud-builders/gsutil", "entrypoint": "sh", "args": [ "-c", "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101 || exit 0" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "-m", "cp", "-r", "/workspace/out/libfuzzer-coverage-x86_64/fuzzer_stats", "gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101" ] }, { "name": "gcr.io/cloud-builders/gsutil", "entrypoint": "sh", "args": [ "-c", "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/textcov_reports/20200101 || exit 0" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "-m", "cp", "-r", "/workspace/out/libfuzzer-coverage-x86_64/textcov_reports", "gs://oss-fuzz-coverage/test-project/textcov_reports/20200101" ] }, { "name": "gcr.io/cloud-builders/gsutil", "entrypoint": "sh", "args": [ "-c", "gsutil -m rm -rf gs://oss-fuzz-coverage/test-project/logs/20200101 || exit 0" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "-m", "cp", "-r", "/workspace/out/libfuzzer-coverage-x86_64/logs", "gs://oss-fuzz-coverage/test-project/logs/20200101" ] }, { "name": "gcr.io/cloud-builders/gsutil", "args": [ "cp", "/workspace/srcmap.json", "gs://oss-fuzz-coverage/test-project/srcmap/20200101.json" ] }, { "name": "gcr.io/cloud-builders/curl", "args": [ "-H", "Content-Type: application/json", "-X", "PUT", "-d", "{\"fuzzer_stats_dir\": \"gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101\", \"html_report_url\": \"https://storage.googleapis.com/oss-fuzz-coverage/test-project/reports/20200101/linux/index.html\", \"report_date\": \"20200101\", \"report_summary_path\": \"gs://oss-fuzz-coverage/test-project/reports/20200101/linux/summary.json\"}", "test_url" ] } ] ================================================ FILE: infra/build/functions/test_data/expected_trial_build_steps.json ================================================ [ { "args": [ "clone", "https://github.com/google/oss-fuzz.git", "--depth", "1", "--branch", "mybranch" ], "name": "gcr.io/cloud-builders/git" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-swift-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-swift-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-swift" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-javascript-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-javascript-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-javascript" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-jvm-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-jvm-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-jvm" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-go-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-go-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-go" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-python-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-python-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-python" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-ruby-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-ruby-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-ruby" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-builder-rust-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-builder-rust-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-builder-rust" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "pull", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch" ], "waitFor": "-" }, { "name": "gcr.io/cloud-builders/docker", "args": [ "tag", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "gcr.io/oss-fuzz-base/base-runner" ] }, { "name": "gcr.io/cloud-builders/docker", "args": [ "build", "--tag", "gcr.io/oss-fuzz/skcms", "--tag", "us-central1-docker.pkg.dev/oss-fuzz/unsafe/skcms", "oss-fuzz/projects/skcms" ], "id": "build-UNIQUE_ID" }, { "name": "gcr.io/oss-fuzz/skcms", "args": [ "bash", "-c", "srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json" ], "env": [ "OSSFUZZ_REVISION=$REVISION_ID", "FUZZING_LANGUAGE=c++" ], "id": "srcmap" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/skcms", "bash", "-c", "rm -r /out && cd /src && cd skcms && mkdir -p /workspace/out/afl-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "compile-afl-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=afl", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/afl-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine afl --architecture x86_64 skcms\\npython infra/helper.py check_build --sanitizer address --engine afl --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "build-check-afl-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=afl", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/afl-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/skcms", "bash", "-c", "rm -r /out && cd /src && cd skcms && mkdir -p /workspace/out/libfuzzer-address-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-x86_64", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture x86_64 skcms\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-x86_64", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz/skcms", "bash", "-c", "rm -r /out && cd /src && cd skcms && mkdir -p /workspace/out/libfuzzer-address-i386 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 skcms\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-address-i386" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=i386", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-address-i386", "-e", "SANITIZER=address", "-t", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer address --engine libfuzzer --architecture i386 skcms\\npython infra/helper.py check_build --sanitizer address --engine libfuzzer --architecture i386 skcms\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-address-i386" }, { "name": "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "env": [ "ARCHITECTURE=i386", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-address-i386", "SANITIZER=address" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.address" ] }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz/skcms", "bash", "-c", "rm -r /out && cd /src && cd skcms && mkdir -p /workspace/out/libfuzzer-undefined-x86_64 && compile || (echo \"********************************************************************************\\nFailed to build.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "compile-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/cloud-builders/docker", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "run", "--platform", "linux/amd64", "-v", "/workspace:/workspace", "--privileged", "--cap-add=all", "-e", "ARCHITECTURE=x86_64", "-e", "FUZZING_ENGINE=libfuzzer", "-e", "FUZZING_LANGUAGE=c++", "-e", "HOME=/root", "-e", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "-e", "SANITIZER=undefined", "-t", "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "bash", "-c", "test_all.py || (echo \"********************************************************************************\\nBuild checks failed.\\nTo reproduce, run:\\npython infra/helper.py build_image skcms\\npython infra/helper.py build_fuzzers --sanitizer undefined --engine libfuzzer --architecture x86_64 skcms\\npython infra/helper.py check_build --sanitizer undefined --engine libfuzzer --architecture x86_64 skcms\\n********************************************************************************\" && false)" ], "id": "build-check-libfuzzer-undefined-x86_64" }, { "name": "gcr.io/oss-fuzz-base/base-runner-testing-legacy-mybranch", "env": [ "ARCHITECTURE=x86_64", "FUZZING_ENGINE=libfuzzer", "FUZZING_LANGUAGE=c++", "HOME=/root", "OUT=/workspace/out/libfuzzer-undefined-x86_64", "SANITIZER=undefined" ], "args": [ "bash", "-c", "targets_list > /workspace/targets.list.undefined" ] } ] ================================================ FILE: infra/build/functions/test_utils.py ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Utility functions for testing cloud functions.""" import datetime import os import subprocess import threading import requests DATASTORE_READY_INDICATOR = b'is now running' DATASTORE_EMULATOR_PORT = 8432 EMULATOR_TIMEOUT = 30 FUNCTIONS_DIR = os.path.dirname(__file__) OSS_FUZZ_DIR = os.path.dirname(os.path.dirname(os.path.dirname(FUNCTIONS_DIR))) PROJECTS_DIR = os.path.join(OSS_FUZZ_DIR, 'projects') FAKE_DATETIME = datetime.datetime(2020, 1, 1, 0, 0, 0) PROJECT = 'test-project' PROJECT_DIR = os.path.join(PROJECTS_DIR, PROJECT) def create_project_data(project, project_yaml_contents, dockerfile_contents='test line'): """Creates a project.yaml with |project_yaml_contents| and a Dockerfile with |dockerfile_contents| for |project|.""" project_dir = os.path.join(PROJECTS_DIR, project) project_yaml_path = os.path.join(project_dir, 'project.yaml') with open(project_yaml_path, 'w') as project_yaml_handle: project_yaml_handle.write(project_yaml_contents) dockerfile_path = os.path.join(project_dir, 'Dockerfile') with open(dockerfile_path, 'w') as dockerfile_handle: dockerfile_handle.write(dockerfile_contents) def start_datastore_emulator(): """Start Datastore emulator.""" return subprocess.Popen([ 'gcloud', 'beta', 'emulators', 'datastore', 'start', '--consistency=1.0', '--host-port=localhost:' + str(DATASTORE_EMULATOR_PORT), '--project=' + PROJECT, '--no-store-on-disk', ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def wait_for_emulator_ready(proc, emulator, indicator, timeout=EMULATOR_TIMEOUT): """Wait for emulator to be ready.""" emulator_output = [] def _read_thread(proc, ready_event): """Thread to continuously read from the process stdout.""" ready = False while True: line = proc.stdout.readline() if not line: break emulator_output.append(line.decode()) if not ready and indicator in line: ready = True ready_event.set() # Wait for process to become ready. ready_event = threading.Event() thread = threading.Thread(target=_read_thread, args=(proc, ready_event)) thread.daemon = True thread.start() if not ready_event.wait(timeout): raise RuntimeError(f'{emulator} emulator did not get ready in time:\n' + '\n'.join(emulator_output)) return thread def reset_ds_emulator(): """Reset ds emulator/clean all entities.""" req = requests.post(f'http://localhost:{DATASTORE_EMULATOR_PORT}/reset') req.raise_for_status() def cleanup_emulator(ds_emulator): """Cleanup the system processes made by ds emulator.""" del ds_emulator #To do, find a better way to cleanup emulator os.system('pkill -f datastore') def set_gcp_environment(): """Set environment variables for simulating in google cloud platform.""" os.environ['DATASTORE_EMULATOR_HOST'] = 'localhost:' + str( DATASTORE_EMULATOR_PORT) os.environ['GOOGLE_CLOUD_PROJECT'] = PROJECT os.environ['DATASTORE_DATASET'] = PROJECT os.environ['GCP_PROJECT'] = PROJECT os.environ['FUNCTION_REGION'] = 'us-central1' def get_test_data_file_path(filename): """Returns the path to a test data file with name |filename|.""" return os.path.join(os.path.dirname(__file__), 'test_data', filename) ================================================ FILE: infra/build/functions/trial_build/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/cloud-builders/gcloud RUN apt-get update && apt-get install python3-pip -y COPY . /opt/oss-fuzz RUN pip install -r /opt/oss-fuzz/infra/build/functions/requirements.txt WORKDIR /opt/oss-fuzz/infra/build/functions/ ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/build/functions/gcb.py"] ================================================ FILE: infra/build/functions/trial_build/cloudbuild.yaml ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ steps: - id: 'Build the trial-build image' name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/trial-build - '-f' - infra/build/functions/trial_build/Dockerfile - . - id: 'Legacy' name: 'gcr.io/oss-fuzz-base/trial-build' args: ['--version-tag', 'legacy'] waitFor: ['Build the trial-build image'] allowFailure: true env: - 'PULL_REQUEST_NUMBER=${_PR_NUMBER}' - 'BRANCH=${_HEAD_BRANCH}' - 'REPO=${_HEAD_REPO_URL}' - 'TIMEOUT=25200' timeout: 25200s - id: 'Ubuntu 20.04' name: 'gcr.io/oss-fuzz-base/trial-build' args: ['--version-tag', 'ubuntu-20-04'] waitFor: ['Build the trial-build image'] allowFailure: true env: - 'PULL_REQUEST_NUMBER=${_PR_NUMBER}' - 'BRANCH=${_HEAD_BRANCH}' - 'REPO=${_HEAD_REPO_URL}' - 'TIMEOUT=25200' timeout: 25200s - id: 'Ubuntu 24.04' name: 'gcr.io/oss-fuzz-base/trial-build' args: ['--version-tag', 'ubuntu-24-04'] waitFor: ['Build the trial-build image'] allowFailure: true env: - 'PULL_REQUEST_NUMBER=${_PR_NUMBER}' - 'BRANCH=${_HEAD_BRANCH}' - 'REPO=${_HEAD_REPO_URL}' - 'TIMEOUT=25200' timeout: 25200s - id: 'Generate Report' name: 'gcr.io/oss-fuzz-base/trial-build' entrypoint: 'python3' args: ['infra/build/functions/report_generator.py'] waitFor: ['Legacy', 'Ubuntu 20.04', 'Ubuntu 24.04'] logsBucket: gs://oss-fuzz-trialbuild-logs timeout: 25200s ================================================ FILE: infra/build/functions/trial_build.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tool for testing changes to base-images in OSS-Fuzz. This script builds test versions of all base images and the builds projects using those test images.""" import argparse import collections import datetime import functools import json import random import logging import os import subprocess import sys import textwrap import time import urllib.request import urllib.error import yaml import oauth2client.client from googleapiclient.discovery import build as cloud_build from googleapiclient.errors import HttpError import build_and_push_test_images import build_and_run_coverage import build_lib import build_project # Default timeout for the entire script in seconds, 7 hours. SCRIPT_DEFAULT_TIMEOUT = 25200 # Default timeout for a single project build in seconds, 4 hours. PROJECT_BUILD_TIMEOUT = 14400 TEST_IMAGE_SUFFIX = 'testing' # Warning time in minutes before build times out. BUILD_TIMEOUT_WARNING_MINUTES = 15 FINISHED_BUILD_STATUSES = ('SUCCESS', 'FAILURE', 'TIMEOUT', 'CANCELLED', 'EXPIRED') BuildType = collections.namedtuple( 'BuildType', ['type_name', 'get_build_steps_func', 'status_filename']) BUILD_TYPES = { 'coverage': BuildType('coverage', build_and_run_coverage.get_build_steps, 'status-coverage.json'), 'introspector': BuildType('introspector', build_and_run_coverage.get_fuzz_introspector_steps, 'status-introspector.json'), 'indexer': BuildType('indexer', build_project.get_indexer_build_steps, 'status.json'), 'fuzzing': BuildType('fuzzing', build_project.get_build_steps, 'status.json'), } def _get_production_build_statuses(build_type): """Gets the statuses for |build_type| that is reported by build-status. Returns a dictionary mapping projects to bools indicating whether the last build of |build_type| succeeded.""" try: request = urllib.request.urlopen( 'https://oss-fuzz-build-logs.storage.googleapis.com/' f'{build_type.status_filename}') project_statuses = json.load(request)['projects'] except urllib.error.URLError: # It is not a critical error if the status file cannot be found. # This is expected for indexer. return {} results = {} for project in project_statuses: name = project['name'] history = project['history'] if not history: continue success = history[0]['success'] results[name] = bool(success) return results @functools.lru_cache def get_all_projects(): """Returns a list of all OSS-Fuzz projects.""" projects_dir = os.path.join(build_and_push_test_images.OSS_FUZZ_ROOT, 'projects') return sorted([ project for project in os.listdir(projects_dir) if os.path.isdir(os.path.join(projects_dir, project)) ]) @functools.lru_cache def get_project_languages(): """Returns a dictionary mapping languages to projects.""" all_projects = get_all_projects() project_languages = collections.defaultdict(list) for project in all_projects: project_yaml_path = os.path.join(build_and_push_test_images.OSS_FUZZ_ROOT, 'projects', project, 'project.yaml') if not os.path.exists(project_yaml_path): continue with open(project_yaml_path, 'r', encoding='utf-8') as file_handle: project_yaml = yaml.safe_load(file_handle) language = project_yaml.get('language', 'c++') project_languages[language].append(project) return project_languages def handle_special_projects(args): """Handles "special" projects that are not actually projects such as "all" or "c++".""" all_projects = get_all_projects() if 'all' in args.projects: args.projects = all_projects return project_languages = get_project_languages() for project in args.projects[:]: if project in project_languages: language = project args.projects.remove(language) args.projects.extend(project_languages[language]) def get_args(args=None): """Parses command line arguments.""" parser = argparse.ArgumentParser(sys.argv[0], description='Test projects') parser.add_argument('projects', help='Projects. "all" for all projects', nargs='+') parser.add_argument('--sanitizers', required=False, default=[ 'address', 'memory', 'undefined', 'coverage', 'introspector', 'indexer' ], nargs='+', help='Sanitizers.') parser.add_argument('--fuzzing-engines', required=False, default=['afl', 'libfuzzer', 'honggfuzz', 'centipede'], nargs='+', help='Fuzzing engines.') parser.add_argument('--repo', required=False, default=build_project.DEFAULT_OSS_FUZZ_REPO, help='Use specified OSS-Fuzz repo.') parser.add_argument('--branch', required=False, default=None, help='Use specified OSS-Fuzz branch.') parser.add_argument('--force-build', action='store_true', help='Build projects that failed to build on OSS-Fuzz\'s ' 'production builder.') parser.add_argument('--version-tag', required=False, default=None, help='Version tag to use for base images.') parser.add_argument('--skip-build-images', action='store_true', help='Skip the base image build phase.') parsed_args = parser.parse_args(args) handle_special_projects(parsed_args) return parsed_args def handle_phase1_failure(version_tag): """Handles the case where phase 1 (image build) fails.""" all_projects = get_all_projects() results = { 'total': len(all_projects), 'successful': 0, 'failed': len(all_projects), 'skipped': 0, 'failed_projects': all_projects, } if version_tag: with open(f'{version_tag}-results.json', 'w') as f: json.dump(results, f) logging.error( 'Failed to build and push images. All projects for this version will be ' 'marked as failed.') return False def get_projects_to_build(specified_projects, build_type, force_build): """Returns the list of projects that should be built.""" buildable_projects = [] project_statuses = _get_production_build_statuses(build_type) for project in specified_projects: if (project not in project_statuses or project_statuses[project] or force_build): buildable_projects.append(project) return buildable_projects def trial_build_main(args=None, local_base_build=True): """Main function for trial_build.""" args = get_args(args) if not args.skip_build_images: logging.info('Starting "Build and Push Images" phase...') versions_to_build = ([args.version_tag] if args.version_tag else build_and_push_test_images.BASE_IMAGE_VERSIONS) for version in versions_to_build: logging.info( '================================================================') logging.info(' BUILDING BASE IMAGES FOR VERSION: %s', version.upper()) logging.info( '================================================================') version_test_image_tag = f'{TEST_IMAGE_SUFFIX}-{version}' if args.branch: version_test_image_tag = ( f'{version_test_image_tag}-{args.branch.lower().replace("/", "-")}') if local_base_build: build_and_push_test_images.build_and_push_images( version_test_image_tag, version) else: if not build_and_push_test_images.gcb_build_and_push_images( version_test_image_tag, version_tag=version): return handle_phase1_failure(version) logging.info('"Build and Push Images" phase completed.') else: logging.info( '================================================================') logging.info(' PHASE 1: SKIPPED') logging.info( '================================================================') logging.info('Skipping "Build and Push Images" phase as requested.') timeout = int(os.environ.get('TIMEOUT', SCRIPT_DEFAULT_TIMEOUT)) end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout) if local_base_build and not args.version_tag: versions_to_build = build_and_push_test_images.BASE_IMAGE_VERSIONS if not versions_to_build: return False overall_result = True for version in versions_to_build: logging.info( '================================================================') logging.info(' RUNNING TEST BUILDS FOR VERSION: %s', version.upper()) logging.info( '================================================================') test_image_tag = f'{TEST_IMAGE_SUFFIX}-{version}' if args.branch: test_image_tag = ( f'{test_image_tag}-{args.branch.lower().replace("/", "-")}') result = _do_test_builds(args, test_image_tag, end_time, version) overall_result = overall_result and result return overall_result # GCB or local single-version case test_image_tag = TEST_IMAGE_SUFFIX if args.version_tag: test_image_tag = f'{test_image_tag}-{args.version_tag}' if args.branch: test_image_tag = f'{test_image_tag}-{args.branch.lower().replace("/", "-")}' return _do_test_builds(args, test_image_tag, end_time, args.version_tag) def _do_test_builds(args, test_image_suffix, end_time, version_tag): """Does test coverage and fuzzing builds.""" build_types = [] sanitizers = list(args.sanitizers) if 'coverage' in sanitizers: sanitizers.pop(sanitizers.index('coverage')) build_types.append(BUILD_TYPES['coverage']) if 'introspector' in sanitizers: sanitizers.pop(sanitizers.index('introspector')) build_types.append(BUILD_TYPES['introspector']) if 'indexer' in sanitizers: sanitizers.pop(sanitizers.index('indexer')) build_types.append(BUILD_TYPES['indexer']) if sanitizers: build_types.append(BUILD_TYPES['fuzzing']) build_ids = collections.defaultdict(list) skipped_projects = collections.defaultdict(list) failed_to_start_builds = [] credentials = oauth2client.client.GoogleCredentials.get_application_default() logging.info( '================================================================') logging.info(' PHASE 2: STARTING TEST BUILDS') logging.info( '================================================================') for build_type in build_types: specified_projects = list(args.projects) projects_to_build = get_projects_to_build(specified_projects, build_type, args.force_build) if not args.force_build: unselected_projects = set(specified_projects) - set(projects_to_build) for project in unselected_projects: skipped_projects[build_type.type_name].append( (project, 'Production build failed')) logging.info('Build type: %s', build_type.type_name) logging.info( ' - Selected projects: %d / %d (due to successful production builds)', len(projects_to_build), len(args.projects)) logging.info(' - To build all projects, use the --force-build flag.') else: logging.info('Build type: %s', build_type.type_name) logging.info(' - Building all %d projects (--force-build)', len(projects_to_build)) logging.info('Starting to create and trigger builds for build type: %s', build_type.type_name) config = build_project.Config(testing=True, test_image_suffix=test_image_suffix, base_image_tag=version_tag, repo=args.repo, branch=args.branch, parallel=False, upload=False, build_type=build_type.type_name) project_builds, new_skipped, new_failed_to_start = _do_build_type_builds( args, config, credentials, build_type, projects_to_build) for project, reason in new_skipped: skipped_projects[build_type.type_name].append((project, reason)) failed_to_start_builds.extend(new_failed_to_start) for project, project_build_id in project_builds.items(): build_ids[project].append((project_build_id, build_type.type_name)) logging.info('Triggered all builds.') if skipped_projects: logging.info( '================================================================') logging.info(' PHASE 2: SKIPPED BUILDS') logging.info( '================================================================') total_skipped_builds = sum( len(skips) for skips in skipped_projects.values()) logging.info('Total skipped builds: %d', total_skipped_builds) logging.info('--- SKIPPED BUILDS ---') for build_type_name, skips in sorted(skipped_projects.items()): logging.info(' - %s:', build_type_name) for project, reason in sorted(skips): logging.info(' - %s: %s', project, reason) logging.info('-----------------------') logging.info( '================================================================') logging.info(' PHASE 2: STARTED BUILDS') logging.info( '================================================================') logging.info('Total projects with builds: %d', len(build_ids)) logging.info('--- STARTED BUILDS ---') for project, project_builds in sorted(build_ids.items()): logging.info(' - %s:', project) for build_id, build_type in project_builds: logging.info(' - Build Type: %s', build_type) for line in build_lib.get_build_info_lines(build_id, build_lib.IMAGE_PROJECT): logging.info(' %s', line) logging.info('-----------------------') wait_result = wait_on_builds(args, build_ids, credentials, build_lib.IMAGE_PROJECT, end_time, skipped_projects, version_tag) if failed_to_start_builds: logging.error( '================================================================') logging.error(' PHASE 2: FAILED TO START BUILDS') logging.error( '================================================================') logging.error('Total projects that failed to start: %d', len(failed_to_start_builds)) for project, reason in sorted(failed_to_start_builds): logging.error(' - %s: %s', project, reason) return wait_result and not failed_to_start_builds def _do_build_type_builds(args, config, credentials, build_type, projects): """Does |build_type| test builds of |projects|.""" build_ids = {} skipped_projects = [] failed_to_start_builds = [] for project_name in projects: try: project_yaml, dockerfile_contents = ( build_project.get_project_data(project_name)) except FileNotFoundError: skipped_projects.append((project_name, 'Missing Dockerfile')) continue build_project.set_yaml_defaults(project_yaml) if project_yaml['disabled']: skipped_projects.append((project_name, 'Disabled')) continue project_yaml_sanitizers = build_project.get_sanitizer_strings( project_yaml['sanitizers']) + ['coverage', 'introspector', 'indexer'] project_yaml['sanitizers'] = list( set(project_yaml_sanitizers).intersection(set(args.sanitizers))) project_yaml['fuzzing_engines'] = list( set(project_yaml['fuzzing_engines']).intersection( set(args.fuzzing_engines))) if not project_yaml['sanitizers'] or not project_yaml['fuzzing_engines']: skipped_projects.append( (project_name, 'No compatible sanitizers or engines')) continue # Check if project's base_os_version matches the current build version. project_base_os = project_yaml.get('base_os_version', 'legacy') current_build_version = config.base_image_tag or 'legacy' if project_base_os != current_build_version: skipped_projects.append( (project_name, f'Project requires {project_base_os}, but ' f'build version is {current_build_version}')) continue steps, reason = build_type.get_build_steps_func(project_name, project_yaml, dockerfile_contents, config) if reason: skipped_projects.append((project_name, reason)) continue try: tags = ['trial-build'] if args.branch: tags.append(f'branch-{args.branch.replace("/", "-")}') build_ids[project_name] = (build_project.run_build( project_name, steps, credentials, build_type.type_name, extra_tags=tags, timeout=PROJECT_BUILD_TIMEOUT))['id'] time.sleep(1) # Avoid going over 75 requests per second limit. except Exception as error: # pylint: disable=broad-except # Handle flake. logging.error('Failed to start build %s: %s', project_name, error) failed_to_start_builds.append((project_name, error)) return build_ids, skipped_projects, failed_to_start_builds def _print_summary_box(title, lines): """Prints a formatted box for summarizing build results.""" box_width = 80 title_line = f'| {title.center(box_width - 4)} |' separator = '+' + '-' * (box_width - 2) + '+' summary_lines = [ '+' + '-' * (box_width - 2) + '+', title_line, '+' + '-' * (box_width - 2) + '+', ] for line in lines: wrapped_lines = textwrap.wrap(line, box_width - 6) for i, sub_line in enumerate(wrapped_lines): summary_lines.append(f'| {sub_line.ljust(box_width - 6)} |') summary_lines.append('+' + '-' * (box_width - 2) + '+') print('\n'.join(summary_lines)) def get_build_status_from_gcb(cloudbuild_api, cloud_project, build_id): """Returns the status of the build: |build_id| from cloudbuild_api.""" build_result = cloudbuild_api.get(projectId=cloud_project, id=build_id).execute() return build_result['status'] def check_finished(build_id, cloudbuild_api, cloud_project, retries_map): """Checks that the build is complete. Returns status if complete, else None""" try: build_status = get_build_status_from_gcb(cloudbuild_api, cloud_project, build_id) except HttpError: logging.debug('build: HttpError when getting build status from gcb') retries_map[build_id] = retries_map.get(build_id, 0) + 1 return None if build_status not in FINISHED_BUILD_STATUSES: logging.debug('build: %d not finished.', build_id) return None return build_status def wait_on_builds(args, build_ids, credentials, cloud_project, end_time, skipped_projects, version_tag): # pylint: disable=too-many-locals """Waits on |builds|. Returns True if all builds succeed.""" cloudbuild = cloud_build('cloudbuild', 'v1', credentials=credentials, cache_discovery=False, client_options=build_lib.REGIONAL_CLIENT_OPTIONS) cloudbuild_api = cloudbuild.projects().builds() # pylylint: disable=no-member wait_builds = build_ids.copy() failed_builds = collections.defaultdict(list) successful_builds = collections.defaultdict(list) finished_builds_count = 0 retries_map = {} next_retry_time = {} MAX_RETRIES = 5 BASE_BACKOFF_SECONDS = 2 builds_count = sum(len(v) for v in build_ids.values()) projects_count = len(build_ids) logging.info('Waiting for %d builds from %d projects to complete...', builds_count, projects_count) timeout_warning_time = end_time - datetime.timedelta( minutes=BUILD_TIMEOUT_WARNING_MINUTES) notified_timeout = False while wait_builds: current_time = datetime.datetime.now() if current_time >= end_time: logging.error( 'Coordinator timeout reached. Marking remaining builds as TIMEOUT.') break if not notified_timeout and current_time >= timeout_warning_time: notified_timeout = True logging.warning( 'Nearing timeout: %d minutes remaining. Remaining builds: %d', BUILD_TIMEOUT_WARNING_MINUTES, len(wait_builds)) processed_a_build_in_iteration = False for project, project_builds in list(wait_builds.items()): for build_id, build_type in project_builds[:]: if (build_id in next_retry_time and datetime.datetime.now() < next_retry_time[build_id]): continue # In backoff period, skip for now. processed_a_build_in_iteration = True status = check_finished(build_id, cloudbuild_api, cloud_project, retries_map) if status: # API call was successful, remove from backoff map if it exists. if build_id in next_retry_time: del next_retry_time[build_id] finished_builds_count += 1 if status == 'SUCCESS': successful_builds[project].append(build_id) else: gcb_url = build_lib.get_gcb_url(build_id, cloud_project) log_url = build_lib.get_logs_url(build_id) failed_builds[project].append( (status, gcb_url, build_type, log_url)) wait_builds[project].remove((build_id, build_type)) if not wait_builds[project]: del wait_builds[project] elif retries_map.get(build_id, 0) >= MAX_RETRIES: # Max retries reached, mark as failed. logging.error('HttpError for build %s. Max retries reached.', build_id) if build_id in next_retry_time: del next_retry_time[build_id] finished_builds_count += 1 status = 'UNKNOWN (too many HttpErrors)' gcb_url = build_lib.get_gcb_url(build_id, cloud_project) log_url = build_lib.get_logs_url(build_id) failed_builds[project].append((status, gcb_url, build_type, log_url)) wait_builds[project].remove((build_id, build_type)) if not wait_builds[project]: del wait_builds[project] else: # API call failed, calculate and set next retry time. retry_count = retries_map.get(build_id, 0) backoff_time = (BASE_BACKOFF_SECONDS * (2**retry_count) + random.uniform(0, 1)) next_retry_time[build_id] = (datetime.datetime.now() + datetime.timedelta(seconds=backoff_time)) if not processed_a_build_in_iteration and wait_builds: # All remaining builds are in backoff, sleep to prevent busy-waiting. time.sleep(1) else: # General rate limiting after one full pass. time.sleep(0.5) # Handle builds that were still running when the coordinator timed out. if wait_builds: for project, project_builds in list(wait_builds.items()): for build_id, build_type in project_builds: gcb_url = build_lib.get_gcb_url(build_id, cloud_project) log_url = build_lib.get_logs_url(build_id) failed_builds[project].append( ('TIMEOUT (Coordinator)', gcb_url, build_type, log_url)) # Final Report successful_builds_count = sum( len(builds) for builds in successful_builds.values()) failed_builds_count = sum(len(builds) for builds in failed_builds.values()) skipped_builds_count = sum(len(skips) for skips in skipped_projects.values()) # Note: To get all unique project names, we create a set from the keys of # successful_builds, failed_builds, and the project names in skipped_projects. all_projects_in_build = set(successful_builds.keys()) | set( failed_builds.keys()) | set( p for sl in skipped_projects.values() for p, r in sl) total_projects = len(all_projects_in_build) results = { 'total_projects_analyzed': total_projects, 'successful_builds': successful_builds_count, 'failed_builds': failed_builds_count, 'skipped_builds': skipped_builds_count, 'failed_projects': sorted(list(failed_builds.keys())), 'skipped_projects': sorted(list(set(p for sl in skipped_projects.values() for p, r in sl)) ), 'all_projects': sorted(list(all_projects_in_build)), } with open(f'{version_tag}-results.json', 'w') as f: json.dump(results, f) summary_title = f'BUILD REPORT: {version_tag.upper()}' summary_lines = [ f"Total projects analyzed: {total_projects}", f"[PASSED] Successful builds: {successful_builds_count}", f"[FAILED] Failed builds: {failed_builds_count}", f"[SKIPPED] Skipped builds: {skipped_builds_count}", ] _print_summary_box(summary_title, summary_lines) if failed_builds: logging.error('--- FAILED BUILDS ---') for project, failures in sorted(failed_builds.items()): logging.error(' - %s:', project) for status, gcb_url, build_type, log_url in failures: build_id = gcb_url.split('/')[-1].split('?')[0] logging.error(' - Build Type: %s', build_type) logging.error(' - Status: %s', status) for line in build_lib.get_build_info_lines(build_id, cloud_project): logging.error(' - %s', line) logging.info('-----------------------') return False if not finished_builds_count and not skipped_builds_count: logging.warning('No builds were run.') if args.skip_build_images: return True return False logging.info('\nAll builds passed successfully!') logging.info('------------------------') return True if __name__ == '__main__': sys.exit(trial_build_main()) ================================================ FILE: infra/build/functions/trial_build_test.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for trial_build.py.""" import json import unittest from unittest import mock import test_utils import trial_build class GetProjectsToBuild(unittest.TestCase): """Tests for get_projects_to_build.""" PROJECTS = ['myproject', 'myfailingproject'] @mock.patch('trial_build._get_production_build_statuses', return_value={ 'myproject': True, 'myfailingproject': False }) def test_force_build(self, mock_get_production_build_statuses): """Tests force build works.""" del mock_get_production_build_statuses buildable_projects = trial_build.get_projects_to_build( self.PROJECTS, 'fuzzing', True) self.assertEqual(self.PROJECTS, buildable_projects) @mock.patch('trial_build._get_production_build_statuses', return_value={ 'myproject': True, 'myfailingproject': False }) def test_get_projects_to_build(self, mock_get_production_build_statuses): """Tests get_projects_to_build works.""" del mock_get_production_build_statuses buildable_projects = trial_build.get_projects_to_build( self.PROJECTS, 'fuzzing', True) self.assertEqual(self.PROJECTS, buildable_projects) class TrialBuildMainTest(unittest.TestCase): """Tests for trial_build_main.""" @mock.patch('build_lib.get_unique_build_step_image_id', return_value='UNIQUE_ID') @mock.patch('trial_build.wait_on_builds', return_value=True) @mock.patch('oauth2client.client.GoogleCredentials.get_application_default', return_value=None) @mock.patch('build_project.run_build') @mock.patch('build_and_push_test_images.build_and_push_images') def test_build_steps_correct(self, mock_gcb_build_and_push_images, mock_run_build, mock_get_application_default, mock_wait_on_builds, mock_get_unique_build_step_image_id): """Tests that the correct build steps for building a project are passed to GCB.""" del mock_gcb_build_and_push_images del mock_get_application_default del mock_wait_on_builds self.maxDiff = None # pylint: disable=invalid-name build_id = 1 mock_run_build.return_value = {'id': build_id} branch_name = 'mybranch' project = 'skcms' args = [ '--sanitizers', 'address', 'undefined', '--fuzzing-engines', 'afl', 'libfuzzer', '--branch', branch_name, '--force-build', project ] self.assertTrue(trial_build.trial_build_main(args)) expected_build_steps_path = test_utils.get_test_data_file_path( 'expected_trial_build_steps.json') with open(expected_build_steps_path, 'r') as file_handle: expected_build_steps = json.load(file_handle) # Snippet for updating this: # f=open('/tmp/a', 'w') # json.dump(mock_run_build.call_args_list[0][0][1], f); f.close() self.assertEqual(mock_run_build.call_args_list[0][0][1], expected_build_steps) if __name__ == '__main__': unittest.main(exit=False) ================================================ FILE: infra/build/fuzz-introspector-webapp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM python:3.11-bullseye # Allow statements and log messages to immediately appear in the Knative logs ENV PYTHONUNBUFFERED True RUN git clone --depth=1 https://github.com/ossf/fuzz-introspector /fuzz-introspector # Copy local code to the container image. ENV APP_HOME /fuzz-introspector/tools/web-fuzzing-introspection/app/ WORKDIR $APP_HOME # Install production dependencies. RUN pip install --no-cache-dir -r $APP_HOME/../requirements.txt # Create the database the webapp will be using RUN cd $APP_HOME/static/assets/db/ && \ python ./web_db_creator_from_summary.py \ --since-date=20-04-2023 \ --output-dir=$PWD \ --input-dir=$PWD ENV WEBAPP_PORT 8080 ENV G_ANALYTICS_TAG "G-VDH9DCD8T8" RUN pip install gunicorn==20.1.0 # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. # Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling. CMD exec gunicorn --bind :${WEBAPP_PORT} --workers 1 --threads 8 --timeout 0 'main:create_app()' ================================================ FILE: infra/build/fuzz-introspector-webapp/cloudbuild.yaml ================================================ # Builds and deploys the fuzz introspector webapp. steps: - name: 'gcr.io/cloud-builders/docker' args: - 'build' - '-t' - 'gcr.io/oss-fuzz-base/fuzz-introspector-webapp' - 'infra/build/fuzz-introspector-webapp' # Push the image here so we deploy the latest build. - name: 'gcr.io/cloud-builders/docker' args: - 'push' - 'gcr.io/oss-fuzz-base/fuzz-introspector-webapp' - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' entrypoint: gcloud args: - 'run' - 'deploy' - 'fuzz-introspector-webapp' - '--image' - 'gcr.io/oss-fuzz-base/fuzz-introspector-webapp' - '--region' - 'us-central1' - '--min-instances' - '1' - '--max-instances' - '100' - '--cpu' - '6' - '--memory' - '24Gi' options: machineType: 'E2_HIGHCPU_32' timeout: 21600s # 6 hours ================================================ FILE: infra/build/request_all_builds.sh ================================================ #!/bin/bash -ex # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ for project in ../../projects/*; do if [[ ! -f $project/Dockerfile ]]; then continue fi ./request_build.sh $(basename $project) $1 done ================================================ FILE: infra/build/request_build.sh ================================================ #!/bin/bash -ex # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ "$2" = "fuzzing" ]; then topic=request-build elif [ "$2" = "coverage" ]; then topic=request-coverage-build elif [ "$2" = "introspector" ]; then topic=request-introspector-build else echo "Invalid build type $2." exit 1 fi gcloud pubsub topics publish $topic --message "$1" --project oss-fuzz ================================================ FILE: infra/build/status/bower.json ================================================ { "name": "build-status", "main": "index.html", "dependencies": { "polymer": "Polymer/polymer#^2.0.0-rc.3", "paper-item": "PolymerElements/paper-item#2.0-preview", "app-layout": "PolymerElements/app-layout#2.0-preview", "paper-card": "PolymerElements/paper-card#2.0-preview", "paper-tabs": "PolymerElements/paper-tabs#2.0-preview", "iron-icons": "PolymerElements/iron-icons#2.0-preview", "iron-ajax": "PolymerElements/iron-ajax#2.0-preview", "iron-flex-layout": "PolymerElements/iron-flex-layout#2.0-preview", "paper-icon-button": "PolymerElements/paper-icon-button#2.0-preview", "app-route": "PolymerElements/app-route#2.0-preview" }, "devDependencies": { "web-component-tester": "^6.0.0-prerelease.5", "webcomponentsjs": "webcomponents/webcomponentsjs#^1.1.0" } } ================================================ FILE: infra/build/status/deploy.sh ================================================ #!/bin/bash -ex # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ gsutil -h "Cache-Control:no-cache,max-age=0" -m cp -r bower_components index.html src manifest.json gs://oss-fuzz-build-logs ================================================ FILE: infra/build/status/index.html ================================================ OSS-Fuzz build status ================================================ FILE: infra/build/status/manifest.json ================================================ { "name": "build-status", "short_name": "build-status", "start_url": "/", "display": "standalone" } ================================================ FILE: infra/build/status/polymer.json ================================================ { "lint": { "rules": [ "polymer-2" ] } } ================================================ FILE: infra/build/status/src/build-status/build-status.html ================================================ ================================================ FILE: infra/build_fuzzers.Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image to run fuzzers for CIFuzz (the run_fuzzers action on GitHub # actions). FROM gcr.io/oss-fuzz-base/cifuzz-base # Python file to execute when the docker container starts up # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/build_fuzzers_entrypoint.py"] WORKDIR ${OSS_FUZZ_ROOT}/infra # Update infra source code. ADD . ${OSS_FUZZ_ROOT}/infra RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt ================================================ FILE: infra/build_fuzzers.ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image to run fuzzers for CIFuzz (the run_fuzzers action on GitHub # actions). FROM gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04 # Python file to execute when the docker container starts up # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/build_fuzzers_entrypoint.py"] WORKDIR ${OSS_FUZZ_ROOT}/infra # Update infra source code. ADD . ${OSS_FUZZ_ROOT}/infra RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt ================================================ FILE: infra/build_specified_commit.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module to build a image from a specific commit, branch or pull request. This module is allows each of the OSS Fuzz projects fuzzers to be built from a specific point in time. This feature can be used for implementations like continuious integration fuzzing and bisection to find errors """ import argparse import bisect import datetime import os import collections import json import logging import re import shutil import tempfile import helper import repo_manager import retry import utils BuildData = collections.namedtuple( 'BuildData', ['project_name', 'engine', 'sanitizer', 'architecture']) _GIT_DIR_MARKER = 'gitdir: ' _IMAGE_BUILD_TRIES = 3 class BaseBuilderRepo: """Repo of base-builder images.""" def __init__(self): self.timestamps = [] self.digests = [] def add_digest(self, timestamp, digest): """Add a digest.""" self.timestamps.append(timestamp) self.digests.append(digest) def find_digest(self, timestamp): """Find the latest image before the given timestamp.""" index = bisect.bisect_right(self.timestamps, timestamp) if index > 0: return self.digests[index - 1] logging.error('Failed to find suitable base-builder.') return None def _replace_gitdir(src_dir, file_path): """Replace gitdir with a relative path.""" with open(file_path) as handle: lines = handle.readlines() new_lines = [] for line in lines: if line.startswith(_GIT_DIR_MARKER): absolute_path = line[len(_GIT_DIR_MARKER):].strip() if not os.path.isabs(absolute_path): # Already relative. return current_dir = os.path.dirname(file_path) # Rebase to /src rather than the host src dir. base_dir = current_dir.replace(src_dir, '/src') relative_path = os.path.relpath(absolute_path, base_dir) logging.info('Replacing absolute submodule gitdir from %s to %s', absolute_path, relative_path) line = _GIT_DIR_MARKER + relative_path new_lines.append(line) with open(file_path, 'w') as handle: handle.write(''.join(new_lines)) def _make_gitdirs_relative(src_dir): """Make gitdirs relative.""" for root_dir, _, files in os.walk(src_dir): for filename in files: if filename != '.git': continue file_path = os.path.join(root_dir, filename) _replace_gitdir(src_dir, file_path) def _replace_base_builder_digest(dockerfile_path, digest): """Replace the base-builder digest in a Dockerfile.""" with open(dockerfile_path) as handle: lines = handle.readlines() new_lines = [] for line in lines: if line.strip().startswith('FROM'): line = 'FROM gcr.io/oss-fuzz-base/base-builder@' + digest + '\n' new_lines.append(line) with open(dockerfile_path, 'w') as handle: handle.write(''.join(new_lines)) def copy_src_from_docker(project_name, host_dir): """Copy /src from docker to the host.""" # Copy /src to host. image_name = 'gcr.io/oss-fuzz/' + project_name src_dir = os.path.join(host_dir, 'src') if os.path.exists(src_dir): shutil.rmtree(src_dir, ignore_errors=True) docker_args = [ '-v', host_dir + ':/out', image_name, 'cp', '-r', '-p', '/src', '/out', ] helper.docker_run(docker_args) # Submodules can have gitdir entries which point to absolute paths. Make them # relative, as otherwise we can't do operations on the checkout on the host. _make_gitdirs_relative(src_dir) return src_dir @retry.wrap(_IMAGE_BUILD_TRIES, 2) def _build_image_with_retries(project_name): """Build image with retries.""" return helper.build_image_impl(helper.Project(project_name)) def get_required_post_checkout_steps(dockerfile_path): """Get required post checkout steps (best effort).""" checkout_pattern = re.compile(r'\s*RUN\s*(git|svn|hg)') # If the build.sh is copied from upstream, we need to copy it again after # changing the revision to ensure correct building. post_run_pattern = re.compile(r'\s*RUN\s*(.*build\.sh.*(\$SRC|/src).*)') with open(dockerfile_path) as handle: lines = handle.readlines() subsequent_run_cmds = [] for i, line in enumerate(lines): if checkout_pattern.match(line): subsequent_run_cmds = [] continue match = post_run_pattern.match(line) if match: workdir = helper.workdir_from_lines(lines[:i]) command = match.group(1) subsequent_run_cmds.append((workdir, command)) return subsequent_run_cmds # pylint: disable=too-many-locals def build_fuzzers_from_commit(commit, build_repo_manager, host_src_path, build_data, base_builder_repo=None): """Builds a OSS-Fuzz fuzzer at a specific commit SHA. Args: commit: The commit SHA to build the fuzzers at. build_repo_manager: The OSS-Fuzz project's repo manager to be built at. build_data: A struct containing project build information. base_builder_repo: A BaseBuilderRepo. Returns: 0 on successful build or error code on failure. """ oss_fuzz_repo_manager = repo_manager.RepoManager(helper.OSS_FUZZ_DIR) num_retry = 1 def cleanup(): # Re-copy /src for a clean checkout every time. copy_src_from_docker(build_data.project_name, os.path.dirname(host_src_path)) build_repo_manager.fetch_all_remotes() projects_dir = os.path.join('projects', build_data.project_name) dockerfile_path = os.path.join(projects_dir, 'Dockerfile') for i in range(num_retry + 1): build_repo_manager.checkout_commit(commit, clean=False) post_checkout_steps = get_required_post_checkout_steps(dockerfile_path) for workdir, post_checkout_step in post_checkout_steps: logging.info('Running post-checkout step `%s` in %s.', post_checkout_step, workdir) helper.docker_run([ '-w', workdir, '-v', host_src_path + ':' + '/src', 'gcr.io/oss-fuzz/' + build_data.project_name, '/bin/bash', '-c', post_checkout_step, ]) project = helper.Project(build_data.project_name) result = helper.build_fuzzers_impl(project=project, clean=True, engine=build_data.engine, sanitizer=build_data.sanitizer, architecture=build_data.architecture, env_to_add=None, source_path=host_src_path, mount_path='/src') if result or i == num_retry: break # Retry with an OSS-Fuzz builder container that's closer to the project # commit date. commit_date = build_repo_manager.commit_date(commit) # Find first change in the projects/ directory before the project # commit date. oss_fuzz_commit, _, _ = oss_fuzz_repo_manager.git([ 'log', '--before=' + commit_date.isoformat(), '-n1', '--format=%H', projects_dir ], check_result=True) oss_fuzz_commit = oss_fuzz_commit.strip() if not oss_fuzz_commit: logging.info( 'Could not find first OSS-Fuzz commit prior to upstream commit. ' 'Falling back to oldest integration commit.') # Find the oldest commit. oss_fuzz_commit, _, _ = oss_fuzz_repo_manager.git( ['log', '--reverse', '--format=%H', projects_dir], check_result=True) oss_fuzz_commit = oss_fuzz_commit.splitlines()[0].strip() if not oss_fuzz_commit: logging.error('Failed to get oldest integration commit.') break logging.info('Build failed. Retrying on earlier OSS-Fuzz commit %s.', oss_fuzz_commit) # Check out projects/ dir to the commit that was found. oss_fuzz_repo_manager.git(['checkout', oss_fuzz_commit, projects_dir], check_result=True) # Also use the closest base-builder we can find. if base_builder_repo: base_builder_digest = base_builder_repo.find_digest(commit_date) if not base_builder_digest: return False logging.info('Using base-builder with digest %s.', base_builder_digest) _replace_base_builder_digest(dockerfile_path, base_builder_digest) # Rebuild image and re-copy src dir since things in /src could have changed. if not _build_image_with_retries(build_data.project_name): logging.error('Failed to rebuild image.') return False cleanup() cleanup() return result def detect_main_repo(project_name, repo_name=None, commit=None): """Checks a docker image for the main repo of an OSS-Fuzz project. Note: The default is to use the repo name to detect the main repo. Args: project_name: The name of the oss-fuzz project. repo_name: The name of the main repo in an OSS-Fuzz project. commit: A commit SHA that is associated with the main repo. Returns: A tuple containing (the repo's origin, the repo's path). """ if not repo_name and not commit: logging.error( 'Error: can not detect main repo without a repo_name or a commit.') return None, None if repo_name and commit: logging.info( 'Both repo name and commit specific. Using repo name for detection.') # Change to oss-fuzz main directory so helper.py runs correctly. utils.chdir_to_root() if not _build_image_with_retries(project_name): logging.error('Error: building %s image failed.', project_name) return None, None docker_image_name = 'gcr.io/oss-fuzz/' + project_name command_to_run = [ 'docker', 'run', '--rm', '-t', docker_image_name, 'python3', os.path.join('/opt', 'cifuzz', 'detect_repo.py') ] if repo_name: command_to_run.extend(['--repo_name', repo_name]) else: command_to_run.extend(['--example_commit', commit]) out, _, _ = utils.execute(command_to_run) match = re.search(r'\bDetected repo: ([^ ]+) ([^ ]+)', out.rstrip()) if match and match.group(1) and match.group(2): return match.group(1), match.group(2) logging.error('Failed to detect repo:\n%s', out) return None, None def load_base_builder_repo(): """Get base-image digests.""" gcloud_path = shutil.which('gcloud') if not gcloud_path: logging.warning('gcloud not found in PATH.') return None result, _, _ = utils.execute([ gcloud_path, 'container', 'images', 'list-tags', 'gcr.io/oss-fuzz-base/base-builder', '--format=json', '--sort-by=timestamp', ], check_result=True) result = json.loads(result) repo = BaseBuilderRepo() for image in result: timestamp = datetime.datetime.fromisoformat( image['timestamp']['datetime']).astimezone(datetime.timezone.utc) repo.add_digest(timestamp, image['digest']) return repo def main(): """Main function.""" logging.getLogger().setLevel(logging.INFO) parser = argparse.ArgumentParser( description='Build fuzzers at a specific commit') parser.add_argument('--project_name', help='The name of the project where the bug occurred.', required=True) parser.add_argument('--commit', help='The newest commit SHA to be bisected.', required=True) parser.add_argument('--engine', help='The default is "libfuzzer".', default='libfuzzer') parser.add_argument('--sanitizer', default='address', help='The default is "address".') parser.add_argument('--architecture', default='x86_64') args = parser.parse_args() repo_url, repo_path = detect_main_repo(args.project_name, commit=args.commit) if not repo_url or not repo_path: raise ValueError('Main git repo can not be determined.') with tempfile.TemporaryDirectory() as tmp_dir: host_src_dir = copy_src_from_docker(args.project_name, tmp_dir) build_repo_manager = repo_manager.RepoManager( os.path.join(host_src_dir, os.path.basename(repo_path))) base_builder_repo = load_base_builder_repo() build_data = BuildData(project_name=args.project_name, engine=args.engine, sanitizer=args.sanitizer, architecture=args.architecture) if not build_fuzzers_from_commit(args.commit, build_repo_manager, host_src_dir, build_data, base_builder_repo=base_builder_repo): raise RuntimeError('Failed to build.') if __name__ == '__main__': main() ================================================ FILE: infra/build_specified_commit_test.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the functionality of the build image from commit module. The will consist of the following functional tests: 1. The inference of the main repo for a specific project. 2. The building of a projects fuzzers from a specific commit. """ import os import tempfile import unittest import build_specified_commit import helper import repo_manager import test_repos # necessary because __file__ changes with os.chdir TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class BuildImageIntegrationTest(unittest.TestCase): """Tests if an image can be built from different states e.g. a commit.""" @unittest.skip('Test is failing (spuriously?).') def test_build_fuzzers_from_commit(self): """Tests if the fuzzers can build at a specified commit. This is done by using a known regression range for a specific test case. The old commit should show the error when its fuzzers run and the new one should not. """ with tempfile.TemporaryDirectory() as tmp_dir: test_repo = test_repos.TEST_REPOS[1] self.assertTrue(helper.build_image_impl(test_repo.project_name)) host_src_dir = build_specified_commit.copy_src_from_docker( test_repo.project_name, tmp_dir) test_repo_manager = repo_manager.clone_repo_and_get_manager( test_repo.git_url, host_src_dir, test_repo.oss_repo_name) build_data = build_specified_commit.BuildData( sanitizer='address', architecture='x86_64', engine='libfuzzer', project_name=test_repo.project_name) build_specified_commit.build_fuzzers_from_commit(test_repo.old_commit, test_repo_manager, host_src_dir, build_data) project = helper.Project(test_repo.project_name) old_result = helper.reproduce_impl(project=project, fuzzer_name=test_repo.fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=test_repo.testcase_path) build_specified_commit.build_fuzzers_from_commit(test_repo.project_name, test_repo_manager, host_src_dir, build_data) new_result = helper.reproduce_impl(project=project, fuzzer_name=test_repo.fuzz_target, valgrind=False, env_to_add=[], fuzzer_args=[], testcase_path=test_repo.testcase_path) self.assertNotEqual(new_result, old_result) def test_detect_main_repo_from_commit(self): """Test the detect main repo function from build specific commit module.""" # TODO(metzman): Fix these tests so they don't randomly break because of # changes in the outside world. for example_repo in test_repos.TEST_REPOS: if example_repo.new_commit: # TODO(metzman): This function calls _build_image_with_retries which # has a long delay (30 seconds). Figure out how to make this quicker. repo_origin, repo_name = build_specified_commit.detect_main_repo( example_repo.project_name, commit=example_repo.new_commit) self.assertEqual(repo_origin, example_repo.git_url) self.assertEqual(repo_name, os.path.join('/src', example_repo.oss_repo_name)) repo_origin, repo_name = build_specified_commit.detect_main_repo( test_repos.INVALID_REPO.project_name, test_repos.INVALID_REPO.new_commit) self.assertIsNone(repo_origin) self.assertIsNone(repo_name) def test_detect_main_repo_from_name(self): """Test the detect main repo function from build specific commit module.""" for example_repo in test_repos.TEST_REPOS: if example_repo.project_name == 'gonids': # It's unclear how this test ever passed, but we can't infer the repo # because gonids doesn't really check it out, it uses "go get". continue repo_origin, repo_name = build_specified_commit.detect_main_repo( example_repo.project_name, repo_name=example_repo.git_repo_name) self.assertEqual(repo_origin, example_repo.git_url) self.assertEqual( repo_name, os.path.join(example_repo.image_location, example_repo.oss_repo_name)) repo_origin, repo_name = build_specified_commit.detect_main_repo( test_repos.INVALID_REPO.project_name, test_repos.INVALID_REPO.oss_repo_name) self.assertIsNone(repo_origin) self.assertIsNone(repo_name) if __name__ == '__main__': # Change to oss-fuzz main directory so helper.py runs correctly. if os.getcwd() != os.path.dirname(TEST_DIR_PATH): os.chdir(os.path.dirname(TEST_DIR_PATH)) unittest.main() ================================================ FILE: infra/chronos/README.md ================================================ # Chronos: rebuilding OSS-Fuzz harnesses using cached builds Chronos is a utility tooling to enable fast re-building of OSS-Fuzz projects and analysis of projects' testing infrastructure. This is used by projects, e.g. [OSS-Fuzz-gen](https://github.com/google/oss-fuzz-gen) to help speed up valuation processes during fuzzing harness generation. At the core, Chronos relies on caching containers after project build, in order to enable fast rebuilding of a project following minor patches, and also enable running of the tests in a given project. To support this, Chronos creates a snapshot of the Docker container given project post build completion. This means that all `.o` files, generated configurations etc. persist in the Docker container. These artifacts are then leveraged for future "replay builds" where only a minor part of the project has changed, e.g. due to some patching on the project. This patching could be e.g. minor adjustments to the fuzzing harness source code e.g. by [oss-fuzz-gen](https://github.com/google/oss-fuzz-gen). As such, at the core of Chronos are cached containers that are generated by taking a snapshot of the container of a project post project build. Chronos is focused on two features, rebuilding projects fast and running the tests of a given project. ## Chronos features: fast rebuilding and running the tests of a project ### CLI interface for Chronos The default route to validating Chronos is using the CLI available in `infra/experimental/chronos/manager.py` ### Chronos feature: Fast rebuilding Chronos enables rebuilding projects efficiently in contexts where only a small patch needs to be evaluated in the target. This is achieved by running a replay build script in the build container, similarly to how a regular `build_fuzzers` command would run, but with the caveat that the replay build script only performs a subset of the operations of the original `build.sh`. The replay build scripts are constructed in two ways: manually or automatically. #### Option 1: Automated rebuilds Chronos supports automated rebuilding. This is meant as a generic mechanism to enable Chronos support for projects by default. This is achieved by: 1. Calling into a `replay_build.sh` script during the building inside the container [here](https://github.com/google/oss-fuzz/blob/206656447b213fb04901d15122692d8dd4d45312/infra/base-images/base-builder/compile#L292-L296) 2. The `replay_build.sh` calls into `make_build_replayable.py`: [here](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/replay_build.sh) 3. `make_build_replayable.py` adjusts the build environment to wrap around common commands, to avoid performing a complete run of `build.sh`: [here](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/make_build_replayable.py). The automated rebuilding works in combination with [Ccache](https://ccache.dev/), in order to facilitate caching of e.g. `.o` files. This means that during rebuild mode as long as we have a cache, we don't need to e.g. run `configure` again and will only have to rebuild the changed source code. #### Option 2: Manually provided replay builds `replay_build.sh` above, is simply just a wrapper script around `build.sh` that aims to enable fast rebuilding of the project. This `replay_build.sh` can, however, be overwritten in the Dockerfile of the project's builder image to support a custom approach to fast rebuilding. Two examples of this is [php](https://github.com/google/oss-fuzz/blob/206656447b213fb04901d15122692d8dd4d45312/projects/php/replay_build.sh#L1) and [ffmpeg](https://github.com/google/oss-fuzz/blob/master/projects/ffmpeg/replay_build.sh#L1). Providing a manual `replay_build.sh` is likely more efficient at build time and can help speed up the process. Automated replay build scripts can also be erroneous. #### Testing the validity of a replay build The Chronos manager can use the `manager.py` to validate the validity of a replay build for a given project: ```sh python3 infra/experimental/chronos/manager.py check-replay tinyobjloader ``` If the above command fails for the relevant project, then the replay build feature does not work for the given project. ### Chronos feature: Running tests of a project The second part of Chronos is a feature to enable running the tests of a given project. This is done by way of a script `run_tests.sh`. Samples of this script include [jsonnet](https://github.com/google/oss-fuzz/blob/master/projects/jsonnet/run_tests.sh#L1) and [tinyobjloader](https://github.com/google/oss-fuzz/blob/master/projects/tinyobjloader/run_tests.sh#L1). #### Run tests constraints 1. The `run_tests.sh` main task is to run the tests of a project and return `0` upon success and non-null otherwise. 2. The `run_tests.sh` script must leave the main repository in the state as it was prior to the execution of `run_tests.sh` relative to `git diff` (or similar diff features of other version control systems). #### Testing the validity of run_tests.sh The Chronos manager can use the `manager.py` to validate the validity of a `run_tests.sh` script: ```sh python3 infra/experimental/chronos/manager.py check-tests json-c ``` ### Constraints imposed on replay_build.sh and run_tests.sh At the core of chronos are the two scripts `replay_build.sh` and `run_tests.sh`. We have a default mechanism for `replay_build.sh` so it's not strictly necessary to have a custom one, although it will likely improve speed and maybe correctness by providing one. There are three stages of the Chronos workflow: 1. The cached containers represent the state of a build container after a successful project build. 2. The `replay_build.sh` is able to rebuild a given project from the state of a cached container. 3. The `run_tests.sh` script is able to run the tests of a given project. This should be able to succeed following the running of a `replay_build.sh`. The stages (2) and (3) must both support running without network connectivity. Specifically, this means that the `replay_build.sh` must not do tasks e.g. fetch dependencies, download corpus, or anything of this nature. Similarly, the `run_tests.sh` must be able to operate completely in a closed network environment. ## Pre-built images. Chronos cached images are built daily, and pre-built images are available at: - `us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/-ofg-cached-address` - `us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/-ofg-cached-coverage` They can be used as drop-in replacements for the usual `gcr.io/oss-fuzz/` images. ================================================ FILE: infra/chronos/__init__.py ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### ================================================ FILE: infra/chronos/container_cache_build.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. echo "Starting prepare cache build script" export PATH=/ccache/bin:$PATH python3.11 -m pip install -r /chronos/requirements.txt rm -rf /out/* compile cp -n /usr/local/bin/replay_build.sh $SRC/ ================================================ FILE: infra/chronos/container_coverage_collection.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. chmod +x /src/run_tests.sh find /src/ -name "*.profraw" -exec rm -f {} \; /src/run_tests.sh python3 /chronos/coverage_test_collection.py chmod -R 755 /out/test-html-generation/ ================================================ FILE: infra/chronos/container_patch_replay_test.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. echo "Starting container patch replay script: $1" python3 /chronos/integrity_validator_check_replay.py $1 export PATH=/ccache/bin$PATH rm -rf /out/* compile ================================================ FILE: infra/chronos/container_patch_tests_test.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. echo "Starting container patch tests script" # Ensure dependencies are installed python3 -m pip install -r /chronos/requirements.txt # Capture patch, run tests and then diff patches. python3 /chronos/integrity_validator_run_tests.py diff-patch before chmod +x /src/run_tests.sh /src/run_tests.sh python3 /chronos/integrity_validator_run_tests.py diff-patch after ================================================ FILE: infra/chronos/coverage_test_collection.py ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### """Module for extracting coverage data from a run of run_tests.sh""" import os import shutil import subprocess COV_WORKDIR = '/tmp/cov-dumps' def collect_coverage_profraw_files(): """Finds profraw files in the most likely places in the OSS-Fuzz build container and copies them to the COV_WORKDIR.""" rootdir = '/src/' for subdir, _, files in os.walk(rootdir): for file in files: if file.endswith('.profraw'): print(os.path.join(subdir, file)) dst_name = os.path.join(subdir, file).replace('/', '_') shutil.copy(os.path.join(subdir, file), f'{COV_WORKDIR}/{dst_name}') def find_all_executables(): """Finds all executables that are likely to be run with coverage collection.""" rootdir = '/src/' objects_string = '' for subdir, _, files in os.walk(rootdir): if any(avoid_dir in subdir for avoid_dir in ['aflplusplus', 'fuzztest', 'honggfuzz', 'libfuzzer', '.git']): continue for file in files: abs_file = os.path.join(subdir, file) if os.access(abs_file, os.X_OK): # Ensure it's an ELF with open(abs_file, 'rb') as binf: magic_bytes = binf.read(4) if len(magic_bytes) != 4: continue is_elf = True if magic_bytes[0] != 0x7f: is_elf = False if magic_bytes[1] != 0x45: is_elf = False if magic_bytes[2] != 0x4c: is_elf = False if magic_bytes[3] != 0x46: is_elf = False if not is_elf: continue dst_name = f'{COV_WORKDIR}/{file}' if not objects_string: objects_string = abs_file + ' ' else: objects_string += f'-object {dst_name} ' shutil.copy(abs_file, dst_name) print('Found the following executables for coverage extraction:') print(objects_string) return objects_string def run_llvm_html_generation(objects, out_dir, workdir=COV_WORKDIR): """Generates HTML coverage report from profraw files.""" prof_raws = '' instr_profile = os.path.join(workdir, 'merged_profdata.profdata') for file in os.listdir(workdir): if file.endswith('.profraw'): prof_raws += os.path.join(workdir, file) + ' ' cmd = [ 'llvm-profdata', 'merge', '-j=1', '-sparse', prof_raws, '-o', instr_profile ] subprocess.check_call(' '.join(cmd), shell=True) # Extract HTML report cmd = [ 'llvm-cov', 'show', '-format=html', f'-output-dir={out_dir}', f'-instr-profile={instr_profile}', objects ] subprocess.check_call(' '.join(cmd), shell=True) # Extract json report cmd = [ 'llvm-cov', 'export', '-summary-only', f'-instr-profile={instr_profile}', objects, ] stdout_fp = open(os.path.join(out_dir, 'summary.json'), 'w') subprocess.check_call(' '.join(cmd), shell=True, stdout=stdout_fp) stdout_fp.close() def reset_cov_workdir(): """Resets the coverage work directory.""" if os.path.exists(COV_WORKDIR): shutil.rmtree(COV_WORKDIR, ignore_errors=True) os.mkdir(COV_WORKDIR) def main(): """Main function to run the coverage test collection.""" reset_cov_workdir() collect_coverage_profraw_files() obj_string = find_all_executables() run_llvm_html_generation(obj_string, '/out/test-html-generation') if __name__ == '__main__': main() ================================================ FILE: infra/chronos/integrity_validator_check_replay.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper to generate bad patches for replay test using different approach.""" import os import pathlib import random import sys EXCLUDE_DIRS = ['tests', 'test', 'examples', 'example', 'build'] ROOT_PATH = os.path.abspath(pathlib.Path.cwd().resolve()) MAX_COUNT = 50 def normal_compile(): """Do nothing and act as a control test that should always success.""" def source_code_white_noise(): """Insert white noise. This is a control test which forces recompilation of good code. We need this to make sure that the system is able to rebuild full source code under the Chronos environment.""" exts = ['.c', '.cc', '.cpp', '.cxx', '.h', '.hpp'] payload = '\n\n\n\n\n\n' # Walk and insert garbage code for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) try: with open(path, 'a', encoding='utf-8') as f: f.write(payload) except Exception: pass def source_code_compile_error(): """Insert garbage code to all found source files in the /src/ directory.""" exts = ['.c', '.cc', '.cpp', '.cxx', '.h', '.hpp'] payload = 'GARBAGE GARBAGE' # Walk and insert garbage code for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) try: with open(path, 'a', encoding='utf-8') as f: f.write(payload) except Exception: pass def macro_compile_error(): """Insert explicit macro error to all found header files in the /src/ directory.""" exts = ['.h', '.hpp'] payload = '#error THIS_SHOULD_BE_FAILING' # Walk and insert error macro for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) try: with open(path, 'a', encoding='utf-8') as f: f.write(payload) except Exception: pass def missing_header_error(): """Insert wrong header inclusion to all found source files in the /src/ directory.""" exts = ['.c', '.cc', '.cpp', '.cxx'] payload = '#include header_not_exist.h\n' count = 0 # Walk and insert missing header inclusion for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: # Only modify a handful of files if count > MAX_COUNT: return # Skip random file if random.choice([True, False]): continue if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) try: # Read source file source = '' with open(path, 'r', encoding='utf-8') as f: source = f.read() if not source: continue # Append a wrong header inclusion at the beginning with open(path, 'w', encoding='utf-8') as f: f.write(payload) f.write(source) count += 1 except Exception: pass def duplicate_symbol_error(): """Insert duplicate symbol to all found source files in the /src/ directory.""" import tree_sitter_cpp from tree_sitter import Language, Parser, Query, QueryCursor exts = ['.c', '.cc', '.cpp', '.cxx'] count = 0 treesitter_lang = Language(tree_sitter_cpp.language()) treesitter_parser = Parser(treesitter_lang) # Walk and insert missing header inclusion for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: # Only modify a handful of files if count > MAX_COUNT: return if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) node = None new_source = None try: # Try read and parse the source with tree-sitter source = '' with open(path, 'r', encoding='utf-8') as f: source = f.read() if source: node = treesitter_parser.parse(source.encode()).root_node except Exception: pass if not node: continue # Found random declaration and duplicate it cursor = QueryCursor(Query(treesitter_lang, '( declaration ) @decl')) for declaration in cursor.captures(node).get('decl', []): if declaration.text: target = declaration.text.decode() new_source = source.replace(target, target + target) break # Add source code with duplicated declaration randomly if new_source and random.choice([True, False]): try: with open(path, 'w', encoding='utf-8') as f: f.write(new_source) count += 1 except Exception: pass def function_linker_error(): """Insert an extern header to some found source files with no real definition in the /src/ directory.""" exts = ['.c', '.cpp', '.cxx', '.cc'] count = 0 payload = '#ifdef __cplusplus\nextern "C" {\n#endif\nvoid __not_defined(void);\n#ifdef __cplusplus\n}\n#endif\n' payload_call = 'void wrong_linking_function_{COUNT}(){\n__not_defined();\n}' # Walk and insert error macro for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: # Only modify a handful of files if count > MAX_COUNT: return if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) try: # Read source file source = '' with open(path, 'r', encoding='utf-8') as f: source = f.read() if not source: continue # Append a wrong header inclusion at the beginning with open(path, 'w', encoding='utf-8') as f: f.write(payload) f.write(source) f.write(payload_call.replace('{COUNT}', str(count))) count += 1 except Exception: pass BAD_PATCH_GENERATOR = { 'control_test': { 'func': normal_compile, 'rc': [0], }, 'white_noise': { 'func': source_code_white_noise, 'rc': [0], }, 'compile_error': { 'func': source_code_compile_error, 'rc': [1, 2], }, 'macro_error': { 'func': macro_compile_error, 'rc': [1, 2], }, 'missing_headers': { 'func': missing_header_error, 'rc': [1, 2], }, 'duplicate_symbols': { 'func': duplicate_symbol_error, 'rc': [1, 2], }, 'function_missing': { 'func': function_linker_error, 'rc': [1, 2], }, } def main(): """Main entrypoint.""" target = sys.argv[1] BAD_PATCH_GENERATOR[target]['func']() if __name__ == "__main__": main() ================================================ FILE: infra/chronos/integrity_validator_run_tests.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Helper to generate logic error patches for general test using different approach.""" from dataclasses import dataclass import os import pathlib import random import subprocess import sys try: import tree_sitter_cpp from tree_sitter import Language, Parser, Query, QueryCursor except (ModuleNotFoundError, ImportError): # pass. Allow this module to be imported even when tree-sitter # is not available. pass EXCLUDE_DIRS = ['tests', 'test', 'examples', 'example', 'build'] ROOT_PATH = os.path.abspath(pathlib.Path.cwd().resolve()) MAX_FILES_TO_PATCH = 50 def _add_payload_random_functions(exts: list[str], payload: str) -> str: """Helper to attach payload to random functions found in any source.""" count = 0 treesitter_parser = Parser(Language(tree_sitter_cpp.language())) # Walk and insert payload on the random line of random functions for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: # Only change some files randomly if count > MAX_FILES_TO_PATCH: return if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) node = None try: # Try read and parse the source with tree-sitter source = '' with open(path, 'r', encoding='utf-8') as f: source = f.read() if source: node = treesitter_parser.parse(source.encode()).root_node except Exception: pass if not node: continue # Insert payload to random line in the function cursor = QueryCursor( Query(Language(tree_sitter_cpp.language()), '( function_definition ) @funcs')) for func in cursor.captures(node).get('funcs', []): body = func.child_by_field_name('body') # Skip Class / Struct definition type_node = func.child_by_field_name('type') if not type_node or type_node.type not in [ 'primitive_type', 'type_identifier' ]: continue if body and body.text and random.choice([True, False]): func_source = body.text.decode() # new_func_source = f'{{ {payload} {func_source[1:]}' if len(func_source) > 10: new_func_source = f'{{ {payload} {func_source[1:]}' source = source.replace(func_source, new_func_source) try: with open(path, 'w', encoding='utf-8') as f: f.write(source) count += 1 except Exception: pass def normal_patch(): """Do nothing and act as a control test that should always success.""" return def signal_abort_crash(): """Insert abort call to force a crash in source files found in the /src/directory.""" exts = ['.c', '.cc', '.cpp', '.cxx'] _add_payload_random_functions(exts, 'abort();') def builtin_trap_crash(): """Insert builtin trap to force a crash in source files found in the /src/directory.""" exts = ['.c', '.cc', '.cpp', '.cxx'] _add_payload_random_functions(exts, '__builtin_trap();') def null_write_crash(): """Insert null pointer write to force a crash in source files found in the /src/directory.""" exts = ['.c', '.cc', '.cpp', '.cxx'] _add_payload_random_functions(exts, '*(volatile int*)0 = 0;') def wrong_return_value(): """modify random return statement to force an unit test failed in source files found in the /src/directory.""" exts = ['.c', '.cc', '.cpp', '.cxx'] primitives = { 'bool', 'char', 'signed', 'unsigned', 'short', 'int', 'long', 'float', 'double', 'wchar_t', 'char8_t', 'char16_t', 'char32_t', 'size_t' } count = 0 treesitter_parser = Parser(Language(tree_sitter_cpp.language())) # Walk and insert payload on the random line of random functions for cur, dirs, files in os.walk(ROOT_PATH): dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS] for file in files: # Only change some files randomly if count > MAX_FILES_TO_PATCH: return if any(file.endswith(ext) for ext in exts): path = os.path.join(cur, file) node = None try: # Try read and parse the source with tree-sitter source = '' with open(path, 'r', encoding='utf-8') as f: source = f.read() if source: node = treesitter_parser.parse(source.encode()).root_node except Exception: pass if not node: continue # Try simulate wrong return statement cursor = QueryCursor( Query(Language(tree_sitter_cpp.language()), '( function_definition ) @funcs')) for func in cursor.captures(node).get('funcs', []): # Get return type rtn_node = func.child_by_field_name('type') if rtn_node and rtn_node.text: rtn = rtn_node.text.decode() else: rtn = None # Determine if return type is a pointer if func.child_by_field_name( 'declarator').type == 'pointer_declarator': is_pointer = True else: is_pointer = False # If the return tyoe is a pointer or primitive types, #add return 0 at the beginning of the function body = func.child_by_field_name('body') if body and body.text and (is_pointer or rtn in primitives): func_source = body.text.decode() new_func_source = f'{{ {func_source[1:]}' source = source.replace(func_source, new_func_source) try: with open(path, 'w', encoding='utf-8') as f: f.write(source) count += 1 except Exception: pass @dataclass class LogicErrorPatch: """Dataclass to hold the patch function and expected result.""" name: str func: callable expected_result: bool LOGIC_ERROR_PATCHES: list[LogicErrorPatch] = [ LogicErrorPatch( name='control_test', func=normal_patch, expected_result=True, ), LogicErrorPatch( name='sigkill_crash', func=builtin_trap_crash, expected_result=False, ), LogicErrorPatch( name='sigabrt_crash', func=signal_abort_crash, expected_result=False, ), LogicErrorPatch( name='sigsegv_crash', func=null_write_crash, expected_result=False, ), LogicErrorPatch( name='random_return_value', func=wrong_return_value, expected_result=False, ) ] def _capture_source_control(): """Capture the source directory where source control is located.""" # List all directories under /src/ oss_fuzz_dirs = [ 'aflplusplus', 'fuzztest', 'honggfuzz', 'libfuzzer', 'googletest' ] project_dirs = [] for dir_name in os.listdir('/src/'): if dir_name in oss_fuzz_dirs: continue if os.path.isdir(os.path.join('/src/', dir_name)): project_dirs.append(dir_name) # If there is only a single new project directory, then we are # almost certain this is the right directory. if len(project_dirs) == 1: # Check if there is a .git directory if os.path.isdir(os.path.join('/src/', project_dirs[0], '.git')): return ('git', os.path.join('/src/', project_dirs[0])) elif os.path.isdir(os.path.join('/src/', project_dirs[0], '.svn')): return ('svn', os.path.join('/src/', project_dirs[0])) else: print('Wrong number of directories found under /src/') print(project_dirs) if len(project_dirs) > 1: print('Multiple project directories found under /src/') # If we have a project name, try to use this project_name = os.getenv('PROJECT_NAME', 'unknown_project') if project_name in project_dirs: if os.path.isdir(os.path.join('/src/', project_name, '.git')): return ('git', os.path.join('/src/', project_name)) elif os.path.isdir(os.path.join('/src/', project_name, '.svn')): return ('svn', os.path.join('/src/', project_name)) return None, None def diff_patch_analysis(stage: str) -> int: """Check if run_tests.sh generates patches that affect source control versioning. Returns: int: 0 if no patch found, 1 if patch found and -1 on unkonwn (such as due to unsupported version control). """ print( f'Diff patch analysis begin. Stage: {stage}, Current working dir: {os.getcwd()}' ) if stage == 'before': print('Diff patch analysis before stage.') type, project_dir = _capture_source_control() if not type: print('Uknown version control system.') return -1 print('%s repo found: %s' % (type, project_dir)) try: subprocess.check_call('cd %s && %s diff ./ >> /tmp/chronos-before.diff' % (project_dir, type), shell=True) except subprocess.CalledProcessError: pass return 0 elif stage == 'after': print('Diff patch analysis after stage.') type, project_dir = _capture_source_control() if not type: print('Uknown version control system.') return -1 print('%s repo found: %s' % (type, project_dir)) subprocess.check_call('cd %s && %s diff ./ >> /tmp/chronos-after.diff' % (project_dir, type), shell=True) try: subprocess.check_call( 'diff /tmp/chronos-before.diff /tmp/chronos-after.diff > /tmp/chronos-diff.patch', shell=True) except subprocess.CalledProcessError: pass print('Diff patch generated at /tmp/chronos-diff.patch') print('Difference between diffs:') with open('/tmp/chronos-diff.patch', 'r', encoding='utf-8') as f: diff_content = f.read() if diff_content.strip(): patch_found = True print(diff_content) else: patch_found = False if patch_found: print( 'Patch result: failed. Patch found that affects source control versioning.' ) return 1 else: print( 'Patch result: success. No patch found that affects source control versioning.' ) return 0 else: print( f'Patch result: failed. Unknown stage {stage} for diff patch analysis.') return -1 def main(): """Main entrypoint.""" project_name = os.getenv('PROJECT_NAME', 'unknown_project') print(f'Integrity validator run tests for project: {project_name}') command = sys.argv[1] if command == 'semantic-patch': target_patch = sys.argv[2] for logic_error_patch in LOGIC_ERROR_PATCHES: if logic_error_patch.name == target_patch: logic_error_patch.func() elif command == 'diff-patch': print(f'Diff patching for stage %s.' % sys.argv[2]) result = diff_patch_analysis(sys.argv[2]) sys.exit(result) if __name__ == "__main__": main() ================================================ FILE: infra/chronos/manager.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for managing Chronos cached builds.""" import os import sys import logging import argparse import time import json import subprocess # Call from the core OSS-Fuzz repository: # PYTHONPATH=$PYTHONPATH:$PWD/infra python3 -m chronos.manager check-tests json-c from chronos import integrity_validator_check_replay from chronos import integrity_validator_run_tests import common_utils logger = logging.getLogger(__name__) def _get_oss_fuzz_root(): """Gets the root directory of the OSS-Fuzz repository.""" return os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)) def _get_project_cached_named(project: common_utils.Project, sanitizer='address'): """Gets the name of the cached project image.""" base_name = 'us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen' return f'{base_name}/{project.name}-ofg-cached-{sanitizer}' def _get_project_cached_named_local(project: common_utils.Project, sanitizer='address'): return f'{project.name}-origin-{sanitizer}' def build_cached_project(project: common_utils.Project, cleanup: bool = True, sanitizer: str = 'address'): """Build cached image for a project.""" container_name = _get_project_cached_named_local(project, sanitizer) logger.info('Building cached image for project: %s', project) # Clean up the container if it exists. if cleanup: logger.info('Cleaning up existing container: %s', container_name) cmd = ['docker', 'container', 'rm', '-f', container_name] subprocess.run(cmd, check=False) project_language = 'c++' oss_fuzz_root = _get_oss_fuzz_root() # Build the cached image. cmd = [ 'docker', 'run', '--env=SANITIZER=' + sanitizer, '--env=CCACHE_DIR=/workspace/ccache', f'--env=FUZZING_LANGUAGE={project_language}', '--env=CAPTURE_REPLAY_SCRIPT=1', f'--name={container_name}', f'-v={oss_fuzz_root}/ccaches/{project.name}/ccache:/workspace/ccache', f'-v={oss_fuzz_root}/build/out/{project.name}/:/out/', '-v=' + os.path.join(oss_fuzz_root, 'infra', 'chronos') + ':/chronos/', f'gcr.io/oss-fuzz/{project.name}', '/bin/bash', '-c', '/chronos/container_cache_build.sh' ] logger.info('Command: %s', ' '.join(cmd)) start = time.time() try: logger.info('Building cached container for project: %s', project.name) subprocess.check_call(cmd, cwd=oss_fuzz_root) end = time.time() logger.info('%s vanilla build Succeeded: Duration: %.2f seconds', project, end - start) except subprocess.CalledProcessError: end = time.time() logger.info('%s vanilla build Failed: Duration: %.2f seconds', project.name, end - start) return False # Save the container. cmd = [ 'docker', 'container', 'commit', '-c', "ENV REPLAY_ENABLED=1", '-c', "ENV CAPTURE_REPLAY_SCRIPT=1", container_name, _get_project_cached_named(project, sanitizer) ] logger.info('Saving image: [%s]', ' '.join(cmd)) try: subprocess.check_call(cmd) except subprocess.CalledProcessError as e: logger.error('Failed to save cached image: %s', e) return False return True def check_cached_replay(project: common_utils.Project, sanitizer: str = 'address', integrity_check: bool = False): """Checks if a cache build succeeds and times is. If integrity_check is True, will run with bad patches to validate the integrity of the cached replay build. The patches will perform three main tasks: 1) A control test to ensure it's working as is. 2) A control test to check that we rebuild when white noise is included. 3) A set of bad patches that should cause the build to fail. """ common_utils.build_image_impl(project) if not build_cached_project(project, sanitizer=sanitizer): logger.info('Failed to build cached image for project: %s', project.name) return start = time.time() cmd = [ 'docker', 'run', '--rm', '--network', 'none', '--env=SANITIZER=' + sanitizer, '--env=FUZZING_LANGUAGE=c++', '-v=' + os.path.join(_get_oss_fuzz_root(), 'build', 'out', project.name) + ':/out', '-v=' + os.path.join(_get_oss_fuzz_root(), 'infra', 'chronos') + ':/chronos', '--name=' + project.name + '-origin-' + sanitizer + '-replay-recached', _get_project_cached_named(project, sanitizer), '/bin/bash', '-c', ] if integrity_check: # Use different bad patches to test the cached replay build failed = [] for bad_patch_name, bad_patch_map in integrity_validator_check_replay.BAD_PATCH_GENERATOR.items( ): # Generate bad patch command using different approaches expected_rc = bad_patch_map['rc'] cmd_to_run = cmd[:] cmd_to_run.append( f'/chronos/container_patch_replay_test.sh {bad_patch_name}') # Run the cached replay script with bad patches result = subprocess.run(cmd_to_run, check=False) if result.returncode not in expected_rc: failed.append(bad_patch_name) logger.info(('%s check cached replay failed on bad patches %s. ' 'Return code: %d. Expected return code: %s'), project.name, bad_patch_name, result.returncode, str(expected_rc)) if failed: logger.info( '%s check cached replay failed to detect these bad patches: %s', project.name, ' '.join(failed)) else: logger.info('%s check cached replay success to detect all bad patches.', project.name) else: # Normal run with no integrity check logger.info('Running cached replay with no integrity check for project: %s', project.name) base_cmd = 'export PATH=/ccache/bin:$PATH && rm -rf /out/* && compile' cmd.append(base_cmd) replay_success = False try: subprocess.run(cmd, check=True) replay_success = True except subprocess.CalledProcessError as e: logger.error('Failed to run cached replay: %s', e) replay_success = False logger.info('%s check cached replay: %s.', project.name, 'succeeded' if replay_success else 'failed') end = time.time() logger.info('%s check cached replay completion time: %.2f seconds', project.name, (end - start)) def check_tests(project: common_utils.Project, sanitizer: str = 'address', run_full_cache_replay: bool = False, integrity_check: bool = False, stop_on_failure: bool = False, semantic_test: bool = False): """Run the `run_tests.sh` script for a specific project. Will build a cached container first. When `integrity_check` is True, a check that validates if the `run_test.sh` changes the source control of the project will be performed. That is, we want to ensure, e.g. `git diff ./` has the same output before and after `run_tests.sh`. Additionally, if `semantic_test` is True, a set of semantic patches will be applied to the source code of the project to validate if the `run_tests.sh` is able to detect them. """ script_path = os.path.join('projects', project.name, 'run_tests.sh') if not os.path.exists(script_path): logger.info('Error: The script for project "%s" does not exist at %s', project.name, script_path) sys.exit(1) logger.info('Building image for project for use in check-tests: %s', project.name) # Build an OSS-Fuzz image of the project if run_full_cache_replay: check_cached_replay(project.name, sanitizer) else: common_utils.build_image_impl(project) # build a cached version of the project if not build_cached_project(project, sanitizer=sanitizer): logger.info('Failed to build cached image for project: %s', project.name) sys.exit(1) # Run the test script start = time.time() run_tests_cmd = 'chmod +x /src/run_tests.sh && /src/run_tests.sh' docker_cmd = [ 'docker', 'run', '--rm', '--network', 'none', '-e', 'PROJECT_NAME=' + project.name, '-v=' + os.path.join(_get_oss_fuzz_root(), 'infra', 'chronos') + ':/chronos', _get_project_cached_named(project, sanitizer), '/bin/bash', '-c', ] if integrity_check or semantic_test: # Run normal build_test logger.info('Running normal run_tests.sh for project: %s', project.name) docker_cmd_vanilla = docker_cmd[:] docker_cmd_vanilla.append(run_tests_cmd) try: subprocess.check_call(docker_cmd_vanilla) logger.info('Successfully ran run_tests.sh for project: %s', project) except subprocess.CalledProcessError: logger.info( 'run_tests.sh result failed: Failed to run vanilla run_tests.sh for project: %s', project.name) sys.exit(0) # First check diffing patch. The approach here is to capture a diff before # and after applying the patch, and see if there are any changes to e.g. git diff. logger.info('Checking diffing patch for project: %s', project.name) patch_command = ( 'python3 -m pip install -r /chronos/requirements.txt &&' 'python3 /chronos/integrity_validator_run_tests.py diff-patch before') cmd_to_run = docker_cmd[:] # Capture the patch after. cmd_to_run.append('/chronos/container_patch_tests_test.sh') ret_code = 0 try: subprocess.check_call(cmd_to_run) except subprocess.CalledProcessError as exc: ret_code = exc.returncode succeeded_patch = ret_code == 0 logger.info('succeeded patch: %s', succeeded_patch) if ret_code == 0: patch_msg = 'run_tests.sh result succeeded: does not patch source control' elif ret_code == 1: patch_msg = 'run_tests.sh result failed: patches source control' else: patch_msg = 'run_tests.sh result uknown: unable to tell if run_tests.sh patches source control' logger.info('%s', patch_msg) patch_details = { 'check-name': 'run_tests_patches_diff', 'patch-message': patch_msg } succeeded = succeeded_patch if semantic_test: # Second, check semantic patching tests. This is a best effort and won't work on some # projects. integrity_checks = [] # Patch the code with some logic error and see if build_test able to detect # them. for logic_patch in integrity_validator_run_tests.LOGIC_ERROR_PATCHES: logger.info('Checking logic patch: %s', logic_patch.name) patch_command = ( 'python3 -m pip install -r /chronos/requirements.txt &&' f'python3 /chronos/integrity_validator_run_tests.py semantic-patch {logic_patch.name} && ' 'compile') cmd_to_run = docker_cmd[:] # In the below, we will apply a set of changes in the source code, rebuild # the target and then run the run_tests.sh script. # The patches are meant to check the semantics of the code, but they are # not bulletproof, which means they may break the build in exceptional # circumstances. So, we first try to compile the code after having applied # the patches, but without running the tests, and if this step fails, then # we skip running the tests for this patch as well. # Patch and build first. cmd_to_run.append(f'set -euo pipefail && {patch_command}') try: subprocess.check_call(cmd_to_run) except subprocess.CalledProcessError: logger.info('%s skipping logic patch %s that failed to compile.', project.name, logic_patch.name) integrity_checks.append({ 'patch': logic_patch.name, 'result': 'compile_fail' }) continue # Patch and build succeeded, now proceed to patch, build and run tests in # one go. This will indicate if the patch was detected by the tests or # not. cmd_to_run[ -1] = f'set -euo pipefail && {patch_command} && {run_tests_cmd}' try: subprocess.check_call(cmd_to_run) exception_thrown = False except subprocess.CalledProcessError: exception_thrown = True if ((exception_thrown and not logic_patch.expected_result) or (not exception_thrown and logic_patch.expected_result)): # The patch was detected by the tests as it should have been. integrity_checks.append({ 'patch': logic_patch.name, 'result': 'Success' }) else: if stop_on_failure: logger.info( '%s integrity check failed on patch %s, stopping as requested.', project.name, logic_patch.name) return False integrity_checks.append({ 'patch': logic_patch.name, 'result': 'Failed' }) logger.info('%s integrity check results:', project.name) for check in integrity_checks: logger.info('%s integrity check patch %s result: %s', project.name, check['patch'], check['result']) succeeded = any([chk['result'] == 'Success' for chk in integrity_checks]) # Print patching results as well. logger.info('run_tests.sh patches version control: %s', patch_details['patch-message']) else: # Run normal build_test docker_cmd.append(run_tests_cmd) try: subprocess.check_call(docker_cmd) succeeded = True succeeded_patch = True except subprocess.CalledProcessError: succeeded = False succeeded_patch = False end = time.time() result = succeeded and succeeded_patch logger.info('%s test completion %s: Duration of run_tests.sh: %.2f seconds', project.name, 'failed' if not result else 'succeeded', (end - start)) return result def extract_test_coverage(project): """Extract code coverage report from run_tests.sh script.""" build_cached_project(project, sanitizer='coverage') os.makedirs(os.path.join('build', 'out', project.name), exist_ok=True) shared_folder = os.path.join(_get_oss_fuzz_root(), 'build', 'out', project.name) cmd = [ 'docker', 'run', '--rm', '--network', 'none', '-v', f'{shared_folder}:/out', '-v=' + os.path.join(_get_oss_fuzz_root(), 'infra', 'chronos') + ':/chronos/', _get_project_cached_named(project, 'coverage'), '/bin/bash', '-c', '/chronos/container_coverage_collection.sh' ] try: subprocess.check_call(cmd) except subprocess.CalledProcessError as e: logger.error('Error occurred while running coverage collection: %s', e) return False # If the summary file is created, dump the total lines covered. if os.path.isfile( os.path.join('build', 'out', project, 'test-html-generation', 'summary.json')): summary_json = os.path.join('build', 'out', project, 'test-html-generation', 'summary.json') with open(summary_json, 'r', encoding='utf-8') as f: summary = json.load(f) total_lines_covered = summary['data'][0]['totals']['lines'] logger.info('Total lines covered for %s: %s', project, json.dumps(total_lines_covered)) return True def cmd_dispatcher_check_tests(args): """Dispatcher for check-tests command.""" # This argument is not enabled by default in helper.py, so we set it here. args.semantic_test = getattr(args, 'semantic_test', False) check_tests(args.project, args.sanitizer, args.run_full_cache_replay, args.integrity_check, args.stop_on_failure, args.semantic_test) def cmd_dispatcher_check_replay(args): """Dispatcher for check-replay command.""" check_cached_replay(args.project, args.sanitizer, integrity_check=args.integrity_check) def cmd_dispatcher_build_cached_image(args): """Dispatcher for build-cached-image command.""" build_cached_project(args.project, sanitizer=args.sanitizer) def cmd_dispatcher_extract_coverage(args): """Dispatcher for extract-test-coverage command.""" extract_test_coverage(args.project) def parse_args(): """Parses command line arguments for the manager script.""" parser = argparse.ArgumentParser( 'manager.py', description='Chronos Manager: a tool for managing cached OSS-Fuzz builds.' ) subparsers = parser.add_subparsers(dest='command') checks_test_parser = subparsers.add_parser( 'check-tests', help='Checks run_test.sh for specific project.') checks_test_parser.add_argument( 'project', type=str, help='The name of the project to check (e.g., "libpng").', ) checks_test_parser.add_argument( '--stop-on-failure', action='store_true', help='If set, will stop integrity checks on first failure.') checks_test_parser.add_argument( '--sanitizer', default='address', help='The sanitizer to use (default: address).') checks_test_parser.add_argument( '--container-output', choices=['silent', 'file', 'stdout'], default='stdout', help='How to handle output from the container. ') checks_test_parser.add_argument( '--run-full-cache-replay', action='store_true', help= 'If set, will run the full cache replay instead of just checking the script.' ) checks_test_parser.add_argument( '--integrity-check', action='store_true', help= 'If set, will patch and test with logic errors to ensure build integrity.' ) checks_test_parser.add_argument( '--semantic-test', help= 'If set, will try and validate semantic correctness of run_tests.sh. This is beta for now.', action='store_true') check_replay_parser = subparsers.add_parser( 'check-replay', help='Checks if the replay script works for a specific project.') check_replay_parser.add_argument('project', help='The name of the project to check.') check_replay_parser.add_argument( '--sanitizer', default='address', help='The sanitizer to use for the cached build (default: address).') check_replay_parser.add_argument( '--integrity-check', action='store_true', help='If set, will test the integrity of the replay script.') build_cached_image_parser = subparsers.add_parser( 'build-cached-image', help='Builds a cached image for a specific project.') build_cached_image_parser.add_argument( 'project', help='The name of the project to build.') build_cached_image_parser.add_argument( '--sanitizer', default='address', help='The sanitizer to use for the cached build (default: address).') build_cached_image_parser.add_argument( '--container-output', choices=['silent', 'file', 'stdout'], default='stdout', help='How to handle output from the container. ') extract_coverage_parser = subparsers.add_parser( 'extract-test-coverage', help='Extract code coverage reports from run_tests.sh script') extract_coverage_parser.add_argument( 'project', help='The name of the project to extract coverage for.') return parser.parse_args() def main(): """Main""" logging.basicConfig(level=logging.INFO) args = parse_args() args.project = common_utils.Project(args.project, False) dispatch_map = { 'check-tests': cmd_dispatcher_check_tests, 'check-replay': cmd_dispatcher_check_replay, 'build-cached-image': cmd_dispatcher_build_cached_image, 'extract-test-coverage': cmd_dispatcher_extract_coverage } dispatch_cmd = dispatch_map.get(args.command, None) if not dispatch_cmd: logger.error('Unknown command: %s', args.command) sys.exit(1) logger.info('Dispatching command: %s', args.command) dispatch_cmd(args) if __name__ == '__main__': main() ================================================ FILE: infra/chronos/requirements.txt ================================================ tree-sitter==0.25.1 tree-sitter-cpp==0.23.4 requests==2.32.5 ================================================ FILE: infra/ci/build.py ================================================ #!/usr/bin/env python # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Build modified projects.""" from __future__ import print_function import enum import os import re import sys import subprocess import yaml # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import constants CANARY_PROJECT = 'skcms' DEFAULT_ARCHITECTURES = ['x86_64'] DEFAULT_ENGINES = ['afl', 'honggfuzz', 'libfuzzer', 'centipede'] DEFAULT_SANITIZERS = ['address', 'undefined'] def get_changed_files_output(): """Returns the output of a git command that discovers changed files.""" branch_commit_hash = subprocess.check_output( ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode() return subprocess.check_output( ['git', 'diff', '--name-only', branch_commit_hash + '..']).decode() def get_modified_buildable_projects(): """Returns a list of all the projects modified in this commit that have a build.sh file.""" git_output = get_changed_files_output() projects_regex = '.*projects/(?P.*)/.*\n' modified_projects = set(re.findall(projects_regex, git_output)) projects_dir = os.path.join(get_oss_fuzz_root(), 'projects') # Filter out projects without Dockerfile files since new projects and reverted # projects frequently don't have them. In these cases we don't want Travis's # builds to fail. modified_buildable_projects = [] for project in modified_projects: if not os.path.exists(os.path.join(projects_dir, project, 'Dockerfile')): print('Project {0} does not have Dockerfile. skipping build.'.format( project)) continue modified_buildable_projects.append(project) return modified_buildable_projects def get_oss_fuzz_root(): """Get the absolute path of the root of the oss-fuzz checkout.""" script_path = os.path.realpath(__file__) return os.path.abspath( os.path.dirname(os.path.dirname(os.path.dirname(script_path)))) def execute_helper_command(helper_command): """Execute |helper_command| using helper.py.""" root = get_oss_fuzz_root() script_path = os.path.join(root, 'infra', 'helper.py') command = ['python', script_path] + helper_command print('Running command: %s' % ' '.join(command)) subprocess.check_call(command) def build_fuzzers(project, engine, sanitizer, architecture): """Execute helper.py's build_fuzzers command on |project|. Build the fuzzers with |engine| and |sanitizer| for |architecture|.""" execute_helper_command([ 'build_fuzzers', project, '--engine', engine, '--sanitizer', sanitizer, '--architecture', architecture ]) def check_build(project, engine, sanitizer, architecture): """Execute helper.py's check_build command on |project|, assuming it was most recently built with |engine| and |sanitizer| for |architecture|.""" execute_helper_command([ 'check_build', project, '--engine', engine, '--sanitizer', sanitizer, '--architecture', architecture ]) def should_build_coverage(project_yaml): """Returns True if a coverage build should be done based on project.yaml contents.""" # Enable coverage builds on projects that use engines. Those that don't use # engines shouldn't get coverage builds. engines = project_yaml.get('fuzzing_engines', DEFAULT_ENGINES) engineless = 'none' in engines if engineless: assert_message = ('Forbidden to specify multiple engines for ' '"fuzzing_engines" if "none" is specified.') assert len(engines) == 1, assert_message return False if 'wycheproof' in engines: return False language = project_yaml.get('language') if language not in constants.LANGUAGES_WITH_COVERAGE_SUPPORT: print(('Project is written in "{language}", ' 'coverage is not supported yet.').format(language=language)) return False return True def flatten_options(option_list): """Generator that flattens |option_list| (a list of sanitizers, architectures or fuzzing engines) by returning each element in the list that isn't a dictionary. For elements that are dictionaries, the sole key is returned.""" result = [] for option in option_list: if isinstance(option, dict): keys = list(option.keys()) assert len(keys) == 1 result.append(keys[0]) continue result.append(option) print(result) return result def should_build(project_yaml): """Returns True on if the build specified is enabled in the project.yaml.""" if os.getenv('SANITIZER') == 'coverage': # This assumes we only do coverage builds with libFuzzer on x86_64. return should_build_coverage(project_yaml) def is_enabled(env_var, yaml_name, defaults): """Is the value of |env_var| enabled in |project_yaml| (in the |yaml_name| section)? Uses |defaults| if |yaml_name| section is unspecified.""" return os.getenv(env_var) in flatten_options( project_yaml.get(yaml_name, defaults)) return (is_enabled('ENGINE', 'fuzzing_engines', DEFAULT_ENGINES) and is_enabled('SANITIZER', 'sanitizers', DEFAULT_SANITIZERS) and is_enabled('ARCHITECTURE', 'architectures', DEFAULT_ARCHITECTURES)) def build_project(project): """Do the build of |project| that is specified by the environment variables - SANITIZER, ENGINE, and ARCHITECTURE.""" root = get_oss_fuzz_root() project_yaml_path = os.path.join(root, 'projects', project, 'project.yaml') with open(project_yaml_path) as file_handle: project_yaml = yaml.safe_load(file_handle) if project_yaml.get('disabled', False): print('Project {0} is disabled, skipping build.'.format(project)) return engine = os.getenv('ENGINE') sanitizer = os.getenv('SANITIZER') architecture = os.getenv('ARCHITECTURE') if not should_build(project_yaml): print(('Specified build: engine: {0}, sanitizer: {1}, architecture: {2} ' 'not enabled for this project: {3}. Skipping build.').format( engine, sanitizer, architecture, project)) return print('Building project', project) build_fuzzers(project, engine, sanitizer, architecture) run_tests = project_yaml.get('run_tests', True) if engine != 'none' and sanitizer != 'coverage' and run_tests: check_build(project, engine, sanitizer, architecture) class BuildModifiedProjectsResult(enum.Enum): """Enum containing the return values of build_modified_projects().""" NONE_BUILT = 0 BUILD_SUCCESS = 1 BUILD_FAIL = 2 def build_modified_projects(): """Build modified projects. Returns BuildModifiedProjectsResult.NONE_BUILT if no builds were attempted. Returns BuildModifiedProjectsResult.BUILD_SUCCESS if all attempts succeed, otherwise returns BuildModifiedProjectsResult.BUILD_FAIL.""" projects = get_modified_buildable_projects() if not projects: return BuildModifiedProjectsResult.NONE_BUILT failed_projects = [] for project in projects: try: build_project(project) except subprocess.CalledProcessError: failed_projects.append(project) if failed_projects: print('Failed projects:', ' '.join(failed_projects)) return BuildModifiedProjectsResult.BUILD_FAIL return BuildModifiedProjectsResult.BUILD_SUCCESS def is_infra_changed(): """Returns True if the infra directory was changed.""" git_output = get_changed_files_output() infra_code_regex = '.*infra/.*\n' return re.search(infra_code_regex, git_output) is not None def build_base_images(): """Builds base images.""" # TODO(jonathanmetzman): Investigate why caching fails so often and # when we improve it, build base-clang as well. Also, move this function # to a helper command when we can support base-clang. execute_helper_command(['pull_images']) images = [ 'base-image', 'base-builder', 'base-builder-go', 'base-builder-javascript', 'base-builder-jvm', 'base-builder-python', 'base-builder-rust', 'base-builder-swift', 'base-builder-ruby', 'base-runner', ] for image in images: try: execute_helper_command(['build_image', image, '--no-pull', '--cache']) except subprocess.CalledProcessError: return 1 return 0 def build_canary_project(): """Builds a specific project when infra/ is changed to verify that infra/ changes don't break things. Returns False if build was attempted but failed.""" try: build_project('skcms') except subprocess.CalledProcessError: return False return True def main(): """Build modified projects or canary project.""" os.environ['OSS_FUZZ_CI'] = '1' infra_changed = is_infra_changed() if infra_changed: print('Pulling and building base images first.') if build_base_images(): return 1 result = build_modified_projects() if result == BuildModifiedProjectsResult.BUILD_FAIL: return 1 # It's unnecessary to build the canary if we've built any projects already. no_projects_built = result == BuildModifiedProjectsResult.NONE_BUILT should_build_canary = no_projects_built and infra_changed if should_build_canary and not build_canary_project(): return 1 return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/ci/build_test.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Tests for build.py""" import os import sys import unittest from unittest import mock # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(INFRA_DIR) from ci import build def patch_environ(testcase_obj): """Patch environment.""" env = {} patcher = mock.patch.dict(os.environ, env) testcase_obj.addCleanup(patcher.stop) patcher.start() def _set_coverage_build(): """Set the right environment variables for a coverage build.""" os.environ['SANITIZER'] = 'coverage' os.environ['ENGINE'] = 'libfuzzer' os.environ['ARCHITECTURE'] = 'x86_64' class TestShouldBuild(unittest.TestCase): """Tests that should_build() works as intended.""" def setUp(self): patch_environ(self) def test_none_engine_coverage_build(self): """Tests that should_build returns False for a coverage build of a project that specifies 'none' for fuzzing_engines.""" _set_coverage_build() project_yaml = { 'language': 'c++', 'fuzzing_engines': ['none'], 'sanitizers': ['address'] } self.assertFalse(build.should_build(project_yaml)) def test_unspecified_engines_coverage_build(self): """Tests that should_build returns True for a coverage build of a project that doesn't specify fuzzing_engines.""" _set_coverage_build() project_yaml = {'language': 'c++'} self.assertTrue(build.should_build(project_yaml)) def test_libfuzzer_coverage_build(self): """Tests that should_build returns True for coverage build of a project specifying 'libfuzzer' for fuzzing_engines.""" _set_coverage_build() project_yaml = { 'language': 'c++', 'fuzzing_engines': ['libfuzzer'], 'sanitizers': ['address'] } self.assertTrue(build.should_build(project_yaml)) def test_go_coverage_build(self): """Tests that should_build returns True for coverage build of a project specifying 'libfuzzer' for fuzzing_engines.""" _set_coverage_build() project_yaml = {'language': 'go'} self.assertTrue(build.should_build(project_yaml)) def test_engine_project_none_build(self): """Tests that should_build returns False for an engine: 'none' build when the project doesn't specify engines.""" os.environ['SANITIZER'] = 'address' os.environ['ENGINE'] = 'none' os.environ['ARCHITECTURE'] = 'x86_64' project_yaml = { 'language': 'c++', 'fuzzing_engines': ['libfuzzer'], 'sanitizers': ['address'] } self.assertFalse(build.should_build(project_yaml)) def test_centipede_none_build(self): """Tests that should_build returns True for none sanitizer build of a project specifying 'centipede' for fuzzing_engines.""" os.environ['SANITIZER'] = 'none' os.environ['ENGINE'] = 'centipede' os.environ['ARCHITECTURE'] = 'x86_64' project_yaml = { 'language': 'c++', 'fuzzing_engines': ['centipede'], 'sanitizers': ['none'] } self.assertTrue(build.should_build(project_yaml)) def test_centipede_address_build(self): """Tests that should_build returns True for address sanitizer build of a project specifying 'centipede' for fuzzing_engines.""" os.environ['SANITIZER'] = 'address' os.environ['ENGINE'] = 'centipede' os.environ['ARCHITECTURE'] = 'x86_64' project_yaml = { 'language': 'c++', 'fuzzing_engines': ['centipede'], 'sanitizers': ['address'] } self.assertTrue(build.should_build(project_yaml)) ================================================ FILE: infra/ci/check_base_os.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """ A CI script to ensure that the base OS version specified in a project's project.yaml file matches the FROM line in its Dockerfile. """ import os import sys import yaml # Defines the base OS versions that are currently supported for use in project.yaml. # For now, only 'legacy' is permitted. This list will be expanded as new # base images are rolled out. SUPPORTED_VERSIONS = [ 'legacy', # 'ubuntu-20-04', 'ubuntu-24-04', ] # A map from the base_os_version in project.yaml to the expected Dockerfile # FROM tag. BASE_OS_TO_DOCKER_TAG = { 'legacy': 'latest', 'ubuntu-20-04': 'ubuntu-20-04', 'ubuntu-24-04': 'ubuntu-24-04', } def main(): """Checks the Dockerfile FROM tag against the project's base_os_version.""" if len(sys.argv) < 2: print(f'Usage: {sys.argv[0]} ', file=sys.stderr) return 1 project_path = sys.argv[1] project_yaml_path = os.path.join(project_path, 'project.yaml') dockerfile_path = os.path.join(project_path, 'Dockerfile') # 1. Get the base_os_version from project.yaml, defaulting to 'legacy'. base_os_version = 'legacy' if os.path.exists(project_yaml_path): with open(project_yaml_path) as f: config = yaml.safe_load(f) if config and 'base_os_version' in config: base_os_version = config['base_os_version'] # 2. Validate that the version is currently supported. if base_os_version not in SUPPORTED_VERSIONS: print( f'Error: base_os_version "{base_os_version}" is not yet supported. ' f'The currently supported versions are: "{", ".join(SUPPORTED_VERSIONS)}"', file=sys.stderr) return 1 # 3. Get the expected Dockerfile tag from our mapping. expected_tag = BASE_OS_TO_DOCKER_TAG[base_os_version] # 4. Read the Dockerfile and find the tag in the FROM line. if not os.path.exists(dockerfile_path): print(f'Error: Dockerfile not found at {dockerfile_path}', file=sys.stderr) return 1 dockerfile_tag = '' with open(dockerfile_path) as f: for line in f: if line.strip().startswith('FROM'): try: if ':' not in line: print( f'Error: Malformed FROM line in Dockerfile (missing tag): {line.strip()}', file=sys.stderr) return 1 dockerfile_tag = line.split(':')[1].strip() except IndexError: print(f'Error: Could not parse tag from Dockerfile FROM line: {line}', file=sys.stderr) return 1 break # 5. Compare and report. if dockerfile_tag != expected_tag: print( f'Error: Mismatch found in {project_path}.\n' f' - project.yaml (base_os_version): "{base_os_version}" (expects Dockerfile tag "{expected_tag}")\n' f' - Dockerfile FROM tag: "{dockerfile_tag}"\n' f'Please align the Dockerfile\'s FROM line to use the tag "{expected_tag}".', file=sys.stderr) return 1 print( f'Success: {project_path} is consistent (base_os_version: "{base_os_version}", Dockerfile tag: "{dockerfile_tag}").' ) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/ci/requirements.txt ================================================ # Requirements for submitting code changes to infra/ (needed by presubmit.py). parameterized==0.7.4 pyfakefs==5.8.0 pylint==3.3.7 pytest==7.1.2 pytest-xdist==2.5.0 PyYAML==6.0.2 requests==2.31.0 yapf==0.43.0 ================================================ FILE: infra/cifuzz/CHANGELOG ================================================ Next Release: Improve detection of changed files better by fixing https://github.com/google/oss-fuzz/issues/7011 ================================================ FILE: infra/cifuzz/actions/build_fuzzers/action.yml ================================================ # action.yml name: 'build-fuzzers' description: "Builds an OSS-Fuzz project's fuzzers." inputs: oss-fuzz-project-name: description: 'Name of the corresponding OSS-Fuzz project.' required: true language: description: 'Programming language project is written in.' required: false default: 'c++' dry-run: description: 'If set, run the action without actually reporting a failure.' default: false allowed-broken-targets-percentage: description: 'The percentage of broken targets allowed in bad_build_check.' required: false sanitizer: description: 'The sanitizer to build the fuzzers with.' default: 'address' architecture: description: 'The architecture used to build the fuzzers.' default: 'x86_64' project-src-path: description: "The path to the project's source code checkout." required: false bad-build-check: description: "Whether or not OSS-Fuzz's check for bad builds should be done." required: false default: true keep-unaffected-fuzz-targets: description: "Whether to keep unaffected fuzzers or delete them." required: false default: false output-sarif: description: "Whether to output fuzzing results to SARIF." required: false default: false runs: using: 'docker' image: '../../../build_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} LANGUAGE: ${{ inputs.language }} DRY_RUN: ${{ inputs.dry-run}} ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}} SANITIZER: ${{ inputs.sanitizer }} ARCHITECTURE: ${{ inputs.architecture }} PROJECT_SRC_PATH: ${{ inputs.project-src-path }} LOW_DISK_SPACE: 'True' BAD_BUILD_CHECK: ${{ inputs.bad-build-check }} CIFUZZ_DEBUG: 'True' CFL_PLATFORM: 'github' KEEP_UNAFFECTED_FUZZ_TARGETS: ${{ inputs.keep-unaffected-fuzz-targets }} OUTPUT_SARIF: ${{ inputs.output-sarif }} ================================================ FILE: infra/cifuzz/actions/run_fuzzers/action.yml ================================================ # action.yml name: 'run-fuzzers' description: 'Runs fuzz target binaries for a specified length of time.' inputs: oss-fuzz-project-name: description: 'The OSS-Fuzz project name.' required: true language: description: 'Programming language project is written in.' required: false default: 'c++' fuzz-seconds: description: 'The total time allotted for fuzzing in seconds.' required: true default: 600 dry-run: description: 'If set, run the action without actually reporting a failure.' default: false sanitizer: description: 'The sanitizer to run the fuzzers with.' default: 'address' mode: description: | The mode to run the fuzzers with ("code-change", "batch", "coverage", or "prune"). "code-change" is for fuzzing a pull request or commit. "batch" is for non-interactive fuzzing of an entire project. "coverage" is for coverage generation. "prune" is for corpus pruning. required: false default: 'code-change' github-token: description: | Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET You should use "secrets.GITHUB_TOKEN" in your workflow file, do not hardcode the token. TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361): Document locking this down. required: false report-unreproducible-crashes: description: 'If True, then unreproducible crashes will be reported.' required: false default: False minimize-crashes: description: 'If True, reportable crashes will be minimized.' required: false default: False parallel-fuzzing: description: "How many cores to use cores for fuzzing. A specific number, True - all available cores or False to run single threaded on a single core." required: false default: false output-sarif: description: "Whether to output fuzzing results to SARIF." required: false default: false report-timeouts: description: "Whether to report fails due to timeout." required: false default: true report-ooms: description: "Whether to report fails due to OOM." required: false default: true runs: using: 'docker' image: '../../../run_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} LANGUAGE: ${{ inputs.language }} FUZZ_SECONDS: ${{ inputs.fuzz-seconds }} DRY_RUN: ${{ inputs.dry-run}} SANITIZER: ${{ inputs.sanitizer }} MODE: ${{ inputs.mode }} GITHUB_TOKEN: ${{ inputs.github-token }} LOW_DISK_SPACE: 'True' REPORT_UNREPRODUCIBLE_CRASHES: ${{ inputs.report-unreproducible-crashes }} MINIMIZE_CRASHES: ${{ inputs.minimize-crashes }} CIFUZZ_DEBUG: 'True' CFL_PLATFORM: 'github' PARALLEL_FUZZING: ${{ inputs.parallel-fuzzing }} OUTPUT_SARIF: ${{ inputs.output-sarif }} REPORT_TIMEOUTS: ${{ inputs.report-timeouts }} REPORT_OOMS: ${{ inputs.report-ooms}} ================================================ FILE: infra/cifuzz/affected_fuzz_targets.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for dealing with fuzz targets affected by the change-under-test (CUT).""" import logging import os import sys # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import utils def remove_unaffected_fuzz_targets(clusterfuzz_deployment, out_dir, files_changed, repo_path): """Removes all non affected fuzz targets in the out directory. Args: clusterfuzz_deployment: The ClusterFuzz deployment object. out_dir: The location of the fuzz target binaries. files_changed: A list of files changed compared to HEAD. repo_path: The location of the OSS-Fuzz repo in the docker image. This function will not delete fuzz targets unless it knows that the fuzz targets are unaffected. For example, this means that fuzz targets which don't have coverage data on will not be deleted. """ if not files_changed: # Don't remove any fuzz targets if there is no difference from HEAD. logging.info('No files changed compared to HEAD.') return logging.info('Files changed in PR: %s', files_changed) fuzz_target_paths = utils.get_fuzz_targets(out_dir) if not fuzz_target_paths: # Nothing to remove. logging.error('No fuzz targets found in out dir.') return coverage = clusterfuzz_deployment.get_coverage(repo_path) if not coverage: # Don't remove any fuzz targets unless we have data. logging.error('Could not find latest coverage report.') return affected_fuzz_targets = get_affected_fuzz_targets(coverage, fuzz_target_paths, files_changed) if not affected_fuzz_targets: logging.info('No affected fuzz targets detected, keeping all as fallback.') return logging.info('Using affected fuzz targets: %s.', affected_fuzz_targets) unaffected_fuzz_targets = set(fuzz_target_paths) - affected_fuzz_targets logging.info('Removing unaffected fuzz targets: %s.', unaffected_fuzz_targets) # Remove all the targets that are not affected. for fuzz_target_path in unaffected_fuzz_targets: try: os.remove(fuzz_target_path) except OSError as error: logging.error('%s occurred while removing file %s', error, fuzz_target_path) def is_fuzz_target_affected(coverage, fuzz_target_path, files_changed): """Returns True if a fuzz target (|fuzz_target_path|) is affected by |files_changed|.""" fuzz_target = os.path.basename(fuzz_target_path) covered_files = coverage.get_files_covered_by_target(fuzz_target) if not covered_files: # Assume a fuzz target is affected if we can't get its coverage from # OSS-Fuzz. # TODO(metzman): Figure out what we should do if covered_files is []. # Should we act as if we couldn't get the coverage? logging.info('Could not get coverage for %s. Treating as affected.', fuzz_target) return True covered_files = [ os.path.normpath(covered_file) for covered_file in covered_files ] logging.info('Fuzz target %s is affected by: %s', fuzz_target, covered_files) for filename in files_changed: if filename in covered_files: logging.info('Fuzz target %s is affected by changed file: %s', fuzz_target, filename) return True logging.info('Fuzz target %s is not affected.', fuzz_target) return False def get_affected_fuzz_targets(coverage, fuzz_target_paths, files_changed): """Returns a list of paths of affected targets.""" affected_fuzz_targets = set() for fuzz_target_path in fuzz_target_paths: if is_fuzz_target_affected(coverage, fuzz_target_path, files_changed): affected_fuzz_targets.add(fuzz_target_path) return affected_fuzz_targets ================================================ FILE: infra/cifuzz/affected_fuzz_targets_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for affected_fuzz_targets.py""" import os import shutil import tempfile import unittest from unittest import mock import parameterized import affected_fuzz_targets import clusterfuzz_deployment import get_coverage import test_helpers import workspace_utils # pylint: disable=protected-access # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. EXAMPLE_PROJECT = 'example' EXAMPLE_FILE_CHANGED = 'test.txt' TEST_DATA_OUT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_data', 'build-out') class RemoveUnaffectedFuzzTargetsTest(unittest.TestCase): """Tests remove_unaffected_fuzzers.""" TEST_FUZZER_1 = os.path.join(TEST_DATA_OUT_PATH, 'example_crash_fuzzer') TEST_FUZZER_2 = os.path.join(TEST_DATA_OUT_PATH, 'example_nocrash_fuzzer') # yapf: disable @parameterized.parameterized.expand([ # Tests specific affected fuzzers are kept. ([[EXAMPLE_FILE_CHANGED], None], 2,), # Tests specific affected fuzzer is kept. ([[EXAMPLE_FILE_CHANGED], ['not/a/real/file']], 1), # Tests all fuzzers are kept if none are deemed affected. ([None, None], 2), # Tests that multiple fuzzers are kept if multiple fuzzers are affected. ([[EXAMPLE_FILE_CHANGED], [EXAMPLE_FILE_CHANGED]], 2), ]) # yapf: enable def test_remove_unaffected_fuzz_targets(self, side_effect, expected_dir_len): """Tests that remove_unaffected_fuzzers has the intended effect.""" config = test_helpers.create_run_config( cfl_platform='github', oss_fuzz_project_name=EXAMPLE_PROJECT, workspace='/workspace') workspace = workspace_utils.Workspace(config) deployment = clusterfuzz_deployment.get_clusterfuzz_deployment( config, workspace) # We can't use fakefs in this test because this test executes # utils.is_fuzz_target_local. This function relies on the executable bit # being set, which doesn't work properly in fakefs. with tempfile.TemporaryDirectory() as tmp_dir, mock.patch( 'get_coverage.OSSFuzzCoverage.get_files_covered_by_target' ) as mock_get_files: with mock.patch('get_coverage._get_oss_fuzz_fuzzer_stats_dir_url', return_value=1): mock_get_files.side_effect = side_effect shutil.copy(self.TEST_FUZZER_1, tmp_dir) shutil.copy(self.TEST_FUZZER_2, tmp_dir) affected_fuzz_targets.remove_unaffected_fuzz_targets( deployment, tmp_dir, [EXAMPLE_FILE_CHANGED], '') self.assertEqual(expected_dir_len, len(os.listdir(tmp_dir))) class IsFuzzTargetAffectedTest(unittest.TestCase): """Tests for is_fuzz_target_affected.""" def setUp(self): self.fuzz_target_path = '/fuzz_target' def test_relative_paths(self): """Tests that is_fuzz_target_affected works as intended when the covered files are relative paths.""" with mock.patch.object( get_coverage.FilesystemCoverage, 'get_files_covered_by_target', ) as get_files_covered_by_target: get_files_covered_by_target.return_value = [ '/work/build/../../src/systemd/src/basic/alloc-util.c' ] coverage = get_coverage.FilesystemCoverage('/', '/') self.assertTrue( affected_fuzz_targets.is_fuzz_target_affected( coverage, self.fuzz_target_path, ['/src/systemd/src/basic/alloc-util.c'])) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/base_runner_utils.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utilities for scripts from gcr.io/oss-fuzz-base/base-runner.""" import os import config_utils def get_env(config, workspace): """Returns a dictionary containing the current environment with additional env vars set to values needed to run a fuzzer.""" env = os.environ.copy() env['SANITIZER'] = config.sanitizer env['FUZZING_LANGUAGE'] = config.language env['OUT'] = workspace.out env['CIFUZZ'] = 'True' env['FUZZING_ENGINE'] = config_utils.DEFAULT_ENGINE env['ARCHITECTURE'] = config.architecture # Do this so we don't fail in tests. env['FUZZER_ARGS'] = '-rss_limit_mb=2560 -timeout=25' return env ================================================ FILE: infra/cifuzz/build-images.sh ================================================ #! /bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Script for building the docker images for cifuzz. CIFUZZ_DIR=$(dirname "$0") CIFUZZ_DIR=$(realpath $CIFUZZ_DIR) INFRA_DIR=$(realpath $CIFUZZ_DIR/..) OSS_FUZZ_ROOT=$(realpath $INFRA_DIR/..) # Build cifuzz-base. docker build --tag gcr.io/oss-fuzz-base/cifuzz-base --file $CIFUZZ_DIR/cifuzz-base/Dockerfile $OSS_FUZZ_ROOT docker build --tag gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04 --file $CIFUZZ_DIR/cifuzz-base/ubuntu-24-04.Dockerfile $OSS_FUZZ_ROOT # Build run-fuzzers and build-fuzzers images. docker build \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers-test:v1 \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 \ --file $INFRA_DIR/build_fuzzers.Dockerfile $INFRA_DIR docker build \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers-test:ubuntu-24-04-v1 \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:ubuntu-24-04-v1 \ --file $INFRA_DIR/build_fuzzers.ubuntu-24-04.Dockerfile $INFRA_DIR docker build \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers-test:v1 \ --file $INFRA_DIR/run_fuzzers.Dockerfile $INFRA_DIR docker build \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04-v1 \ --tag gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers-test:ubuntu-24-04-v1 \ --file $INFRA_DIR/run_fuzzers.ubuntu-24-04.Dockerfile $INFRA_DIR ================================================ FILE: infra/cifuzz/build_fuzzers.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module used by CI tools in order to interact with fuzzers. This module helps CI tools to build fuzzers.""" import logging import os import sys import affected_fuzz_targets import base_runner_utils import clusterfuzz_deployment import continuous_integration import docker import logs import workspace_utils # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import helper import utils logs.init() def check_project_src_path(project_src_path): """Returns True if |project_src_path| exists.""" if not os.path.exists(project_src_path): logging.error( 'PROJECT_SRC_PATH: %s does not exist. ' 'Are you mounting it correctly?', project_src_path) return False return True # pylint: disable=too-many-arguments class Builder: # pylint: disable=too-many-instance-attributes """Class for fuzzer builders.""" def __init__(self, config, ci_system): self.config = config self.ci_system = ci_system self.workspace = workspace_utils.Workspace(config) self.workspace.initialize_dir(self.workspace.out) self.workspace.initialize_dir(self.workspace.work) self.clusterfuzz_deployment = ( clusterfuzz_deployment.get_clusterfuzz_deployment( self.config, self.workspace)) self.image_repo_path = None self.host_repo_path = None self.repo_manager = None def build_image_and_checkout_src(self): """Builds the project builder image and checkout source code for the patch we want to fuzz (if necessary). Returns True on success.""" result = self.ci_system.prepare_for_fuzzer_build() if not result.success: return False self.image_repo_path = result.image_repo_path self.repo_manager = result.repo_manager if self.config.output_sarif: self.workspace.make_repo_for_sarif(self.repo_manager) logging.info('repo_dir: %s.', self.repo_manager.repo_dir) self.host_repo_path = self.repo_manager.repo_dir return True def build_fuzzers(self): """Moves the source code we want to fuzz into the project builder and builds the fuzzers from that source code. Returns True on success.""" docker_args, docker_container = docker.get_base_docker_run_args( self.workspace, self.config.sanitizer, self.config.language, self.config.architecture, self.config.docker_in_docker) if not docker_container: docker_args.extend( _get_docker_build_fuzzers_args_not_container(self.host_repo_path)) build_command = self.ci_system.get_build_command(self.host_repo_path, self.image_repo_path) # Set extra environment variables so that they are visible to the build. for key in self.config.extra_environment_variables: # Don't specify their value in case they get echoed. docker_args.extend(['-e', key]) docker_args.extend([ docker.get_project_image_name(self.config.oss_fuzz_project_name), '/bin/bash', '-c', build_command, ]) logging.info('Building with %s sanitizer.', self.config.sanitizer) # TODO(metzman): Stop using helper.docker_run so we can get rid of # docker.get_base_docker_run_args and merge its contents into # docker.get_base_docker_run_command. if not helper.docker_run(docker_args): logging.error('Building fuzzers failed.') return False return True def upload_build(self): """Upload build.""" if self.config.upload_build: self.clusterfuzz_deployment.upload_build( self.repo_manager.get_current_commit()) return True def check_fuzzer_build(self): """Checks the fuzzer build. Returns True on success or if config specifies to skip check.""" if not self.config.bad_build_check: return True return check_fuzzer_build(self.config) def build(self): """Builds the image, checkouts the source (if needed), builds the fuzzers and then removes the unaffectted fuzzers. Returns True on success.""" methods = [ self.build_image_and_checkout_src, self.build_fuzzers, self.remove_unaffected_fuzz_targets, self.upload_build, self.check_fuzzer_build, ] for method in methods: if not method(): return False return True def remove_unaffected_fuzz_targets(self): """Removes the fuzzers unaffected by the patch.""" if self.config.keep_unaffected_fuzz_targets: logging.info('Not removing unaffected fuzz targets.') return True logging.info('Removing unaffected fuzz targets.') changed_files = self.ci_system.get_changed_code_under_test( self.repo_manager) affected_fuzz_targets.remove_unaffected_fuzz_targets( self.clusterfuzz_deployment, self.workspace.out, changed_files, self.image_repo_path) return True def build_fuzzers(config): """Builds all of the fuzzers for a specific OSS-Fuzz project. Args: config: The configuration object for building fuzzers. Returns: True if build succeeded. """ # Do some quick validation. if config.project_src_path and not check_project_src_path( config.project_src_path): return False # Get the builder and then build the fuzzers. ci_system = continuous_integration.get_ci(config) logging.info('ci_system: %s.', ci_system) builder = Builder(config, ci_system) return builder.build() def check_fuzzer_build(config): """Checks the integrity of the built fuzzers. Args: config: The config object. Returns: True if fuzzers pass OSS-Fuzz's build check. """ workspace = workspace_utils.Workspace(config) if not os.path.exists(workspace.out): logging.error('Invalid out directory: %s.', workspace.out) return False if not os.listdir(workspace.out): logging.error('No fuzzers found in out directory: %s.', workspace.out) return False env = base_runner_utils.get_env(config, workspace) if config.allowed_broken_targets_percentage is not None: env['ALLOWED_BROKEN_TARGETS_PERCENTAGE'] = ( config.allowed_broken_targets_percentage) stdout, stderr, retcode = utils.execute('test_all.py', env=env) print(f'Build check: stdout: {stdout}\nstderr: {stderr}') if retcode == 0: logging.info('Build check passed.') return True logging.error('Build check failed.') return False def _get_docker_build_fuzzers_args_not_container(host_repo_path): """Returns arguments to the docker build arguments that are needed to use |host_repo_path| when the host of the OSS-Fuzz builder container is not another container.""" return ['-v', f'{host_repo_path}:{host_repo_path}'] ================================================ FILE: infra/cifuzz/build_fuzzers_entrypoint.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Builds a specific OSS-Fuzz project's fuzzers for CI tools.""" import logging import sys import build_fuzzers import logs import config_utils # pylint: disable=c-extension-no-member # pylint gets confused because of the relative import of cifuzz. logs.init() def build_fuzzers_entrypoint(): """Builds OSS-Fuzz project's fuzzers for CI tools.""" config = config_utils.BuildFuzzersConfig() if config.base_os_version == 'ubuntu-24-04': result = config_utils.pivot_to_ubuntu_24_04( 'build-fuzzers', '/opt/oss-fuzz/infra/cifuzz/build_fuzzers_entrypoint.py') if result is not None: return result if config.dry_run: # Sets the default return code on error to success. returncode = 0 else: # The default return code when an error occurs. returncode = 1 if not build_fuzzers.build_fuzzers(config): logging.error('Error building fuzzers for (commit: %s, pr_ref: %s).', config.git_sha, config.pr_ref) return returncode return 0 def main(): """Builds OSS-Fuzz project's fuzzers for CI tools. Note: The resulting fuzz target binaries of this build are placed in the directory: ${GITHUB_WORKSPACE}/out Returns: 0 on success or nonzero on failure. """ return build_fuzzers_entrypoint() if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/cifuzz/build_fuzzers_test.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests the functionality of the cifuzz module.""" import os import shutil import sys import tempfile import unittest from unittest import mock import parameterized # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(INFRA_DIR) OSS_FUZZ_DIR = os.path.dirname(INFRA_DIR) import build_fuzzers import continuous_integration import repo_manager import test_helpers # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. EXAMPLE_PROJECT = 'example' # Location of data used for testing. TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_data') # An example fuzzer that triggers an crash. # Binary is a copy of the example project's do_stuff_fuzzer and can be # generated by running "python3 infra/helper.py build_fuzzers example". EXAMPLE_CRASH_FUZZER = 'example_crash_fuzzer' # An example fuzzer that does not trigger a crash. # Binary is a modified version of example project's do_stuff_fuzzer. It is # created by removing the bug in my_api.cpp. EXAMPLE_NOCRASH_FUZZER = 'example_nocrash_fuzzer' # A fuzzer to be built in build_fuzzers integration tests. EXAMPLE_BUILD_FUZZER = 'do_stuff_fuzzer' # pylint: disable=no-self-use,protected-access,too-few-public-methods,unused-argument def docker_command_has_env_var_arg(command, env_var_arg): """Returns True if a docker command has a specific env var argument.""" for idx, element in enumerate(command): if idx == 0: # We're looking for the variable which can't be the first argument. continue if element == env_var_arg and command[idx - 1] == '-e': return True return False class BuildFuzzersTest(unittest.TestCase): """Unit tests for build_fuzzers.""" @mock.patch('build_specified_commit.detect_main_repo', return_value=('example.com', '/path')) @mock.patch('repo_manager._clone', return_value=None) @mock.patch('continuous_integration.checkout_specified_commit') @mock.patch('helper.docker_run', return_value=False) # We want to quit early. def test_cifuzz_env_var(self, mock_docker_run, _, __, ___): """Tests that the CIFUZZ env var is set.""" with tempfile.TemporaryDirectory() as tmp_dir: build_fuzzers.build_fuzzers( test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name=EXAMPLE_PROJECT, workspace=tmp_dir, pr_ref='refs/pull/1757/merge')) docker_run_command = mock_docker_run.call_args_list[0][0][0] self.assertTrue( docker_command_has_env_var_arg(docker_run_command, 'CIFUZZ=True')) @mock.patch('build_specified_commit.detect_main_repo', return_value=('example.com', '/path')) @mock.patch('repo_manager._clone', return_value=None) @mock.patch('continuous_integration.checkout_specified_commit') @mock.patch('helper.docker_run', return_value=False) # We want to quit early. def test_extra_env_var(self, mock_docker_run, _, __, ___): """Tests that the CIFUZZ env var is set.""" extra_env_var = 'CFL_EXTRA_TOKEN' with tempfile.TemporaryDirectory() as tmp_dir: with mock.patch.dict(os.environ, {extra_env_var: 'BLAH'}): build_fuzzers.build_fuzzers( test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name=EXAMPLE_PROJECT, workspace=tmp_dir, pr_ref='refs/pull/1757/merge')) docker_run_command = mock_docker_run.call_args_list[0][0][0] self.assertTrue( docker_command_has_env_var_arg(docker_run_command, extra_env_var)) class InternalGithubBuildTest(unittest.TestCase): """Tests for building OSS-Fuzz projects on GitHub actions.""" PROJECT_REPO_NAME = 'myproject' SANITIZER = 'address' GIT_SHA = 'fake' PR_REF = 'fake' def _create_builder(self, tmp_dir, oss_fuzz_project_name='myproject'): """Creates an InternalGithubBuilder and returns it.""" config = test_helpers.create_build_config( oss_fuzz_project_name=oss_fuzz_project_name, project_repo_name=self.PROJECT_REPO_NAME, workspace=tmp_dir, sanitizer=self.SANITIZER, git_sha=self.GIT_SHA, pr_ref=self.PR_REF, cfl_platform='github') cfl_platform = continuous_integration.get_ci(config) builder = build_fuzzers.Builder(config, cfl_platform) builder.repo_manager = repo_manager.RepoManager('/fake') return builder @mock.patch('helper.docker_run', return_value=True) @mock.patch('continuous_integration.checkout_specified_commit', side_effect=None) def test_correct_host_repo_path(self, _, __): """Tests that the correct self.host_repo_path is set by build_image_and_checkout_src. Specifically, we want the name of the directory the repo is in to match the name used in the docker image/container, so that it will replace the host's copy properly.""" image_repo_path = '/src/repo_dir' with tempfile.TemporaryDirectory() as tmp_dir, mock.patch( 'build_specified_commit.detect_main_repo', return_value=('inferred_url', image_repo_path)): builder = self._create_builder(tmp_dir) builder.build_image_and_checkout_src() self.assertEqual(os.path.basename(builder.host_repo_path), os.path.basename(image_repo_path)) @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build', return_value=True) def test_upload_build_disabled(self, mock_upload_build): """Test upload build (disabled).""" with tempfile.TemporaryDirectory() as tmp_dir: builder = self._create_builder(tmp_dir) builder.upload_build() mock_upload_build.assert_not_called() @mock.patch('repo_manager.RepoManager.get_current_commit', return_value='commit') @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build', return_value=True) def test_upload_build(self, mock_upload_build, mock_get_current_commit): """Test upload build.""" with tempfile.TemporaryDirectory() as tmp_dir: builder = self._create_builder(tmp_dir, oss_fuzz_project_name='') builder.config.upload_build = True builder.upload_build() mock_upload_build.assert_called_with('commit') @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class BuildFuzzersIntegrationTest(unittest.TestCase): """Integration tests for build_fuzzers.""" def setUp(self): self.temp_dir_ctx_manager = test_helpers.docker_temp_dir() self.workspace = self.temp_dir_ctx_manager.__enter__() self.out_dir = os.path.join(self.workspace, 'build-out') test_helpers.patch_environ(self) base_runner_path = os.path.join(INFRA_DIR, 'base-images', 'base-runner') os.environ['PATH'] = os.environ['PATH'] + os.pathsep + base_runner_path def tearDown(self): self.temp_dir_ctx_manager.__exit__(None, None, None) def test_external_github_project(self): """Tests building fuzzers from an external project on Github.""" project_repo_name = 'external-project' git_url = 'https://github.com/jonathanmetzman/cifuzz-external-example.git' # This test is dependant on the state of # github.com/jonathanmetzman/cifuzz-external-example. config = test_helpers.create_build_config( project_repo_name=project_repo_name, workspace=self.workspace, git_url=git_url, git_sha='HEAD', cfl_platform='github', base_commit='HEAD^1') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_external_generic_project(self): """Tests building fuzzers from an external project not on Github.""" project_repo_name = 'cifuzz-external-example' git_url = 'https://github.com/jonathanmetzman/cifuzz-external-example.git' # This test is dependant on the state of # github.com/jonathanmetzman/cifuzz-external-example. manager = repo_manager.clone_repo_and_get_manager( 'https://github.com/jonathanmetzman/cifuzz-external-example', self.workspace) project_src_path = manager.repo_dir config = test_helpers.create_build_config( project_repo_name=project_repo_name, workspace=self.workspace, git_url=git_url, filestore='no_filestore', git_sha='HEAD', project_src_path=project_src_path, base_commit='HEAD^1') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_valid_commit(self): """Tests building fuzzers with valid inputs.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=self.workspace, git_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523', base_commit='da0746452433dc18bae699e355a9821285d863c8', cfl_platform='github') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_valid_pull_request(self): """Tests building fuzzers with valid pull request.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=self.workspace, pr_ref='refs/pull/1757/merge', base_ref='master', cfl_platform='github') self.assertTrue(build_fuzzers.build_fuzzers(config)) self.assertTrue( os.path.exists(os.path.join(self.out_dir, EXAMPLE_BUILD_FUZZER))) def test_invalid_pull_request(self): """Tests building fuzzers with invalid pull request.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=self.workspace, pr_ref='ref-1/merge', base_ref='master', cfl_platform='github') self.assertTrue(build_fuzzers.build_fuzzers(config)) def test_invalid_oss_fuzz_project_name(self): """Tests building fuzzers with invalid project name.""" config = test_helpers.create_build_config( oss_fuzz_project_name='not_a_valid_project', project_repo_name='oss-fuzz', workspace=self.workspace, git_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523') self.assertFalse(build_fuzzers.build_fuzzers(config)) def test_invalid_repo_name(self): """Tests building fuzzers with invalid repo name.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='not-real-repo', workspace=self.workspace, git_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523') self.assertFalse(build_fuzzers.build_fuzzers(config)) def test_invalid_git_sha(self): """Tests building fuzzers with invalid commit SHA.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=self.workspace, git_sha='', cfl_platform='github') with self.assertRaises(AssertionError): build_fuzzers.build_fuzzers(config) def test_invalid_workspace(self): """Tests building fuzzers with invalid workspace.""" config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=os.path.join(self.workspace, 'not', 'a', 'dir'), git_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523') self.assertFalse(build_fuzzers.build_fuzzers(config)) class CheckFuzzerBuildTest(unittest.TestCase): """Tests the check_fuzzer_build function in the cifuzz module.""" SANITIZER = 'address' LANGUAGE = 'c++' def setUp(self): self.temp_dir_obj = tempfile.TemporaryDirectory() workspace_path = os.path.join(self.temp_dir_obj.name, 'workspace') self.config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, sanitizer=self.SANITIZER, language=self.LANGUAGE, workspace=workspace_path, pr_ref='refs/pull/1757/merge') self.workspace = test_helpers.create_workspace(workspace_path) shutil.copytree(TEST_DATA_PATH, workspace_path) test_helpers.patch_environ(self, runner=True) def tearDown(self): self.temp_dir_obj.cleanup() def test_correct_fuzzer_build(self): """Checks check_fuzzer_build function returns True for valid fuzzers.""" self.assertTrue(build_fuzzers.check_fuzzer_build(self.config)) def test_not_a_valid_path(self): """Tests that False is returned when a nonexistent path is given.""" self.config.workspace = 'not/a/valid/path' self.assertFalse(build_fuzzers.check_fuzzer_build(self.config)) def test_no_valid_fuzzers(self): """Tests that False is returned when an empty directory is given.""" with tempfile.TemporaryDirectory() as tmp_dir: self.config.workspace = tmp_dir os.mkdir(os.path.join(self.config.workspace, 'build-out')) self.assertFalse(build_fuzzers.check_fuzzer_build(self.config)) @mock.patch('utils.execute', return_value=(None, None, 0)) def test_allow_broken_fuzz_targets_percentage(self, mock_execute): """Tests that ALLOWED_BROKEN_TARGETS_PERCENTAGE is set when running docker if passed to check_fuzzer_build.""" percentage = '0' self.config.allowed_broken_targets_percentage = percentage build_fuzzers.check_fuzzer_build(self.config) self.assertEqual( mock_execute.call_args[1]['env']['ALLOWED_BROKEN_TARGETS_PERCENTAGE'], percentage) @unittest.skip('Test is too long to be run with presubmit.') class BuildSantizerIntegrationTest(unittest.TestCase): """Integration tests for the build_fuzzers. Note: This test relies on "curl" being an OSS-Fuzz project.""" PROJECT_NAME = 'curl' PR_REF = 'fake_pr' @classmethod def _create_config(cls, tmp_dir, sanitizer): return test_helpers.create_build_config( oss_fuzz_project_name=cls.PROJECT_NAME, project_repo_name=cls.PROJECT_NAME, workspace=tmp_dir, pr_ref=cls.PR_REF, sanitizer=sanitizer) @parameterized.parameterized.expand([('memory',), ('undefined',)]) def test_valid_project_curl(self, sanitizer): """Tests that MSAN can be detected from project.yaml""" with tempfile.TemporaryDirectory() as tmp_dir: self.assertTrue( build_fuzzers.build_fuzzers(self._create_config(tmp_dir, sanitizer))) class GetDockerBuildFuzzersArgsNotContainerTest(unittest.TestCase): """Tests that _get_docker_build_fuzzers_args_not_container works as intended.""" def test_get_docker_build_fuzzers_args_no_container(self): """Tests that _get_docker_build_fuzzers_args_not_container works as intended.""" host_repo_path = '/host/repo' result = build_fuzzers._get_docker_build_fuzzers_args_not_container( host_repo_path) expected_result = ['-v', '/host/repo:/host/repo'] self.assertEqual(result, expected_result) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/cifuzz-base/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner RUN apt-get update && \ apt-get install -y systemd wget gnupg && \ install -m 0755 -d /etc/apt/keyrings && \ wget -qO- https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ chmod a+r /etc/apt/keyrings/docker.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list && \ apt-get update && \ apt-get install -y docker-ce-cli ENV PATH=/opt/gcloud/google-cloud-sdk/bin/:$PATH ENV OSS_FUZZ_ROOT=/opt/oss-fuzz # Do this step before copying to make rebuilding faster when developing. COPY ./infra/cifuzz/requirements.txt /tmp/requirements.txt RUN python3 -m pip install -r /tmp/requirements.txt && rm /tmp/requirements.txt ADD . ${OSS_FUZZ_ROOT} # Don't use the default npm location since jazzer.js can break us. # This means javascript needed by cifuzz/clusterfuzzlite must be executed in # OSS_FUZZ_ROOT. RUN cd ${OSS_FUZZ_ROOT} && npm install ${OSS_FUZZ_ROOT}/infra/cifuzz ENV PYTHONUNBUFFERED=1 # Python file to execute when the docker container starts up. # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"] ================================================ FILE: infra/cifuzz/cifuzz-base/ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-runner:ubuntu-24-04 RUN apt-get update && \ apt-get install -y systemd wget gnupg && \ install -m 0755 -d /etc/apt/keyrings && \ wget -qO- https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ chmod a+r /etc/apt/keyrings/docker.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable" > /etc/apt/sources.list.d/docker.list && \ apt-get update && \ apt-get install -y docker-ce-cli ENV PATH=/opt/gcloud/google-cloud-sdk/bin/:$PATH ENV OSS_FUZZ_ROOT=/opt/oss-fuzz # Do this step before copying to make rebuilding faster when developing. COPY ./infra/cifuzz/requirements.txt /tmp/requirements.txt RUN python3 -m pip install -r /tmp/requirements.txt && rm /tmp/requirements.txt ADD . ${OSS_FUZZ_ROOT} # Don't use the default npm location since jazzer.js can break us. # This means javascript needed by cifuzz/clusterfuzzlite must be executed in # OSS_FUZZ_ROOT. RUN cd ${OSS_FUZZ_ROOT} && npm install ${OSS_FUZZ_ROOT}/infra/cifuzz ENV PYTHONUNBUFFERED=1 # Python file to execute when the docker container starts up. # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"] ================================================ FILE: infra/cifuzz/cifuzz_combined_entrypoint.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Builds fuzzers and runs fuzzers. Entrypoint used for external users""" import logging import sys import build_fuzzers_entrypoint import run_fuzzers_entrypoint def main(): """Builds and runs fuzzers for CI tools. NOTE: Any crash report will be in the filepath: $WORKSPACE/out/testcase This can be used with GitHub's upload-artifact action to surface the logs. Required environment variables: Returns: 0 on success or 1 on failure. """ logging.debug("Using cifuzz_combined_entrypoint.") result = build_fuzzers_entrypoint.build_fuzzers_entrypoint() if result != 0: return result return run_fuzzers_entrypoint.run_fuzzers_entrypoint() if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/cifuzz/cifuzz_end_to_end_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """End-to-End tests for CIFuzz.""" import os import unittest import run_cifuzz import test_helpers CIFUZZ_DIR = os.path.dirname(os.path.abspath(__file__)) EXTERNAL_PROJECT_PATH = os.path.join(CIFUZZ_DIR, 'test_data', 'external-project') # This test will fail if not run as root because the fuzzer build process # creates binaries that only root can write to. # Use a seperate env var to keep this seperate from integration tests which # don't have this annoying property. @unittest.skipIf(not os.getenv('END_TO_END_TESTS'), 'END_TO_END_TESTS=1 not set') class EndToEndTest(unittest.TestCase): """End-to-End tests for CIFuzz.""" def setUp(self): test_helpers.patch_environ(self, runner=True) def test_simple(self): """Simple end-to-end test using run_cifuzz.main().""" os.environ['REPOSITORY'] = 'external-project' os.environ['PROJECT_SRC_PATH'] = EXTERNAL_PROJECT_PATH os.environ['FILESTORE'] = 'no_filestore' os.environ['NO_CLUSTERFUZZ_DEPLOYMENT'] = 'True' with test_helpers.docker_temp_dir() as temp_dir: os.environ['WORKSPACE'] = temp_dir # TODO(metzman): Verify the crash, affected fuzzers, and other things. self.assertEqual(run_cifuzz.main(), 1) ================================================ FILE: infra/cifuzz/cloudbuild.yaml ================================================ # TODO(metzman): Get rid of cifuzz-build-fuzzers and cifuzz-run-fuzzers. steps: - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/cifuzz-base - '-t' - gcr.io/oss-fuzz-base/cifuzz-base:v1 - '-f' - infra/cifuzz/cifuzz-base/Dockerfile - . - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers - '-t' - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:v1 - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 - '-f' - infra/build_fuzzers.Dockerfile - infra - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers - '-t' - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:v1 - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 - '-f' - infra/run_fuzzers.Dockerfile - infra - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04-v1 - '-t' - gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04 - '-f' - infra/cifuzz/cifuzz-base/ubuntu-24-04.Dockerfile - . - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:ubuntu-24-04-v1 - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:ubuntu-24-04 - '-t' - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:ubuntu-24-04-v1 - '-t' - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:ubuntu-24-04 - '-f' - infra/build_fuzzers.ubuntu-24-04.Dockerfile - infra - name: 'gcr.io/cloud-builders/docker' args: - build - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04-v1 - '-t' - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04 - '-t' - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:ubuntu-24-04-v1 - '-t' - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:ubuntu-24-04 - '-f' - infra/run_fuzzers.ubuntu-24-04.Dockerfile - infra images: - gcr.io/oss-fuzz-base/cifuzz-base - gcr.io/oss-fuzz-base/cifuzz-base:v1 - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:v1 - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:v1 - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:v1 - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:v1 - gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04-v1 - gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04 - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:ubuntu-24-04-v1 - gcr.io/oss-fuzz-base/cifuzz-run-fuzzers:ubuntu-24-04 - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:ubuntu-24-04-v1 - gcr.io/oss-fuzz-base/cifuzz-build-fuzzers:ubuntu-24-04 - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04-v1 - gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04 - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:ubuntu-24-04-v1 - gcr.io/oss-fuzz-base/clusterfuzzlite-build-fuzzers:ubuntu-24-04 timeout: 1800s ================================================ FILE: infra/cifuzz/clusterfuzz_deployment.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for interacting with the ClusterFuzz deployment.""" import logging import os import sys import urllib.error import urllib.request import config_utils import continuous_integration import filestore_utils import http_utils import get_coverage import repo_manager # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import utils class BaseClusterFuzzDeployment: """Base class for ClusterFuzz deployments.""" def __init__(self, config, workspace): self.config = config self.workspace = workspace self.ci_system = continuous_integration.get_ci(config) def download_latest_build(self): """Downloads the latest build from ClusterFuzz. Returns: A path to where the OSS-Fuzz build was stored, or None if it wasn't. """ raise NotImplementedError('Child class must implement method.') def upload_build(self, commit): """Uploads the build with the given commit sha to the filestore.""" raise NotImplementedError('Child class must implement method.') def download_corpus(self, target_name, corpus_dir): """Downloads the corpus for |target_name| from ClusterFuzz to |corpus_dir|. Returns: A path to where the OSS-Fuzz build was stored, or None if it wasn't. """ raise NotImplementedError('Child class must implement method.') def upload_crashes(self): """Uploads crashes in |crashes_dir| to filestore.""" raise NotImplementedError('Child class must implement method.') def upload_corpus(self, target_name, corpus_dir, replace=False): # pylint: disable=no-self-use,unused-argument """Uploads the corpus for |target_name| to filestore.""" raise NotImplementedError('Child class must implement method.') def upload_coverage(self): """Uploads the coverage report to the filestore.""" raise NotImplementedError('Child class must implement method.') def get_coverage(self, repo_path): """Returns the project coverage object for the project.""" raise NotImplementedError('Child class must implement method.') def _make_empty_dir_if_nonexistent(path): """Makes an empty directory at |path| if it does not exist.""" os.makedirs(path, exist_ok=True) class ClusterFuzzLite(BaseClusterFuzzDeployment): """Class representing a deployment of ClusterFuzzLite.""" COVERAGE_NAME = 'latest' LATEST_BUILD_WINDOW = 3 def __init__(self, config, workspace): super().__init__(config, workspace) self.filestore = filestore_utils.get_filestore(self.config) def download_latest_build(self): if os.path.exists(self.workspace.clusterfuzz_build): # This path is necessary because download_latest_build can be called # multiple times.That is the case because it is called only when we need # to see if a bug is novel, i.e. until we want to check a bug is novel we # don't want to waste time calling this, but therefore this method can be # called if multiple bugs are found. return self.workspace.clusterfuzz_build repo_dir = self.ci_system.repo_dir if not repo_dir: raise RuntimeError('Repo checkout does not exist.') _make_empty_dir_if_nonexistent(self.workspace.clusterfuzz_build) repo = repo_manager.RepoManager(repo_dir) diff_base = self.ci_system.get_diff_base() if not diff_base: diff_base = 'HEAD^' # Builds are stored by commit, so try the latest |LATEST_BUILD_WINDOW| # commits before the current diff base. # TODO(ochang): If API usage becomes an issue, this can be optimized by the # filestore accepting a list of filenames to try. try: # TODO(metzman): Why do we default to 'origin', we should avoid going down # this path entirely and not need to catch an exception. commit_list = repo.get_commit_list(diff_base, limit=self.LATEST_BUILD_WINDOW) except ValueError as error: logging.error('Can\'t get commit list: %s', error) return None for old_commit in commit_list: logging.info('Trying to downloading previous build %s.', old_commit) build_name = self._get_build_name(old_commit) try: if self.filestore.download_build(build_name, self.workspace.clusterfuzz_build): logging.info('Done downloading previous build.') return self.workspace.clusterfuzz_build logging.info('Build for %s does not exist.', old_commit) except Exception as err: # pylint: disable=broad-except logging.error('Could not download build for %s because of: %s', old_commit, err) return None def download_corpus(self, target_name, corpus_dir): _make_empty_dir_if_nonexistent(corpus_dir) logging.info('Downloading corpus for %s to %s.', target_name, corpus_dir) corpus_name = self._get_corpus_name(target_name) try: self.filestore.download_corpus(corpus_name, corpus_dir) logging.info('Done downloading corpus. Contains %d elements.', len(os.listdir(corpus_dir))) except Exception as err: # pylint: disable=broad-except logging.error('Failed to download corpus for target: %s. Error: %s', target_name, str(err)) return corpus_dir def _get_build_name(self, name): return f'{self.config.sanitizer}-{name}' def _get_corpus_name(self, target_name): # pylint: disable=no-self-use """Returns the name of the corpus artifact.""" return target_name def upload_corpus(self, target_name, corpus_dir, replace=False): """Upload the corpus produced by |target_name|.""" logging.info('Uploading corpus in %s for %s.', corpus_dir, target_name) name = self._get_corpus_name(target_name) try: self.filestore.upload_corpus(name, corpus_dir, replace=replace) logging.info('Done uploading corpus.') except Exception as err: # pylint: disable=broad-except logging.error('Failed to upload corpus for target: %s. Error: %s.', target_name, err) def upload_build(self, commit): """Upload the build produced by CIFuzz as the latest build.""" logging.info('Uploading latest build in %s.', self.workspace.out) build_name = self._get_build_name(commit) try: result = self.filestore.upload_build(build_name, self.workspace.out) logging.info('Done uploading latest build.') return result except Exception as err: # pylint: disable=broad-except logging.error('Failed to upload latest build: %s. Error: %s', self.workspace.out, err) def upload_crashes(self): """Uploads crashes.""" artifact_dirs = os.listdir(self.workspace.artifacts) if not artifact_dirs: logging.info('No crashes in %s. Not uploading.', self.workspace.artifacts) return for crash_target in artifact_dirs: artifact_dir = os.path.join(self.workspace.artifacts, crash_target) if not os.path.isdir(artifact_dir): logging.warning('%s is not an expected artifact directory, skipping.', crash_target) continue logging.info('Uploading crashes in %s.', artifact_dir) try: self.filestore.upload_crashes(crash_target, artifact_dir) logging.info('Done uploading crashes.') except Exception as err: # pylint: disable=broad-except logging.error('Failed to upload crashes. Error: %s', err) def upload_coverage(self): """Uploads the coverage report to the filestore.""" self.filestore.upload_coverage(self.COVERAGE_NAME, self.workspace.coverage_report) def get_coverage(self, repo_path): """Returns the project coverage object for the project.""" _make_empty_dir_if_nonexistent(self.workspace.clusterfuzz_coverage) try: if not self.filestore.download_coverage( self.COVERAGE_NAME, self.workspace.clusterfuzz_coverage): logging.error('Could not download coverage.') return None return get_coverage.FilesystemCoverage( repo_path, self.workspace.clusterfuzz_coverage) except Exception as err: # pylint: disable=broad-except logging.error('Could not get coverage: %s.', err) return None class OSSFuzz(BaseClusterFuzzDeployment): """The OSS-Fuzz ClusterFuzz deployment.""" # Location of clusterfuzz builds on GCS. CLUSTERFUZZ_BUILDS = 'clusterfuzz-builds' # Zip file name containing the corpus. CORPUS_ZIP_NAME = 'public.zip' def get_latest_build_name(self): """Gets the name of the latest OSS-Fuzz build of a project. Returns: A string with the latest build version or None. """ version_file = ( f'{self.config.oss_fuzz_project_name}-{self.config.sanitizer}' '-latest.version') version_url = utils.url_join(utils.GCS_BASE_URL, self.CLUSTERFUZZ_BUILDS, self.config.oss_fuzz_project_name, version_file) try: response = urllib.request.urlopen(version_url) except urllib.error.HTTPError: logging.error('Error getting latest build version for %s from: %s.', self.config.oss_fuzz_project_name, version_url) return None return response.read().decode() def download_latest_build(self): """Downloads the latest OSS-Fuzz build from GCS. Returns: A path to where the OSS-Fuzz build was stored, or None if it wasn't. """ if os.path.exists(self.workspace.clusterfuzz_build): # This function can be called multiple times, don't download the build # again. return self.workspace.clusterfuzz_build _make_empty_dir_if_nonexistent(self.workspace.clusterfuzz_build) latest_build_name = self.get_latest_build_name() if not latest_build_name: return None logging.info('Downloading latest build.') oss_fuzz_build_url = utils.url_join(utils.GCS_BASE_URL, self.CLUSTERFUZZ_BUILDS, self.config.oss_fuzz_project_name, latest_build_name) if http_utils.download_and_unpack_zip(oss_fuzz_build_url, self.workspace.clusterfuzz_build): logging.info('Done downloading latest build.') return self.workspace.clusterfuzz_build return None def upload_build(self, commit): # pylint: disable=no-self-use """Noop Implementation of upload_build.""" logging.info('Not uploading latest build because on OSS-Fuzz.') def upload_corpus(self, target_name, corpus_dir, replace=False): # pylint: disable=no-self-use,unused-argument """Noop Implementation of upload_corpus.""" logging.info('Not uploading corpus because on OSS-Fuzz.') def upload_crashes(self): # pylint: disable=no-self-use """Noop Implementation of upload_crashes.""" logging.info('Not uploading crashes because on OSS-Fuzz.') def download_corpus(self, target_name, corpus_dir): """Downloads the latest OSS-Fuzz corpus for the target. Returns: The local path to to corpus or None if download failed. """ _make_empty_dir_if_nonexistent(corpus_dir) project_qualified_fuzz_target_name = target_name qualified_name_prefix = self.config.oss_fuzz_project_name + '_' if not target_name.startswith(qualified_name_prefix): project_qualified_fuzz_target_name = qualified_name_prefix + target_name corpus_url = (f'{utils.GCS_BASE_URL}{self.config.oss_fuzz_project_name}' '-backup.clusterfuzz-external.appspot.com/corpus/' f'libFuzzer/{project_qualified_fuzz_target_name}/' f'{self.CORPUS_ZIP_NAME}') logging.info('Downloading corpus from OSS-Fuzz: %s', corpus_url) if not http_utils.download_and_unpack_zip(corpus_url, corpus_dir): logging.warning('Failed to download corpus for %s.', target_name) return corpus_dir def upload_coverage(self): """Noop Implementation of upload_coverage_report.""" logging.info('Not uploading coverage report because on OSS-Fuzz.') def get_coverage(self, repo_path): """Returns the project coverage object for the project.""" try: return get_coverage.OSSFuzzCoverage(repo_path, self.config.oss_fuzz_project_name) except get_coverage.CoverageError: return None class NoClusterFuzzDeployment(BaseClusterFuzzDeployment): """ClusterFuzzDeployment implementation used when there is no deployment of ClusterFuzz to use.""" def upload_build(self, commit): # pylint: disable=no-self-use """Noop Implementation of upload_build.""" logging.info('Not uploading latest build because no ClusterFuzz ' 'deployment.') def upload_corpus(self, target_name, corpus_dir, replace=False): # pylint: disable=no-self-use,unused-argument """Noop Implementation of upload_corpus.""" logging.info('Not uploading corpus because no ClusterFuzz deployment.') def upload_crashes(self): # pylint: disable=no-self-use """Noop Implementation of upload_crashes.""" logging.info('Not uploading crashes because no ClusterFuzz deployment.') def download_corpus(self, target_name, corpus_dir): """Noop Implementation of download_corpus.""" logging.info('Not downloading corpus because no ClusterFuzz deployment.') return _make_empty_dir_if_nonexistent(corpus_dir) def download_latest_build(self): # pylint: disable=no-self-use """Noop Implementation of download_latest_build.""" logging.info( 'Not downloading latest build because no ClusterFuzz deployment.') def upload_coverage(self): """Noop Implementation of upload_coverage.""" logging.info( 'Not uploading coverage report because no ClusterFuzz deployment.') def get_coverage(self, repo_path): """Noop Implementation of get_coverage.""" logging.info( 'Not getting project coverage because no ClusterFuzz deployment.') _PLATFORM_CLUSTERFUZZ_DEPLOYMENT_MAPPING = { config_utils.BaseConfig.Platform.INTERNAL_GENERIC_CI: OSSFuzz, config_utils.BaseConfig.Platform.INTERNAL_GITHUB: OSSFuzz, config_utils.BaseConfig.Platform.EXTERNAL_GENERIC_CI: ClusterFuzzLite, config_utils.BaseConfig.Platform.EXTERNAL_GITHUB: ClusterFuzzLite, } def get_clusterfuzz_deployment(config, workspace): """Returns object reprsenting deployment of ClusterFuzz used by |config|.""" deployment_cls = _PLATFORM_CLUSTERFUZZ_DEPLOYMENT_MAPPING[config.platform] if config.no_clusterfuzz_deployment: logging.info('Overriding ClusterFuzzDeployment. Using None.') deployment_cls = NoClusterFuzzDeployment result = deployment_cls(config, workspace) logging.info('ClusterFuzzDeployment: %s.', result) return result ================================================ FILE: infra/cifuzz/clusterfuzz_deployment_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for clusterfuzz_deployment.py""" import os import unittest from unittest import mock import parameterized from pyfakefs import fake_filesystem_unittest import clusterfuzz_deployment import config_utils import test_helpers import workspace_utils # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. EXAMPLE_PROJECT = 'example' # An example fuzzer that triggers an error. EXAMPLE_FUZZER = 'example_crash_fuzzer' WORKSPACE = '/workspace' EXPECTED_LATEST_BUILD_PATH = os.path.join(WORKSPACE, 'cifuzz-prev-build') # pylint: disable=unused-argument def _create_config(**kwargs): """Creates a config object and then sets every attribute that is a key in |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an attribute of Config.""" defaults = { 'cfl_platform': 'github', 'oss_fuzz_project_name': EXAMPLE_PROJECT, 'workspace': WORKSPACE, } for default_key, default_value in defaults.items(): if default_key not in kwargs: kwargs[default_key] = default_value return test_helpers.create_run_config(**kwargs) def _create_deployment(**kwargs): config = _create_config(**kwargs) workspace = workspace_utils.Workspace(config) return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace) class OSSFuzzTest(fake_filesystem_unittest.TestCase): """Tests OSSFuzz.""" def setUp(self): self.setUpPyfakefs() self.deployment = _create_deployment() self.corpus_dir = os.path.join(self.deployment.workspace.corpora, EXAMPLE_FUZZER) @mock.patch('http_utils.download_and_unpack_zip', return_value=True) def test_download_corpus(self, mock_download_and_unpack_zip): """Tests that we can download a corpus for a valid project.""" self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir) expected_url = ('https://storage.googleapis.com/example-backup.' 'clusterfuzz-external.appspot.com/corpus/libFuzzer/' 'example_crash_fuzzer/public.zip') call_args, _ = mock_download_and_unpack_zip.call_args self.assertEqual(call_args, (expected_url, self.corpus_dir)) self.assertTrue(os.path.exists(self.corpus_dir)) @mock.patch('http_utils.download_and_unpack_zip', return_value=False) def test_download_corpus_fail(self, _): """Tests that when downloading fails, an empty corpus directory is still returned.""" self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir) self.assertEqual(os.listdir(self.corpus_dir), []) def test_get_latest_build_name(self): """Tests that the latest build name can be retrieved from GCS.""" latest_build_name = self.deployment.get_latest_build_name() self.assertTrue(latest_build_name.endswith('.zip')) self.assertTrue('address' in latest_build_name) @parameterized.parameterized.expand([ ('upload_build', ('commit',), 'Not uploading latest build because on OSS-Fuzz.'), ('upload_corpus', ('target', 'corpus-dir'), 'Not uploading corpus because on OSS-Fuzz.'), ('upload_crashes', tuple(), 'Not uploading crashes because on OSS-Fuzz.'), ]) def test_noop_methods(self, method, method_args, expected_message): """Tests that certain methods are noops for OSS-Fuzz.""" with mock.patch('logging.info') as mock_info: method = getattr(self.deployment, method) self.assertIsNone(method(*method_args)) mock_info.assert_called_with(expected_message) @mock.patch('http_utils.download_and_unpack_zip', return_value=True) def test_download_latest_build(self, mock_download_and_unpack_zip): """Tests that downloading the latest build works as intended under normal circumstances.""" self.assertEqual(self.deployment.download_latest_build(), EXPECTED_LATEST_BUILD_PATH) expected_url = ('https://storage.googleapis.com/clusterfuzz-builds/example/' 'example-address-202008030600.zip') # This is broken # TODO: fix # mock_download_and_unpack_zip.assert_called_with(expected_url, # EXPECTED_LATEST_BUILD_PATH) @mock.patch('http_utils.download_and_unpack_zip', return_value=False) def test_download_latest_build_fail(self, _): """Tests that download_latest_build returns None when it fails to download a build.""" self.assertIsNone(self.deployment.download_latest_build()) class ClusterFuzzLiteTest(fake_filesystem_unittest.TestCase): """Tests for ClusterFuzzLite.""" def setUp(self): self.setUpPyfakefs() self.deployment = _create_deployment(mode='batch', oss_fuzz_project_name='', cloud_bucket='gs://bucket') self.corpus_dir = os.path.join(self.deployment.workspace.corpora, EXAMPLE_FUZZER) @mock.patch('filestore.github_actions.GithubActionsFilestore.download_corpus', return_value=True) def test_download_corpus(self, mock_download_corpus): """Tests that download_corpus works for a valid project.""" self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir) mock_download_corpus.assert_called_with('example_crash_fuzzer', self.corpus_dir) self.assertTrue(os.path.exists(self.corpus_dir)) @mock.patch('filestore.github_actions.GithubActionsFilestore.download_corpus', side_effect=Exception) def test_download_corpus_fail(self, _): """Tests that when downloading fails, an empty corpus directory is still returned.""" self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir) self.assertEqual(os.listdir(self.corpus_dir), []) @mock.patch('filestore.github_actions.GithubActionsFilestore.download_build', side_effect=[False, True]) @mock.patch('repo_manager.RepoManager.get_commit_list', return_value=['commit1', 'commit2']) @mock.patch('continuous_integration.GithubCiMixin.repo_dir', return_value='/path/to/repo') def test_download_latest_build(self, mock_repo_dir, mock_get_commit_list, mock_download_build): """Tests that downloading the latest build works as intended under normal circumstances.""" self.assertEqual(self.deployment.download_latest_build(), EXPECTED_LATEST_BUILD_PATH) expected_artifact_name = 'address-commit2' mock_download_build.assert_called_with(expected_artifact_name, EXPECTED_LATEST_BUILD_PATH) @mock.patch('filestore.github_actions.GithubActionsFilestore.download_build', side_effect=Exception) @mock.patch('repo_manager.RepoManager.get_commit_list', return_value=['commit1', 'commit2']) @mock.patch('continuous_integration.GithubCiMixin.repo_dir', return_value='/path/to/repo') def test_download_latest_build_fail(self, mock_repo_dir, mock_get_commit_list, _): """Tests that download_latest_build returns None when it fails to download a build.""" self.assertIsNone(self.deployment.download_latest_build()) @mock.patch('filestore.github_actions.GithubActionsFilestore.upload_build') def test_upload_build(self, mock_upload_build): """Tests that upload_build works as intended.""" self.deployment.upload_build('commit') mock_upload_build.assert_called_with('address-commit', '/workspace/build-out') class NoClusterFuzzDeploymentTest(fake_filesystem_unittest.TestCase): """Tests for NoClusterFuzzDeployment.""" def setUp(self): self.setUpPyfakefs() config = test_helpers.create_run_config(workspace=WORKSPACE, cfl_platform='other', filestore='no_filestore', no_clusterfuzz_deployment=True) workspace = workspace_utils.Workspace(config) self.deployment = clusterfuzz_deployment.get_clusterfuzz_deployment( config, workspace) self.corpus_dir = os.path.join(workspace.corpora, EXAMPLE_FUZZER) @mock.patch('logging.info') def test_download_corpus(self, mock_info): """Tests that download corpus returns the path to the empty corpus directory.""" self.deployment.download_corpus(EXAMPLE_FUZZER, self.corpus_dir) mock_info.assert_called_with( 'Not downloading corpus because no ClusterFuzz deployment.') self.assertTrue(os.path.exists(self.corpus_dir)) @parameterized.parameterized.expand([ ('upload_build', ('commit',), 'Not uploading latest build because no ClusterFuzz deployment.'), ('upload_corpus', ('target', 'corpus-dir'), 'Not uploading corpus because no ClusterFuzz deployment.'), ('upload_crashes', tuple(), 'Not uploading crashes because no ClusterFuzz deployment.'), ('download_latest_build', tuple(), 'Not downloading latest build because no ClusterFuzz deployment.') ]) def test_noop_methods(self, method, method_args, expected_message): """Tests that certain methods are noops for NoClusterFuzzDeployment.""" with mock.patch('logging.info') as mock_info: method = getattr(self.deployment, method) self.assertIsNone(method(*method_args)) mock_info.assert_called_with(expected_message) class GetClusterFuzzDeploymentTest(unittest.TestCase): """Tests for get_clusterfuzz_deployment.""" def setUp(self): test_helpers.patch_environ(self) os.environ['GITHUB_REPOSITORY'] = 'owner/myproject' @parameterized.parameterized.expand([ (config_utils.BaseConfig.Platform.INTERNAL_GENERIC_CI, clusterfuzz_deployment.OSSFuzz), (config_utils.BaseConfig.Platform.INTERNAL_GITHUB, clusterfuzz_deployment.OSSFuzz), (config_utils.BaseConfig.Platform.EXTERNAL_GENERIC_CI, clusterfuzz_deployment.ClusterFuzzLite), (config_utils.BaseConfig.Platform.EXTERNAL_GITHUB, clusterfuzz_deployment.ClusterFuzzLite), ]) def test_get_clusterfuzz_deployment(self, platform, expected_deployment_cls): """Tests that get_clusterfuzz_deployment returns the correct value.""" with mock.patch('config_utils.BaseConfig.platform', return_value=platform, new_callable=mock.PropertyMock): with mock.patch('filestore_utils.get_filestore', return_value=None): with mock.patch('platform_config.github._get_event_data', return_value={}): config = _create_config() workspace = workspace_utils.Workspace(config) self.assertIsInstance( clusterfuzz_deployment.get_clusterfuzz_deployment( config, workspace), expected_deployment_cls) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/config_utils.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run.""" import enum import importlib import logging import os import sys import environment # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import platform_config import constants import re import subprocess SANITIZERS = ['address', 'memory', 'undefined', 'coverage'] BASE_OS_VERSION_REGEX = re.compile(r'\s*base_os_version\s*:\s*([^\s]+)') # TODO(metzman): Set these on config objects so there's one source of truth. DEFAULT_ENGINE = 'libfuzzer' # This module deals a lot with env variables. Many of these will be set by users # and others beyond CIFuzz's control. Thus, you should be careful about using # the environment.py helpers for getting env vars, since it can cause values # that should be interpreted as strings to be returned as other types (bools or # ints for example). The environment.py helpers should not be used for values # that are supposed to be strings. def _get_sanitizer(): return os.getenv('SANITIZER', constants.DEFAULT_SANITIZER).lower() def _get_architecture(): return os.getenv('ARCHITECTURE', constants.DEFAULT_ARCHITECTURE).lower() def _is_dry_run(): """Returns True if configured to do a dry run.""" return environment.get_bool('DRY_RUN', False) def _get_language(): """Returns the project language.""" # Get language from environment. We took this approach because the convenience # given to OSS-Fuzz users by not making them specify the language again (and # getting it from the project.yaml) is outweighed by the complexity in # implementing this. A lot of the complexity comes from our unittests not # setting a proper projet at this point. return os.getenv('LANGUAGE', constants.DEFAULT_LANGUAGE) def _get_extra_environment_variables(): """Gets extra environment variables specified by the user with CFL_EXTRA_$NAME=$VALUE.""" return [key for key in os.environ if key.startswith('CFL_EXTRA_')] # pylint: disable=too-many-instance-attributes class ConfigError(Exception): """Error for invalid configuration.""" class BaseConfig: """Object containing constant configuration for CIFuzz.""" class Platform(enum.Enum): """Enum representing the different platforms CIFuzz runs on.""" EXTERNAL_GITHUB = 0 # Non-OSS-Fuzz on GitHub actions. INTERNAL_GITHUB = 1 # OSS-Fuzz on GitHub actions. INTERNAL_GENERIC_CI = 2 # OSS-Fuzz on any CI. EXTERNAL_GENERIC_CI = 3 # Non-OSS-Fuzz on any CI. @property def is_github(self): """Returns True if running on GitHub.""" return self.cfl_platform == 'github' def __init__(self): # Need to set these before calling self.platform. self.oss_fuzz_project_name = os.getenv('OSS_FUZZ_PROJECT_NAME') self.cfl_platform = os.getenv('CFL_PLATFORM') logging.debug('Is github: %s.', self.is_github) self.platform_conf = _get_platform_config(self.cfl_platform) self.base_commit = self.platform_conf.base_commit self.base_ref = self.platform_conf.base_ref self.pr_ref = self.platform_conf.pr_ref self.workspace = self.platform_conf.workspace self.project_src_path = self.platform_conf.project_src_path self.actor = self.platform_conf.actor self.token = self.platform_conf.token self.project_repo_owner = self.platform_conf.project_repo_owner self.project_repo_name = self.platform_conf.project_repo_name self.filestore = self.platform_conf.filestore # This determines if builds are done using docker in docker # rather than the normal method which is sibling containers. self.docker_in_docker = self.platform_conf.docker_in_docker self.dry_run = _is_dry_run() # Check if failures should not be reported. self.sanitizer = _get_sanitizer() self.architecture = _get_architecture() self.language = _get_language() self.low_disk_space = environment.get_bool('LOW_DISK_SPACE', False) self.git_store_repo = os.environ.get('GIT_STORE_REPO') self.git_store_branch = os.environ.get('GIT_STORE_BRANCH') self.git_store_branch_coverage = os.environ.get('GIT_STORE_BRANCH_COVERAGE', self.git_store_branch) self.cloud_bucket = os.environ.get('CLOUD_BUCKET') self.no_clusterfuzz_deployment = environment.get_bool( 'NO_CLUSTERFUZZ_DEPLOYMENT', False) self.build_integration_path = ( constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH) self.parallel_fuzzing = environment.get('PARALLEL_FUZZING', False) self.extra_environment_variables = _get_extra_environment_variables() self.output_sarif = environment.get_bool('OUTPUT_SARIF', False) # TODO(metzman): Fix tests to create valid configurations and get rid of # CIFUZZ_TEST here and in presubmit.py. if not os.getenv('CIFUZZ_TEST') and not self.validate(): raise ConfigError('Invalid Configuration.') def validate(self): """Returns False if the configuration is invalid.""" # Do validation here so that unittests don't need to make a fully-valid # config. # pylint: disable=too-many-return-statements if not self.workspace: logging.error('Must set WORKSPACE.') return False if self.sanitizer not in SANITIZERS: logging.error('Invalid SANITIZER: %s. Must be one of: %s.', self.sanitizer, SANITIZERS) return False if self.architecture not in constants.ARCHITECTURES: logging.error('Invalid ARCHITECTURE: %s. Must be one of: %s.', self.architecture, constants.ARCHITECTURES) return False if self.architecture == 'i386' and self.sanitizer != 'address': logging.error( 'ARCHITECTURE=i386 can be used with SANITIZER=address only.') return False if self.language not in constants.LANGUAGES: logging.error('Invalid LANGUAGE: %s. Must be one of: %s.', self.language, constants.LANGUAGES) return False if not self.project_repo_name: logging.error('Must set REPOSITORY.') return False return True @property def is_internal(self): """Returns True if this is an OSS-Fuzz project.""" return bool(self.oss_fuzz_project_name) @property def platform(self): """Returns the platform CIFuzz is runnning on.""" if not self.is_internal: if not self.is_github: return self.Platform.EXTERNAL_GENERIC_CI return self.Platform.EXTERNAL_GITHUB if self.is_github: return self.Platform.INTERNAL_GITHUB return self.Platform.INTERNAL_GENERIC_CI @property def is_coverage(self): """Returns True if this CIFuzz run (building fuzzers and running them) for generating a coverage report.""" return self.sanitizer == 'coverage' @property def base_os_version(self): """Returns the project's base OS version.""" if self.oss_fuzz_project_name: # Internal/OSS-Fuzz project. project_yaml_path = os.path.join('/opt/oss-fuzz/projects', self.oss_fuzz_project_name, 'project.yaml') else: # External project. project_src_path = self.project_src_path if project_src_path is None: logging.info('PROJECT_SRC_PATH not set. Using workspace: %s', self.workspace) project_src_path = self.workspace project_yaml_path = os.path.join(project_src_path, self.build_integration_path, 'project.yaml') try: if not os.path.exists(project_yaml_path): return 'legacy' with open(project_yaml_path) as file_handle: content = file_handle.read() for line in content.splitlines(): match = BASE_OS_VERSION_REGEX.match(line) if match: return match.group(1).strip('\'"') except Exception: # pylint: disable=broad-except logging.warning( 'Failed to read project.yaml at %s. Falling back to legacy.', project_yaml_path) return 'legacy' return 'legacy' def pivot_to_ubuntu_24_04(image_suffix, script_path, check_result=True): """Pivots execution to an Ubuntu 24.04 container if needed.""" with open('/etc/os-release') as file_handle: if '24.04' not in file_handle.read(): logging.info( 'Base OS version is Ubuntu 24.04, but running in a different OS. Pivoting to Ubuntu 24.04 container.' ) env = os.environ.copy() # Ensure we don't loop indefinitely. env['CIFUZZ_PIVOTED'] = '1' command = [ 'docker', 'run', '--rm', '--privileged', '--volumes-from', os.environ.get('HOSTNAME', ''), '-e', 'CIFUZZ_PIVOTED=1' ] # Propagate environment variables. for key, value in os.environ.items(): command.extend(['-e', f'{key}={value}']) # Use the ubuntu-24-04 version of the image. command.append('--entrypoint') command.append('python3') command.append( f'gcr.io/oss-fuzz-base/clusterfuzzlite-{image_suffix}:ubuntu-24-04-v1' ) # Run the same command. command.append(script_path) if check_result: subprocess.check_call(command) return 0 else: try: subprocess.check_call(command) except subprocess.CalledProcessError as e: return e.returncode return 0 return None def _get_platform_config(cfl_platform): """Returns the CI environment object for |cfl_platform|.""" module_name = f'platform_config.{cfl_platform}' try: cls = importlib.import_module(module_name).PlatformConfig except ImportError: cls = platform_config.BasePlatformConfig return cls() class RunFuzzersConfig(BaseConfig): """Class containing constant configuration for running fuzzers in CIFuzz.""" MODES = ['batch', 'code-change', 'coverage', 'prune'] def __init__(self): super().__init__() # TODO(metzman): Pick a better default for pruning. self.fuzz_seconds = int(os.environ.get('FUZZ_SECONDS', 600)) self.mode = os.environ.get('MODE', 'code-change').lower() if self.is_coverage: self.mode = 'coverage' self.report_unreproducible_crashes = environment.get_bool( 'REPORT_UNREPRODUCIBLE_CRASHES', False) self.minimize_crashes = environment.get_bool('MINIMIZE_CRASHES', False) if self.mode == 'batch': logging.warning( 'Minimizing crashes reduces fuzzing time in batch fuzzing.') self.report_timeouts = environment.get_bool('REPORT_TIMEOUTS', False) self.report_ooms = environment.get_bool('REPORT_OOMS', True) self.upload_all_crashes = environment.get_bool('UPLOAD_ALL_CRASHES', False) # TODO(metzman): Fix tests to create valid configurations and get rid of # CIFUZZ_TEST here and in presubmit.py. if not os.getenv('CIFUZZ_TEST') and not self._run_config_validate(): raise ConfigError('Invalid Run Configuration.') def _run_config_validate(self): """Do extra validation on RunFuzzersConfig.__init__(). Do not name this validate or else it will be called when using the parent's __init__ and will fail. Returns True if valid.""" if self.mode not in self.MODES: logging.error('Invalid MODE: %s. Must be one of %s.', self.mode, self.MODES) return False return True class BuildFuzzersConfig(BaseConfig): """Class containing constant configuration for building fuzzers in CIFuzz.""" def __init__(self): """Get the configuration from CIFuzz from the environment. These variables are set by GitHub or the user.""" super().__init__() self.git_sha = self.platform_conf.git_sha self.git_url = self.platform_conf.git_url self.allowed_broken_targets_percentage = os.getenv( 'ALLOWED_BROKEN_TARGETS_PERCENTAGE') self.bad_build_check = environment.get_bool('BAD_BUILD_CHECK', True) self.keep_unaffected_fuzz_targets = environment.get_bool( 'KEEP_UNAFFECTED_FUZZ_TARGETS') self.upload_build = environment.get_bool('UPLOAD_BUILD', False) if not self.keep_unaffected_fuzz_targets: has_base_for_diff = (self.base_ref or self.base_commit) if not has_base_for_diff: logging.info( 'Keeping all fuzzers because there is nothing to diff against.') self.keep_unaffected_fuzz_targets = True elif self.upload_build: logging.info('Keeping all fuzzers because we are uploading build.') self.keep_unaffected_fuzz_targets = True elif self.sanitizer == 'coverage': logging.info('Keeping all fuzzers because we are doing coverage.') self.keep_unaffected_fuzz_targets = True if self.sanitizer == 'coverage': self.bad_build_check = False ================================================ FILE: infra/cifuzz/config_utils_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for config_utils.""" import os import unittest from unittest import mock import config_utils import constants import test_helpers # pylint: disable=no-self-use,protected-access class BaseConfigTest(unittest.TestCase): """Tests for BaseConfig.""" def setUp(self): test_helpers.patch_environ(self) os.environ['CIFUZZ_TEST'] = '1' def _create_config(self): return config_utils.BuildFuzzersConfig() def test_language_default(self): """Tests that the correct default language is set.""" config = self._create_config() self.assertEqual(config.language, 'c++') def test_language(self): """Tests that the correct language is set.""" language = 'python' os.environ['LANGUAGE'] = language config = self._create_config() self.assertEqual(config.language, language) def test_is_coverage(self): """Tests that is_coverage is set correctly.""" # Test it is set when it is supposed to be. os.environ['SANITIZER'] = 'coverage' config = self._create_config() self.assertTrue(config.is_coverage) # Test it is not set when it is not supposed to be. os.environ['SANITIZER'] = 'address' config = self._create_config() self.assertFalse(config.is_coverage) @mock.patch('logging.error') def test_validate_no_workspace(self, mock_error): """Tests that validate returns False if GITHUB_WORKSPACE isn't set.""" os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example' config = self._create_config() self.assertFalse(config.validate()) mock_error.assert_called_with('Must set WORKSPACE.') @mock.patch('logging.error') def test_validate_invalid_language(self, mock_error): """Tests that validate returns False if GITHUB_WORKSPACE isn't set.""" os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example' os.environ['WORKSPACE'] = '/workspace' os.environ['LANGUAGE'] = 'invalid-language' config = self._create_config() self.assertFalse(config.validate()) mock_error.assert_called_with('Invalid LANGUAGE: %s. Must be one of: %s.', os.environ['LANGUAGE'], constants.LANGUAGES) @mock.patch('logging.error') def test_validate_invalid_sanitizer(self, mock_error): """Tests that validate returns False if GITHUB_WORKSPACE isn't set.""" os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example' os.environ['WORKSPACE'] = '/workspace' os.environ['SANITIZER'] = 'invalid-sanitizer' config = self._create_config() self.assertFalse(config.validate()) mock_error.assert_called_with('Invalid SANITIZER: %s. Must be one of: %s.', os.environ['SANITIZER'], config_utils.SANITIZERS) def test_validate(self): """Tests that validate returns True if config is valid.""" os.environ['OSS_FUZZ_PROJECT_NAME'] = 'example' os.environ['WORKSPACE'] = '/workspace' os.environ['REPOSITORY'] = 'repo' config = self._create_config() self.assertTrue(config.validate()) def test_base_os_version_external(self): """Tests that base_os_version is read correctly for external projects.""" os.environ['PROJECT_SRC_PATH'] = '/src' # Use patch to mock os.path.exists and open for the project.yaml with mock.patch('os.path.exists', return_value=True) as mock_exists: with mock.patch( 'builtins.open', mock.mock_open( read_data='base_os_version: ubuntu-24-04')) as mock_open: config = self._create_config() self.assertEqual(config.base_os_version, 'ubuntu-24-04') # Verify it looked in the right place (PROJECT_SRC_PATH + .clusterfuzzlite) expected_path = os.path.join('/src', '.clusterfuzzlite', 'project.yaml') # We can't easily check the exact path without more mocking, but we can check it was called mock_open.assert_called() def test_base_os_version_external_quoted(self): """Tests that base_os_version handles quoted values for external projects.""" os.environ['PROJECT_SRC_PATH'] = '/src' # Use patch to mock os.path.exists and open for the project.yaml with mock.patch('os.path.exists', return_value=True) as mock_exists: with mock.patch( 'builtins.open', mock.mock_open( read_data='base_os_version: "ubuntu-24-04"')) as mock_open: config = self._create_config() self.assertEqual(config.base_os_version, 'ubuntu-24-04') def test_base_os_version_default(self): """Tests that base_os_version defaults to legacy if not present.""" os.environ['PROJECT_SRC_PATH'] = '/src' with mock.patch('os.path.exists', return_value=False): config = self._create_config() self.assertEqual(config.base_os_version, 'legacy') class BuildFuzzersConfigTest(unittest.TestCase): """Tests for BuildFuzzersConfig.""" def setUp(self): test_helpers.patch_environ(self) os.environ['CIFUZZ_TEST'] = '1' def _create_config(self): return config_utils.BuildFuzzersConfig() @mock.patch('platform_config.github._get_event_data', return_value={}) def test_github_base_ref(self, _): """Tests that base_ref is set properly.""" expected_base_ref = 'expected_base_ref' os.environ['GITHUB_BASE_REF'] = expected_base_ref os.environ['CFL_PLATFORM'] = 'github' os.environ['GITHUB_REPOSITORY'] = 'owner/repo' config = self._create_config() self.assertEqual(config.base_ref, expected_base_ref) def test_base_ref(self): """Tests that base_ref is set properly.""" expected_base_ref = 'expected_base_ref' os.environ['GIT_BASE_REF'] = expected_base_ref config = self._create_config() self.assertEqual(config.base_ref, expected_base_ref) def test_keep_unaffected_defaults_to_true(self): """Tests that keep_unaffected_fuzz_targets defaults to true.""" config = self._create_config() self.assertTrue(config.keep_unaffected_fuzz_targets) def test_keep_unaffected_defaults_to_false_when_pr(self): """Tests that keep_unaffected_fuzz_targets defaults to false when from a pr.""" os.environ['GIT_BASE_REF'] = 'base-ref' config = self._create_config() self.assertFalse(config.keep_unaffected_fuzz_targets) class RunFuzzersConfigTest(unittest.TestCase): """Tests for RunFuzzersConfig.""" def setUp(self): test_helpers.patch_environ(self) os.environ['CIFUZZ_TEST'] = '1' def _create_config(self): return config_utils.RunFuzzersConfig() def test_coverage(self): """Tests that mode is overriden properly based on is_coverage.""" # Test that it is overriden when it is supposed to be. os.environ['SANITIZER'] = 'coverage' os.environ['MODE'] = 'code-change' config = self._create_config() self.assertEqual(config.mode, 'coverage') # Test that it isn't overriden when it isn't supposed to be. os.environ['SANITIZER'] = 'address' mode = 'code-change' os.environ['MODE'] = mode config = self._create_config() self.assertEqual(config.mode, mode) def test_run_config_validate(self): """Tests that _run_config_validate returns True when the config is valid.""" self.assertTrue(self._create_config()._run_config_validate()) @mock.patch('logging.error') def test_run_config_invalid_mode(self, mock_error): """Tests that _run_config_validate returns False when mode is invalid.""" fake_mode = 'fake-mode' os.environ['MODE'] = fake_mode self.assertFalse(self._create_config()._run_config_validate()) mock_error.assert_called_with('Invalid MODE: %s. Must be one of %s.', fake_mode, config_utils.RunFuzzersConfig.MODES) class GetSanitizerTest(unittest.TestCase): """Tests for _get_sanitizer.""" def setUp(self): test_helpers.patch_environ(self) self.sanitizer = 'memory' def test_default_value(self): """Tests that the default value returned by _get_sanitizer is correct.""" self.assertEqual(config_utils._get_sanitizer(), 'address') def test_normal_case(self): """Tests that _get_sanitizer returns the correct value in normal cases.""" os.environ['SANITIZER'] = self.sanitizer self.assertEqual(config_utils._get_sanitizer(), self.sanitizer) def test_capitalization(self): """Tests that that _get_sanitizer handles capitalization properly.""" os.environ['SANITIZER'] = self.sanitizer.upper() self.assertEqual(config_utils._get_sanitizer(), self.sanitizer) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/continuous_integration.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementations for various CI systems.""" import os import collections import sys import logging # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import build_specified_commit import docker import helper import repo_manager import retry import utils import workspace_utils # pylint: disable=too-few-public-methods BuildPreparationResult = collections.namedtuple( 'BuildPreparationResult', ['success', 'image_repo_path', 'repo_manager']) _IMAGE_BUILD_TRIES = 3 _IMAGE_BUILD_BACKOFF = 2 def fix_git_repo_for_diff(repo_manager_obj): """Fixes git repos cloned by the "checkout" action so that diffing works on them.""" command = [ 'git', 'symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/master' ] return utils.execute(command, location=repo_manager_obj.repo_dir) class BaseCi: """Class representing common CI functionality.""" def __init__(self, config): self.config = config self.workspace = workspace_utils.Workspace(config) self._repo_dir = None @property def repo_dir(self): """Returns the source repo path, if it has been checked out. None is returned otherwise.""" raise NotImplementedError('Child class must implement method.') def prepare_for_fuzzer_build(self): """Builds the fuzzer builder image and gets the source code we need to fuzz.""" raise NotImplementedError('Child class must implement method.') def get_diff_base(self): """Returns the base to diff against with git to get the change under test.""" if self.config.base_ref: logging.debug('Diffing against base_ref: %s.', self.config.base_ref) return self.config.base_ref if self.config.base_commit: logging.debug('Diffing against base_commit: %s.', self.config.base_commit) return self.config.base_commit # TODO(metzman): Do we want this at all? What purpose does it serve? I guess # it is a decent fallback when there is no base_commit or base_ref. logging.debug('Diffing against origin.') return 'origin' def get_changed_code_under_test(self, repo_manager_obj): """Returns the changed files that need to be tested.""" if self.config.base_ref: repo_manager_obj.fetch_branch(self.config.base_ref) fix_git_repo_for_diff(repo_manager_obj) base = self.get_diff_base() logging.info('Diffing against %s.', base) # git diff ... is equivalent to # git diff $(git merge-base HEAD) return repo_manager_obj.get_git_diff(base + '...') def get_build_command(self, host_repo_path, image_repo_path): """Returns the command for building the project that is run inside the project builder container.""" raise NotImplementedError('Child class must implement method.') def _build_external_project_docker_image(self, manager): """Helper for child classes that builds an external project's docker image. Returns a BuildPreparationResult indicating failure or success.""" build_integration_abs_path = os.path.join( manager.repo_dir, self.config.build_integration_path) if not build_external_project_docker_image(manager.repo_dir, build_integration_abs_path): logging.error('Failed to build external project.') return get_build_preparation_failure() image_repo_path = os.path.join('/src', self.config.project_repo_name) return BuildPreparationResult(success=True, image_repo_path=image_repo_path, repo_manager=manager) def _make_repo_storage_dir(self): os.makedirs(self.workspace.repo_storage, exist_ok=True) def _clone_repo_and_checkout(self, repo_url, repo_name): """Helper for child classes that clones the git repo specified by |repo_url| to |repo_name|, checks out the specified commit, and returns the |manager|.""" self._make_repo_storage_dir() # Checkout project's repo in the shared volume. manager = repo_manager.clone_repo_and_get_manager( repo_url, self.workspace.repo_storage, repo_name=repo_name, username=self.config.actor, password=self.config.token) self._checkout_specified_commit(manager) return manager def _checkout_specified_commit(self, manager): checkout_specified_commit(manager, self.config.pr_ref, self.config.git_sha) def _detect_main_repo(self): """Helper for child classes that detects the main repo and returns a tuple containing the inffered url and path to the repo in the image.""" inferred_url, image_repo_path = build_specified_commit.detect_main_repo( self.config.oss_fuzz_project_name, repo_name=self.config.project_repo_name) if not inferred_url or not image_repo_path: logging.error('Could not detect repo.') return inferred_url, image_repo_path def _create_repo_manager_for_project_src_path(self): """Returns a repo manager for |project_src_path|.""" return repo_manager.RepoManager(self.config.project_src_path) def get_build_command(): """Returns the command to build the project inside the project builder container.""" return 'compile' def get_replace_repo_and_build_command(host_repo_path, image_repo_path): """Returns the command to replace the repo located at |image_repo_path| with |host_repo_path| and build the project inside the project builder container.""" rm_path = os.path.join(image_repo_path, '*') image_src_path = os.path.dirname(image_repo_path) build_command = get_build_command() command = (f'cd / && rm -rf {rm_path} && cp -r {host_repo_path} ' f'{image_src_path} && cd - && {build_command}') return command def get_ci(config): """Determines what kind of CI is being used and returns the object representing that system.""" if config.platform == config.Platform.EXTERNAL_GENERIC_CI: # Non-OSS-Fuzz projects must bring their own source and their own build # integration (which is relative to that source). return ExternalGeneric(config) if config.platform == config.Platform.EXTERNAL_GITHUB: # Non-OSS-Fuzz projects must bring their own source and their own build # integration (which is relative to that source). return ExternalGithub(config) if config.platform == config.Platform.INTERNAL_GENERIC_CI: # Builds of OSS-Fuzz projects not hosted on Github must bring their own # source since the checkout logic CIFuzz implements is github-specific. # TODO(metzman): Consider moving Github-actions builds of OSS-Fuzz projects # to this system to reduce implementation complexity. return InternalGeneric(config) return InternalGithub(config) def checkout_specified_commit(repo_manager_obj, pr_ref, git_sha): """Checks out the specified commit or pull request using |repo_manager_obj|.""" try: if pr_ref: repo_manager_obj.checkout_pr(pr_ref) else: repo_manager_obj.checkout_commit(git_sha) except (RuntimeError, ValueError): logging.error( 'Can not check out requested state %s. ' 'Using current repo state.', pr_ref or git_sha) class GithubCiMixin: """Mixin for Github based CI systems.""" def __init__(self, config): super().__init__(config) # Unlike in other classes, here _repo_dir is the parent directory of the # repo, not its actual directory. self._repo_dir = self.workspace.repo_storage @property def repo_dir(self): """Returns the source repo path, if it has been checked out. None is returned otherwise.""" if not os.path.exists(self._repo_dir): logging.warning('Repo dir: %s does not exist.', self._repo_dir) return None # Note: this assumes there is only one repo checked out here. listing = os.listdir(self._repo_dir) if len(listing) != 1: raise RuntimeError('Invalid repo directory.') repo_path = os.path.join(self._repo_dir, listing[0]) if not os.path.isdir(repo_path): raise RuntimeError('Repo is not a directory.') return repo_path class InternalGithub(GithubCiMixin, BaseCi): """Class representing CI for an OSS-Fuzz project on Github Actions.""" def _copy_repo_from_image(self, image_repo_path): self._make_repo_storage_dir() repo_name = os.path.basename(image_repo_path) host_repo_path = os.path.join(self._repo_dir, repo_name) bash_command = f'cp -r {image_repo_path} {host_repo_path}' docker_args, _ = docker.get_base_docker_run_args( self.workspace, self.config.sanitizer, self.config.language, self.config.architecture, self.config.docker_in_docker) docker_args.extend([ docker.get_project_image_name(self.config.oss_fuzz_project_name), '/bin/bash', '-c', bash_command ]) if not helper.docker_run(docker_args): raise RuntimeError('Failed to copy repo.') return repo_manager.RepoManager(host_repo_path) def prepare_for_fuzzer_build(self): """Builds the fuzzer builder image, checks out the pull request/commit and returns the BuildPreparationResult.""" logging.info('InternalGithub: preparing for fuzzer build.') assert self.config.pr_ref or self.config.git_sha # _detect_main_repo builds the image as a side effect. _, image_repo_path = self._detect_main_repo() if not image_repo_path: return get_build_preparation_failure() # Use the same name used in the docker image so we can overwrite it. manager = self._copy_repo_from_image(image_repo_path) self._checkout_specified_commit(manager) return BuildPreparationResult(success=True, image_repo_path=image_repo_path, repo_manager=manager) def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use """Returns the command for building the project that is run inside the project builder container. Command also replaces |image_repo_path| with |host_repo_path|.""" return get_replace_repo_and_build_command(host_repo_path, image_repo_path) def get_build_preparation_failure(): """Returns a BuildPreparationResult indicating failure.""" return BuildPreparationResult(success=False, image_repo_path=None, repo_manager=None) class InternalGeneric(BaseCi): """Class representing CI for an OSS-Fuzz project on a CI other than Github actions.""" def __init__(self, config): super().__init__(config) self._repo_dir = config.project_src_path @property def repo_dir(self): """Returns the source repo path, if it has been checked out. None is returned otherwise.""" return self._repo_dir def prepare_for_fuzzer_build(self): """Builds the project builder image for an OSS-Fuzz project outside of GitHub actions. Returns the repo_manager. Does not checkout source code since external projects are expected to bring their own source code to CIFuzz.""" logging.info('InternalGeneric: preparing for fuzzer build.') # detect_main_repo builds the image as a side effect. _, image_repo_path = self._detect_main_repo() if not image_repo_path: return get_build_preparation_failure() manager = self._create_repo_manager_for_project_src_path() return BuildPreparationResult(success=True, image_repo_path=image_repo_path, repo_manager=manager) def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use """Returns the command for building the project that is run inside the project builder container. Command also replaces |image_repo_path| with |host_repo_path|.""" return get_replace_repo_and_build_command(host_repo_path, image_repo_path) @retry.wrap(_IMAGE_BUILD_TRIES, _IMAGE_BUILD_BACKOFF) def build_external_project_docker_image(project_src, build_integration_path): """Builds the project builder image for an external (non-OSS-Fuzz) project. Returns True on success.""" dockerfile_path = os.path.join(build_integration_path, 'Dockerfile') command = [ '-t', docker.EXTERNAL_PROJECT_IMAGE, '-f', dockerfile_path, project_src ] return helper.docker_build(command) class ExternalGeneric(BaseCi): """CI implementation for generic CI for external (non-OSS-Fuzz) projects.""" def __init__(self, config): super().__init__(config) self._repo_dir = config.project_src_path @property def repo_dir(self): """Returns the source repo path, if it has been checked out. None is returned otherwise.""" return self._repo_dir def prepare_for_fuzzer_build(self): logging.info('ExternalGeneric: preparing for fuzzer build.') manager = self._create_repo_manager_for_project_src_path() return self._build_external_project_docker_image(manager) def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use """Returns the command for building the project that is run inside the project builder container.""" return get_build_command() class ExternalGithub(GithubCiMixin, BaseCi): """Class representing CI for a non-OSS-Fuzz project on Github Actions.""" def prepare_for_fuzzer_build(self): """Builds the project builder image for a non-OSS-Fuzz project on GitHub actions. Sets the repo manager. Does not checkout source code since external projects are expected to bring their own source code to CIFuzz. Returns True on success.""" logging.info('ExternalGithub: preparing for fuzzer build.') # Checkout before building, so we don't need to rely on copying the source # from the image. # TODO(metzman): Figure out if we want second copy at all. manager = self._clone_repo_and_checkout(self.config.git_url, self.config.project_repo_name) return self._build_external_project_docker_image(manager) def get_build_command(self, host_repo_path, image_repo_path): # pylint: disable=no-self-use """Returns the command for building the project that is run inside the project builder container.""" return get_build_command() ================================================ FILE: infra/cifuzz/continuous_integration_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for continuous_integration_module.""" import os import sys import unittest from unittest import mock import continuous_integration import docker # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import repo_manager # pylint: disable=no-self-use class FixGitRepoForDiffTest(unittest.TestCase): """Tests for fix_git_repo_for_diff.""" @mock.patch('utils.execute') def test_fix_git_repo_for_diff(self, mock_execute): """Tests that fix_git_repo_for_diff works as intended.""" repo_dir = '/dir' repo_manager_obj = repo_manager.RepoManager(repo_dir) continuous_integration.fix_git_repo_for_diff(repo_manager_obj) expected_command = [ 'git', 'symbolic-ref', 'refs/remotes/origin/HEAD', 'refs/remotes/origin/master' ] mock_execute.assert_called_with(expected_command, location=repo_dir) class GetBuildCommand(unittest.TestCase): """Tests for get_build_command.""" def test_build_command(self): """Tests that get_build_command works as intended.""" self.assertEqual(continuous_integration.get_build_command(), 'compile') class GetReplaceRepoAndBuildCommand(unittest.TestCase): """Tests for get_replace_repo_and_build_command.""" def test_get_replace_repo_and_build_command(self): """Tests that get_replace_repo_and_build_command works as intended.""" host_repo_path = '/path/on/host/to/repo' image_repo_path = '/src/repo' command = continuous_integration.get_replace_repo_and_build_command( host_repo_path, image_repo_path) expected_command = ('cd / && rm -rf /src/repo/* && ' 'cp -r /path/on/host/to/repo /src && cd - ' '&& compile') self.assertEqual(command, expected_command) class BuildExternalProjetDockerImage(unittest.TestCase): """Tests for build_external_project_docker_image.""" @mock.patch('helper.docker_build') def test_build_external_project_docker_image(self, mock_docker_build): """Tests that build_external_project_docker_image works as intended.""" build_integration_path = '.clusterfuzzlite' project_src = '/path/to/project/src' continuous_integration.build_external_project_docker_image( project_src, build_integration_path) mock_docker_build.assert_called_with([ '-t', docker.EXTERNAL_PROJECT_IMAGE, '-f', os.path.join('.clusterfuzzlite', 'Dockerfile'), project_src ]) # TODO(metzman): Write tests for the rest of continuous_integration.py. ================================================ FILE: infra/cifuzz/docker.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for dealing with docker.""" import logging import os import sys import uuid # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import constants import utils import environment BASE_BUILDER_TAG = 'gcr.io/oss-fuzz-base/base-builder' PROJECT_TAG_PREFIX = 'gcr.io/oss-fuzz/' # Default fuzz configuration. _DEFAULT_DOCKER_RUN_ARGS = [ '-e', 'FUZZING_ENGINE=' + constants.DEFAULT_ENGINE, '-e', 'CIFUZZ=True' ] UNIQUE_ID_SUFFIX = '-' + uuid.uuid4().hex # TODO(metzman): Make run_fuzzers able to delete this image. EXTERNAL_PROJECT_IMAGE = 'external-cfl-project' + UNIQUE_ID_SUFFIX _DEFAULT_DOCKER_RUN_COMMAND = [ 'docker', 'run', '--rm', '--privileged', ] def get_docker_env_vars(env_mapping): """Returns a list of docker arguments that sets each key in |env_mapping| as an env var and the value of that key in |env_mapping| as the value.""" env_var_args = [] for env_var, env_var_val in env_mapping.items(): env_var_args.extend(['-e', f'{env_var}={env_var_val}']) return env_var_args def get_project_image_name(project): """Returns the name of the project builder image for |project_name|.""" # TODO(jonathanmetzman): We may need unique names to support parallel fuzzing # for CIFuzz (like CFL supports). Don't do this for now because no one has # asked for it and build_specified_commit would need to be modified to support # this. if project: return PROJECT_TAG_PREFIX + project return EXTERNAL_PROJECT_IMAGE def delete_images(images): """Deletes |images|.""" command = ['docker', 'rmi', '-f'] + images utils.execute(command) utils.execute(['docker', 'builder', 'prune', '-f']) def get_base_docker_run_args(workspace, sanitizer=constants.DEFAULT_SANITIZER, language=constants.DEFAULT_LANGUAGE, architecture=constants.DEFAULT_ARCHITECTURE, docker_in_docker=False): """Returns arguments that should be passed to every invocation of 'docker run'.""" docker_args = _DEFAULT_DOCKER_RUN_ARGS.copy() env_mapping = { 'SANITIZER': sanitizer, 'ARCHITECTURE': architecture, 'FUZZING_LANGUAGE': language, 'OUT': workspace.out } docker_args += get_docker_env_vars(env_mapping) docker_container = environment.get('CFL_CONTAINER_ID', utils.get_container_name()) logging.info('Docker container: %s.', docker_container) if docker_container and not docker_in_docker: # Don't map specific volumes if in a docker container, it breaks when # running a sibling container. docker_args += ['--volumes-from', docker_container] else: docker_args += _get_args_mapping_host_path_to_container(workspace.workspace) return docker_args, docker_container def get_base_docker_run_command(workspace, sanitizer=constants.DEFAULT_SANITIZER, language=constants.DEFAULT_LANGUAGE, architecture=constants.DEFAULT_ARCHITECTURE, docker_in_docker=False): """Returns part of the command that should be used everytime 'docker run' is invoked.""" docker_args, docker_container = get_base_docker_run_args( workspace, sanitizer, language, architecture, docker_in_docker=docker_in_docker) command = _DEFAULT_DOCKER_RUN_COMMAND.copy() + docker_args return command, docker_container def _get_args_mapping_host_path_to_container(host_path, container_path=None): """Get arguments to docker run that will map |host_path| a path on the host to a path in the container. If |container_path| is specified, that path is mapped to. If not, then |host_path| is mapped to itself in the container.""" # WARNING: Do not use this function when running in production (and # --volumes-from) is used for mapping volumes. It will break production. container_path = host_path if container_path is None else container_path return ['-v', f'{host_path}:{container_path}'] ================================================ FILE: infra/cifuzz/docker_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests the functionality of the docker module.""" import unittest from unittest import mock import docker import test_helpers import workspace_utils CONTAINER_NAME = 'example-container' config = test_helpers.create_run_config(oss_fuzz_project_name='project', workspace='/workspace') config.workspace = '/workspace' WORKSPACE = workspace_utils.Workspace(config) SANITIZER = 'example-sanitizer' LANGUAGE = 'example-language' class GetProjectImageTest(unittest.TestCase): """Tests for get_project_image.""" def test_get_project_image(self): """Tests that get_project_image_name works as intended.""" project = 'my-project' self.assertEqual(docker.get_project_image_name(project), 'gcr.io/oss-fuzz/my-project') class GetDeleteImagesTest(unittest.TestCase): """Tests for delete_images.""" @mock.patch('utils.execute') def test_delete_images(self, mock_execute): # pylint: disable=no-self-use """Tests that get_project_image_name works as intended.""" images = ['image'] docker.delete_images(images) expected_calls = [ mock.call(['docker', 'rmi', '-f'] + images), mock.call(['docker', 'builder', 'prune', '-f']) ] mock_execute.assert_has_calls(expected_calls) class GetBaseDockerRunArgsTest(unittest.TestCase): """Tests get_base_docker_run_args.""" @mock.patch('utils.get_container_name', return_value=CONTAINER_NAME) def test_get_base_docker_run_args_container(self, _): """Tests that get_base_docker_run_args works as intended when inside a container.""" docker_args, docker_container = docker.get_base_docker_run_args( WORKSPACE, SANITIZER, LANGUAGE) self.assertEqual(docker_container, CONTAINER_NAME) expected_docker_args = [] expected_docker_args = [ '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'CIFUZZ=True', '-e', f'SANITIZER={SANITIZER}', '-e', 'ARCHITECTURE=x86_64', '-e', f'FUZZING_LANGUAGE={LANGUAGE}', '-e', f'OUT={WORKSPACE.out}', '--volumes-from', CONTAINER_NAME, ] self.assertEqual(docker_args, expected_docker_args) @mock.patch('utils.get_container_name', return_value=None) def test_get_base_docker_run_args_no_container(self, _): """Tests that get_base_docker_run_args works as intended when not inside a container.""" docker_args, docker_container = docker.get_base_docker_run_args( WORKSPACE, SANITIZER, LANGUAGE) self.assertEqual(docker_container, None) expected_docker_args = [ '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'CIFUZZ=True', '-e', f'SANITIZER={SANITIZER}', '-e', 'ARCHITECTURE=x86_64', '-e', f'FUZZING_LANGUAGE={LANGUAGE}', '-e', f'OUT={WORKSPACE.out}', '-v', f'{WORKSPACE.workspace}:{WORKSPACE.workspace}' ] self.assertEqual(docker_args, expected_docker_args) class GetBaseDockerRunCommandTest(unittest.TestCase): """Tests get_base_docker_run_args.""" @mock.patch('utils.get_container_name', return_value=None) def test_get_base_docker_run_command_no_container(self, _): """Tests that get_base_docker_run_args works as intended when not inside a container.""" docker_args, docker_container = docker.get_base_docker_run_command( WORKSPACE, SANITIZER, LANGUAGE) self.assertEqual(docker_container, None) expected_docker_command = [ 'docker', 'run', '--rm', '--privileged', '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'CIFUZZ=True', '-e', f'SANITIZER={SANITIZER}', '-e', 'ARCHITECTURE=x86_64', '-e', f'FUZZING_LANGUAGE={LANGUAGE}', '-e', f'OUT={WORKSPACE.out}', '-v', f'{WORKSPACE.workspace}:{WORKSPACE.workspace}' ] self.assertEqual(docker_args, expected_docker_command) ================================================ FILE: infra/cifuzz/environment.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for dealing with env vars.""" import ast import os def _eval_value(value_string): """Returns evaluated value.""" try: return ast.literal_eval(value_string) except: # pylint: disable=bare-except # String fallback. return value_string def get(env_var, default_value=None): """Returns an environment variable value.""" value_string = os.getenv(env_var) if value_string is None: return default_value return _eval_value(value_string) def get_bool(env_var, default_value=None): """Returns a boolean environment variable value. This is needed because a lot of CIFuzz users specified 'false' for dry-run. So we need to special case this.""" value = get(env_var, default_value) if not isinstance(value, str): return bool(value) lower_value = value.lower() allowed_values = {'true', 'false'} if lower_value not in allowed_values: raise Exception(f'Bool env var {env_var} value {value} is invalid. ' f'Must be one of {allowed_values}.') return lower_value == 'true' ================================================ FILE: infra/cifuzz/example_cifuzz.yml ================================================ name: CIFuzz on: [pull_request] permissions: {} jobs: Fuzzing: runs-on: ubuntu-latest permissions: security-events: write steps: - name: Build Fuzzers id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: oss-fuzz-project-name: 'example' - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'example' fuzz-seconds: 600 output-sarif: true - name: Upload Crash uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts path: ./out/artifacts - name: Upload Sarif if: always() && steps.build.outcome == 'success' uses: github/codeql-action/upload-sarif@v2 with: # Path to SARIF file relative to the root of the repository sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif ================================================ FILE: infra/cifuzz/external-actions/build_fuzzers/action.yml ================================================ # action.yml name: 'build-fuzzers' description: "Builds an OSS-Fuzz project's fuzzers." inputs: language: description: 'Programming language project is written in.' required: false default: 'c++' dry-run: description: 'If set, run the action without actually reporting a failure.' default: false allowed-broken-targets-percentage: description: 'The percentage of broken targets allowed in bad_build_check.' required: false sanitizer: description: 'The sanitizer to build the fuzzers with.' default: 'address' project-src-path: description: "The path to the project's source code checkout." required: false bad-build-check: description: "Whether or not OSS-Fuzz's check for bad builds should be done." required: false default: true keep-unaffected-fuzz-targets: description: "Whether to keep unaffected fuzzers or delete them." required: false default: false storage-repo: description: | The git repo to use for storing certain artifacts from fuzzing. required: false storage-repo-branch: description: | The branch of the git repo to use for storing certain artifacts from fuzzing. required: false storage-repo-branch-coverage: description: | The branch of the git repo to use for storing coverage reports. required: false upload-build: description: | If set, will upload the build. default: false github-token: description: | Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET You should use "secrets.GITHUB_TOKEN" in your workflow file, do not hardcode the token. TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361): Document locking this down. required: false output-sarif: description: "Whether to output fuzzing results to SARIF." required: false default: false runs: using: 'docker' image: '../../../build_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} LANGUAGE: ${{ inputs.language }} DRY_RUN: ${{ inputs.dry-run}} ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}} SANITIZER: ${{ inputs.sanitizer }} PROJECT_SRC_PATH: ${{ inputs.project-src-path }} GITHUB_TOKEN: ${{ inputs.github-token }} LOW_DISK_SPACE: 'True' BAD_BUILD_CHECK: ${{ inputs.bad-build-check }} UPLOAD_BUILD: ${{ inputs.upload-build }} CIFUZZ_DEBUG: 'True' CFL_PLATFORM: 'github' KEEP_UNAFFECTED_FUZZ_TARGETS: ${{ inputs.keep-unaffected-fuzz-targets }} OUTPUT_SARIF: ${{ inputs.output-sarif }} ================================================ FILE: infra/cifuzz/external-actions/run_fuzzers/action.yml ================================================ # action.yml name: 'run-fuzzers' description: 'Runs fuzz target binaries for a specified length of time.' inputs: language: description: 'Programming language project is written in.' required: false default: 'c++' fuzz-seconds: description: 'The total time allotted for fuzzing in seconds.' required: true default: 600 dry-run: description: 'If set, run the action without actually reporting a failure.' default: false sanitizer: description: 'The sanitizer to run the fuzzers with.' default: 'address' mode: description: | The mode to run the fuzzers with ("code-change", "batch", "coverage", or "prune"). "code-change" is for fuzzing a pull request or commit. "batch" is for non-interactive fuzzing of an entire project. "coverage" is for coverage generation. "prune" is for corpus pruning. required: false default: 'code-change' github-token: description: | Token for GitHub API. WARNING: THIS SHOULD NOT BE USED IN PRODUCTION YET You should use "secrets.GITHUB_TOKEN" in your workflow file, do not hardcode the token. TODO(https://github.com/google/oss-fuzz/pull/5841#discussion_r639393361): Document locking this down. required: true storage-repo: description: | The git repo to use for storing certain artifacts from fuzzing. required: false storage-repo-branch: description: | The branch of the git repo to use for storing certain artifacts from fuzzing. default: main required: false storage-repo-branch-coverage: description: | The branch of the git repo to use for storing coverage reports. default: gh-pages required: false report-unreproducible-crashes: description: 'If True, then unreproducible crashes will be reported.' required: false default: false minimize-crashes: description: 'If True, reportable crashes will be minimized.' required: false default: False parallel-fuzzing: description: "How many cores to use cores for fuzzing. A specific number, True - all available cores or False to run single threaded on a single core." required: false default: false output-sarif: description: "Whether to output fuzzing results to SARIF." required: false default: false report-timeouts: description: "Whether to report fails due to timeout." required: false default: true report-ooms: description: "Whether to report fails due to OOM." required: false default: true runs: using: 'docker' image: '../../../run_fuzzers.Dockerfile' env: OSS_FUZZ_PROJECT_NAME: ${{ inputs.oss-fuzz-project-name }} LANGUAGE: ${{ inputs.language }} FUZZ_SECONDS: ${{ inputs.fuzz-seconds }} DRY_RUN: ${{ inputs.dry-run}} SANITIZER: ${{ inputs.sanitizer }} MODE: ${{ inputs.mode }} GITHUB_TOKEN: ${{ inputs.github-token }} LOW_DISK_SPACE: 'True' GIT_STORE_REPO: ${{ inputs.storage-repo }} GIT_STORE_BRANCH: ${{ inputs.storage-repo-branch }} GIT_STORE_BRANCH_COVERAGE: ${{ inputs.storage-repo-branch-coverage }} REPORT_UNREPRODUCIBLE_CRASHES: ${{ inputs.report-unreproducible-crashes }} MINIMIZE_CRASHES: ${{ inputs.minimize-crashes }} CIFUZZ_DEBUG: 'True' CFL_PLATFORM: 'github' PARALLEL_FUZZING: ${{ inputs.parallel-fuzzing }} OUTPUT_SARIF: ${{ inputs.output-sarif }} REPORT_TIMEOUTS: ${{ inputs.report-timeouts }} REPORT_OOMS: ${{ inputs.report-ooms}} ================================================ FILE: infra/cifuzz/filestore/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for a generic filestore.""" class FilestoreError(Exception): """Error using the filestore.""" # pylint: disable=unused-argument,no-self-use class BaseFilestore: """Base class for a filestore.""" def __init__(self, config): self.config = config def upload_crashes(self, name, directory): """Uploads the crashes at |directory| to |name|.""" raise NotImplementedError('Child class must implement method.') def upload_corpus(self, name, directory, replace=False): """Uploads the corpus at |directory| to |name|.""" raise NotImplementedError('Child class must implement method.') def upload_build(self, name, directory): """Uploads the build at |directory| to |name|.""" raise NotImplementedError('Child class must implement method.') def upload_coverage(self, name, directory): """Uploads the coverage report at |directory| to |name|.""" raise NotImplementedError('Child class must implement method.') def download_corpus(self, name, dst_directory): """Downloads the corpus located at |name| to |dst_directory|.""" raise NotImplementedError('Child class must implement method.') def download_build(self, name, dst_directory): """Downloads the build with |name| to |dst_directory|.""" raise NotImplementedError('Child class must implement method.') def download_coverage(self, name, dst_directory): """Downloads the latest project coverage report.""" raise NotImplementedError('Child class must implement method.') ================================================ FILE: infra/cifuzz/filestore/filesystem/__init__.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Filestore implementation using a filesystem directory.""" import logging import os import shutil import subprocess import sys from distutils import dir_util # pylint: disable=wrong-import-position,import-error sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, os.pardir)) import filestore def recursive_list_dir(directory): """Returns list of all files in |directory|, including those in subdirectories.""" files = [] for root, _, filenames in os.walk(directory): for filename in filenames: files.append(os.path.join(root, filename)) return files class FilesystemFilestore(filestore.BaseFilestore): """Filesystem implementation using a filesystem directory.""" BUILD_DIR = 'build' CRASHES_DIR = 'crashes' CORPUS_DIR = 'corpus' COVERAGE_DIR = 'coverage' def __init__(self, config): super().__init__(config) self._filestore_root_dir = self.config.platform_conf.filestore_root_dir def _get_filestore_path(self, name, prefix_dir): """Returns the filesystem path in the filestore for |name| and |prefix_dir|.""" return os.path.join(self._filestore_root_dir, prefix_dir, name) def _upload_directory(self, name, directory, prefix, delete=False): filestore_path = self._get_filestore_path(name, prefix) if os.path.exists(filestore_path): initial_files = set(recursive_list_dir(filestore_path)) else: initial_files = set() # Make directory and any parents. os.makedirs(filestore_path, exist_ok=True) copied_files = set(dir_util.copy_tree(directory, filestore_path)) if not delete: return True files_to_delete = initial_files - copied_files for file_path in files_to_delete: os.remove(file_path) return True def _download_directory(self, name, dst_directory, prefix): filestore_path = self._get_filestore_path(name, prefix) return dir_util.copy_tree(filestore_path, dst_directory) def upload_crashes(self, name, directory): """Uploads the crashes at |directory| to |name|.""" return self._upload_directory(name, directory, self.CRASHES_DIR) def upload_corpus(self, name, directory, replace=False): """Uploads the crashes at |directory| to |name|.""" return self._upload_directory(name, directory, self.CORPUS_DIR, delete=replace) def upload_build(self, name, directory): """Uploads the build located at |directory| to |name|.""" return self._upload_directory(name, directory, self.BUILD_DIR) def upload_coverage(self, name, directory): """Uploads the coverage report at |directory| to |name|.""" return self._upload_directory(name, directory, self.COVERAGE_DIR) def download_corpus(self, name, dst_directory): """Downloads the corpus located at |name| to |dst_directory|.""" return self._download_directory(name, dst_directory, self.CORPUS_DIR) def download_build(self, name, dst_directory): """Downloads the build with |name| to |dst_directory|.""" return self._download_directory(name, dst_directory, self.BUILD_DIR) def download_coverage(self, name, dst_directory): """Downloads the latest project coverage report.""" return self._download_directory(name, dst_directory, self.COVERAGE_DIR) ================================================ FILE: infra/cifuzz/filestore/git/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for a git based filestore.""" import logging import os import shutil import subprocess import sys import tempfile import filestore # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__))))) sys.path.append(INFRA_DIR) import retry _PUSH_RETRIES = 3 _PUSH_BACKOFF = 1 _CLONE_RETRIES = 5 _CLONE_DELAY = 1 _GIT_EMAIL = 'cifuzz@clusterfuzz.com' _GIT_NAME = 'CIFuzz' _CORPUS_DIR = 'corpus' _COVERAGE_DIR = 'coverage' def git_runner(repo_path): """Returns a gits runner for the repo_path.""" def func(*args): return subprocess.check_call(('git', '-C', repo_path) + args) return func # pylint: disable=unused-argument,no-self-use class GitFilestore(filestore.BaseFilestore): """Generic git filestore. This still relies on another filestore provided by the CI for larger artifacts or artifacts which make sense to be included as the result of a workflow run.""" def __init__(self, config, ci_filestore): super().__init__(config) self.repo_path = tempfile.mkdtemp() self._git = git_runner(self.repo_path) self._clone(self.config.git_store_repo) self._ci_filestore = ci_filestore def __del__(self): shutil.rmtree(self.repo_path) @retry.wrap(_CLONE_RETRIES, _CLONE_DELAY) def _clone(self, repo_url): """Clones repo URL.""" self._git('clone', repo_url, '.') self._git('config', '--local', 'user.email', _GIT_EMAIL) self._git('config', '--local', 'user.name', _GIT_NAME) def _reset_git(self, branch): """Resets the git repo.""" self._git('fetch', 'origin') try: self._git('checkout', '-B', branch, 'origin/' + branch) self._git('reset', '--hard', 'HEAD') except subprocess.CalledProcessError: self._git('checkout', '--orphan', branch) self._git('clean', '-fxd') # pylint: disable=too-many-arguments @retry.wrap(_PUSH_RETRIES, _PUSH_BACKOFF) def _upload_to_git(self, message, branch, upload_path, local_path, replace=False): """Uploads a directory to git. If `replace` is True, then existing contents in the upload_path is deleted.""" self._reset_git(branch) full_repo_path = os.path.join(self.repo_path, upload_path) if replace and os.path.exists(full_repo_path): shutil.rmtree(full_repo_path) shutil.copytree(local_path, full_repo_path, dirs_exist_ok=True) self._git('add', '.') try: self._git('commit', '-m', message) except subprocess.CalledProcessError: logging.debug('No changes, skipping git push.') return self._git('push', 'origin', branch) def upload_crashes(self, name, directory): """Uploads the crashes at |directory| to |name|.""" return self._ci_filestore.upload_crashes(name, directory) def upload_corpus(self, name, directory, replace=False): """Uploads the corpus at |directory| to |name|.""" self._upload_to_git('Corpus upload', self.config.git_store_branch, os.path.join(_CORPUS_DIR, name), directory, replace=replace) def upload_build(self, name, directory): """Uploads the build at |directory| to |name|.""" return self._ci_filestore.upload_build(name, directory) def upload_coverage(self, name, directory): """Uploads the coverage report at |directory| to |name|.""" self._upload_to_git('Coverage upload', self.config.git_store_branch_coverage, os.path.join(_COVERAGE_DIR, name), directory, replace=True) def download_corpus(self, name, dst_directory): """Downloads the corpus located at |name| to |dst_directory|.""" self._reset_git(self.config.git_store_branch) path = os.path.join(self.repo_path, _CORPUS_DIR, name) if not os.path.exists(path): logging.debug('Corpus does not exist at %s.', path) return False shutil.copytree(path, dst_directory, dirs_exist_ok=True) return True def download_build(self, name, dst_directory): """Downloads the build with |name| to |dst_directory|.""" return self._ci_filestore.download_build(name, dst_directory) def download_coverage(self, name, dst_directory): """Downloads the latest project coverage report.""" self._reset_git(self.config.git_store_branch_coverage) path = os.path.join(self.repo_path, _COVERAGE_DIR, name) if not os.path.exists(path): logging.debug('Coverage does not exist at %s.', path) return False shutil.copytree(path, dst_directory, dirs_exist_ok=True) return True ================================================ FILE: infra/cifuzz/filestore/git/git_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for git.""" import filecmp import os import tempfile import subprocess import sys import unittest from unittest import mock # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__))))) sys.path.append(INFRA_DIR) from filestore import git import test_helpers # pylint: disable=protected-access,no-self-use class GitFilestoreTest(unittest.TestCase): """Tests for GitFilestore.""" def setUp(self): self.git_dir = tempfile.TemporaryDirectory() self.addCleanup(self.git_dir.cleanup) self.local_dir = tempfile.TemporaryDirectory() self.addCleanup(self.local_dir.cleanup) self.download_dir = tempfile.TemporaryDirectory() self.addCleanup(self.download_dir.cleanup) with open(os.path.join(self.local_dir.name, 'a'), 'w') as handle: handle.write('') os.makedirs(os.path.join(self.local_dir.name, 'b')) with open(os.path.join(self.local_dir.name, 'b', 'c'), 'w') as handle: handle.write('') self.git_repo = git.git_runner(self.git_dir.name) self.git_repo('init', '--bare') self.config = test_helpers.create_run_config( git_store_repo='file://' + self.git_dir.name, git_store_branch='main', git_store_branch_coverage='cov-branch') self.mock_ci_filestore = mock.MagicMock() self.git_store = git.GitFilestore(self.config, self.mock_ci_filestore) def assert_dirs_same(self, first, second): """Asserts two dirs are the same.""" dcmp = filecmp.dircmp(first, second) if dcmp.diff_files or dcmp.left_only or dcmp.right_only: return False return all( self.assert_dirs_same(os.path.join(first, subdir), os.path.join(second, subdir)) for subdir in dcmp.common_dirs) def get_repo_filelist(self, branch): """Get files in repo.""" return subprocess.check_output([ 'git', '-C', self.git_dir.name, 'ls-tree', '-r', '--name-only', branch ]).decode().splitlines() def test_upload_download_corpus(self): """Tests uploading and downloading corpus.""" self.git_store.upload_corpus('target', self.local_dir.name) self.git_store.download_corpus('target', self.download_dir.name) self.assert_dirs_same(self.local_dir.name, self.download_dir.name) self.assertCountEqual([ 'corpus/target/a', 'corpus/target/b/c', ], self.get_repo_filelist('main')) def test_upload_download_coverage(self): """Tests uploading and downloading corpus.""" self.git_store.upload_coverage('latest', self.local_dir.name) self.git_store.download_coverage('latest', self.download_dir.name) self.assert_dirs_same(self.local_dir.name, self.download_dir.name) self.assertCountEqual([ 'coverage/latest/a', 'coverage/latest/b/c', ], self.get_repo_filelist('cov-branch')) def test_upload_crashes(self): """Tests uploading crashes.""" self.git_store.upload_crashes('current', self.local_dir.name) self.mock_ci_filestore.upload_crashes.assert_called_with( 'current', self.local_dir.name) def test_upload_build(self): """Tests uploading build.""" self.git_store.upload_build('sanitizer', self.local_dir.name) self.mock_ci_filestore.upload_build.assert_called_with( 'sanitizer', self.local_dir.name) def test_download_build(self): """Tests downloading build.""" self.git_store.download_build('sanitizer', self.download_dir.name) self.mock_ci_filestore.download_build.assert_called_with( 'sanitizer', self.download_dir.name) ================================================ FILE: infra/cifuzz/filestore/github_actions/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Implementation of a filestore using Github actions artifacts.""" import logging import os import shutil import sys import tarfile import tempfile # pylint: disable=wrong-import-position,import-error INFRA_DIR = os.path.abspath( os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir, os.path.pardir)) sys.path.append(INFRA_DIR) OSS_FUZZ_ROOT_DIR = os.path.dirname(INFRA_DIR) import utils import http_utils import filestore from filestore.github_actions import github_api UPLOAD_JS = os.path.join(os.path.dirname(__file__), 'upload.js') def tar_directory(directory, archive_path): """Tars a |directory| and stores archive at |archive_path|. |archive_path| must end in .tar""" assert archive_path.endswith('.tar') # Do this because make_archive will append the extension to archive_path. archive_path = os.path.splitext(archive_path)[0] root_directory = os.path.abspath(directory) shutil.make_archive(archive_path, 'tar', root_dir=root_directory, base_dir='./') class GithubActionsFilestore(filestore.BaseFilestore): """Implementation of BaseFilestore using Github actions artifacts. Relies on github_actions_toolkit for using the GitHub actions API and the github_api module for using GitHub's standard API. We need to use both because the GitHub actions API is the only way to upload an artifact but it does not support downloading artifacts from other runs. The standard GitHub API does support this however.""" ARTIFACT_PREFIX = 'cifuzz-' BUILD_PREFIX = 'build-' CRASHES_PREFIX = 'crashes-' CORPUS_PREFIX = 'corpus-' COVERAGE_PREFIX = 'coverage-' def __init__(self, config): super().__init__(config) self.github_api_http_headers = github_api.get_http_auth_headers(config) def _get_artifact_name(self, name): """Returns |name| prefixed with |self.ARITFACT_PREFIX| if it isn't already prefixed. Otherwise returns |name|.""" if name.startswith(self.ARTIFACT_PREFIX): return name return f'{self.ARTIFACT_PREFIX}{name}' def _upload_directory(self, name, directory): # pylint: disable=no-self-use """Uploads |directory| as artifact with |name|.""" name = self._get_artifact_name(name) with tempfile.TemporaryDirectory() as temp_dir: archive_path = os.path.join(temp_dir, name + '.tar') tar_directory(directory, archive_path) _raw_upload_directory(name, temp_dir) def upload_crashes(self, name, directory): """Uploads the crashes at |directory| to |name|.""" return _raw_upload_directory(self.CRASHES_PREFIX + name, directory) def upload_corpus(self, name, directory, replace=False): """Uploads the corpus at |directory| to |name|.""" # Not applicable as the the entire corpus is uploaded under a single # artifact name. del replace return self._upload_directory(self.CORPUS_PREFIX + name, directory) def upload_build(self, name, directory): """Uploads the build at |directory| to |name|.""" return self._upload_directory(self.BUILD_PREFIX + name, directory) def upload_coverage(self, name, directory): """Uploads the coverage report at |directory| to |name|.""" return self._upload_directory(self.COVERAGE_PREFIX + name, directory) def download_corpus(self, name, dst_directory): # pylint: disable=unused-argument,no-self-use """Downloads the corpus located at |name| to |dst_directory|.""" return self._download_artifact(self.CORPUS_PREFIX + name, dst_directory) def _find_artifact(self, name): """Finds an artifact using the GitHub API and returns it.""" logging.debug('Listing artifacts.') artifacts = self._list_artifacts() artifact = github_api.find_artifact(name, artifacts) logging.debug('Artifact: %s.', artifact) return artifact def _download_artifact(self, name, dst_directory): """Downloads artifact with |name| to |dst_directory|. Returns True on success.""" name = self._get_artifact_name(name) with tempfile.TemporaryDirectory() as temp_dir: if not self._raw_download_artifact(name, temp_dir): logging.warning('Could not download artifact: %s.', name) return False artifact_tarfile_path = os.path.join(temp_dir, name + '.tar') if not os.path.exists(artifact_tarfile_path): logging.error('Artifact zip did not contain a tarfile.') return False # TODO(jonathanmetzman): Replace this with archive.unpack from # libClusterFuzz so we can avoid path traversal issues. with tarfile.TarFile(artifact_tarfile_path) as artifact_tarfile: artifact_tarfile.extractall(dst_directory) return True def _raw_download_artifact(self, name, dst_directory): """Downloads the artifact with |name| to |dst_directory|. Returns True on success. Does not do any untarring or adding prefix to |name|.""" artifact = self._find_artifact(name) if not artifact: logging.warning('Could not find artifact: %s.', name) return False download_url = artifact['archive_download_url'] return http_utils.download_and_unpack_zip( download_url, dst_directory, headers=self.github_api_http_headers) def _list_artifacts(self): """Returns a list of artifacts.""" return github_api.list_artifacts(self.config.project_repo_owner, self.config.project_repo_name, self.github_api_http_headers) def download_build(self, name, dst_directory): """Downloads the build with name |name| to |dst_directory|.""" return self._download_artifact(self.BUILD_PREFIX + name, dst_directory) def download_coverage(self, name, dst_directory): """Downloads the latest project coverage report.""" return self._download_artifact(self.COVERAGE_PREFIX + name, dst_directory) def _upload_artifact_with_upload_js(name, artifact_paths, directory): """Uploads the artifacts in |artifact_paths| that are located in |directory| to |name|, using the upload.js script.""" command = [UPLOAD_JS, name, directory] + artifact_paths _, _, retcode = utils.execute(command, location=OSS_FUZZ_ROOT_DIR) return retcode == 0 def _raw_upload_directory(name, directory): """Uploads the artifacts located in |directory| to |name|. Does not do any tarring or adding prefixes to |name|.""" # Get file paths. artifact_paths = [] for root, _, curr_file_paths in os.walk(directory): for file_path in curr_file_paths: artifact_paths.append(os.path.join(root, file_path)) logging.debug('Artifact paths: %s.', artifact_paths) return _upload_artifact_with_upload_js(name, artifact_paths, directory) ================================================ FILE: infra/cifuzz/filestore/github_actions/github_actions_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for github_actions.""" import os import shutil import sys import tarfile import tempfile import unittest from unittest import mock # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(INFRA_DIR) from filestore import github_actions import test_helpers # pylint: disable=protected-access,no-self-use class GithubActionsFilestoreTest(unittest.TestCase): """Tests for GithubActionsFilestore.""" @mock.patch('platform_config.github._get_event_data', return_value={}) def setUp(self, _): # pylint: disable=arguments-differ test_helpers.patch_environ(self) self.token = 'example githubtoken' self.owner = 'exampleowner' self.repo = 'examplerepo' os.environ['GITHUB_REPOSITORY'] = f'{self.owner}/{self.repo}' os.environ['GITHUB_EVENT_PATH'] = '/fake' os.environ['CFL_PLATFORM'] = 'github' os.environ['GITHUB_WORKSPACE'] = '/workspace' self.config = test_helpers.create_run_config(token=self.token) self.local_dir = tempfile.mkdtemp() self.testcase = os.path.join(self.local_dir, 'testcase') def tearDown(self): shutil.rmtree(self.local_dir) def _get_expected_http_headers(self): return { 'Authorization': f'token {self.token}', 'Accept': 'application/vnd.github.v3+json', } @mock.patch('filestore.github_actions.github_api.list_artifacts') def test_list_artifacts(self, mock_list_artifacts): """Tests that _list_artifacts works as intended.""" filestore = github_actions.GithubActionsFilestore(self.config) filestore._list_artifacts() mock_list_artifacts.assert_called_with(self.owner, self.repo, self._get_expected_http_headers()) @mock.patch('logging.warning') @mock.patch('filestore.github_actions.GithubActionsFilestore._list_artifacts', return_value=None) @mock.patch('filestore.github_actions.github_api.find_artifact', return_value=None) def test_download_build_no_artifact(self, _, __, mock_warning): """Tests that download_build returns None and doesn't exception when find_artifact can't find an artifact.""" filestore = github_actions.GithubActionsFilestore(self.config) name = 'name' build_dir = 'build-dir' self.assertFalse(filestore.download_build(name, build_dir)) mock_warning.assert_called_with('Could not download artifact: %s.', 'cifuzz-build-' + name) @mock.patch('logging.warning') @mock.patch('filestore.github_actions.GithubActionsFilestore._list_artifacts', return_value=None) @mock.patch('filestore.github_actions.github_api.find_artifact', return_value=None) def test_download_corpus_no_artifact(self, _, __, mock_warning): """Tests that download_corpus_build returns None and doesn't exception when find_artifact can't find an artifact.""" filestore = github_actions.GithubActionsFilestore(self.config) name = 'name' dst_dir = self.local_dir self.assertFalse(filestore.download_corpus(name, dst_dir)) mock_warning.assert_called_with('Could not download artifact: %s.', 'cifuzz-corpus-' + name) @mock.patch('filestore.github_actions.tar_directory') @mock.patch('filestore.github_actions._upload_artifact_with_upload_js') def test_upload_corpus(self, mock_upload_artifact, mock_tar_directory): """Test uploading corpus.""" self._create_local_dir() def mock_tar_directory_impl(_, archive_path): with open(archive_path, 'w') as f: pass mock_tar_directory.side_effect = mock_tar_directory_impl filestore = github_actions.GithubActionsFilestore(self.config) filestore.upload_corpus('target', self.local_dir) self.assert_upload(mock_upload_artifact, mock_tar_directory, 'corpus-target') @mock.patch('filestore.github_actions._upload_artifact_with_upload_js') def test_upload_crashes(self, mock_upload_artifact): """Test uploading crashes.""" self._create_local_dir() filestore = github_actions.GithubActionsFilestore(self.config) filestore.upload_crashes('current', self.local_dir) mock_upload_artifact.assert_has_calls([ mock.call('crashes-current', [f'{self.local_dir}/testcase'], self.local_dir) ]) @mock.patch('filestore.github_actions.tar_directory') @mock.patch('filestore.github_actions._upload_artifact_with_upload_js') def test_upload_build(self, mock_upload_artifact, mock_tar_directory): """Test uploading build.""" self._create_local_dir() def mock_tar_directory_impl(_, archive_path): with open(archive_path, 'w') as f: pass mock_tar_directory.side_effect = mock_tar_directory_impl filestore = github_actions.GithubActionsFilestore(self.config) filestore.upload_build('sanitizer', self.local_dir) self.assert_upload(mock_upload_artifact, mock_tar_directory, 'build-sanitizer') @mock.patch('filestore.github_actions.tar_directory') @mock.patch('filestore.github_actions._upload_artifact_with_upload_js') def test_upload_coverage(self, mock_upload_artifact, mock_tar_directory): """Test uploading coverage.""" self._create_local_dir() def mock_tar_directory_impl(_, archive_path): with open(archive_path, 'w') as f: pass mock_tar_directory.side_effect = mock_tar_directory_impl filestore = github_actions.GithubActionsFilestore(self.config) filestore.upload_coverage('latest', self.local_dir) self.assert_upload(mock_upload_artifact, mock_tar_directory, 'coverage-latest') def assert_upload(self, mock_upload_artifact, mock_tar_directory, expected_artifact_name): """Tests that upload_directory invokes tar_directory and artifact_client.upload_artifact properly.""" # Don't assert what second argument will be since it's a temporary # directory. self.assertEqual(mock_tar_directory.call_args_list[0][0][0], self.local_dir) # Don't assert what second and third arguments will be since they are # temporary directories. expected_artifact_name = 'cifuzz-' + expected_artifact_name self.assertEqual(mock_upload_artifact.call_args_list[0][0][0], expected_artifact_name) # Assert artifacts list contains one tarfile. artifacts_list = mock_upload_artifact.call_args_list[0][0][1] self.assertEqual(len(artifacts_list), 1) self.assertEqual(os.path.basename(artifacts_list[0]), expected_artifact_name + '.tar') def _create_local_dir(self): """Create fake testcase.""" with open(self.testcase, 'w') as f: f.write('hi') @mock.patch('filestore.github_actions.GithubActionsFilestore._find_artifact') @mock.patch('http_utils.download_and_unpack_zip') def test_download_artifact(self, mock_download_and_unpack_zip, mock_find_artifact): """Tests that _download_artifact works as intended.""" artifact_download_url = 'http://example.com/download' artifact_listing = { 'expired': False, 'name': 'corpus', 'archive_download_url': artifact_download_url } mock_find_artifact.return_value = artifact_listing self._create_local_dir() with tempfile.TemporaryDirectory() as temp_dir: # Create a tarball. archive_path = os.path.join(temp_dir, 'cifuzz-corpus.tar') github_actions.tar_directory(self.local_dir, archive_path) artifact_download_dst_dir = os.path.join(temp_dir, 'dst') os.mkdir(artifact_download_dst_dir) def mock_download_and_unpack_zip_impl(url, download_artifact_temp_dir, headers): self.assertEqual(url, artifact_download_url) self.assertEqual(headers, self._get_expected_http_headers()) shutil.copy( archive_path, os.path.join(download_artifact_temp_dir, os.path.basename(archive_path))) return True mock_download_and_unpack_zip.side_effect = ( mock_download_and_unpack_zip_impl) filestore = github_actions.GithubActionsFilestore(self.config) self.assertTrue( filestore._download_artifact('corpus', artifact_download_dst_dir)) mock_find_artifact.assert_called_with('cifuzz-corpus') self.assertTrue( os.path.exists( os.path.join(artifact_download_dst_dir, os.path.basename(self.testcase)))) @mock.patch('filestore.github_actions.github_api.list_artifacts') def test_find_artifact(self, mock_list_artifacts): """Tests that _find_artifact works as intended.""" artifact_listing_1 = { 'expired': False, 'name': 'other', 'archive_download_url': 'http://download1' } artifact_listing_2 = { 'expired': False, 'name': 'artifact', 'archive_download_url': 'http://download2' } artifact_listing_3 = { 'expired': True, 'name': 'artifact', 'archive_download_url': 'http://download3' } artifact_listing_4 = { 'expired': False, 'name': 'artifact', 'archive_download_url': 'http://download4' } artifacts = [ artifact_listing_1, artifact_listing_2, artifact_listing_3, artifact_listing_4 ] mock_list_artifacts.return_value = artifacts filestore = github_actions.GithubActionsFilestore(self.config) # Test that find_artifact will return the most recent unexpired artifact # with the correct name. self.assertEqual(filestore._find_artifact('artifact'), artifact_listing_2) mock_list_artifacts.assert_called_with(self.owner, self.repo, self._get_expected_http_headers()) class TarDirectoryTest(unittest.TestCase): """Tests for tar_directory.""" def test_tar_directory(self): """Tests that tar_directory writes the archive to the correct location and archives properly.""" with tempfile.TemporaryDirectory() as temp_dir: archive_path = os.path.join(temp_dir, 'myarchive.tar') archived_dir = os.path.join(temp_dir, 'toarchive') os.mkdir(archived_dir) archived_filename = 'file1' archived_file_path = os.path.join(archived_dir, archived_filename) with open(archived_file_path, 'w') as file_handle: file_handle.write('hi') github_actions.tar_directory(archived_dir, archive_path) self.assertTrue(os.path.exists(archive_path)) # Now check it archives correctly. unpacked_directory = os.path.join(temp_dir, 'unpacked') with tarfile.TarFile(archive_path) as artifact_tarfile: artifact_tarfile.extractall(unpacked_directory) unpacked_archived_file_path = os.path.join(unpacked_directory, archived_filename) self.assertTrue(os.path.exists(unpacked_archived_file_path)) ================================================ FILE: infra/cifuzz/filestore/github_actions/github_api.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for dealing with the GitHub API. This is different from github_actions_toolkit which only deals with the actions API. We need to use both.""" import logging import os import sys import requests import filestore # pylint: disable=wrong-import-position,import-error sys.path.append( os.path.join(__file__, os.path.pardir, os.path.pardir, os.path.pardir, os.path.pardir)) import retry _MAX_ITEMS_PER_PAGE = 100 _GET_ATTEMPTS = 3 _GET_BACKOFF = 1 def get_http_auth_headers(config): """Returns HTTP headers for authentication to the API.""" authorization = f'token {config.token}' return { 'Authorization': authorization, 'Accept': 'application/vnd.github.v3+json' } def _get_artifacts_list_api_url(repo_owner, repo_name): """Returns the artifacts_api_url for |repo_name| owned by |repo_owner|.""" github_api_url = os.getenv('GITHUB_API_URL', 'https://api.github.com') return (f'{github_api_url}/repos/{repo_owner}/' f'{repo_name}/actions/artifacts') @retry.wrap(_GET_ATTEMPTS, _GET_BACKOFF) def _do_get_request(*args, **kwargs): """Wrapped version of requests.get that does retries.""" return requests.get(*args, **kwargs) def _get_items(url, headers): """Generator that gets and yields items from a GitHub API endpoint (specified by |URL|) sending |headers| with the get request.""" # Github API response pages are 1-indexed. page_counter = 1 # Set to infinity so we run loop at least once. total_num_items = float('inf') item_num = 0 while item_num < total_num_items: params = {'per_page': _MAX_ITEMS_PER_PAGE, 'page': str(page_counter)} response = _do_get_request(url, params=params, headers=headers) response_json = response.json() if not response.status_code == 200: # Check that request was successful. logging.error('Request to %s failed. Code: %d. Response: %s', response.request.url, response.status_code, response_json) raise filestore.FilestoreError('Github API request failed.') if total_num_items == float('inf'): # Set proper total_num_items total_num_items = response_json['total_count'] # Get the key for the items we are after. keys = [key for key in response_json.keys() if key != 'total_count'] assert len(keys) == 1, keys items_key = keys[0] for item in response_json[items_key]: yield item item_num += 1 page_counter += 1 def find_artifact(artifact_name, artifacts): """Find the artifact with the name |artifact_name| in |artifacts|.""" for artifact in artifacts: # TODO(metzman): Handle multiple by making sure we download the latest. if artifact['name'] == artifact_name and not artifact['expired']: return artifact return None def list_artifacts(owner, repo, headers): """Returns a generator of all the artifacts for |owner|/|repo|.""" url = _get_artifacts_list_api_url(owner, repo) logging.debug('Getting artifacts from: %s', url) return _get_items(url, headers) ================================================ FILE: infra/cifuzz/filestore/github_actions/github_api_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for github_api.""" import os import sys import unittest # pylint: disable=wrong-import-position,import-error sys.path.append( os.path.abspath( os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir, os.path.pardir))) from filestore.github_actions import github_api import test_helpers class GetHttpAuthHeaders(unittest.TestCase): """Tests for get_http_auth_headers.""" def test_get_http_auth_headers(self): """Tests that get_http_auth_headers returns the correct result.""" token = 'example githubtoken' run_config = test_helpers.create_run_config(token=token) expected_headers = { 'Authorization': f'token {token}', 'Accept': 'application/vnd.github.v3+json', } self.assertEqual(expected_headers, github_api.get_http_auth_headers(run_config)) ================================================ FILE: infra/cifuzz/filestore/github_actions/upload.js ================================================ #!/usr/bin/env node // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Script for uploading an artifact. Returns 0 on success. // Usage: upload.js ... const fs = require('fs'); const { DefaultArtifactClient } = require('@actions/artifact'); const artifactClient = new DefaultArtifactClient(); const artifactName = process.argv[2]; const rootDirectory = process.argv[3] const files = process.argv.slice(4); const options = { continueOnError: true }; async function uploadArtifact() { try { const uploadResult = await artifactClient.uploadArtifact(artifactName, files, rootDirectory, options); console.log(uploadResult); if (uploadResult.failedItems.length > 0) { return 1; } return 0; } catch (error) { console.error('Error uploading artifact:', error); return 1; } } uploadArtifact().then(exitCode => { process.exit(exitCode); }); ================================================ FILE: infra/cifuzz/filestore/gitlab/__init__.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """GitLab filestore implementation.""" import logging import json import os import shutil import tempfile import filestore import http_utils # pylint: disable=no-self-use,unused-argument class GitlabFilestore(filestore.BaseFilestore): """Implementation of BaseFilestore using GitLab. Needs a cache to upload and download builds. Needs a git repository for corpus and coverage. """ BUILD_PREFIX = 'build-' CORPUS_PREFIX = 'corpus-' COVERAGE_PREFIX = 'coverage-' CRASHES_PREFIX = 'crashes-' def __init__(self, config): super().__init__(config) self.artifacts_dir = self.config.platform_conf.artifacts_dir self.cache_dir = self.config.platform_conf.cache_dir if self.config.git_store_repo: self.git_filestore = filestore.git.GitFilestore(config, None) else: self.git_filestore = None def upload_crashes(self, name, directory): """GitLab artifacts implementation of upload_crashes.""" # Upload crashes as job artifacts. if os.listdir(directory): dest_dir_artifacts = os.path.join(self.config.project_src_path, self.artifacts_dir, self.CRASHES_PREFIX + name) logging.info('Uploading artifacts to %s.', dest_dir_artifacts) shutil.copytree(directory, dest_dir_artifacts) def upload_corpus(self, name, directory, replace=False): """GitLab artifacts implementation of upload_corpus.""" # Use the git filestore if any. if self.git_filestore: self.git_filestore.upload_corpus(name, directory, replace) return # Fall back to cache. dest_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.CORPUS_PREFIX + name) logging.info('Copying from %s to cache %s.', directory, dest_dir_cache) # Remove previous corpus from cache if any. shutil.rmtree(dest_dir_cache, ignore_errors=True) shutil.copytree(directory, dest_dir_cache, dirs_exist_ok=True) def upload_build(self, name, directory): """GitLab artifacts implementation of upload_build.""" # Puts build into the cache. dest_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.BUILD_PREFIX + name) logging.info('Copying from %s to cache %s.', directory, dest_dir_cache) shutil.copytree(directory, dest_dir_cache, dirs_exist_ok=True) def upload_coverage(self, name, directory): """GitLab artifacts implementation of upload_coverage.""" # Use the git filestore. if self.git_filestore: self.git_filestore.upload_coverage(name, directory) return # Fall back to cache. dest_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.COVERAGE_PREFIX + name) logging.info('Copying from %s to cache %s.', directory, dest_dir_cache) shutil.copytree(directory, dest_dir_cache, dirs_exist_ok=True) # And also updates coverage reports as artifacts # as it should not be too big. dest_dir_artifacts = os.path.join(self.config.project_src_path, self.artifacts_dir, self.COVERAGE_PREFIX + name) logging.info('Uploading artifacts to %s.', dest_dir_artifacts) shutil.copytree(directory, dest_dir_artifacts) def _copy_from_cache(self, src_dir_cache, dst_directory): if not os.path.exists(src_dir_cache): logging.info('Cache %s does not exist.', src_dir_cache) return False logging.info('Copying %s from cache to %s.', src_dir_cache, dst_directory) shutil.copytree(src_dir_cache, dst_directory, dirs_exist_ok=True) return True def download_corpus(self, name, dst_directory): """GitLab artifacts implementation of download_corpus.""" # Use the git filestore if any. if self.git_filestore: self.git_filestore.download_corpus(name, dst_directory) return # Fall back to cache. src_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.CORPUS_PREFIX + name) self._copy_from_cache(src_dir_cache, dst_directory) def download_build(self, name, dst_directory): """GitLab artifacts implementation of download_build.""" # Gets build from the cache. src_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.BUILD_PREFIX + name) return self._copy_from_cache(src_dir_cache, dst_directory) def download_coverage(self, name, dst_directory): """GitLab artifacts implementation of download_coverage.""" # Use the git filestore if any. if self.git_filestore: return self.git_filestore.download_coverage(name, dst_directory) # Fall back to cache. src_dir_cache = os.path.join(self.config.project_src_path, self.cache_dir, self.COVERAGE_PREFIX + name) return self._copy_from_cache(src_dir_cache, dst_directory) ================================================ FILE: infra/cifuzz/filestore/gsutil/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Filestore implementation using gsutil.""" import logging import os import posixpath import subprocess import sys # pylint: disable=wrong-import-position,import-error sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir, os.pardir)) import filestore import utils def _gsutil_execute(*args, parallel=True): """Executes a gsutil command, passing |*args| to gsutil and returns the stdout, stderr and returncode. Exceptions on failure.""" command = ['gsutil'] if parallel: command.append('-m') command += list(args) logging.info('Executing gsutil command: %s', command) return utils.execute(command, check_result=True) def _rsync(src, dst, recursive=True, delete=False): """Executes gsutil rsync on |src| and |dst|""" args = ['rsync'] if recursive: args.append('-r') if delete: args.append('-d') args += [src, dst] return _gsutil_execute(*args) class GSUtilFilestore(filestore.BaseFilestore): """Filestore implementation using gsutil.""" BUILD_DIR = 'build' CRASHES_DIR = 'crashes' CORPUS_DIR = 'corpus' COVERAGE_DIR = 'coverage' def __init__(self, config): super().__init__(config) self._cloud_bucket = self.config.cloud_bucket def _get_gsutil_url(self, name, prefix_dir): """Returns the gsutil URL for |name| and |prefix_dir|.""" if not prefix_dir: return posixpath.join(self._cloud_bucket, name) return posixpath.join(self._cloud_bucket, prefix_dir, name) def _upload_directory(self, name, directory, prefix, delete=False): gsutil_url = self._get_gsutil_url(name, prefix) return _rsync(directory, gsutil_url, delete=delete) def _download_directory(self, name, dst_directory, prefix): gsutil_url = self._get_gsutil_url(name, prefix) return _rsync(gsutil_url, dst_directory) def upload_crashes(self, name, directory): """Uploads the crashes at |directory| to |name|.""" # Name is going to be "current". I don't know if this makes sense outside of # GitHub Actions. gsutil_url = self._get_gsutil_url(name, self.CRASHES_DIR) logging.info('Uploading crashes to %s.', gsutil_url) return _rsync(directory, gsutil_url) def upload_corpus(self, name, directory, replace=False): """Uploads the crashes at |directory| to |name|.""" return self._upload_directory(name, directory, self.CORPUS_DIR, delete=replace) def upload_build(self, name, directory): """Uploads the build located at |directory| to |name|.""" return self._upload_directory(name, directory, self.BUILD_DIR) def upload_coverage(self, name, directory): """Uploads the coverage report at |directory| to |name|.""" return self._upload_directory(name, directory, self.COVERAGE_DIR) def download_corpus(self, name, dst_directory): """Downloads the corpus located at |name| to |dst_directory|.""" return self._download_directory(name, dst_directory, self.CORPUS_DIR) def download_build(self, name, dst_directory): """Downloads the build with |name| to |dst_directory|.""" return self._download_directory(name, dst_directory, self.BUILD_DIR) def download_coverage(self, name, dst_directory): """Downloads the latest project coverage report.""" return self._download_directory(name, dst_directory, self.COVERAGE_DIR) ================================================ FILE: infra/cifuzz/filestore/no_filestore/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Empty filestore implementation for platforms that haven't implemented it.""" import logging import filestore # pylint:disable=no-self-use,unused-argument class NoFilestore(filestore.BaseFilestore): """Empty Filestore implementation.""" def upload_crashes(self, name, directory): """Noop implementation of upload_crashes.""" logging.info('Not uploading crashes because no Filestore.') def upload_corpus(self, name, directory, replace=False): """Noop implementation of upload_corpus.""" logging.info('Not uploading corpus because no Filestore.') def upload_build(self, name, directory): """Noop implementation of upload_build.""" logging.info('Not uploading build because no Filestore.') def upload_coverage(self, name, directory): """Noop implementation of upload_coverage.""" logging.info('Not uploading coverage because no Filestore.') def download_corpus(self, name, dst_directory): """Noop implementation of download_corpus.""" logging.info('Not downloading corpus because no Filestore.') def download_build(self, name, dst_directory): """Noop implementation of download_build.""" logging.info('Not downloading build because no Filestore.') def download_coverage(self, name, dst_directory): """Noop implementation of download_coverage.""" logging.info('Not downloading coverage because no Filestore.') ================================================ FILE: infra/cifuzz/filestore_utils.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """External filestore interface. Cannot be depended on by filestore code.""" import filestore import filestore.filesystem import filestore.git import filestore.github_actions import filestore.gsutil import filestore.no_filestore import filestore.gitlab FILESTORE_MAPPING = { 'filesystem': filestore.filesystem.FilesystemFilestore, 'gsutil': filestore.gsutil.GSUtilFilestore, 'github-actions': filestore.github_actions.GithubActionsFilestore, 'git': filestore.git.GitFilestore, # TODO(metzman): Change to "no-filestore" 'no_filestore': filestore.no_filestore.NoFilestore, 'gitlab': filestore.gitlab.GitlabFilestore, } def get_filestore(config): """Returns the correct filestore object based on the platform in |config|. Raises an exception if there is no correct filestore for the platform.""" if config.platform == config.Platform.EXTERNAL_GITHUB: ci_filestore = filestore.github_actions.GithubActionsFilestore(config) if not config.git_store_repo: return ci_filestore return filestore.git.GitFilestore(config, ci_filestore) filestore_cls = FILESTORE_MAPPING.get(config.filestore) if filestore_cls is None: raise filestore.FilestoreError( f'Filestore: {config.filestore} doesn\'t exist.') return filestore_cls(config) ================================================ FILE: infra/cifuzz/filestore_utils_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for filestore_utils.""" import unittest from unittest import mock import parameterized import platform_config import filestore from filestore import github_actions import filestore_utils import test_helpers class GetFilestoreTest(unittest.TestCase): """Tests for get_filestore.""" @parameterized.parameterized.expand([ ({ 'cfl_platform': 'github', }, github_actions.GithubActionsFilestore), ]) def test_get_filestore(self, config_kwargs, filestore_cls): """Tests that get_filestore returns the right filestore given a certain platform.""" run_config = test_helpers.create_run_config(**config_kwargs) filestore_impl = filestore_utils.get_filestore(run_config) self.assertIsInstance(filestore_impl, filestore_cls) @mock.patch('config_utils.BaseConfig.platform', return_value='other') @mock.patch('config_utils._get_platform_config', return_value=platform_config.BasePlatformConfig()) def test_get_filestore_unsupported_platform(self, _, __): """Tests that get_filestore exceptions given a platform it doesn't support.""" run_config = test_helpers.create_run_config() with self.assertRaises(filestore.FilestoreError): filestore_utils.get_filestore(run_config) ================================================ FILE: infra/cifuzz/fuzz_target.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A module to handle running a fuzz target for a specified amount of time.""" import collections import logging import multiprocessing import os import shutil import stat import tempfile from typing import Optional import clusterfuzz.environment import clusterfuzz.fuzz import config_utils import logs logs.init() # Use len_control=0 since we don't have enough time fuzzing for len_control to # make sense (probably). LIBFUZZER_OPTIONS_BATCH = ['-len_control=0'] # Use a fixed seed for determinism for code change fuzzing. LIBFUZZER_OPTIONS_CODE_CHANGE = LIBFUZZER_OPTIONS_BATCH + ['-seed=1337'] LIBFUZZER_OPTIONS_NO_REPORT_OOM = ['-rss_limit_mb=0'] # The number of reproduce attempts for a crash. REPRODUCE_ATTEMPTS = 10 DEFAULT_REPRODUCE_TIME_SECONDS = 30 PER_LANGUAGE_REPRODUCE_TIMEOUTS = { 'python': 30 * 4 # Python takes a bit longer on startup. } MINIMIZE_TIME_SECONDS = 60 * 4 # Seconds on top of duration until a timeout error is raised. BUFFER_TIME = 10 # Log message if we can't check if crash reproduces on an recent build. COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE = ( 'Could not run previous build of target to determine if this code change ' '(pr/commit) introduced crash. Assuming crash was newly introduced.') FuzzResult = collections.namedtuple('FuzzResult', ['testcase', 'stacktrace', 'corpus_path']) def get_libfuzzer_parallel_options(option): """Returns a list containing options to pass to libFuzzer to fuzz using all available or the specified number of cores.""" if option == 'true' or (isinstance(option, bool) and option == True): cpu_count = str(multiprocessing.cpu_count()) else: cpu_count = option return [f'-jobs={cpu_count}', f'-workers={cpu_count}'] class ReproduceError(Exception): """Error for when we can't attempt to reproduce a crash.""" def get_fuzz_target_corpus_dir(workspace, target_name): """Returns the directory for storing |target_name|'s corpus in |workspace|.""" return os.path.join(workspace.corpora, target_name) def get_fuzz_target_pruned_corpus_dir(workspace, target_name): """Returns the directory for storing |target_name|'s puned corpus in |workspace|.""" return os.path.join(workspace.pruned_corpora, target_name) class FuzzTarget: # pylint: disable=too-many-instance-attributes """A class to manage a single fuzz target. Attributes: target_name: The name of the fuzz target. duration: The length of time in seconds that the target should run. target_path: The location of the fuzz target binary. workspace: The workspace for storing things related to fuzzing. """ # pylint: disable=too-many-arguments def __init__(self, target_path, duration, workspace, clusterfuzz_deployment, config): """Represents a single fuzz target. Args: target_path: The location of the fuzz target binary. duration: The length of time in seconds the target should run. workspace: The path used for storing things needed for fuzzing. clusterfuzz_deployment: The object representing the ClusterFuzz deployment. config: The config of this project. """ self.target_path = target_path self.target_name = os.path.basename(self.target_path) self.duration = int(duration) self.workspace = workspace self.clusterfuzz_deployment = clusterfuzz_deployment self.config = config self.latest_corpus_path = get_fuzz_target_corpus_dir( self.workspace, self.target_name) os.makedirs(self.latest_corpus_path, exist_ok=True) self.pruned_corpus_path = get_fuzz_target_pruned_corpus_dir( self.workspace, self.target_name) os.makedirs(self.pruned_corpus_path, exist_ok=True) def _download_corpus(self): """Downloads the corpus for the target from ClusterFuzz and returns the path to the corpus. An empty directory is provided if the corpus can't be downloaded or is empty.""" self.clusterfuzz_deployment.download_corpus(self.target_name, self.latest_corpus_path) return self.latest_corpus_path def _target_artifact_path(self): """Target artifact path.""" artifact_path = os.path.join(self.workspace.artifacts, self.target_name, self.config.sanitizer) os.makedirs(artifact_path, exist_ok=True) return artifact_path def _save_crash(self, crash): """Add stacktraces to crashes.""" target_reproducer_path = os.path.join(self._target_artifact_path(), os.path.basename(crash.input_path)) shutil.copy(crash.input_path, target_reproducer_path) bug_summary_artifact_path = target_reproducer_path + '.summary' with open(bug_summary_artifact_path, 'w') as handle: handle.write(crash.stacktrace) # Set permissions of testcase to be the same as summary so that we're sure # it can be read by necessary users. permissions_mode = os.stat(bug_summary_artifact_path).st_mode os.chmod(target_reproducer_path, permissions_mode & 0o777) return target_reproducer_path def prune(self): """Prunes the corpus and returns the result.""" self._download_corpus() with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE, self.config.sanitizer, self.target_path): engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE) result = engine_impl.minimize_corpus(self.target_path, [], [self.latest_corpus_path], self.pruned_corpus_path, self._target_artifact_path(), self.duration) print(result.logs) return FuzzResult(None, result.logs, self.pruned_corpus_path) def fuzz(self, batch=False) -> Optional[FuzzResult]: """Starts the fuzz target run for the length of time specified by duration. Returns: FuzzResult namedtuple with stacktrace and testcase if applicable. """ logging.info('Running fuzzer: %s.', self.target_name) self._download_corpus() corpus_path = self.latest_corpus_path logging.info('Starting fuzzing') with tempfile.TemporaryDirectory() as artifacts_dir: with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE, self.config.sanitizer, self.target_path) as env: engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE) options = engine_impl.prepare(corpus_path, env.target_path, env.build_dir) options.merge_back_new_testcases = False options.analyze_dictionary = False if batch: options.arguments.extend(LIBFUZZER_OPTIONS_BATCH) else: options.arguments.extend(LIBFUZZER_OPTIONS_CODE_CHANGE) if not self.config.report_ooms: options.arguments.extend(LIBFUZZER_OPTIONS_NO_REPORT_OOM) if (self.config.parallel_fuzzing == 'true' or (isinstance(self.config.parallel_fuzzing, int) and not isinstance(self.config.parallel_fuzzing, bool)) or (isinstance(self.config.parallel_fuzzing, bool) and self.config.parallel_fuzzing == True)): if self.config.sanitizer == 'memory': # TODO(https://github.com/google/oss-fuzz/issues/11915): Don't gate # this after jobs is fixed for MSAN. logging.info('Not using jobs because it breaks MSAN.') else: options.arguments.extend( get_libfuzzer_parallel_options(self.config.parallel_fuzzing)) result = engine_impl.fuzz(self.target_path, options, artifacts_dir, self.duration) print(f'Fuzzing logs:\n{result.logs}') if not result.crashes: # Libfuzzer max time was reached. logging.info('Fuzzer %s finished with no crashes discovered.', self.target_name) return FuzzResult(None, None, self.latest_corpus_path) if result.timed_out: logging.info('Not reporting crash in %s because process timed out.', self.target_name) return FuzzResult(None, None, self.latest_corpus_path) # Only report first crash. crash = result.crashes[0] logging.info('Fuzzer: %s. Detected bug.', self.target_name) is_reportable = self.is_crash_reportable(crash.input_path, crash.reproduce_args, batch=batch) if is_reportable or self.config.upload_all_crashes: logging.info('SAVING CRASH') fuzzer_logs = result.logs testcase_path = self._save_crash(crash) if is_reportable and self.config.minimize_crashes: # TODO(metzman): We don't want to minimize unreproducible crashes. # Use is_reportable to decide this even though reportable crashes # are a subset of reproducible ones. self.minimize_testcase(testcase_path) else: logging.info('NOT MINIMIZED') else: fuzzer_logs = None testcase_path = None return FuzzResult(testcase_path, fuzzer_logs, self.latest_corpus_path) def minimize_testcase(self, testcase_path): """Minimizes the testcase located at |testcase_path|.""" with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE, self.config.sanitizer, self.target_path): engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE) minimized_testcase_path = testcase_path + '-minimized' return engine_impl.minimize_testcase(self.target_path, [], testcase_path, minimized_testcase_path, max_time=MINIMIZE_TIME_SECONDS) def free_disk_if_needed(self, delete_fuzz_target=True): """Deletes things that are no longer needed from fuzzing this fuzz target to save disk space if needed.""" if not self.config.low_disk_space: logging.info('Not freeing disk space after running fuzz target.') return logging.info('Deleting corpus and seed corpus of %s to save disk.', self.target_name) # Delete the seed corpus, corpus, and fuzz target. for corpus_path in [self.latest_corpus_path, self.pruned_corpus_path]: # Use ignore_errors=True to fix # https://github.com/google/oss-fuzz/issues/5383. shutil.rmtree(corpus_path, ignore_errors=True) target_seed_corpus_path = self.target_path + '_seed_corpus.zip' if os.path.exists(target_seed_corpus_path): os.remove(target_seed_corpus_path) if delete_fuzz_target: logging.info('Deleting fuzz target: %s.', self.target_name) os.remove(self.target_path) logging.info('Done deleting.') def is_reproducible(self, testcase, target_path, reproduce_args): """Checks if the testcase reproduces. Args: testcase: The path to the testcase to be tested. target_path: The path to the fuzz target to be tested reproduce_args: The arguments to pass to the target to reproduce the crash. Returns: True if crash is reproducible and we were able to run the binary. Raises: ReproduceError if we can't attempt to reproduce the crash. """ if not os.path.exists(target_path): logging.info('Target: %s does not exist.', target_path) raise ReproduceError(f'Target {target_path} not found.') os.chmod(target_path, stat.S_IRWXO) logging.info('Trying to reproduce crash using: %s.', testcase) with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE, self.config.sanitizer, target_path): reproduce_time_seconds = PER_LANGUAGE_REPRODUCE_TIMEOUTS.get( self.config.language, DEFAULT_REPRODUCE_TIME_SECONDS) for _ in range(REPRODUCE_ATTEMPTS): engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE) try: result = engine_impl.reproduce(target_path, testcase, arguments=reproduce_args, max_time=reproduce_time_seconds) except TimeoutError as error: logging.error('%s.', error) return False if result.return_code != 0: logging.info('Reproduce command returned: %s. Reproducible on %s.', result.return_code, target_path) return True logging.info('Reproduce command returned: 0. Not reproducible on %s.', target_path) return False def is_crash_reportable(self, testcase, reproduce_args, batch=False): """Returns True if a crash is reportable. This means the crash is reproducible but not reproducible on a build from the ClusterFuzz deployment (meaning the crash was introduced by this PR/commit/code change). Args: testcase: The path to the testcase that triggered the crash. reproduce_args: The arguments to pass to the target to reproduce the crash. Returns: True if the crash was introduced by the current pull request. Raises: ReproduceError if we can't attempt to reproduce the crash on the PR build. """ if not self.is_crash_type_reportable(testcase): return False if not os.path.exists(testcase): raise ReproduceError(f'Testcase {testcase} not found.') try: reproducible_on_code_change = self.is_reproducible( testcase, self.target_path, reproduce_args) except ReproduceError as error: logging.error('Could not check for crash reproducibility.' 'Please file an issue:' 'https://github.com/google/oss-fuzz/issues/new.') raise error if not reproducible_on_code_change: logging.info('Crash is not reproducible.') return self.config.report_unreproducible_crashes logging.info('Crash is reproducible.') if batch: # We don't need to check if the crash is novel for batch fuzzing. return True return self.is_crash_novel(testcase, reproduce_args) def is_crash_type_reportable(self, testcase): """Returns True if |testcase| is an actual crash. If crash is a timeout or OOM then returns True if config says we should report those.""" # TODO(metzman): Use a less hacky method. testcase = os.path.basename(testcase) if testcase.startswith('oom-'): return self.config.report_ooms if testcase.startswith('timeout-'): return self.config.report_timeouts return True def is_crash_novel(self, testcase, reproduce_args): """Returns whether or not the crash is new. A crash is considered new if it can't be reproduced on an older ClusterFuzz build of the target.""" if not os.path.exists(testcase): raise ReproduceError('Testcase %s not found.' % testcase) clusterfuzz_build_dir = self.clusterfuzz_deployment.download_latest_build() if not clusterfuzz_build_dir: # Crash is reproducible on PR build and we can't test on a recent # ClusterFuzz/OSS-Fuzz build. logging.info(COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE) return True clusterfuzz_target_path = os.path.join(clusterfuzz_build_dir, self.target_name) try: reproducible_on_clusterfuzz_build = self.is_reproducible( testcase, clusterfuzz_target_path, reproduce_args) except ReproduceError: # This happens if the project has ClusterFuzz builds, but the fuzz target # is not in it (e.g. because the fuzz target is new). logging.info(COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE) return True if reproducible_on_clusterfuzz_build: logging.info('The crash is reproducible on previous build. ' 'Code change (pr/commit) did not introduce crash.') return False logging.info('The crash is not reproducible on previous build. ' 'Code change (pr/commit) introduced crash.') return True ================================================ FILE: infra/cifuzz/fuzz_target_test.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests the functionality of the fuzz_target module.""" import os import shutil import tempfile import unittest from unittest import mock import certifi # Importing this later causes import failures with pytest for some reason. # TODO(ochang): Figure out why. import parameterized import google.cloud.ndb # pylint: disable=unused-import from pyfakefs import fake_filesystem_unittest from clusterfuzz.fuzz import engine import clusterfuzz_deployment import fuzz_target import test_helpers import workspace_utils # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. EXAMPLE_PROJECT = 'example' # An example fuzzer that triggers an error. EXAMPLE_FUZZER = 'example_crash_fuzzer' # Mock return values for engine_impl.reproduce. EXECUTE_SUCCESS_RESULT = engine.ReproduceResult([], 0, 0, '') EXECUTE_FAILURE_RESULT = engine.ReproduceResult([], 1, 0, '') TEST_DATA_PATH = os.path.join(os.path.dirname(__file__), 'test_data') def _create_config(**kwargs): """Creates a config object and then sets every attribute that is a key in |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an attribute of Config.""" defaults = { 'cfl_platform': 'github', 'oss_fuzz_project_name': EXAMPLE_PROJECT, 'workspace': '/workspace' } for default_key, default_value in defaults.items(): if default_key not in kwargs: kwargs[default_key] = default_value return test_helpers.create_run_config(**kwargs) def _create_deployment(**kwargs): config = _create_config(**kwargs) workspace = workspace_utils.Workspace(config) return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace) @mock.patch('utils.get_container_name', return_value='container') class IsReproducibleTest(fake_filesystem_unittest.TestCase): """Tests the is_reproducible method in the fuzz_target.FuzzTarget class.""" def setUp(self): """Sets up example fuzz target to test is_reproducible method.""" self.fuzz_target_name = 'fuzz-target' deployment = _create_deployment() self.config = deployment.config self.workspace = deployment.workspace self.fuzz_target_path = os.path.join(self.workspace.out, self.fuzz_target_name) self.setUpPyfakefs() self.fs.create_file(self.fuzz_target_path) self.testcase_path = '/testcase' self.fs.create_file(self.testcase_path) self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, self.workspace, deployment, deployment.config) # ClusterFuzz requires ROOT_DIR. root_dir = os.environ['ROOT_DIR'] test_helpers.patch_environ(self, empty=True) os.environ['ROOT_DIR'] = root_dir # There's an extremely bad issue that happens if this test is run: Other tests # in this file fail in CI with stacktraces using referencing fakefs even if # the tests do not use fakefs. # TODO(metzman): Stop using fakefs. @mock.patch('os.chmod') @unittest.skip('Skip because of weird failures.') def test_repro_timed_out(self, mock_chmod, mock_get_container_name): """Tests that is_reproducible behaves correctly when reproduction times out.""" del mock_get_container_name del mock_chmod with mock.patch( 'clusterfuzz._internal.bot.fuzzers.libFuzzer.engine.LibFuzzerEngine.' 'reproduce', side_effect=TimeoutError): self.assertFalse( self.target.is_reproducible('/testcase', self.target.target_path, [])) def test_reproducible(self, _): """Tests that is_reproducible returns True if crash is detected and that is_reproducible uses the correct command to reproduce a crash.""" all_repro = [EXECUTE_FAILURE_RESULT] * fuzz_target.REPRODUCE_ATTEMPTS with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine: mock_get_engine().reproduce.side_effect = all_repro result = self.target.is_reproducible(self.testcase_path, self.fuzz_target_path, []) mock_get_engine().reproduce.assert_called_once_with( '/workspace/build-out/fuzz-target', '/testcase', arguments=[], max_time=30) self.assertTrue(result) self.assertEqual(1, mock_get_engine().reproduce.call_count) def test_flaky(self, _): """Tests that is_reproducible returns True if crash is detected on the last attempt.""" last_time_repro = [EXECUTE_SUCCESS_RESULT] * 9 + [EXECUTE_FAILURE_RESULT] with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine: mock_get_engine().reproduce.side_effect = last_time_repro self.assertTrue( self.target.is_reproducible(self.testcase_path, self.fuzz_target_path, [])) self.assertEqual(fuzz_target.REPRODUCE_ATTEMPTS, mock_get_engine().reproduce.call_count) def test_nonexistent_fuzzer(self, _): """Tests that is_reproducible raises an error if it could not attempt reproduction because the fuzzer doesn't exist.""" with self.assertRaises(fuzz_target.ReproduceError): self.target.is_reproducible(self.testcase_path, '/non-existent-path', []) def test_unreproducible(self, _): """Tests that is_reproducible returns False for a crash that did not reproduce.""" all_unrepro = [EXECUTE_SUCCESS_RESULT] * fuzz_target.REPRODUCE_ATTEMPTS with mock.patch('clusterfuzz.fuzz.get_engine') as mock_get_engine: mock_get_engine().reproduce.side_effect = all_unrepro result = self.target.is_reproducible(self.testcase_path, self.fuzz_target_path, []) self.assertFalse(result) class IsCrashReportableTest(fake_filesystem_unittest.TestCase): """Tests the is_crash_reportable method of FuzzTarget.""" def setUp(self): """Sets up example fuzz target to test is_crash_reportable method.""" self.setUpPyfakefs() self.fuzz_target_path = '/example/do_stuff_fuzzer' deployment = _create_deployment() self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100, deployment.workspace, deployment, deployment.config) self.oss_fuzz_build_path = '/oss-fuzz-build' self.fs.create_file(self.fuzz_target_path) self.oss_fuzz_target_path = os.path.join( self.oss_fuzz_build_path, os.path.basename(self.fuzz_target_path)) self.fs.create_file(self.oss_fuzz_target_path) self.testcase_path = '/testcase' self.fs.create_file(self.testcase_path, contents='') # Do this to prevent pyfakefs from messing with requests. self.fs.add_real_directory(os.path.dirname(certifi.__file__)) @mock.patch('fuzz_target.FuzzTarget.is_reproducible', side_effect=[True, False]) @mock.patch('logging.info') def test_new_reproducible_crash(self, mock_info, _): """Tests that a new reproducible crash returns True.""" with tempfile.TemporaryDirectory() as tmp_dir: self.target.out_dir = tmp_dir self.assertTrue(self.target.is_crash_reportable(self.testcase_path, [])) mock_info.assert_called_with( 'The crash is not reproducible on previous build. ' 'Code change (pr/commit) introduced crash.') # yapf: disable @parameterized.parameterized.expand([ # Reproducible on PR build, but also reproducible on OSS-Fuzz. ([True, True],), # Not reproducible on PR build, but somehow reproducible on OSS-Fuzz. # Unlikely to happen in real world except if test is flaky. ([False, True],), # Not reproducible on PR build, and not reproducible on OSS-Fuzz. ([False, False],), ]) # yapf: enable def test_invalid_crash(self, is_reproducible_retvals): """Tests that a nonreportable crash causes the method to return False.""" with mock.patch('fuzz_target.FuzzTarget.is_reproducible', side_effect=is_reproducible_retvals): with mock.patch('clusterfuzz_deployment.OSSFuzz.download_latest_build', return_value=self.oss_fuzz_build_path): self.assertFalse(self.target.is_crash_reportable( self.testcase_path, [])) @mock.patch('logging.info') @mock.patch('fuzz_target.FuzzTarget.is_reproducible', return_value=[True]) def test_reproducible_no_oss_fuzz_target(self, _, mock_info): """Tests that is_crash_reportable returns True when a crash reproduces on the PR build but the target is not in the OSS-Fuzz build (usually because it is new).""" os.remove(self.oss_fuzz_target_path) def is_reproducible_side_effect(testcase, target_path, reproduce_arguments): del testcase del reproduce_arguments if os.path.dirname(target_path) == self.oss_fuzz_build_path: raise fuzz_target.ReproduceError() return True with mock.patch( 'fuzz_target.FuzzTarget.is_reproducible', side_effect=is_reproducible_side_effect) as mock_is_reproducible: with mock.patch('clusterfuzz_deployment.OSSFuzz.download_latest_build', return_value=self.oss_fuzz_build_path): self.assertTrue(self.target.is_crash_reportable(self.testcase_path, [])) mock_is_reproducible.assert_any_call(self.testcase_path, self.oss_fuzz_target_path, []) mock_info.assert_called_with( 'Could not run previous build of target to determine if this code ' 'change (pr/commit) introduced crash. Assuming crash was newly ' 'introduced.') class FuzzTest(fake_filesystem_unittest.TestCase): """Fuzz test.""" def setUp(self): """Sets up example fuzz target.""" self.setUpPyfakefs() deployment = _create_deployment() config = deployment.config workspace = deployment.workspace self.fuzz_target = fuzz_target.FuzzTarget('/path/fuzz-target', 10, workspace, deployment, config) def test_get_fuzz_target_artifact(self): """Tests that get_fuzz_target_artifact works as intended.""" # pylint: disable=protected-access fuzz_target_artifact = self.fuzz_target._target_artifact_path() self.assertEqual('/workspace/out/artifacts/fuzz-target/address', fuzz_target_artifact) class TimeoutIntegrationTest(unittest.TestCase): """Tests handling of fuzzer timeout (timeout crashes reported by libFuzzer).""" TIMEOUT_FUZZER_NAME = 'timeout_fuzzer' @parameterized.parameterized.expand([(True, True), (False, False)]) def test_timeout_reported(self, report_timeouts, expect_crash): """Tests that timeouts are not reported.""" with test_helpers.temp_dir_copy(TEST_DATA_PATH) as temp_dir: fuzz_target_path = os.path.join(temp_dir, 'build-out', self.TIMEOUT_FUZZER_NAME) shutil.copy(os.path.join(temp_dir, self.TIMEOUT_FUZZER_NAME), fuzz_target_path) deployment = _create_deployment(workspace=temp_dir, report_timeouts=report_timeouts) config = deployment.config fuzz_target_obj = fuzz_target.FuzzTarget(fuzz_target_path, fuzz_target.REPRODUCE_ATTEMPTS, deployment.workspace, deployment, config) with mock.patch('clusterfuzz._internal.bot.fuzzers.libfuzzer.' 'fix_timeout_argument_for_reproduction') as _: with mock.patch( 'clusterfuzz._internal.bot.fuzzers.libFuzzer.fuzzer.get_arguments', return_value=['-timeout=1', '-rss_limit_mb=2560']): fuzz_result = fuzz_target_obj.fuzz() self.assertEqual(bool(fuzz_result.testcase), expect_crash) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/generate_coverage_report.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for generating coverage reports.""" import os import base_runner_utils import fuzz_target import utils def run_coverage_command(config, workspace): """Runs the coverage command in base-runner to generate a coverage report.""" env = base_runner_utils.get_env(config, workspace) env['HTTP_PORT'] = '' env['COVERAGE_EXTRA_ARGS'] = '' env['CORPUS_DIR'] = workspace.corpora env['COVERAGE_OUTPUT_DIR'] = workspace.coverage_report command = 'coverage' return utils.execute(command, env=env) def download_corpora(fuzz_target_paths, clusterfuzz_deployment): """Downloads corpora for fuzz targets in |fuzz_target_paths| using |clusterfuzz_deployment| to download corpora from ClusterFuzz/OSS-Fuzz.""" for target_path in fuzz_target_paths: target_name = os.path.basename(target_path) corpus_dir = fuzz_target.get_fuzz_target_corpus_dir( clusterfuzz_deployment.workspace, target_name) clusterfuzz_deployment.download_corpus(target_name, corpus_dir) def generate_coverage_report(fuzz_target_paths, workspace, clusterfuzz_deployment, config): """Generates a coverage report using Clang's source based coverage.""" download_corpora(fuzz_target_paths, clusterfuzz_deployment) run_coverage_command(config, workspace) clusterfuzz_deployment.upload_coverage() ================================================ FILE: infra/cifuzz/generate_coverage_report_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for generate_coverage_report.""" import unittest from unittest import mock import generate_coverage_report import test_helpers OUT_DIR = '/outdir' PROJECT = 'example-project' SANITIZER = 'coverage' class TestRunCoverageCommand(unittest.TestCase): """Tests run_coverage_command""" def setUp(self): test_helpers.patch_environ(self, empty=True) @mock.patch('utils.execute') def test_run_coverage_command(self, mock_execute): # pylint: disable=no-self-use """Tests that run_coverage_command works as intended.""" config = test_helpers.create_run_config(oss_fuzz_project_name=PROJECT, sanitizer=SANITIZER) workspace = test_helpers.create_workspace() generate_coverage_report.run_coverage_command(config, workspace) expected_command = 'coverage' expected_env = { 'SANITIZER': config.sanitizer, 'FUZZING_LANGUAGE': config.language, 'OUT': workspace.out, 'CIFUZZ': 'True', 'FUZZING_ENGINE': 'libfuzzer', 'ARCHITECTURE': 'x86_64', 'FUZZER_ARGS': '-rss_limit_mb=2560 -timeout=25', 'HTTP_PORT': '', 'COVERAGE_EXTRA_ARGS': '', 'CORPUS_DIR': workspace.corpora, 'COVERAGE_OUTPUT_DIR': workspace.coverage_report } mock_execute.assert_called_with(expected_command, env=expected_env) class DownloadCorporaTest(unittest.TestCase): """Tests for download_corpora.""" def test_download_corpora(self): # pylint: disable=no-self-use """Tests that download_corpora works as intended.""" clusterfuzz_deployment = mock.Mock() clusterfuzz_deployment.workspace = test_helpers.create_workspace() fuzz_target_paths = ['/path/to/fuzzer1', '/path/to/fuzzer2'] expected_calls = [ mock.call('fuzzer1', '/workspace/cifuzz-corpus/fuzzer1'), mock.call('fuzzer2', '/workspace/cifuzz-corpus/fuzzer2') ] generate_coverage_report.download_corpora(fuzz_target_paths, clusterfuzz_deployment) clusterfuzz_deployment.download_corpus.assert_has_calls(expected_calls) ================================================ FILE: infra/cifuzz/get_coverage.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for determining coverage of fuzz targets.""" import json import logging import os import sys import http_utils # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import utils # The path to get OSS-Fuzz project's latest report json file.` OSS_FUZZ_LATEST_COVERAGE_INFO_PATH = 'oss-fuzz-coverage/latest_report_info/' # pylint: disable=too-few-public-methods class CoverageError(Exception): """Exceptions for project coverage.""" class BaseCoverage: """Gets coverage data for a project.""" def __init__(self, repo_path): self.repo_path = _normalize_repo_path(repo_path) def get_files_covered_by_target(self, target): """Returns a list of source files covered by the specific fuzz target. Args: target: The name of the fuzz target whose coverage is requested. Returns: A list of files that the fuzz target covers or None. """ target_cov = self.get_target_coverage(target) if not target_cov: logging.info('No coverage available for %s.', target) return None coverage_per_file = get_coverage_per_file(target_cov) if not coverage_per_file: logging.info('No files found in coverage report.') return None affected_file_list = [] for file_cov in coverage_per_file: norm_file_path = os.path.normpath(file_cov['filename']) if not norm_file_path.startswith(self.repo_path): # Exclude files outside of the main repo. continue if not is_file_covered(file_cov): # Don't consider a file affected if code in it is never executed. continue # TODO(metzman): It's weird to me that we access file_cov['filename'] # again and not norm_file_path, figure out if this makes sense. relative_path = utils.remove_prefix(file_cov['filename'], self.repo_path) affected_file_list.append(relative_path) return affected_file_list def get_target_coverage(self, target): """Get the coverage report for a specific fuzz target. Args: target: The name of the fuzz target whose coverage is requested. Returns: The target's coverage json dict or None on failure. """ raise NotImplementedError('Child class must implement method.') class OSSFuzzCoverage(BaseCoverage): """Gets coverage data for a project from OSS-Fuzz.""" def __init__(self, repo_path, oss_fuzz_project_name): """Constructor for OSSFuzzCoverage.""" super().__init__(repo_path) self.oss_fuzz_project_name = oss_fuzz_project_name self.fuzzer_stats_url = _get_oss_fuzz_fuzzer_stats_dir_url( self.oss_fuzz_project_name) if self.fuzzer_stats_url is None: raise CoverageError('Could not get latest coverage.') def get_target_coverage(self, target): """Get the coverage report for a specific fuzz target. Args: target: The name of the fuzz target whose coverage is requested. Returns: The target's coverage json dict or None on failure. """ if not self.fuzzer_stats_url: return None target_url = utils.url_join(self.fuzzer_stats_url, target + '.json') return http_utils.get_json_from_url(target_url) def _get_oss_fuzz_latest_cov_report_info(oss_fuzz_project_name): """Gets and returns a dictionary containing the latest coverage report info for |project|.""" latest_report_info_url = utils.url_join(utils.GCS_BASE_URL, OSS_FUZZ_LATEST_COVERAGE_INFO_PATH, oss_fuzz_project_name + '.json') latest_cov_info = http_utils.get_json_from_url(latest_report_info_url) if latest_cov_info is None: logging.error('Could not get the coverage report json from url: %s.', latest_report_info_url) return None return latest_cov_info def _get_oss_fuzz_fuzzer_stats_dir_url(oss_fuzz_project_name): """Gets latest coverage report info for a specific OSS-Fuzz project from GCS. Args: oss_fuzz_project_name: The name of the project. Returns: The projects coverage report info in json dict or None on failure. """ latest_cov_info = _get_oss_fuzz_latest_cov_report_info(oss_fuzz_project_name) if not latest_cov_info: return None if 'fuzzer_stats_dir' not in latest_cov_info: logging.error('fuzzer_stats_dir not in latest coverage info.') return None fuzzer_stats_dir_gs_url = latest_cov_info['fuzzer_stats_dir'] fuzzer_stats_dir_url = utils.gs_url_to_https(fuzzer_stats_dir_gs_url) return fuzzer_stats_dir_url class FilesystemCoverage(BaseCoverage): """Class that gets a project's coverage from the filesystem.""" def __init__(self, repo_path, project_coverage_dir): super().__init__(repo_path) self.project_coverage_dir = project_coverage_dir def get_target_coverage(self, target): """Get the coverage report for a specific fuzz target. Args: target: The name of the fuzz target whose coverage is requested. Returns: The target's coverage json dict or None on failure. """ logging.info('Getting coverage for %s from filesystem.', target) fuzzer_stats_json_path = os.path.join(self.project_coverage_dir, 'fuzzer_stats', target + '.json') if not os.path.exists(fuzzer_stats_json_path): logging.warning('%s does not exist.', fuzzer_stats_json_path) return None with open(fuzzer_stats_json_path) as fuzzer_stats_json_file_handle: try: return json.load(fuzzer_stats_json_file_handle) except json.decoder.JSONDecodeError as err: logging.error('Could not decode: %s. Error: %s.', fuzzer_stats_json_path, err) return None def is_file_covered(file_cov): """Returns whether the file is covered.""" return file_cov['summary']['regions']['covered'] def get_coverage_per_file(target_cov): """Returns the coverage per file within |target_cov|.""" try: return target_cov['data'][0]['files'] except (IndexError, TypeError, KeyError): logging.error('target_cov: %s is malformed.', target_cov) return None def _normalize_repo_path(repo_path): """Normalizes and returns |repo_path| to make sure cases like /src/curl and /src/curl/ are both handled.""" repo_path = os.path.normpath(repo_path) if not repo_path.endswith('/'): repo_path += '/' return repo_path ================================================ FILE: infra/cifuzz/get_coverage_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for get_coverage.py""" import os import json import unittest from unittest import mock import parameterized from pyfakefs import fake_filesystem_unittest import pytest import get_coverage # pylint: disable=protected-access TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_data') PROJECT_NAME = 'curl' REPO_PATH = '/src/curl' FUZZ_TARGET = 'curl_fuzzer' PROJECT_COV_JSON_FILENAME = 'example_curl_cov.json' FUZZ_TARGET_COV_JSON_FILENAME = 'example_curl_fuzzer_cov.json' INVALID_TARGET = 'not-a-fuzz-target' with open(os.path.join(TEST_DATA_PATH, PROJECT_COV_JSON_FILENAME),) as cov_file_handle: PROJECT_COV_INFO = json.loads(cov_file_handle.read()) class GetOssFuzzFuzzerStatsDirUrlTest(unittest.TestCase): """Tests _get_oss_fuzz_fuzzer_stats_dir_url.""" @mock.patch('http_utils.get_json_from_url', return_value={ 'fuzzer_stats_dir': 'gs://oss-fuzz-coverage/systemd/fuzzer_stats/20210303' }) def test_get_valid_project(self, mock_get_json_from_url): """Tests that a project's coverage report can be downloaded and parsed. NOTE: This test relies on the PROJECT_NAME repo's coverage report. The "example" project was not used because it has no coverage reports. """ result = get_coverage._get_oss_fuzz_fuzzer_stats_dir_url(PROJECT_NAME) (url,), _ = mock_get_json_from_url.call_args self.assertEqual( 'https://storage.googleapis.com/oss-fuzz-coverage/' 'latest_report_info/curl.json', url) expected_result = ( 'https://storage.googleapis.com/oss-fuzz-coverage/systemd/fuzzer_stats/' '20210303') self.assertEqual(result, expected_result) def test_get_invalid_project(self): """Tests that passing a bad project returns None.""" self.assertIsNone( get_coverage._get_oss_fuzz_fuzzer_stats_dir_url('not-a-proj')) class OSSFuzzCoverageGetTargetCoverageTest(unittest.TestCase): """Tests OSSFuzzCoverage.get_target_coverage.""" def setUp(self): with mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info', return_value=PROJECT_COV_INFO): self.oss_fuzz_coverage = get_coverage.OSSFuzzCoverage( REPO_PATH, PROJECT_NAME) @mock.patch('http_utils.get_json_from_url', return_value={}) def test_valid_target(self, mock_get_json_from_url): """Tests that a target's coverage report can be downloaded and parsed.""" self.oss_fuzz_coverage.get_target_coverage(FUZZ_TARGET) (url,), _ = mock_get_json_from_url.call_args self.assertEqual( 'https://storage.googleapis.com/oss-fuzz-coverage/' 'curl/fuzzer_stats/20200226/curl_fuzzer.json', url) def test_invalid_target(self): """Tests that passing an invalid target coverage report returns None.""" self.assertIsNone( self.oss_fuzz_coverage.get_target_coverage(INVALID_TARGET)) @mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info', return_value=None) def test_invalid_project_json(self, _): # pylint: disable=no-self-use """Tests an invalid project JSON results in None being returned.""" with pytest.raises(get_coverage.CoverageError): get_coverage.OSSFuzzCoverage(REPO_PATH, PROJECT_NAME) def _get_expected_curl_covered_file_list(): """Returns the expected covered file list for FUZZ_TARGET_COV_JSON_FILENAME.""" curl_files_list_path = os.path.join(TEST_DATA_PATH, 'example_curl_file_list.json') with open(curl_files_list_path) as file_handle: return json.loads(file_handle.read()) def _get_example_curl_coverage(): """Returns the contents of the fuzzer stats JSON file for FUZZ_TARGET_COV_JSON_FILENAME.""" with open(os.path.join(TEST_DATA_PATH, FUZZ_TARGET_COV_JSON_FILENAME)) as file_handle: return json.loads(file_handle.read()) class OSSFuzzCoverageGetFilesCoveredByTargetTest(unittest.TestCase): """Tests OSSFuzzCoverage.get_files_covered_by_target.""" def setUp(self): with mock.patch('get_coverage._get_oss_fuzz_latest_cov_report_info', return_value=PROJECT_COV_INFO): self.oss_fuzz_coverage = get_coverage.OSSFuzzCoverage( REPO_PATH, PROJECT_NAME) @parameterized.parameterized.expand([({ 'data': [] },), ({ 'data': [[]] },), ({ 'data': [{}] },)]) def test_malformed_cov_data(self, coverage_data): """Tests that covered files can be retrieved from a coverage report.""" with mock.patch('get_coverage.OSSFuzzCoverage.get_target_coverage', return_value=coverage_data): self.oss_fuzz_coverage.get_files_covered_by_target(FUZZ_TARGET) def test_valid_target(self): """Tests that covered files can be retrieved from a coverage report.""" fuzzer_cov_data = _get_example_curl_coverage() with mock.patch('get_coverage.OSSFuzzCoverage.get_target_coverage', return_value=fuzzer_cov_data): file_list = self.oss_fuzz_coverage.get_files_covered_by_target( FUZZ_TARGET) expected_file_list = _get_expected_curl_covered_file_list() self.assertCountEqual(file_list, expected_file_list) def test_invalid_target(self): """Tests passing invalid fuzz target returns None.""" self.assertIsNone( self.oss_fuzz_coverage.get_files_covered_by_target(INVALID_TARGET)) class FilesystemCoverageGetFilesCoveredByTargetTest( fake_filesystem_unittest.TestCase): """Tests FilesystemCoverage.get_files_covered_by_target.""" def setUp(self): _fuzzer_cov_data = _get_example_curl_coverage() self._expected_file_list = _get_expected_curl_covered_file_list() self.coverage_path = '/coverage' self.filesystem_coverage = get_coverage.FilesystemCoverage( REPO_PATH, self.coverage_path) self.setUpPyfakefs() self.fs.create_file(os.path.join(self.coverage_path, 'fuzzer_stats', FUZZ_TARGET + '.json'), contents=json.dumps(_fuzzer_cov_data)) def test_valid_target(self): """Tests that covered files can be retrieved from a coverage report.""" file_list = self.filesystem_coverage.get_files_covered_by_target( FUZZ_TARGET) self.assertCountEqual(file_list, self._expected_file_list) def test_invalid_target(self): """Tests passing invalid fuzz target returns None.""" self.assertIsNone( self.filesystem_coverage.get_files_covered_by_target(INVALID_TARGET)) class IsFileCoveredTest(unittest.TestCase): """Tests for is_file_covered.""" def test_is_file_covered_covered(self): """Tests that is_file_covered returns True for a covered file.""" file_coverage = { 'filename': '/src/systemd/src/basic/locale-util.c', 'summary': { 'regions': { 'count': 204, 'covered': 200, 'notcovered': 200, 'percent': 98.03 } } } self.assertTrue(get_coverage.is_file_covered(file_coverage)) def test_is_file_covered_not_covered(self): """Tests that is_file_covered returns False for a not covered file.""" file_coverage = { 'filename': '/src/systemd/src/basic/locale-util.c', 'summary': { 'regions': { 'count': 204, 'covered': 0, 'notcovered': 0, 'percent': 0 } } } self.assertFalse(get_coverage.is_file_covered(file_coverage)) class GetOssFuzzLatestCovReportInfo(unittest.TestCase): """Tests that _get_oss_fuzz_latest_cov_report_info works as intended.""" PROJECT = 'project' LATEST_REPORT_INFO_URL = ('https://storage.googleapis.com/oss-fuzz-coverage/' 'latest_report_info/project.json') @mock.patch('logging.error') @mock.patch('http_utils.get_json_from_url', return_value={'coverage': 1}) def test_get_oss_fuzz_latest_cov_report_info(self, mock_get_json_from_url, mock_error): """Tests that _get_oss_fuzz_latest_cov_report_info works as intended.""" result = get_coverage._get_oss_fuzz_latest_cov_report_info(self.PROJECT) self.assertEqual(result, {'coverage': 1}) mock_error.assert_not_called() mock_get_json_from_url.assert_called_with(self.LATEST_REPORT_INFO_URL) @mock.patch('logging.error') @mock.patch('http_utils.get_json_from_url', return_value=None) def test_get_oss_fuzz_latest_cov_report_info_fail(self, _, mock_error): """Tests that _get_oss_fuzz_latest_cov_report_info works as intended when we can't get latest report info.""" result = get_coverage._get_oss_fuzz_latest_cov_report_info('project') self.assertIsNone(result) mock_error.assert_called_with( 'Could not get the coverage report json from url: %s.', self.LATEST_REPORT_INFO_URL) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/http_utils.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utility module for HTTP.""" import json import logging import os import sys import tempfile import zipfile import requests # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import retry _DOWNLOAD_URL_RETRIES = 3 _DOWNLOAD_URL_BACKOFF = 1 _HTTP_REQUEST_TIMEOUT = 10 def download_and_unpack_zip(url, extract_directory, headers=None): """Downloads and unpacks a zip file from an HTTP URL. Args: url: A url to the zip file to be downloaded and unpacked. extract_directory: The path where the zip file should be extracted to. headers: (Optional) HTTP headers to send with the download request. Returns: True on success. """ if headers is None: headers = {} if not os.path.exists(extract_directory): logging.error('Extract directory: %s does not exist.', extract_directory) return False # Gives the temporary zip file a unique identifier in the case that # that download_and_unpack_zip is done in parallel. with tempfile.NamedTemporaryFile(suffix='.zip') as tmp_file: if not download_url(url, tmp_file.name, headers=headers): return False try: with zipfile.ZipFile(tmp_file.name, 'r') as zip_file: zip_file.extractall(extract_directory) except zipfile.BadZipFile: logging.error('Error unpacking zip from %s. Bad Zipfile.', url) return False return True def download_url(*args, **kwargs): """Wrapper around _download_url that returns False if _download_url exceptions.""" try: return _download_url(*args, **kwargs) except Exception: # pylint: disable=broad-except return False def get_json_from_url(url): """Gets a json object from a specified HTTP URL. Args: url: The url of the json to be downloaded. Returns: A dictionary deserialized from JSON or None on failure. """ try: return requests.get(url, timeout=_HTTP_REQUEST_TIMEOUT).json() except (ValueError, TypeError, json.JSONDecodeError, requests.exceptions.ReadTimeout) as err: logging.error('Loading json from url %s failed with: %s.', url, str(err)) return None @retry.wrap(_DOWNLOAD_URL_RETRIES, _DOWNLOAD_URL_BACKOFF) def _download_url(url, filename, headers=None): """Downloads the file located at |url|, using HTTP to |filename|. Args: url: A url to a file to download. filename: The path the file should be downloaded to. headers: (Optional) HTTP headers to send with the download request. Returns: True on success. """ if headers is None: headers = {} response = requests.get(url, headers=headers) if response.status_code != 200: logging.error('Unable to download from: %s. Code: %d. Content: %s.', url, response.status_code, response.content) return False with open(filename, 'wb') as file_handle: file_handle.write(response.content) return True ================================================ FILE: infra/cifuzz/http_utils_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for http_utils.py""" import unittest from unittest import mock from pyfakefs import fake_filesystem_unittest import http_utils mock_get_response = mock.MagicMock(status_code=200, content=b'') class DownloadUrlTest(unittest.TestCase): """Tests that download_url works.""" URL = 'https://example.com/file' FILE_PATH = '/tmp/file' @mock.patch('time.sleep') @mock.patch('requests.get', return_value=mock_get_response) def test_download_url_no_error(self, mock_urlretrieve, _): """Tests that download_url works when there is no error.""" self.assertTrue(http_utils.download_url(self.URL, self.FILE_PATH)) self.assertEqual(1, mock_urlretrieve.call_count) @mock.patch('time.sleep') @mock.patch('logging.error') @mock.patch('requests.get', return_value=mock.MagicMock(status_code=404, content=b'')) def test_download_url_http_error(self, mock_get, mock_error, _): """Tests that download_url doesn't retry when there is an HTTP error.""" self.assertFalse(http_utils.download_url(self.URL, self.FILE_PATH)) mock_error.assert_called_with( 'Unable to download from: %s. Code: %d. Content: %s.', self.URL, 404, b'') self.assertEqual(1, mock_get.call_count) @mock.patch('time.sleep') @mock.patch('requests.get', side_effect=ConnectionResetError) def test_download_url_connection_error(self, mock_get, mock_sleep): """Tests that download_url doesn't retry when there is an HTTP error.""" self.assertFalse(http_utils.download_url(self.URL, self.FILE_PATH)) self.assertEqual(4, mock_get.call_count) self.assertEqual(3, mock_sleep.call_count) class DownloadAndUnpackZipTest(fake_filesystem_unittest.TestCase): """Tests download_and_unpack_zip.""" def setUp(self): self.setUpPyfakefs() @mock.patch('requests.get', return_value=mock_get_response) def test_bad_zip_download(self, _): """Tests download_and_unpack_zip returns none when a bad zip is passed.""" self.fs.create_file('/url_tmp.zip', contents='Test file.') self.assertFalse( http_utils.download_and_unpack_zip('/not/a/real/url', '/extract-directory')) ================================================ FILE: infra/cifuzz/logs.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Log helpers.""" import logging import os def init(): """Initialize logging.""" log_level = logging.DEBUG if os.getenv('CIFUZZ_DEBUG') else logging.INFO logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=log_level) ================================================ FILE: infra/cifuzz/package.json ================================================ { "name": "cifuzz", "version": "1.0.0", "description": "", "author": "Google", "license": "Apache2", "dependencies": { "@actions/artifact": "^2.2.0" } } ================================================ FILE: infra/cifuzz/platform_config/__init__.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run.""" import logging import os import environment class BasePlatformConfig: """Base class for PlatformConfig subclasses.""" @property def project_src_path(self): """Returns the manually checked out path of the project's source if specified or None.""" path = os.getenv('PROJECT_SRC_PATH') if not path: logging.debug('No PROJECT_SRC_PATH.') return path logging.debug('PROJECT_SRC_PATH: %s.', path) return path @property def workspace(self): """Returns the workspace.""" return os.getenv('WORKSPACE') # Optional config variables. @property def git_sha(self): """Returns the Git SHA to checkout and fuzz. This is used only by GitHub projects when commit fuzzing. It is not used when PR fuzzing. It is definitely needed by OSS-Fuzz on GitHub since they have no copy of the repo on the host and the repo on the builder image is a clone from main/master. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. TODO(metzman): Try to eliminate the need for this by 1. Making the clone from external github projects usable. 2. Forcing OSS-Fuzz on Github to clone before starting CIFuzz.""" return None @property def base_commit(self): """Returns the base commit to diff against (commit fuzzing).""" # TODO(metzman) Rename base_commit to git_base_commit. return os.getenv('GIT_BASE_COMMIT') @property def base_ref(self): """Returns the base branch to diff against (pr fuzzing).""" # TODO(metzman) Rename base_ref to git_base_ref. return os.getenv('GIT_BASE_REF') @property def pr_ref(self): """Returns the pull request to checkout and fuzz. This is used only by GitHub projects when PR fuzzing. It is not used when commit fuzzing. It is definitely needed by OSS-Fuzz on GitHub since they have no copy of the repo on the host and the repo on the builder image is a clone from main/master. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. TODO(metzman): Try to eliminate the need for this by 1. Making the clone from external github projects usable. 2. Forcing OSS-Fuzz on Github to clone before starting CIFuzz.""" return None @property def project_repo_owner(self): """Returns the project repo owner (githubism).""" return None @property def project_repo_name(self): """Returns the project repo name.""" return os.environ.get('REPOSITORY') @property def actor(self): """Name of the actor for the CI.""" return None @property def token(self): """Returns the CI API token.""" return None @property def docker_in_docker(self): """Returns whether or not CFL is running using Docker in Docker.""" return environment.get_bool('DOCKER_IN_DOCKER', False) @property def filestore(self): """Returns the filestore used to store persistent data.""" return os.environ.get('FILESTORE') @property def git_url(self): """Returns the repo URL. This is only used by GitHub users. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. It isn't used by OSS-Fuzz on github users since the Git URL is determined using repo detection. TODO(metzman): Try to eliminate the need for this by making the clone from external github projects usable. TODO(metzman): As an easier goal, maybe make OSS-Fuzz GitHub use this too for: 1. Consistency 2. Maybe it will allow use on forks.""" return None ================================================ FILE: infra/cifuzz/platform_config/gcb.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run on Github.""" import logging import os import platform_config class PlatformConfig(platform_config.BasePlatformConfig): """CI environment for Google Cloud Build.""" @property def project_src_path(self): """Returns the manually checked out path of the project's source if specified or the default.""" project_src_path = os.getenv('PROJECT_SRC_PATH', '/workspace') logging.debug('PROJECT_SRC_PATH: %s.', project_src_path) return project_src_path @property def workspace(self): """Returns the workspace.""" return os.getenv('WORKSPACE', '/builder/home') @property def filestore(self): """Returns the filestore used to store persistent data.""" return os.environ.get('FILESTORE', 'gsutil') ================================================ FILE: infra/cifuzz/platform_config/github.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run on Github.""" import json import logging import os import platform_config def _get_github_event_path(): return os.getenv('GITHUB_EVENT_PATH') def _get_event_data(): """Returns the GitHub event data.""" github_event_path = _get_github_event_path() with open(github_event_path, encoding='utf-8') as file_handle: return json.load(file_handle) class PlatformConfig(platform_config.BasePlatformConfig): """CI environment for GitHub.""" def __init__(self): self._event_data = _get_event_data() self._event = os.getenv('GITHUB_EVENT_NAME') @property def workspace(self): """Returns the workspace.""" return os.getenv('GITHUB_WORKSPACE') @property def git_sha(self): """Returns the Git SHA to checkout and fuzz. This is used only by GitHub projects when commit fuzzing. It is not used when PR fuzzing. It is definitely needed by OSS-Fuzz on GitHub since they have no copy of the repo on the host and the repo on the builder image is a clone from main/master. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. TODO(metzman): Try to eliminate the need for this by 1. Making the clone from external github projects usable. 2. Forcing OSS-Fuzz on Github to clone before starting CIFuzz.""" return os.getenv('GITHUB_SHA') @property def actor(self): """Name of the actor for the CI.""" return os.getenv('GITHUB_ACTOR') @property def token(self): """Returns the CI API token.""" return os.getenv('GITHUB_TOKEN') @property def project_src_path(self): """Returns the manually checked out path of the project's source if specified or None. The path returned is relative to |self.workspace| since on github the checkout will be relative to there.""" project_src_path = super().project_src_path if project_src_path is None: # Not set for internal GitHub users. return project_src_path # On GitHub (external users), this path is relative to |workspace|. return os.path.join(self.workspace, project_src_path) @property def _project_repo_owner_and_name(self): """Returns a tuple containing the project repo owner and the name of the repo.""" # On GitHub this includes owner and repo name. repository = os.getenv('GITHUB_REPOSITORY') # Use os.path.split to split owner from repo. return os.path.split(repository) @property def project_repo_owner(self): """Returns the project repo owner (githubism).""" return self._project_repo_owner_and_name[0] @property def project_repo_name(self): """Returns the project repo name.""" return self._project_repo_owner_and_name[1] @property def git_url(self): """Returns the repo URL. This is only used by GitHub users. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. It isn't used by OSS-Fuzz on github users since the Git URL is determined using repo detection. TODO(metzman): Try to eliminate the need for this by making the clone from external github projects usable. TODO(metzman): As an easier goal, maybe make OSS-Fuzz GitHub use this too for: 1. Consistency 2. Maybe it will allow use on forks.""" repository = os.getenv('GITHUB_REPOSITORY') github_server_url = os.getenv('GITHUB_SERVER_URL', 'https://github.com') # TODO(metzman): Probably need to change this to github.server_url. return os.path.join(github_server_url, repository) @property def base_commit(self): """Returns the base commit to diff against (commit fuzzing).""" base_commit = None if self._event == 'push': base_commit = self._event_data['before'] logging.debug('base_commit: %s', base_commit) return base_commit @property def pr_ref(self): """Returns the pull request to checkout and fuzz. This is used only by GitHub projects when PR fuzzing. It is not used when commit fuzzing. It is definitely needed by OSS-Fuzz on GitHub since they have no copy of the repo on the host and the repo on the builder image is a clone from main/master. Right now it is needed by external on GitHub because we need to clone a new repo because the copy they give us doesn't work for diffing. TODO(metzman): Try to eliminate the need for this by 1. Making the clone from external github projects usable. 2. Forcing OSS-Fuzz on Github to clone before starting CIFuzz.""" if self._event == 'pull_request': pr_ref = f'refs/pull/{self._event_data["pull_request"]["number"]}/merge' logging.debug('pr_ref: %s', pr_ref) return pr_ref return None @property def base_ref(self): """Returns the base branch to diff against (pr fuzzing).""" return os.getenv('GITHUB_BASE_REF') ================================================ FILE: infra/cifuzz/platform_config/github_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for platform_config.github.""" import os import unittest from unittest import mock import platform_config.github import test_helpers # pylint: disable=arguments-differ class GetProjectRepoOwnerAndNameTest(unittest.TestCase): """Tests for get_project_repo_owner and get_project_repo_name.""" @mock.patch('platform_config.github._get_event_data', return_value={}) def setUp(self, _): test_helpers.patch_environ(self) self.repo_owner = 'repo-owner' self.repo_name = 'repo-name' os.environ['GITHUB_REPOSITORY'] = f'{self.repo_owner}/{self.repo_name}' self.platform_conf = platform_config.github.PlatformConfig() def test_github_repository_owner(self): """Tests that the correct result is returned when repository contains the owner and repo name (as it does on GitHub).""" self.assertEqual(self.platform_conf.project_repo_owner, self.repo_owner) def test_github_repository_name(self): """Tests that the correct result is returned when repository contains the owner and repo name (as it does on GitHub).""" os.environ['GITHUB_REPOSITORY'] = f'{self.repo_owner}/{self.repo_name}' self.assertEqual(self.platform_conf.project_repo_name, self.repo_name) class ProjectSrcPathTest(unittest.TestCase): """Tests for project_src_path.""" def setUp(self): test_helpers.patch_environ(self) self.workspace = '/workspace' os.environ['GITHUB_WORKSPACE'] = self.workspace self.project_src_dir_name = 'project-src' @mock.patch('platform_config.github._get_event_data', return_value={}) def test_github_unset(self, _): """Tests that project_src_path returns None when no PROJECT_SRC_PATH is set.""" github_env = platform_config.github.PlatformConfig() self.assertIsNone(github_env.project_src_path) @mock.patch('platform_config.github._get_event_data', return_value={}) def test_github(self, _): """Tests that project_src_path returns the correct result on GitHub.""" os.environ['PROJECT_SRC_PATH'] = self.project_src_dir_name expected_project_src_path = os.path.join(self.workspace, self.project_src_dir_name) github_env = platform_config.github.PlatformConfig() self.assertEqual(github_env.project_src_path, expected_project_src_path) class GetGitUrlTest(unittest.TestCase): """Tests for GenericPlatformConfig.git_url.""" @mock.patch('platform_config.github._get_event_data', return_value={}) def setUp(self, _): test_helpers.patch_environ(self) self.platform_conf = platform_config.github.PlatformConfig() def test_repository(self): """Tests that the correct result is returned when repository contains the owner and repo name (as it does on GitHub).""" os.environ['GITHUB_REPOSITORY'] = 'repo/owner' self.assertEqual('https://github.com/repo/owner', self.platform_conf.git_url) ================================================ FILE: infra/cifuzz/platform_config/gitlab.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run on GitLab.""" import logging import os import environment import platform_config class PlatformConfig(platform_config.BasePlatformConfig): """CI environment for GitLab.""" @property def workspace(self): """Returns the workspace.""" return os.path.join(os.getenv('CI_BUILDS_DIR'), os.getenv('CI_JOB_ID')) @property def git_sha(self): """Returns the Git SHA to checkout and fuzz.""" return os.getenv('CI_COMMIT_SHA') @property def project_src_path(self): """Returns the directory with the source of the project""" return os.getenv('CI_PROJECT_DIR') @property def token(self): """Returns the job token""" return os.getenv('CI_JOB_TOKEN') @property def project_repo_name(self): """Returns the project's name""" return os.getenv('CI_PROJECT_NAME') @property def base_commit(self): """Returns the previous commit sha for commit-fuzzing""" base_commit = None if os.getenv('CI_PIPELINE_SOURCE') == 'push': base_commit = os.getenv('CI_COMMIT_BEFORE_SHA') logging.debug('base_commit: %s.', base_commit) return base_commit @property def base_ref(self): """Returns the base commit sha for a merge request""" # Could also be CI_MERGE_REQUEST_TARGET_BRANCH_NAME. return os.getenv('CI_MERGE_REQUEST_DIFF_BASE_SHA') @property def filestore(self): """Returns the filestore used to store persistent data.""" return os.environ.get('FILESTORE', 'gitlab') @property def artifacts_dir(self): """Gitlab: returns the directory to put artifacts""" return environment.get('CFL_ARTIFACTS_DIR', 'artifacts') @property def cache_dir(self): """Gitlab: returns the directory to use as cache""" return environment.get('CFL_CACHE_DIR', 'cache') ================================================ FILE: infra/cifuzz/platform_config/platform_config_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for platform_config.""" import os import unittest import platform_config import test_helpers class GetProjectRepoOwnerAndNameTest(unittest.TestCase): """Tests for get_project_repo_owner and get_project_repo_name.""" def setUp(self): test_helpers.patch_environ(self) self.repo_owner = 'repo-owner' self.repo_name = 'repo-name' self.env = platform_config.BasePlatformConfig() def test_unset_repository(self): """Tests that the correct result is returned when repository is not set.""" self.assertIsNone(self.env.project_repo_name) def test_owner(self): """Tests that the correct result is returned for owner.""" self.assertIsNone(self.env.project_repo_owner) def test_empty_repository(self): """Tests that the correct result is returned when repository is an empty string.""" os.environ['REPOSITORY'] = '' self.assertEqual(self.env.project_repo_name, '') def test_repository(self): """Tests that the correct result is returned when repository contains the just the repo name (as it does outside of GitHub).""" os.environ['REPOSITORY'] = self.repo_name self.assertEqual(self.env.project_repo_name, self.repo_name) class ProjectSrcPathTest(unittest.TestCase): """Tests for project_src_path.""" def setUp(self): test_helpers.patch_environ(self) def test_not_github(self): """Tests that project_src_path returns the correct result not on GitHub.""" project_src_path = 'project-src' os.environ['PROJECT_SRC_PATH'] = project_src_path generic_ci_env = platform_config.BasePlatformConfig() self.assertEqual(generic_ci_env.project_src_path, project_src_path) class GetGitUrlTest(unittest.TestCase): """Tests for BasePlatformConfig.git_url.""" def setUp(self): test_helpers.patch_environ(self) self.env = platform_config.BasePlatformConfig() def test_unset_repository(self): """Tests that the correct result is returned when repository is not set.""" self.assertEqual(self.env.git_url, None) def test_repository(self): """Tests that the correct result is returned when GITHUB_REPOSITORY is set.""" os.environ['GITHUB_REPOSITORY'] = 'repo/owner' self.assertIsNone(self.env.git_url) ================================================ FILE: infra/cifuzz/platform_config/prow.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run on prow.""" import logging import os import platform_config # pylint: disable=too-few-public-methods class PlatformConfig(platform_config.BasePlatformConfig): """CI environment for Prow.""" @property def project_src_path(self): """Returns the manually checked out path of the project's source if specified or the current directory if not. Prow will run ClusterfuzzLite at the directory head for the repo.""" project_src_path = os.getenv('PROJECT_SRC_PATH', os.getcwd()) logging.debug('PROJECT_SRC_PATH: %s.', project_src_path) return project_src_path @property def workspace(self): """Returns the workspace.""" # Let Prow user override workspace, but default to using artifacts dir return os.getenv('WORKSPACE', os.getenv('ARTIFACTS')) @property def base_ref(self): """Returns the base branch to diff against (pr fuzzing).""" return os.getenv('PULL_BASE_REF') @property def project_repo_name(self): """Returns the project repo name.""" return os.getenv('REPO_NAME') @property def base_commit(self): """Returns the base commit to diff against (commit fuzzing).""" return os.getenv('PULL_BASE_SHA') @property def docker_in_docker(self): """Returns True if using Docker in Docker.""" return True @property def filestore(self): """Returns the filestore used to store persistent data.""" return os.environ.get('FILESTORE', 'gsutil') ================================================ FILE: infra/cifuzz/platform_config/standalone.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for getting the configuration CIFuzz needs to run standalone.""" import os import platform_config # pylint: disable=too-few-public-methods class PlatformConfig(platform_config.BasePlatformConfig): """CI environment for Standalone.""" @property def filestore(self): """Returns the filestore used to store persistent data.""" return os.environ.get('FILESTORE', 'filesystem') @property def filestore_root_dir(self): """Returns the filestore used to store persistent data.""" return os.environ['FILESTORE_ROOT_DIR'] ================================================ FILE: infra/cifuzz/requirements.txt ================================================ clusterfuzz==2.5.9 requests==2.28.0 protobuf==3.20.2 gsutil==5.20 ================================================ FILE: infra/cifuzz/run_cifuzz.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Script for running CIFuzz end-to-end. This is meant to work outside any docker image. This cannot depend on any CIFuzz code or third party packages.""" import os import subprocess import sys import tempfile import logging INFRA_DIR = os.path.dirname(os.path.dirname(__file__)) DEFAULT_ENVS = [('DRY_RUN', '0'), ('SANITIZER', 'address')] BASE_CIFUZZ_DOCKER_TAG = 'gcr.io/oss-fuzz-base' def set_default_env_var_if_unset(env_var, default_value): """Sets the value of |env_var| in the environment to |default_value| if it was not already set.""" if env_var not in os.environ: os.environ[env_var] = default_value def docker_run(name, workspace, project_src_path): """Runs a CIFuzz docker container with |name|.""" command = [ 'docker', 'run', '--name', name, '--rm', '-e', 'PROJECT_SRC_PATH', '-e', 'OSS_FUZZ_PROJECT_NAME', '-e', 'WORKSPACE', '-e', 'REPOSITORY', '-e', 'DRY_RUN', '-e', 'CI', '-e', 'SANITIZER', '-e', 'GIT_SHA', '-e', 'FILESTORE', '-e', 'NO_CLUSTERFUZZ_DEPLOYMENT' ] if project_src_path: command += ['-v', f'{project_src_path}:{project_src_path}'] command += [ '-v', '/var/run/docker.sock:/var/run/docker.sock', '-v', f'{workspace}:{workspace}', f'{BASE_CIFUZZ_DOCKER_TAG}/{name}' ] print('Running docker command:', command) subprocess.run(command, check=True) def docker_build(image): """Builds the CIFuzz |image|. Only suitable for building CIFuzz images.""" command = [ 'docker', 'build', '-t', f'{BASE_CIFUZZ_DOCKER_TAG}/{image}', '--file', f'{image}.Dockerfile', '.' ] subprocess.run(command, check=True, cwd=INFRA_DIR) def main(): """Builds and runs fuzzers using CIFuzz.""" for env_var, default_value in DEFAULT_ENVS: set_default_env_var_if_unset(env_var, default_value) repository = os.getenv('REPOSITORY') assert repository project_src_path = os.getenv('PROJECT_SRC_PATH') with tempfile.TemporaryDirectory() as temp_dir: if 'WORKSPACE' not in os.environ: os.environ['WORKSPACE'] = temp_dir workspace = os.environ['WORKSPACE'] docker_build('build_fuzzers') docker_run('build_fuzzers', workspace, project_src_path) docker_build('run_fuzzers') try: docker_run('run_fuzzers', workspace, project_src_path) except subprocess.CalledProcessError: logging.error('run_fuzzers failed.') return 1 return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/cifuzz/run_fuzzers.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for running fuzzers.""" import enum import logging import os import sys import time import clusterfuzz_deployment import fuzz_target import generate_coverage_report import workspace_utils import sarif_utils # pylint: disable=wrong-import-position,import-error sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import utils class RunFuzzersResult(enum.Enum): """Enum result from running fuzzers.""" ERROR = 0 BUG_FOUND = 1 NO_BUG_FOUND = 2 class BaseFuzzTargetRunner: """Base class for fuzzer runners.""" def __init__(self, config): self.config = config self.workspace = workspace_utils.Workspace(config) self.clusterfuzz_deployment = ( clusterfuzz_deployment.get_clusterfuzz_deployment( self.config, self.workspace)) # Set by the initialize method. self.fuzz_target_paths = None def get_fuzz_targets(self): """Returns fuzz targets in out directory.""" return utils.get_fuzz_targets(self.workspace.out) def initialize(self): """Initialization method. Must be called before calling run_fuzz_targets. Returns True on success.""" # Use a separate initialization function so we can return False on failure # instead of exceptioning like we need to do if this were done in the # __init__ method. logging.info('Using %s sanitizer.', self.config.sanitizer) # TODO(metzman) Add a check to ensure we aren't over time limit. if not self.config.fuzz_seconds or self.config.fuzz_seconds < 1: logging.error( 'Fuzz_seconds argument must be greater than 1, but was: %s.', self.config.fuzz_seconds) return False if not os.path.exists(self.workspace.out): logging.error('Out directory: %s does not exist.', self.workspace.out) return False if not os.path.exists(self.workspace.artifacts): os.makedirs(self.workspace.artifacts) elif (not os.path.isdir(self.workspace.artifacts) or os.listdir(self.workspace.artifacts)): logging.error('Artifacts path: %s exists and is not an empty directory.', self.workspace.artifacts) return False self.fuzz_target_paths = self.get_fuzz_targets() logging.info('Fuzz targets: %s', self.fuzz_target_paths) if not self.fuzz_target_paths: logging.error('No fuzz targets were found in out directory: %s.', self.workspace.out) return False return True def cleanup_after_fuzz_target_run(self, fuzz_target_obj): # pylint: disable=no-self-use """Cleans up after running |fuzz_target_obj|.""" raise NotImplementedError('Child class must implement method.') def run_fuzz_target(self, fuzz_target_obj): # pylint: disable=no-self-use """Fuzzes with |fuzz_target_obj| and returns the result.""" raise NotImplementedError('Child class must implement method.') @property def quit_on_bug_found(self): """Property that is checked to determine if fuzzing should quit after first bug is found.""" raise NotImplementedError('Child class must implement method.') def create_fuzz_target_obj(self, target_path, run_seconds): """Returns a fuzz target object.""" return fuzz_target.FuzzTarget(target_path, run_seconds, self.workspace, self.clusterfuzz_deployment, self.config) def run_fuzz_targets(self): """Runs fuzz targets. Returns True if a bug was found.""" fuzzers_left_to_run = len(self.fuzz_target_paths) # Make a copy since we will mutate it. fuzz_seconds = self.config.fuzz_seconds min_seconds_per_fuzzer = fuzz_seconds // fuzzers_left_to_run bug_found = False for target_path in self.fuzz_target_paths: # By doing this, we can ensure that every fuzz target runs for at least # min_seconds_per_fuzzer, but that other fuzzers will have longer to run # if one ends early. run_seconds = max(fuzz_seconds // fuzzers_left_to_run, min_seconds_per_fuzzer) target = self.create_fuzz_target_obj(target_path, run_seconds) start_time = time.time() result = self.run_fuzz_target(target) self.cleanup_after_fuzz_target_run(target) # It's OK if this goes negative since we take max when determining # run_seconds. fuzz_seconds -= time.time() - start_time fuzzers_left_to_run -= 1 if not result.testcase or not result.stacktrace: logging.info('Fuzzer %s finished running without reportable crashes.', target.target_name) continue bug_found = True if self.quit_on_bug_found: logging.info('Bug found. Stopping fuzzing.') break # pylint: disable=undefined-loop-variable if not target_path: logging.error('Ran no fuzz targets.') elif self.config.output_sarif: # TODO(metzman): Handle multiple crashes. write_fuzz_result_to_sarif(result, target_path, self.workspace) self.clusterfuzz_deployment.upload_crashes() return bug_found def write_fuzz_result_to_sarif(fuzz_result, target_path, workspace): """Write results of fuzzing to SARIF.""" logging.info('Writing sarif results.') sarif_utils.write_stacktrace_to_sarif(fuzz_result.stacktrace, target_path, workspace) class PruneTargetRunner(BaseFuzzTargetRunner): """Runner that prunes corpora.""" @property def quit_on_bug_found(self): return False def run_fuzz_target(self, fuzz_target_obj): """Prunes with |fuzz_target_obj| and returns the result.""" result = fuzz_target_obj.prune() logging.debug('Corpus path contents: %s.', os.listdir(result.corpus_path)) self.clusterfuzz_deployment.upload_corpus(fuzz_target_obj.target_name, result.corpus_path, replace=True) return result def cleanup_after_fuzz_target_run(self, fuzz_target_obj): # pylint: disable=no-self-use """Cleans up after pruning with |fuzz_target_obj|.""" fuzz_target_obj.free_disk_if_needed() NON_FUZZ_TARGETS_FOR_COVERAGE = { 'llvm-symbolizer', 'jazzer_agent_deploy.jar', 'jazzer_driver', 'jazzer_driver_with_sanitizer', } def is_coverage_fuzz_target(file_path): """Returns whether |file_path| is a fuzz target binary for the purposes of a coverage report. Inspired by infra/base-images/base-runner/coverage.""" if not os.path.isfile(file_path): return False if not utils.is_executable(file_path): return False filename = os.path.basename(file_path) return filename not in NON_FUZZ_TARGETS_FOR_COVERAGE def get_coverage_fuzz_targets(out): """Returns a list of fuzz targets in |out| for coverage.""" # We only want fuzz targets from the root because during the coverage build, # a lot of the image's filesystem is copied into /out for the purpose of # generating coverage reports. fuzz_targets = [] for filename in os.listdir(out): file_path = os.path.join(out, filename) if is_coverage_fuzz_target(file_path): fuzz_targets.append(file_path) return fuzz_targets class CoverageTargetRunner(BaseFuzzTargetRunner): """Runner that runs the 'coverage' command.""" @property def quit_on_bug_found(self): raise NotImplementedError('Not implemented for CoverageTargetRunner.') def get_fuzz_targets(self): """Returns fuzz targets in out directory.""" return get_coverage_fuzz_targets(self.workspace.out) def run_fuzz_targets(self): """Generates a coverage report. Always returns False since it never finds any bugs.""" generate_coverage_report.generate_coverage_report( self.fuzz_target_paths, self.workspace, self.clusterfuzz_deployment, self.config) return False def run_fuzz_target(self, fuzz_target_obj): # pylint: disable=no-self-use """Fuzzes with |fuzz_target_obj| and returns the result.""" raise NotImplementedError('Not implemented for CoverageTargetRunner.') def cleanup_after_fuzz_target_run(self, fuzz_target_obj): # pylint: disable=no-self-use """Cleans up after running |fuzz_target_obj|.""" raise NotImplementedError('Not implemented for CoverageTargetRunner.') class CiFuzzTargetRunner(BaseFuzzTargetRunner): """Runner for fuzz targets used in CI (patch-fuzzing) context.""" @property def quit_on_bug_found(self): return True def cleanup_after_fuzz_target_run(self, fuzz_target_obj): # pylint: disable=no-self-use """Cleans up after running |fuzz_target_obj|.""" fuzz_target_obj.free_disk_if_needed() def run_fuzz_target(self, fuzz_target_obj): # pylint: disable=no-self-use return fuzz_target_obj.fuzz() class BatchFuzzTargetRunner(BaseFuzzTargetRunner): """Runner for fuzz targets used in batch fuzzing context.""" @property def quit_on_bug_found(self): return False def run_fuzz_target(self, fuzz_target_obj): """Fuzzes with |fuzz_target_obj| and returns the result.""" result = fuzz_target_obj.fuzz(batch=True) logging.debug('Corpus path contents: %s.', os.listdir(result.corpus_path)) self.clusterfuzz_deployment.upload_corpus(fuzz_target_obj.target_name, result.corpus_path) return result def cleanup_after_fuzz_target_run(self, fuzz_target_obj): """Cleans up after running |fuzz_target_obj|.""" # This must be done after we upload the corpus, otherwise it will be deleted # before we get a chance to upload it. We can't delete the fuzz target # because it is needed when we upload the build. fuzz_target_obj.free_disk_if_needed(delete_fuzz_target=False) _MODE_RUNNER_MAPPING = { 'batch': BatchFuzzTargetRunner, 'coverage': CoverageTargetRunner, 'prune': PruneTargetRunner, 'code-change': CiFuzzTargetRunner, } def get_fuzz_target_runner(config): """Returns a fuzz target runner object based on the mode of |config|.""" runner = _MODE_RUNNER_MAPPING[config.mode](config) logging.info('run fuzzers MODE is: %s. Runner: %s.', config.mode, runner) return runner def run_fuzzers(config): # pylint: disable=too-many-locals """Runs fuzzers for a specific OSS-Fuzz project. Args: config: A RunFuzzTargetsConfig. Returns: A RunFuzzersResult enum value indicating what happened during fuzzing. """ fuzz_target_runner = get_fuzz_target_runner(config) if not fuzz_target_runner.initialize(): # We didn't fuzz at all because of internal (CIFuzz) errors. And we didn't # find any bugs. return RunFuzzersResult.ERROR if not fuzz_target_runner.run_fuzz_targets(): # We fuzzed successfully, but didn't find any bugs (in the fuzz target). return RunFuzzersResult.NO_BUG_FOUND # We fuzzed successfully and found bug(s) in the fuzz targets. return RunFuzzersResult.BUG_FOUND ================================================ FILE: infra/cifuzz/run_fuzzers_entrypoint.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Runs a specific OSS-Fuzz project's fuzzers for CI tools.""" import logging import sys import config_utils import docker import logs import run_fuzzers # pylint: disable=c-extension-no-member # pylint gets confused because of the relative import of cifuzz. logs.init() def delete_unneeded_docker_images(config): """Deletes unneeded docker images if running in an environment with low disk space.""" if not config.low_disk_space: return logging.info('Deleting builder docker images to save disk space.') project_image = docker.get_project_image_name(config.oss_fuzz_project_name) images = [ project_image, docker.BASE_BUILDER_TAG, docker.BASE_BUILDER_TAG + '-go', docker.BASE_BUILDER_TAG + '-javascript', docker.BASE_BUILDER_TAG + '-jvm', docker.BASE_BUILDER_TAG + '-python', docker.BASE_BUILDER_TAG + '-rust', docker.BASE_BUILDER_TAG + '-ruby', docker.BASE_BUILDER_TAG + '-swift', ] docker.delete_images(images) def run_fuzzers_entrypoint(): """This is the entrypoint for the run_fuzzers github action. This action can be added to any OSS-Fuzz project's workflow that uses Github.""" config = config_utils.RunFuzzersConfig() if config.base_os_version == 'ubuntu-24-04': result = config_utils.pivot_to_ubuntu_24_04( 'run-fuzzers', '/opt/oss-fuzz/infra/cifuzz/run_fuzzers_entrypoint.py', check_result=not config.dry_run) if result is not None: return result # The default return code when an error occurs. returncode = 1 if config.dry_run: # Sets the default return code on error to success. returncode = 0 delete_unneeded_docker_images(config) # Run the specified project's fuzzers from the build. result = run_fuzzers.run_fuzzers(config) if result == run_fuzzers.RunFuzzersResult.ERROR: logging.error('Error occurred while running in workspace %s.', config.workspace) return returncode if result == run_fuzzers.RunFuzzersResult.BUG_FOUND: logging.info('Bug found.') if not config.dry_run: # Return 2 when a bug was found by a fuzzer causing the CI to fail. return 2 return 0 def main(): """Runs project's fuzzers for CI tools. This is the entrypoint for the run_fuzzers github action. NOTE: libFuzzer binaries must be located in the $WORKSPACE/build-out directory in order for this action to be used. This action will only fuzz the binaries that are located in that directory. It is recommended that you add the build_fuzzers action preceding this one. NOTE: Any crash report will be in the filepath: ${GITHUB_WORKSPACE}/out/testcase This can be used in parallel with the upload-artifact action to surface the logs. Returns: 0 on success or nonzero on failure. """ return run_fuzzers_entrypoint() if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/cifuzz/run_fuzzers_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for running fuzzers.""" import json import os import shutil import stat import sys import tempfile import unittest from unittest import mock import parameterized from pyfakefs import fake_filesystem_unittest import build_fuzzers import fuzz_target import run_fuzzers # pylint: disable=wrong-import-position INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(INFRA_DIR) import helper import test_helpers # NOTE: This integration test relies on # https://github.com/google/oss-fuzz/tree/master/projects/example project. EXAMPLE_PROJECT = 'example' # Location of files used for testing. TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_data') MEMORY_FUZZER_DIR = os.path.join(TEST_DATA_PATH, 'memory') MEMORY_FUZZER = 'curl_fuzzer_memory' UNDEFINED_FUZZER_DIR = os.path.join(TEST_DATA_PATH, 'undefined') UNDEFINED_FUZZER = 'curl_fuzzer_undefined' FUZZ_SECONDS = 10 class RunFuzzerIntegrationTestMixin: # pylint: disable=too-few-public-methods,invalid-name """Mixin for integration test classes that runbuild_fuzzers on builds of a specific sanitizer.""" # These must be defined by children. FUZZER_DIR = None FUZZER = None def setUp(self): """Patch the environ so that we can execute runner scripts.""" test_helpers.patch_environ(self, runner=True) def _test_run_with_sanitizer(self, fuzzer_dir, sanitizer): """Calls run_fuzzers on fuzzer_dir and |sanitizer| and asserts the run succeeded and that no bug was found.""" with test_helpers.temp_dir_copy(fuzzer_dir) as fuzzer_dir_copy: config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, workspace=fuzzer_dir_copy, oss_fuzz_project_name='curl', sanitizer=sanitizer) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class RunMemoryFuzzerIntegrationTest(RunFuzzerIntegrationTestMixin, unittest.TestCase): """Integration test for build_fuzzers with an MSAN build.""" FUZZER_DIR = MEMORY_FUZZER_DIR FUZZER = MEMORY_FUZZER def test_run_with_memory_sanitizer(self): """Tests run_fuzzers with a valid MSAN build.""" self._test_run_with_sanitizer(self.FUZZER_DIR, 'memory') @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class RunUndefinedFuzzerIntegrationTest(RunFuzzerIntegrationTestMixin, unittest.TestCase): """Integration test for build_fuzzers with an UBSAN build.""" FUZZER_DIR = UNDEFINED_FUZZER_DIR FUZZER = UNDEFINED_FUZZER def test_run_with_undefined_sanitizer(self): """Tests run_fuzzers with a valid UBSAN build.""" self._test_run_with_sanitizer(self.FUZZER_DIR, 'undefined') class BaseFuzzTargetRunnerTest(unittest.TestCase): """Tests BaseFuzzTargetRunner.""" def _create_runner(self, **kwargs): # pylint: disable=no-self-use defaults = { 'fuzz_seconds': FUZZ_SECONDS, 'oss_fuzz_project_name': EXAMPLE_PROJECT } for default_key, default_value in defaults.items(): if default_key not in kwargs: kwargs[default_key] = default_value config = test_helpers.create_run_config(**kwargs) return run_fuzzers.BaseFuzzTargetRunner(config) def _test_initialize_fail(self, expected_error_args, **create_runner_kwargs): with mock.patch('logging.error') as mock_error: runner = self._create_runner(**create_runner_kwargs) self.assertFalse(runner.initialize()) mock_error.assert_called_with(*expected_error_args) @parameterized.parameterized.expand([(0,), (None,), (-1,)]) def test_initialize_invalid_fuzz_seconds(self, fuzz_seconds): """Tests initialize fails with an invalid fuzz seconds.""" expected_error_args = ('Fuzz_seconds argument must be greater than 1, ' 'but was: %s.', fuzz_seconds) with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) with mock.patch('utils.get_fuzz_targets') as mock_get_fuzz_targets: mock_get_fuzz_targets.return_value = [ os.path.join(out_path, 'fuzz_target') ] self._test_initialize_fail(expected_error_args, fuzz_seconds=fuzz_seconds, workspace=tmp_dir) def test_initialize_no_out_dir(self): """Tests initialize fails with no out dir.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') expected_error_args = ('Out directory: %s does not exist.', out_path) self._test_initialize_fail(expected_error_args, workspace=tmp_dir) def test_initialize_nonempty_artifacts(self): """Tests initialize with a file artifacts path.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) os.makedirs(os.path.join(tmp_dir, 'out')) artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts') with open(artifacts_path, 'w') as artifacts_handle: artifacts_handle.write('fake') expected_error_args = ( 'Artifacts path: %s exists and is not an empty directory.', artifacts_path) self._test_initialize_fail(expected_error_args, workspace=tmp_dir) def test_initialize_bad_artifacts(self): """Tests initialize with a non-empty artifacts path.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts') os.makedirs(artifacts_path) artifact_path = os.path.join(artifacts_path, 'artifact') with open(artifact_path, 'w') as artifact_handle: artifact_handle.write('fake') expected_error_args = ( 'Artifacts path: %s exists and is not an empty directory.', artifacts_path) self._test_initialize_fail(expected_error_args, workspace=tmp_dir) @mock.patch('utils.get_fuzz_targets') @mock.patch('logging.error') def test_initialize_empty_artifacts(self, mock_log_error, mock_get_fuzz_targets): """Tests initialize with an empty artifacts dir.""" mock_get_fuzz_targets.return_value = ['fuzz-target'] with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) artifacts_path = os.path.join(tmp_dir, 'out', 'artifacts') os.makedirs(artifacts_path) runner = self._create_runner(workspace=tmp_dir) self.assertTrue(runner.initialize()) mock_log_error.assert_not_called() self.assertTrue(os.path.isdir(artifacts_path)) @mock.patch('utils.get_fuzz_targets') @mock.patch('logging.error') def test_initialize_no_artifacts(self, mock_log_error, mock_get_fuzz_targets): """Tests initialize with no artifacts dir (the expected setting).""" mock_get_fuzz_targets.return_value = ['fuzz-target'] with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) runner = self._create_runner(workspace=tmp_dir) self.assertTrue(runner.initialize()) mock_log_error.assert_not_called() self.assertTrue(os.path.isdir(os.path.join(tmp_dir, 'out', 'artifacts'))) def test_initialize_no_fuzz_targets(self): """Tests initialize with no fuzz targets.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.makedirs(out_path) expected_error_args = ('No fuzz targets were found in out directory: %s.', out_path) self._test_initialize_fail(expected_error_args, workspace=tmp_dir) class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): """Tests that CiFuzzTargetRunner works as intended.""" def setUp(self): self.setUpPyfakefs() @mock.patch('clusterfuzz_deployment.OSSFuzz.upload_crashes') @mock.patch('utils.get_fuzz_targets') @mock.patch('run_fuzzers.CiFuzzTargetRunner.run_fuzz_target') @mock.patch('run_fuzzers.CiFuzzTargetRunner.create_fuzz_target_obj') def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj, mock_run_fuzz_target, mock_get_fuzz_targets, mock_upload_crashes): """Tests that run_fuzz_targets quits on the first crash it finds.""" workspace = 'workspace' out_path = os.path.join(workspace, 'build-out') self.fs.create_dir(out_path) config = test_helpers.create_run_config( fuzz_seconds=FUZZ_SECONDS, workspace=workspace, oss_fuzz_project_name=EXAMPLE_PROJECT) runner = run_fuzzers.CiFuzzTargetRunner(config) mock_get_fuzz_targets.return_value = ['target1', 'target2'] runner.initialize() testcase = os.path.join(workspace, 'testcase') self.fs.create_file(testcase) stacktrace = 'stacktrace' corpus_dir = 'corpus' self.fs.create_dir(corpus_dir) mock_run_fuzz_target.return_value = fuzz_target.FuzzResult( testcase, stacktrace, corpus_dir) magic_mock = mock.MagicMock() magic_mock.target_name = 'target1' mock_create_fuzz_target_obj.return_value = magic_mock self.assertTrue(runner.run_fuzz_targets()) self.assertEqual(mock_run_fuzz_target.call_count, 1) self.assertEqual(mock_upload_crashes.call_count, 1) class BatchFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase): """Tests that BatchFuzzTargetRunnerTest works as intended.""" WORKSPACE = 'workspace' STACKTRACE = 'stacktrace' CORPUS_DIR = 'corpus' def setUp(self): self.setUpPyfakefs() out_dir = os.path.join(self.WORKSPACE, 'build-out') self.fs.create_dir(out_dir) self.testcase1 = os.path.join(out_dir, 'testcase-aaa') self.fs.create_file(self.testcase1) self.testcase2 = os.path.join(out_dir, 'testcase-bbb') self.fs.create_file(self.testcase2) self.config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, workspace=self.WORKSPACE, cfl_platform='github') @mock.patch('utils.get_fuzz_targets', return_value=['target1', 'target2']) @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_crashes') @mock.patch('run_fuzzers.BatchFuzzTargetRunner.run_fuzz_target') @mock.patch('run_fuzzers.BatchFuzzTargetRunner.create_fuzz_target_obj') def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj, mock_run_fuzz_target, mock_upload_crashes, _): """Tests that run_fuzz_targets doesn't quit on the first crash it finds.""" runner = run_fuzzers.BatchFuzzTargetRunner(self.config) runner.initialize() call_count = 0 def mock_run_fuzz_target_impl(_): nonlocal call_count if call_count == 0: testcase = self.testcase1 elif call_count == 1: testcase = self.testcase2 assert call_count != 2 call_count += 1 if not os.path.exists(self.CORPUS_DIR): self.fs.create_dir(self.CORPUS_DIR) return fuzz_target.FuzzResult(testcase, self.STACKTRACE, self.CORPUS_DIR) mock_run_fuzz_target.side_effect = mock_run_fuzz_target_impl magic_mock = mock.MagicMock() magic_mock.target_name = 'target1' mock_create_fuzz_target_obj.return_value = magic_mock self.assertTrue(runner.run_fuzz_targets()) self.assertEqual(mock_run_fuzz_target.call_count, 2) self.assertEqual(mock_upload_crashes.call_count, 1) class GetCoverageTargetsTest(unittest.TestCase): """Tests for get_coverage_fuzz_targets.""" def test_get_fuzz_targets(self): """Tests that get_coverage_fuzz_targets returns expected targets.""" with tempfile.TemporaryDirectory() as temp_dir: # Setup. fuzz_target_path = os.path.join(temp_dir, 'fuzz-target') with open(fuzz_target_path, 'w') as file_handle: file_handle.write('') fuzz_target_st = os.stat(fuzz_target_path) os.chmod(fuzz_target_path, fuzz_target_st.st_mode | stat.S_IEXEC) non_fuzz_target1 = os.path.join(temp_dir, 'non-fuzz-target1') with open(non_fuzz_target1, 'w') as file_handle: file_handle.write('LLVMFuzzerTestOneInput') subdir = os.path.join(temp_dir, 'subdir') os.mkdir(subdir) non_fuzz_target2 = os.path.join(subdir, 'non-fuzz-target1') with open(non_fuzz_target2, 'w') as file_handle: file_handle.write('LLVMFuzzerTestOneInput') self.assertEqual(run_fuzzers.get_coverage_fuzz_targets(temp_dir), [fuzz_target_path]) @unittest.skip('TODO(metzman): Fix this test') @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class CoverageReportIntegrationTest(unittest.TestCase): """Integration tests for coverage reports.""" SANITIZER = 'coverage' def setUp(self): test_helpers.patch_environ(self, runner=True) @mock.patch('filestore.github_actions._upload_artifact_with_upload_js') def test_coverage_report(self, _): """Tests generation of coverage reports end-to-end, from building to generation.""" with test_helpers.docker_temp_dir() as temp_dir: shared = os.path.join(temp_dir, 'shared') os.mkdir(shared) copy_command = ('cp -r /opt/code_coverage /shared && ' 'cp $(which llvm-profdata) /shared && ' 'cp $(which llvm-cov) /shared') assert helper.docker_run([ '-v', f'{shared}:/shared', 'gcr.io/oss-fuzz-base/base-runner', 'bash', '-c', copy_command ]) os.environ['CODE_COVERAGE_SRC'] = os.path.join(shared, 'code_coverage') os.environ['PATH'] += os.pathsep + shared # Do coverage build. build_config = test_helpers.create_build_config( oss_fuzz_project_name=EXAMPLE_PROJECT, project_repo_name='oss-fuzz', workspace=temp_dir, git_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523', base_commit='da0746452433dc18bae699e355a9821285d863c8', sanitizer=self.SANITIZER, cfl_platform='github', # Needed for test not to fail because of permissions issues. bad_build_check=False) self.assertTrue(build_fuzzers.build_fuzzers(build_config)) # TODO(metzman): Get rid of this here and make 'compile' do this. chmod_command = ('chmod -R +r /out && ' 'find /out -type d -exec chmod +x {} +') assert helper.docker_run([ '-v', f'{os.path.join(temp_dir, "build-out")}:/out', 'gcr.io/oss-fuzz-base/base-builder', 'bash', '-c', chmod_command ]) # Generate report. run_config = test_helpers.create_run_config(fuzz_seconds=FUZZ_SECONDS, workspace=temp_dir, sanitizer=self.SANITIZER, mode='coverage', cfl_platform='github') result = run_fuzzers.run_fuzzers(run_config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND) expected_summary_path = os.path.join( TEST_DATA_PATH, 'example_coverage_report_summary.json') with open(expected_summary_path) as file_handle: expected_summary = json.loads(file_handle.read()) actual_summary_path = os.path.join(temp_dir, 'cifuzz-coverage', 'report', 'linux', 'summary.json') with open(actual_summary_path) as file_handle: actual_summary = json.loads(file_handle.read()) self.assertEqual(expected_summary, actual_summary) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin, unittest.TestCase): """Integration tests for build_fuzzers with an ASAN build.""" BUILD_DIR_NAME = 'cifuzz-latest-build' def test_new_bug_found(self): """Tests run_fuzzers with a valid ASAN build.""" # Set the first return value to True, then the second to False to # emulate a bug existing in the current PR but not on the downloaded # OSS-Fuzz build. with mock.patch('fuzz_target.FuzzTarget.is_reproducible', side_effect=[True, False]): with tempfile.TemporaryDirectory() as tmp_dir: workspace = os.path.join(tmp_dir, 'workspace') shutil.copytree(TEST_DATA_PATH, workspace) config = test_helpers.create_run_config( fuzz_seconds=FUZZ_SECONDS, workspace=workspace, oss_fuzz_project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.BUG_FOUND) @mock.patch('fuzz_target.FuzzTarget.is_reproducible', side_effect=[True, True]) def test_old_bug_found(self, _): """Tests run_fuzzers with a bug found in OSS-Fuzz before.""" with tempfile.TemporaryDirectory() as tmp_dir: workspace = os.path.join(tmp_dir, 'workspace') shutil.copytree(TEST_DATA_PATH, workspace) config = test_helpers.create_run_config( fuzz_seconds=FUZZ_SECONDS, workspace=workspace, oss_fuzz_project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.NO_BUG_FOUND) def test_invalid_build(self): """Tests run_fuzzers with an invalid ASAN build.""" with tempfile.TemporaryDirectory() as tmp_dir: out_path = os.path.join(tmp_dir, 'build-out') os.mkdir(out_path) config = test_helpers.create_run_config( fuzz_seconds=FUZZ_SECONDS, workspace=tmp_dir, oss_fuzz_project_name=EXAMPLE_PROJECT) result = run_fuzzers.run_fuzzers(config) self.assertEqual(result, run_fuzzers.RunFuzzersResult.ERROR) class GetFuzzTargetRunnerTest(unittest.TestCase): """Tests for get_fuzz_fuzz_target_runner.""" @parameterized.parameterized.expand([ ('batch', run_fuzzers.BatchFuzzTargetRunner), ('code-change', run_fuzzers.CiFuzzTargetRunner), ('coverage', run_fuzzers.CoverageTargetRunner) ]) def test_get_fuzz_target_runner(self, mode, fuzz_target_runner_cls): """Tests that get_fuzz_target_runner returns the correct runner based on the specified mode.""" with tempfile.TemporaryDirectory() as tmp_dir: run_config = test_helpers.create_run_config( fuzz_seconds=FUZZ_SECONDS, workspace=tmp_dir, oss_fuzz_project_name='example', mode=mode) runner = run_fuzzers.get_fuzz_target_runner(run_config) self.assertTrue(isinstance(runner, fuzz_target_runner_cls)) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/cifuzz/sarif_utils.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for outputting SARIF data.""" import copy import json import logging import os from clusterfuzz import stacktraces SARIF_RULES = [ { 'id': 'no-crashes', 'shortDescription': { 'text': 'Don\'t crash' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/416.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'heap-use-after-free', 'shortDescription': { 'text': 'Use of a heap-object after it has been freed.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/416.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'heap-buffer-overflow', 'shortDescription': { 'text': 'A read or write past the end of a heap buffer.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/122.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'stack-buffer-overflow', 'shortDescription': { 'text': 'A read or write past the end of a stack buffer.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/121.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'global-buffer-overflow', 'shortDescription': { 'text': 'A read or write past the end of a global buffer.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/121.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'stack-use-after-return', 'shortDescription': { 'text': 'A stack-based variable has been used after the function returned.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/562.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'stack-use-after-scope', 'shortDescription': { 'text': 'A stack-based variable has been used outside of the scope in which it exists.' }, 'helpUri': 'https://cwe.mitre.org/data/definitions/562.html', 'properties': { 'category': 'Crashes' } }, { 'id': 'initialization-order-fiasco', 'shortDescription': { 'text': 'Problem with order of initialization of global objects.' }, 'helpUri': 'https://isocpp.org/wiki/faq/ctors#static-init-order', 'properties': { 'category': 'Crashes' } }, { 'id': 'direct-leak', 'shortDescription': { 'text': 'Memory is leaked.' }, 'helpUri': 'https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer', 'properties': { 'category': 'Crashes' } }, { 'id': 'indirect-leak', 'shortDescription': { 'text': 'Memory is leaked.' }, 'helpUri': 'https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer', 'properties': { 'category': 'Crashes' } }, ] SARIF_DATA = { 'version': '2.1.0', '$schema': 'http://json.schemastore.org/sarif-2.1.0-rtm.4', 'runs': [{ 'tool': { 'driver': { 'name': 'ClusterFuzzLite/CIFuzz', 'informationUri': 'https://google.github.io/clusterfuzzlite/', 'rules': SARIF_RULES, } }, 'results': [] }] } SRC_ROOT = '/src/' def redact_src_path(src_path): """Redact the src path so that it can be reported to users.""" src_path = os.path.normpath(src_path) if src_path.startswith(SRC_ROOT): src_path = src_path[len(SRC_ROOT):] src_path = os.sep.join(src_path.split(os.sep)[1:]) return src_path def get_error_frame(crash_info): """Returns the stackframe where the error occurred.""" if not crash_info.crash_state: return None state = crash_info.crash_state.split('\n')[0] logging.info('state: %s frames %s, %s', state, crash_info.frames, [f.function_name for f in crash_info.frames[0]]) for crash_frames in crash_info.frames: for frame in crash_frames: # TODO(metzman): Do something less fragile here. if frame.function_name is None: continue if state in frame.function_name: return frame return None def get_error_source_info(crash_info): """Returns the filename and the line where the bug occurred.""" frame = get_error_frame(crash_info) if not frame: return (None, 1) try: return redact_src_path(frame.filename), int(frame.fileline or 1) except TypeError: return (None, 1) def get_rule_index(crash_type): """Returns the rule index describe the rule that |crash_type| ran afoul of.""" # Don't include "READ" or "WRITE" or number of bytes. crash_type = crash_type.replace('\n', ' ').split(' ')[0].lower() logging.info('crash_type: %s.', crash_type) for idx, rule in enumerate(SARIF_RULES): if rule['id'] == crash_type: logging.info('Rule index: %d.', idx) return idx return get_rule_index('no-crashes') def get_sarif_data(stacktrace, target_path): """Returns a description of the crash in SARIF.""" data = copy.deepcopy(SARIF_DATA) if stacktrace is None: return data fuzz_target = os.path.basename(target_path) stack_parser = stacktraces.StackParser(fuzz_target=fuzz_target, symbolized=True, detect_ooms_and_hangs=True, include_ubsan=True) crash_info = stack_parser.parse(stacktrace) error_source_info = get_error_source_info(crash_info) rule_idx = get_rule_index(crash_info.crash_type) rule_id = SARIF_RULES[rule_idx]['id'] uri = error_source_info[0] result = { 'level': 'error', 'message': { 'text': crash_info.crash_type }, 'locations': [{ 'physicalLocation': { 'artifactLocation': { 'uri': uri, 'index': 0 }, 'region': { 'startLine': error_source_info[1], # We don't have this granualarity fuzzing. 'startColumn': 1, } } }], 'ruleId': rule_id, 'ruleIndex': rule_idx } if uri: data['runs'][0]['results'].append(result) return data def write_stacktrace_to_sarif(stacktrace, target_path, workspace): """Writes a description of the crash in stacktrace to a SARIF file.""" data = get_sarif_data(stacktrace, target_path) if not os.path.exists(workspace.sarif): os.makedirs(workspace.sarif) with open(os.path.join(workspace.sarif, 'results.sarif'), 'w') as file_handle: file_handle.write(json.dumps(data)) ================================================ FILE: infra/cifuzz/sarif_utils_test.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for sarif_utils.py""" import os import unittest from unittest import mock import sarif_utils CRASH_INFO_FILELINE = 403 TEST_DATA = os.path.join(os.path.dirname(__file__), 'test_data') class GetSarifDataTest(unittest.TestCase): """Tests for get_sarif_data.""" def setUp(self): self.maxDiff = None # pylint: disable=invalid-name def test_get_sarif_data_none(self): """Tests get_sarif_data when there was no crash.""" self.assertEqual(sarif_utils.get_sarif_data(None, '/root/target'), sarif_utils.SARIF_DATA) def test_ordinary_case(self): stacktrace_filename = os.path.join(TEST_DATA, 'sarif_utils_systemd_stack.txt') with open(stacktrace_filename, 'r') as fp: stacktrace = fp.read() expected_result = { 'level': 'error', 'message': { 'text': 'Heap-buffer-overflow\nREAD 4' }, 'locations': [{ 'physicalLocation': { 'artifactLocation': { 'uri': 'src/core/fuzz-unit-file.c', 'index': 0 }, 'region': { 'startLine': 30, # We don't have this granualarity fuzzing. 'startColumn': 1, } } }], 'ruleId': 'heap-buffer-overflow', 'ruleIndex': 2 } actual_result = sarif_utils.get_sarif_data( stacktrace, '/root/target')['runs'][0]['results'][0] self.assertEqual(actual_result, expected_result) def test_llvmfuzzertestoneinput_case(self): stacktrace_filename = os.path.join(TEST_DATA, 'sarif_utils_only_llvmfuzzer_stack.txt') with open(stacktrace_filename, 'r') as fp: stacktrace = fp.read() actual_result = sarif_utils.get_sarif_data( stacktrace, '/root/target')['runs'][0]['results'] self.assertEqual(actual_result, []) def test_msan(self): """Tests that MSAN stacktraces don't exception.""" stacktrace_filename = os.path.join(TEST_DATA, 'sarif_utils_msan_stack.txt') with open(stacktrace_filename, 'r') as fp: stacktrace = fp.read() actual_result = sarif_utils.get_sarif_data(stacktrace, '/root/target') class RedactSrcPathTest(unittest.TestCase): """Tests for redact_src_path.""" def test_redact_src_path(self): """Tests redact_src_path.""" path = '/src/src-repo/subdir/file' self.assertEqual(sarif_utils.redact_src_path(path), 'subdir/file') def _get_mock_crash_info(): """Returns a mock crash_info to be used in tests.""" stack_frame = mock.MagicMock() stack_frame.filename = '/src/repo-dir/sub/vuln.cc' stack_frame.function_name = 'vuln_func' stack_frame.fileline = CRASH_INFO_FILELINE crash1_frames = [stack_frame, stack_frame] frames = [crash1_frames] crash_info = mock.MagicMock() crash_info.frames = frames crash_info.crash_state = 'vuln_func\nvuln_func0\nvuln_func1' return crash_info class GetErrorSourceInfoTest(unittest.TestCase): """Tests for get_error_source_info.""" def test_redact_src_path(self): """Tests that get_error_source_info finds the right source info.""" crash_info = _get_mock_crash_info() source_info = sarif_utils.get_error_source_info(crash_info) expected_source_info = ('sub/vuln.cc', CRASH_INFO_FILELINE) self.assertEqual(source_info, expected_source_info) class GetRuleIndexTest(unittest.TestCase): """Tests for get_rule_index.""" CRASH_INFO_CRASH_TYPE = 'Heap-use-after-free READ 8' def test_get_rule_index(self): """Tests that get_rule_index finds the right rule index.""" index = sarif_utils.get_rule_index(self.CRASH_INFO_CRASH_TYPE) self.assertEqual(sarif_utils.SARIF_RULES[index]['id'], 'heap-use-after-free') self.assertEqual(sarif_utils.get_rule_index('no-crashes'), 0) ================================================ FILE: infra/cifuzz/test_data/TimeoutFuzzer.cpp ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Example of a standalone runner for "fuzz targets". // It reads all files passed as parameters and feeds their contents // one by one into the fuzz target (LLVMFuzzerTestOneInput). // This runner does not do any fuzzing, but allows us to run the fuzz target // on the test corpus (e.g. "do_stuff_test_data") or on a single file, // e.g. the one that comes from a bug report. // This is a fuzz target that times out on every input by infinite looping. // This is used for testing. // Build instructions: // 1. clang++ -fsanitize=fuzzer TimeoutFuzzer.cpp -o timeout_fuzzer // 2. strip timeout_fuzzer // The binary is stripped to save space in the git repo. #include #include extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { while (true) ; return 0; } ================================================ FILE: infra/cifuzz/test_data/example_coverage_report_summary.json ================================================ {"data": [{"files": [{"filename": "/src/my-git-repo/projects/example/my-api-repo/do_stuff_fuzzer.cpp", "summary": {"branches": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}, "functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 5, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/my-git-repo/projects/example/my-api-repo/my_api.cpp", "summary": {"branches": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}, "functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 15, "covered": 0, "percent": 0}, "regions": {"count": 11, "covered": 0, "notcovered": 11, "percent": 0}}}], "totals": {"branches": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}, "functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 20, "covered": 0, "percent": 0}, "regions": {"count": 12, "covered": 0, "notcovered": 12, "percent": 0}}}], "type": "llvm.coverage.json.export", "version": "2.0.1"} ================================================ FILE: infra/cifuzz/test_data/example_crash_fuzzer_bug_summary.txt ================================================ AddressSanitizer: heap-buffer-overflow on address 0x62500001b530 at pc 0x00000052138a bp 0x7ffe62db2c10 sp 0x7ffe62db23d8 READ of size 52 at 0x62500001b530 thread T0 SCARINESS: 26 (multi-byte-read-heap-buffer-overflow) #0 0x521389 in __asan_memcpy /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 #1 0x567590 in yr_object_set_string /src/yara/libyara/object.c:1122:5 #2 0x5afced in dex_parse /src/yara/libyara/modules/dex/dex.c:781:5 #3 0x5b4a8b in dex__load /src/yara/libyara/modules/dex/dex.c:1218:7 #4 0x56537c in yr_modules_load /src/yara/libyara/modules.c:179:16 #5 0x5d6583 in yr_execute_code /src/yara/libyara/exec.c:1276:18 #6 0x56f5c0 in yr_scanner_scan_mem_blocks /src/yara/libyara/scanner.c:444:3 #7 0x56bf23 in yr_rules_scan_mem_blocks /src/yara/libyara/rules.c:235:12 #8 0x56c182 in yr_rules_scan_mem /src/yara/libyara/rules.c:285:10 #9 0x5548d2 in LLVMFuzzerTestOneInput /src/yara/tests/oss-fuzz/dex_fuzzer.cc:40:3 #10 0x45a3b1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:556:15 #11 0x459ad5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:470:3 #12 0x45be77 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:698:19 #13 0x45cc05 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:830:5 #14 0x44ac88 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:824:6 #15 0x474ab2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:19:10 #16 0x7f4409b7a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #17 0x41e348 in _start (out/dex_fuzzer+0x41e348) 0x62500001b530 is located 0 bytes to the right of 9264-byte region [0x625000019100,0x62500001b530) allocated by thread T0 here: #0 0x521f4d in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3 #1 0x4331b7 in operator new(unsigned long) (out/dex_fuzzer+0x4331b7) #2 0x459ad5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:470:3 #3 0x45be77 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:698:19 #4 0x45cc05 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:830:5 #5 0x44ac88 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:824:6 #6 0x474ab2 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:19:10 #7 0x7f4409b7a82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) SUMMARY: AddressSanitizer: heap-buffer-overflow /src/llvm-project/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cpp:22:3 in __asan_memcpy Shadow bytes around the buggy address: 0x0c4a7fffb650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fffb660: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fffb670: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fffb680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x0c4a7fffb690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c4a7fffb6a0: 00 00 00 00 00 00[fa]fa fa fa fa fa fa fa fa fa 0x0c4a7fffb6b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fffb6c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fffb6d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fffb6e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c4a7fffb6f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc ==12==ABORTING ================================================ FILE: infra/cifuzz/test_data/example_crash_fuzzer_output.txt ================================================ /github/workspace/build-out/do_stuff_fuzzer -timeout=25 -rss_limit_mb=2560 -dict=/github/workspace/build-out/do_stuff_fuzzer.dict -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmp9p1w4p8r/ -max_total_time=600 -print_final_stats=1 /github/workspace/cifuzz-corpus/do_stuff_fuzzer >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 77 ============ Dictionary: 3 entries INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 1 modules (86 inline 8-bit counters): 86 [0x6150e0, 0x615136), INFO: Loaded 1 PC tables (86 PCs): 86 [0x5c8b08,0x5c9068), INFO: 5 files found in /github/workspace/cifuzz-corpus/do_stuff_fuzzer INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes INFO: seed corpus: files: 5 min: 3b max: 44b total: 64b rss: 31Mb #6 INITED cov: 64 ft: 70 corp: 5/64b exec/s: 0 rss: 32Mb #9 NEW cov: 64 ft: 72 corp: 6/74b lim: 4096 exec/s: 0 rss: 32Mb L: 10/44 MS: 3 ChangeBit-InsertByte-ManualDict- DE: "foo"- #17 NEW cov: 64 ft: 74 corp: 7/86b lim: 4096 exec/s: 0 rss: 32Mb L: 12/44 MS: 3 ChangeBit-ManualDict-PersAutoDict- DE: "ouch"-"foo"- #18 NEW cov: 64 ft: 76 corp: 8/100b lim: 4096 exec/s: 0 rss: 32Mb L: 14/44 MS: 1 CrossOver- #22 NEW cov: 64 ft: 78 corp: 9/141b lim: 4096 exec/s: 0 rss: 32Mb L: 41/44 MS: 4 InsertRepeatedBytes-CopyPart-ChangeBinInt-ChangeBit- #24 NEW cov: 64 ft: 80 corp: 10/151b lim: 4096 exec/s: 0 rss: 32Mb L: 10/44 MS: 2 CrossOver-CopyPart- #28 NEW cov: 64 ft: 81 corp: 11/171b lim: 4096 exec/s: 0 rss: 32Mb L: 20/44 MS: 4 InsertByte-PersAutoDict-ShuffleBytes-ManualDict- DE: "foo"-"ouch"- #43 NEW cov: 65 ft: 83 corp: 12/175b lim: 4096 exec/s: 0 rss: 32Mb L: 4/44 MS: 5 InsertByte-ChangeBit-ManualDict-ManualDict-EraseBytes- DE: "bar"-"bar"- #54 NEW cov: 65 ft: 84 corp: 13/191b lim: 4096 exec/s: 0 rss: 32Mb L: 16/44 MS: 1 CrossOver- #64 NEW cov: 65 ft: 86 corp: 14/209b lim: 4096 exec/s: 0 rss: 32Mb L: 18/44 MS: 5 InsertByte-ChangeBinInt-CMP-PersAutoDict-CopyPart- DE: "\000\000"-"foo"- #75 REDUCE cov: 65 ft: 86 corp: 14/203b lim: 4096 exec/s: 0 rss: 32Mb L: 35/44 MS: 1 EraseBytes- #76 REDUCE cov: 65 ft: 86 corp: 14/195b lim: 4096 exec/s: 0 rss: 32Mb L: 36/36 MS: 1 EraseBytes- ================================================================= ==26==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000003114 at pc 0x00000056d1db bp 0x7fffd6a72bf0 sp 0x7fffd6a72be8 READ of size 4 at 0x603000003114 thread T0 SCARINESS: 17 (4-byte-read-heap-buffer-overflow) #0 0x56d1da in DoStuff(std::__1::basic_string, std::__1::allocator > const&) /src/cifuzz-example/my_api.cpp:26:10 #1 0x56c5d6 in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:15:3 #2 0x43de23 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x43d60a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x43ecd9 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:757:19 #5 0x43f9a5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:895:5 #6 0x42ed0f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x458362 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7fcfaa2aa082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #9 0x41f74d in _start (build-out/do_stuff_fuzzer+0x41f74d) DEDUP_TOKEN: DoStuff(std::__1::basic_string, std::__1::allocator > const&)--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) 0x603000003114 is located 0 bytes to the right of 20-byte region [0x603000003100,0x603000003114) allocated by thread T0 here: #0 0x569dfd in operator new(unsigned long) /src/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3 #1 0x56c9d4 in __libcpp_operator_new /usr/local/bin/../include/c++/v1/new:245:10 #2 0x56c9d4 in __libcpp_allocate /usr/local/bin/../include/c++/v1/new:271:10 #3 0x56c9d4 in allocate /usr/local/bin/../include/c++/v1/__memory/allocator.h:105:38 #4 0x56c9d4 in allocate /usr/local/bin/../include/c++/v1/__memory/allocator_traits.h:262:20 #5 0x56c9d4 in __vallocate /usr/local/bin/../include/c++/v1/vector:931:37 #6 0x56c9d4 in vector /usr/local/bin/../include/c++/v1/vector:1236:9 #7 0x56c9d4 in DoStuff(std::__1::basic_string, std::__1::allocator > const&) /src/cifuzz-example/my_api.cpp:14:20 #8 0x56c5d6 in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:15:3 #9 0x43de23 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #10 0x43d60a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #11 0x43ecd9 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:757:19 #12 0x43f9a5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:895:5 #13 0x42ed0f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #14 0x458362 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #15 0x7fcfaa2aa082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: operator new(unsigned long)--__libcpp_operator_new--__libcpp_allocate SUMMARY: AddressSanitizer: heap-buffer-overflow /src/cifuzz-example/my_api.cpp:26:10 in DoStuff(std::__1::basic_string, std::__1::allocator > const&) Shadow bytes around the buggy address: 0x0c067fff85d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff85e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff85f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8600: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd 0x0c067fff8610: fd fa fa fa fd fd fd fa fa fa 00 00 00 00 fa fa =>0x0c067fff8620: 00 00[04]fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8630: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8640: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8650: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8660: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8670: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==26==ABORTING MS: 4 PersAutoDict-ManualDict-CrossOver-PersAutoDict- DE: "foo"-"ouch"-"bar"-; base unit: 1a25c32303e03f997166aee1c665b5ae9f66ec7d 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x66,0x6f,0x6f,0xff,0x1,0x62,0x61,0x72,0x63,0x68,0x6f,0x75,0x63,0x68,0x66,0x6f,0x66,0x6e,0x6f,0x6d,0x67,0x6d, \377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377foo\377\001barchouchfofnomgm artifact_prefix='/tmp/tmp9p1w4p8r/'; Test unit written to /tmp/tmp9p1w4p8r/crash-1c750df432fe458b738987ba69cd20a598708775 Base64: //////////////////////9mb2//AWJhcmNob3VjaGZvZm5vbWdt stat::number_of_executed_units: 90 stat::average_exec_per_sec: 0 stat::new_units_added: 11 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 33 /github/workspace/build-out/do_stuff_fuzzer -timeout=25 -rss_limit_mb=2560 -dict=/github/workspace/build-out/do_stuff_fuzzer.dict -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmp9p1w4p8r/ -max_total_time=600 -print_final_stats=1 /github/workspace/cifuzz-corpus/do_stuff_fuzzer >fuzz-1.log 2>&1 ================== Job 1 exited with exit code 77 ============ Dictionary: 3 entries INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 1 modules (86 inline 8-bit counters): 86 [0x6150e0, 0x615136), INFO: Loaded 1 PC tables (86 PCs): 86 [0x5c8b08,0x5c9068), INFO: 15 files found in /github/workspace/cifuzz-corpus/do_stuff_fuzzer INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes INFO: seed corpus: files: 15 min: 3b max: 44b total: 239b rss: 31Mb #16 INITED cov: 65 ft: 86 corp: 13/159b exec/s: 0 rss: 32Mb #38 NEW cov: 65 ft: 88 corp: 14/188b lim: 4096 exec/s: 0 rss: 32Mb L: 29/35 MS: 2 InsertByte-CopyPart- #43 REDUCE cov: 65 ft: 88 corp: 14/187b lim: 4096 exec/s: 0 rss: 32Mb L: 2/35 MS: 5 InsertByte-ChangeByte-ChangeBinInt-EraseBytes-EraseBytes- #64 NEW cov: 66 ft: 89 corp: 15/191b lim: 4096 exec/s: 0 rss: 32Mb L: 4/35 MS: 1 ChangeByte- #78 REDUCE cov: 66 ft: 89 corp: 15/190b lim: 4096 exec/s: 0 rss: 32Mb L: 15/35 MS: 4 ChangeBinInt-CopyPart-EraseBytes-EraseBytes- #95 REDUCE cov: 66 ft: 89 corp: 15/188b lim: 4096 exec/s: 0 rss: 32Mb L: 16/35 MS: 2 ChangeBinInt-EraseBytes- #110 REDUCE cov: 66 ft: 89 corp: 15/184b lim: 4096 exec/s: 0 rss: 32Mb L: 31/31 MS: 5 CrossOver-ChangeByte-ShuffleBytes-InsertByte-EraseBytes- #146 REDUCE cov: 66 ft: 89 corp: 15/183b lim: 4096 exec/s: 0 rss: 32Mb L: 1/31 MS: 1 EraseBytes- #157 NEW cov: 66 ft: 90 corp: 16/210b lim: 4096 exec/s: 0 rss: 32Mb L: 27/31 MS: 1 CrossOver- #230 REDUCE cov: 66 ft: 92 corp: 17/318b lim: 4096 exec/s: 0 rss: 32Mb L: 108/108 MS: 3 CopyPart-InsertRepeatedBytes-CrossOver- #277 NEW cov: 66 ft: 94 corp: 18/429b lim: 4096 exec/s: 0 rss: 32Mb L: 111/111 MS: 2 ManualDict-CMP- DE: "bar"-"\000\000\000\000"- #337 NEW cov: 67 ft: 95 corp: 19/439b lim: 4096 exec/s: 0 rss: 32Mb L: 10/111 MS: 5 ChangeByte-ChangeBit-ManualDict-CopyPart-EraseBytes- DE: "bar"- ================================================================= ==30==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000007d94 at pc 0x00000056d1db bp 0x7ffdb9da4b50 sp 0x7ffdb9da4b48 READ of size 4 at 0x603000007d94 thread T0 SCARINESS: 17 (4-byte-read-heap-buffer-overflow) #0 0x56d1da in DoStuff(std::__1::basic_string, std::__1::allocator > const&) /src/cifuzz-example/my_api.cpp:26:10 #1 0x56c5d6 in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:15:3 #2 0x43de23 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x43d60a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x43ecd9 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:757:19 #5 0x43f9a5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:895:5 #6 0x42ed0f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x458362 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7fc2c6bd3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #9 0x41f74d in _start (build-out/do_stuff_fuzzer+0x41f74d) DEDUP_TOKEN: DoStuff(std::__1::basic_string, std::__1::allocator > const&)--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) 0x603000007d94 is located 0 bytes to the right of 20-byte region [0x603000007d80,0x603000007d94) allocated by thread T0 here: #0 0x569dfd in operator new(unsigned long) /src/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:95:3 #1 0x56c9d4 in __libcpp_operator_new /usr/local/bin/../include/c++/v1/new:245:10 #2 0x56c9d4 in __libcpp_allocate /usr/local/bin/../include/c++/v1/new:271:10 #3 0x56c9d4 in allocate /usr/local/bin/../include/c++/v1/__memory/allocator.h:105:38 #4 0x56c9d4 in allocate /usr/local/bin/../include/c++/v1/__memory/allocator_traits.h:262:20 #5 0x56c9d4 in __vallocate /usr/local/bin/../include/c++/v1/vector:931:37 #6 0x56c9d4 in vector /usr/local/bin/../include/c++/v1/vector:1236:9 #7 0x56c9d4 in DoStuff(std::__1::basic_string, std::__1::allocator > const&) /src/cifuzz-example/my_api.cpp:14:20 #8 0x56c5d6 in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:15:3 #9 0x43de23 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #10 0x43d60a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #11 0x43ecd9 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:757:19 #12 0x43f9a5 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:895:5 #13 0x42ed0f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #14 0x458362 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #15 0x7fc2c6bd3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: operator new(unsigned long)--__libcpp_operator_new--__libcpp_allocate SUMMARY: AddressSanitizer: heap-buffer-overflow /src/cifuzz-example/my_api.cpp:26:10 in DoStuff(std::__1::basic_string, std::__1::allocator > const&) Shadow bytes around the buggy address: 0x0c067fff8f60: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd 0x0c067fff8f70: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa 0x0c067fff8f80: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa 0x0c067fff8f90: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd 0x0c067fff8fa0: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa =>0x0c067fff8fb0: 00 00[04]fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8fc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8fd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8fe0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff8ff0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c067fff9000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==30==ABORTING MS: 4 ShuffleBytes-ManualDict-CrossOver-PersAutoDict- DE: "foo"-"bar"-; base unit: 8fc7da8d952ed1aa5c7415e21b3d52b42402973d 0x66,0x6f,0x6f,0x63,0x6f,0x75,0x6f,0x75,0x63,0x68,0x63,0x68,0x66,0x62,0x61,0x72,0x6f,0x6f,0x6d,0x67,0x66,0x6f,0x6f,0x2f,0x99,0x6f,0x6f,0x90,0x6f,0x6f,0x6d,0x0,0x0,0x67,0x2f, foocououchchfbaroomgfoo/\231oo\220oom\000\000g/ artifact_prefix='/tmp/tmp9p1w4p8r/'; Test unit written to /tmp/tmp9p1w4p8r/crash-f8a2a1e84f58a2d676e5ad8078119a39b78df901 Base64: Zm9vY291b3VjaGNoZmJhcm9vbWdmb28vmW9vkG9vbQAAZy8= stat::number_of_executed_units: 366 stat::average_exec_per_sec: 0 stat::new_units_added: 11 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 33 ================================================ FILE: infra/cifuzz/test_data/example_curl_cov.json ================================================ {"report_summary_path": "gs://oss-fuzz-coverage/curl/reports/20200226/linux/summary.json", "html_report_url": "https://storage.googleapis.com/oss-fuzz-coverage/curl/reports/20200226/linux/index.html", "report_date": "20200226", "fuzzer_stats_dir": "gs://oss-fuzz-coverage/curl/fuzzer_stats/20200226"} ================================================ FILE: infra/cifuzz/test_data/example_curl_file_list.json ================================================ ["lib/asyn-thread.c", "lib/base64.c", "lib/conncache.c", "lib/connect.c", "lib/content_encoding.c", "lib/cookie.c", "lib/curl_addrinfo.c", "lib/curl_ctype.c", "lib/curl_endian.c", "lib/curl_fnmatch.c", "lib/curl_gethostname.c", "lib/curl_memrchr.c", "lib/curl_ntlm_core.c", "lib/curl_ntlm_wb.c", "lib/curl_range.c", "lib/curl_sasl.c", "lib/curl_threads.c", "lib/dict.c", "lib/dotdot.c", "lib/easy.c", "lib/escape.c", "lib/file.c", "lib/fileinfo.c", "lib/ftp.c", "lib/ftplistparser.c", "lib/getenv.c", "lib/getinfo.c", "lib/gopher.c", "lib/hash.c", "lib/hmac.c", "lib/hostasyn.c", "lib/hostip.c", "lib/hostip6.c", "lib/http.c", "lib/http2.c", "lib/http_chunks.c", "lib/http_digest.c", "lib/http_ntlm.c", "lib/http_proxy.c", "lib/if2ip.c", "lib/imap.c", "lib/llist.c", "lib/md4.c", "lib/md5.c", "lib/memdebug.c", "lib/mime.c", "lib/mprintf.c", "lib/multi.c", "lib/nonblock.c", "lib/parsedate.c", "lib/pingpong.c", "lib/pop3.c", "lib/progress.c", "lib/rand.c", "lib/rename.c", "lib/rtsp.c", "lib/select.c", "lib/sendf.c", "lib/setopt.c", "lib/share.c", "lib/sigpipe.h", "lib/slist.c", "lib/smb.c", "lib/smtp.c", "lib/speedcheck.c", "lib/splay.c", "lib/strcase.c", "lib/strdup.c", "lib/strerror.c", "lib/strtoofft.c", "lib/tftp.c", "lib/timeval.c", "lib/transfer.c", "lib/url.c", "lib/urlapi.c", "lib/vauth/cleartext.c", "lib/vauth/cram.c", "lib/vauth/digest.c", "lib/vauth/ntlm.c", "lib/version.c", "lib/vtls/openssl.c", "lib/vtls/vtls.c", "lib/warnless.c", "lib/wildcard.c"] ================================================ FILE: infra/cifuzz/test_data/example_curl_fuzzer_cov.json ================================================ {"data": [{"files": [{"filename": "/src/curl/include/curl/curl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/include/curl/curlver.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/include/curl/multi.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/include/curl/system.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/include/curl/urlapi.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/amigaos.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/arpa_telnet.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/asyn-thread.c", "summary": {"functions": {"count": 24, "covered": 17, "percent": 70.83333333333334}, "instantiations": {"count": 24, "covered": 17, "percent": 70.83333333333334}, "lines": {"count": 454, "covered": 316, "percent": 69.60352422907489}, "regions": {"count": 206, "covered": 133, "notcovered": 73, "percent": 64.56310679611651}}}, {"filename": "/src/curl/lib/asyn.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/base64.c", "summary": {"functions": {"count": 5, "covered": 5, "percent": 100}, "instantiations": {"count": 5, "covered": 5, "percent": 100}, "lines": {"count": 205, "covered": 199, "percent": 97.07317073170731}, "regions": {"count": 81, "covered": 76, "notcovered": 5, "percent": 93.82716049382715}}}, {"filename": "/src/curl/lib/conncache.c", "summary": {"functions": {"count": 22, "covered": 20, "percent": 90.9090909090909}, "instantiations": {"count": 22, "covered": 20, "percent": 90.9090909090909}, "lines": {"count": 405, "covered": 267, "percent": 65.92592592592592}, "regions": {"count": 225, "covered": 123, "notcovered": 102, "percent": 54.666666666666664}}}, {"filename": "/src/curl/lib/conncache.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/connect.c", "summary": {"functions": {"count": 21, "covered": 16, "percent": 76.19047619047619}, "instantiations": {"count": 21, "covered": 16, "percent": 76.19047619047619}, "lines": {"count": 1074, "covered": 439, "percent": 40.87523277467412}, "regions": {"count": 596, "covered": 233, "notcovered": 363, "percent": 39.09395973154363}}}, {"filename": "/src/curl/lib/connect.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/content_encoding.c", "summary": {"functions": {"count": 28, "covered": 27, "percent": 96.42857142857143}, "instantiations": {"count": 28, "covered": 27, "percent": 96.42857142857143}, "lines": {"count": 582, "covered": 404, "percent": 69.41580756013745}, "regions": {"count": 338, "covered": 223, "notcovered": 115, "percent": 65.97633136094674}}}, {"filename": "/src/curl/lib/cookie.c", "summary": {"functions": {"count": 27, "covered": 20, "percent": 74.07407407407408}, "instantiations": {"count": 27, "covered": 20, "percent": 74.07407407407408}, "lines": {"count": 1341, "covered": 837, "percent": 62.41610738255034}, "regions": {"count": 1020, "covered": 615, "notcovered": 405, "percent": 60.29411764705882}}}, {"filename": "/src/curl/lib/cookie.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_addrinfo.c", "summary": {"functions": {"count": 8, "covered": 5, "percent": 62.5}, "instantiations": {"count": 8, "covered": 5, "percent": 62.5}, "lines": {"count": 339, "covered": 149, "percent": 43.95280235988201}, "regions": {"count": 148, "covered": 52, "notcovered": 96, "percent": 35.13513513513514}}}, {"filename": "/src/curl/lib/curl_config.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_ctype.c", "summary": {"functions": {"count": 10, "covered": 8, "percent": 80}, "instantiations": {"count": 10, "covered": 8, "percent": 80}, "lines": {"count": 50, "covered": 39, "percent": 78}, "regions": {"count": 96, "covered": 73, "notcovered": 23, "percent": 76.04166666666666}}}, {"filename": "/src/curl/lib/curl_ctype.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_endian.c", "summary": {"functions": {"count": 5, "covered": 2, "percent": 40}, "instantiations": {"count": 5, "covered": 2, "percent": 40}, "lines": {"count": 22, "covered": 8, "percent": 36.36363636363637}, "regions": {"count": 5, "covered": 2, "notcovered": 3, "percent": 40}}}, {"filename": "/src/curl/lib/curl_fnmatch.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 18, "covered": 15, "percent": 83.33333333333334}, "regions": {"count": 13, "covered": 9, "notcovered": 4, "percent": 69.23076923076923}}}, {"filename": "/src/curl/lib/curl_fnmatch.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_get_line.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 21, "covered": 0, "percent": 0}, "regions": {"count": 18, "covered": 0, "notcovered": 18, "percent": 0}}}, {"filename": "/src/curl/lib/curl_gethostname.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 30, "covered": 25, "percent": 83.33333333333334}, "regions": {"count": 9, "covered": 6, "notcovered": 3, "percent": 66.66666666666666}}}, {"filename": "/src/curl/lib/curl_hmac.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_md5.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_memrchr.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 15, "covered": 15, "percent": 100}, "regions": {"count": 9, "covered": 9, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/curl_memrchr.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_ntlm_core.c", "summary": {"functions": {"count": 10, "covered": 6, "percent": 60}, "instantiations": {"count": 10, "covered": 6, "percent": 60}, "lines": {"count": 234, "covered": 106, "percent": 45.2991452991453}, "regions": {"count": 102, "covered": 43, "notcovered": 59, "percent": 42.15686274509804}}}, {"filename": "/src/curl/lib/curl_ntlm_wb.c", "summary": {"functions": {"count": 6, "covered": 4, "percent": 66.66666666666666}, "instantiations": {"count": 6, "covered": 4, "percent": 66.66666666666666}, "lines": {"count": 392, "covered": 130, "percent": 33.16326530612245}, "regions": {"count": 293, "covered": 66, "notcovered": 227, "percent": 22.525597269624573}}}, {"filename": "/src/curl/lib/curl_printf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_range.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 57, "covered": 57, "percent": 100}, "regions": {"count": 42, "covered": 42, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/curl_sasl.c", "summary": {"functions": {"count": 8, "covered": 8, "percent": 100}, "instantiations": {"count": 8, "covered": 8, "percent": 100}, "lines": {"count": 411, "covered": 312, "percent": 75.91240875912408}, "regions": {"count": 272, "covered": 188, "notcovered": 84, "percent": 69.11764705882352}}}, {"filename": "/src/curl/lib/curl_sasl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_setup.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_setup_once.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/curl_threads.c", "summary": {"functions": {"count": 4, "covered": 3, "percent": 75}, "instantiations": {"count": 4, "covered": 3, "percent": 75}, "lines": {"count": 44, "covered": 31, "percent": 70.45454545454545}, "regions": {"count": 26, "covered": 15, "notcovered": 11, "percent": 57.692307692307686}}}, {"filename": "/src/curl/lib/curl_threads.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/dict.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 179, "covered": 165, "percent": 92.17877094972067}, "regions": {"count": 117, "covered": 107, "notcovered": 10, "percent": 91.45299145299145}}}, {"filename": "/src/curl/lib/doh.c", "summary": {"functions": {"count": 21, "covered": 0, "percent": 0}, "instantiations": {"count": 21, "covered": 0, "percent": 0}, "lines": {"count": 839, "covered": 0, "percent": 0}, "regions": {"count": 656, "covered": 0, "notcovered": 656, "percent": 0}}}, {"filename": "/src/curl/lib/doh.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/dotdot.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 129, "covered": 103, "percent": 79.84496124031007}, "regions": {"count": 56, "covered": 46, "notcovered": 10, "percent": 82.14285714285714}}}, {"filename": "/src/curl/lib/easy.c", "summary": {"functions": {"count": 28, "covered": 4, "percent": 14.285714285714285}, "instantiations": {"count": 28, "covered": 4, "percent": 14.285714285714285}, "lines": {"count": 767, "covered": 49, "percent": 6.388526727509778}, "regions": {"count": 421, "covered": 26, "notcovered": 395, "percent": 6.175771971496437}}}, {"filename": "/src/curl/lib/escape.c", "summary": {"functions": {"count": 7, "covered": 1, "percent": 14.285714285714285}, "instantiations": {"count": 7, "covered": 1, "percent": 14.285714285714285}, "lines": {"count": 160, "covered": 52, "percent": 32.5}, "regions": {"count": 156, "covered": 32, "notcovered": 124, "percent": 20.51282051282051}}}, {"filename": "/src/curl/lib/file.c", "summary": {"functions": {"count": 6, "covered": 6, "percent": 100}, "instantiations": {"count": 6, "covered": 6, "percent": 100}, "lines": {"count": 347, "covered": 306, "percent": 88.18443804034582}, "regions": {"count": 200, "covered": 169, "notcovered": 31, "percent": 84.5}}}, {"filename": "/src/curl/lib/fileinfo.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 10, "covered": 10, "percent": 100}, "regions": {"count": 12, "covered": 12, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/formdata.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 720, "covered": 0, "percent": 0}, "regions": {"count": 513, "covered": 0, "notcovered": 513, "percent": 0}}}, {"filename": "/src/curl/lib/ftp.c", "summary": {"functions": {"count": 65, "covered": 54, "percent": 83.07692307692308}, "instantiations": {"count": 65, "covered": 54, "percent": 83.07692307692308}, "lines": {"count": 3626, "covered": 2078, "percent": 57.30832873690016}, "regions": {"count": 2133, "covered": 1182, "notcovered": 951, "percent": 55.41490857946554}}}, {"filename": "/src/curl/lib/ftp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/ftplistparser.c", "summary": {"functions": {"count": 6, "covered": 6, "percent": 100}, "instantiations": {"count": 6, "covered": 6, "percent": 100}, "lines": {"count": 818, "covered": 735, "percent": 89.85330073349633}, "regions": {"count": 498, "covered": 463, "notcovered": 35, "percent": 92.9718875502008}}}, {"filename": "/src/curl/lib/getenv.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 7, "covered": 7, "percent": 100}, "regions": {"count": 5, "covered": 3, "notcovered": 2, "percent": 60}}}, {"filename": "/src/curl/lib/getinfo.c", "summary": {"functions": {"count": 8, "covered": 1, "percent": 12.5}, "instantiations": {"count": 8, "covered": 1, "percent": 12.5}, "lines": {"count": 427, "covered": 44, "percent": 10.304449648711945}, "regions": {"count": 165, "covered": 4, "notcovered": 161, "percent": 2.4242424242424243}}}, {"filename": "/src/curl/lib/gopher.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 97, "covered": 72, "percent": 74.22680412371135}, "regions": {"count": 51, "covered": 38, "notcovered": 13, "percent": 74.50980392156863}}}, {"filename": "/src/curl/lib/hash.c", "summary": {"functions": {"count": 13, "covered": 13, "percent": 100}, "instantiations": {"count": 13, "covered": 13, "percent": 100}, "lines": {"count": 186, "covered": 171, "percent": 91.93548387096774}, "regions": {"count": 98, "covered": 92, "notcovered": 6, "percent": 93.87755102040816}}}, {"filename": "/src/curl/lib/hmac.c", "summary": {"functions": {"count": 4, "covered": 3, "percent": 75}, "instantiations": {"count": 4, "covered": 3, "percent": 75}, "lines": {"count": 84, "covered": 67, "percent": 79.76190476190477}, "regions": {"count": 22, "covered": 16, "notcovered": 6, "percent": 72.72727272727273}}}, {"filename": "/src/curl/lib/hostasyn.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 44, "covered": 22, "percent": 50}, "regions": {"count": 15, "covered": 5, "notcovered": 10, "percent": 33.33333333333333}}}, {"filename": "/src/curl/lib/hostcheck.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 81, "covered": 0, "percent": 0}, "regions": {"count": 72, "covered": 0, "notcovered": 72, "percent": 0}}}, {"filename": "/src/curl/lib/hostcheck.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/hostip.c", "summary": {"functions": {"count": 20, "covered": 14, "percent": 70}, "instantiations": {"count": 20, "covered": 14, "percent": 70}, "lines": {"count": 603, "covered": 260, "percent": 43.117744610281925}, "regions": {"count": 276, "covered": 107, "notcovered": 169, "percent": 38.768115942028984}}}, {"filename": "/src/curl/lib/hostip.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/hostip6.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 30, "covered": 30, "percent": 100}, "regions": {"count": 20, "covered": 18, "notcovered": 2, "percent": 90}}}, {"filename": "/src/curl/lib/http.c", "summary": {"functions": {"count": 38, "covered": 32, "percent": 84.21052631578947}, "instantiations": {"count": 38, "covered": 32, "percent": 84.21052631578947}, "lines": {"count": 3373, "covered": 2572, "percent": 76.25259412985473}, "regions": {"count": 2208, "covered": 1696, "notcovered": 512, "percent": 76.81159420289855}}}, {"filename": "/src/curl/lib/http.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/http2.c", "summary": {"functions": {"count": 46, "covered": 37, "percent": 80.43478260869566}, "instantiations": {"count": 46, "covered": 37, "percent": 80.43478260869566}, "lines": {"count": 1978, "covered": 1318, "percent": 66.6329625884732}, "regions": {"count": 1147, "covered": 741, "notcovered": 406, "percent": 64.60331299040976}}}, {"filename": "/src/curl/lib/http2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/http_chunks.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 248, "covered": 227, "percent": 91.53225806451613}, "regions": {"count": 122, "covered": 108, "notcovered": 14, "percent": 88.52459016393442}}}, {"filename": "/src/curl/lib/http_chunks.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/http_digest.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 122, "covered": 111, "percent": 90.98360655737704}, "regions": {"count": 54, "covered": 46, "notcovered": 8, "percent": 85.18518518518519}}}, {"filename": "/src/curl/lib/http_ntlm.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 166, "covered": 110, "percent": 66.26506024096386}, "regions": {"count": 94, "covered": 50, "notcovered": 44, "percent": 53.191489361702125}}}, {"filename": "/src/curl/lib/http_proxy.c", "summary": {"functions": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "instantiations": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "lines": {"count": 594, "covered": 17, "percent": 2.861952861952862}, "regions": {"count": 357, "covered": 10, "notcovered": 347, "percent": 2.801120448179272}}}, {"filename": "/src/curl/lib/if2ip.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 97, "covered": 8, "percent": 8.24742268041237}, "regions": {"count": 59, "covered": 4, "notcovered": 55, "percent": 6.779661016949152}}}, {"filename": "/src/curl/lib/if2ip.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/imap.c", "summary": {"functions": {"count": 49, "covered": 41, "percent": 83.6734693877551}, "instantiations": {"count": 49, "covered": 41, "percent": 83.6734693877551}, "lines": {"count": 1567, "covered": 1285, "percent": 82.00382897255903}, "regions": {"count": 1081, "covered": 865, "notcovered": 216, "percent": 80.01850138760406}}}, {"filename": "/src/curl/lib/imap.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/inet_ntop.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/inet_pton.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/llist.c", "summary": {"functions": {"count": 5, "covered": 5, "percent": 100}, "instantiations": {"count": 5, "covered": 5, "percent": 100}, "lines": {"count": 80, "covered": 78, "percent": 97.5}, "regions": {"count": 41, "covered": 39, "notcovered": 2, "percent": 95.1219512195122}}}, {"filename": "/src/curl/lib/md4.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 7, "covered": 7, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/md5.c", "summary": {"functions": {"count": 4, "covered": 4, "percent": 100}, "instantiations": {"count": 4, "covered": 4, "percent": 100}, "lines": {"count": 42, "covered": 38, "percent": 90.47619047619048}, "regions": {"count": 15, "covered": 12, "notcovered": 3, "percent": 80}}}, {"filename": "/src/curl/lib/memdebug.c", "summary": {"functions": {"count": 18, "covered": 15, "percent": 83.33333333333334}, "instantiations": {"count": 18, "covered": 15, "percent": 83.33333333333334}, "lines": {"count": 283, "covered": 202, "percent": 71.37809187279152}, "regions": {"count": 165, "covered": 99, "notcovered": 66, "percent": 60}}}, {"filename": "/src/curl/lib/memdebug.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/mime.c", "summary": {"functions": {"count": 56, "covered": 34, "percent": 60.71428571428571}, "instantiations": {"count": 56, "covered": 34, "percent": 60.71428571428571}, "lines": {"count": 1277, "covered": 671, "percent": 52.54502740798747}, "regions": {"count": 828, "covered": 412, "notcovered": 416, "percent": 49.75845410628019}}}, {"filename": "/src/curl/lib/mime.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/mprintf.c", "summary": {"functions": {"count": 17, "covered": 11, "percent": 64.70588235294117}, "instantiations": {"count": 17, "covered": 11, "percent": 64.70588235294117}, "lines": {"count": 905, "covered": 585, "percent": 64.64088397790056}, "regions": {"count": 591, "covered": 323, "notcovered": 268, "percent": 54.653130287648054}}}, {"filename": "/src/curl/lib/multi.c", "summary": {"functions": {"count": 70, "covered": 43, "percent": 61.42857142857143}, "instantiations": {"count": 70, "covered": 43, "percent": 61.42857142857143}, "lines": {"count": 2793, "covered": 1523, "percent": 54.52918009308987}, "regions": {"count": 1565, "covered": 756, "notcovered": 809, "percent": 48.30670926517572}}}, {"filename": "/src/curl/lib/multihandle.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/multiif.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/netrc.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 180, "covered": 0, "percent": 0}, "regions": {"count": 143, "covered": 0, "notcovered": 143, "percent": 0}}}, {"filename": "/src/curl/lib/non-ascii.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/nonblock.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 8, "covered": 6, "percent": 75}, "regions": {"count": 7, "covered": 5, "notcovered": 2, "percent": 71.42857142857143}}}, {"filename": "/src/curl/lib/parsedate.c", "summary": {"functions": {"count": 9, "covered": 8, "percent": 88.88888888888889}, "instantiations": {"count": 9, "covered": 8, "percent": 88.88888888888889}, "lines": {"count": 317, "covered": 289, "percent": 91.16719242902208}, "regions": {"count": 218, "covered": 202, "notcovered": 16, "percent": 92.66055045871559}}}, {"filename": "/src/curl/lib/pingpong.c", "summary": {"functions": {"count": 10, "covered": 9, "percent": 90}, "instantiations": {"count": 10, "covered": 9, "percent": 90}, "lines": {"count": 386, "covered": 329, "percent": 85.23316062176166}, "regions": {"count": 202, "covered": 165, "notcovered": 37, "percent": 81.68316831683168}}}, {"filename": "/src/curl/lib/pop3.c", "summary": {"functions": {"count": 40, "covered": 36, "percent": 90}, "instantiations": {"count": 40, "covered": 36, "percent": 90}, "lines": {"count": 1087, "covered": 995, "percent": 91.53633854645814}, "regions": {"count": 559, "covered": 508, "notcovered": 51, "percent": 90.87656529516994}}}, {"filename": "/src/curl/lib/pop3.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/progress.c", "summary": {"functions": {"count": 15, "covered": 11, "percent": 73.33333333333333}, "instantiations": {"count": 15, "covered": 11, "percent": 73.33333333333333}, "lines": {"count": 488, "covered": 208, "percent": 42.62295081967213}, "regions": {"count": 499, "covered": 83, "notcovered": 416, "percent": 16.63326653306613}}}, {"filename": "/src/curl/lib/progress.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/rand.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 115, "covered": 65, "percent": 56.52173913043478}, "regions": {"count": 50, "covered": 26, "notcovered": 24, "percent": 52}}}, {"filename": "/src/curl/lib/rename.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 6, "covered": 5, "percent": 83.33333333333334}, "regions": {"count": 4, "covered": 3, "notcovered": 1, "percent": 75}}}, {"filename": "/src/curl/lib/rtsp.c", "summary": {"functions": {"count": 11, "covered": 8, "percent": 72.72727272727273}, "instantiations": {"count": 11, "covered": 8, "percent": 72.72727272727273}, "lines": {"count": 673, "covered": 579, "percent": 86.03268945022289}, "regions": {"count": 409, "covered": 323, "notcovered": 86, "percent": 78.97310513447434}}}, {"filename": "/src/curl/lib/select.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 154, "covered": 79, "percent": 51.298701298701296}, "regions": {"count": 111, "covered": 51, "notcovered": 60, "percent": 45.94594594594595}}}, {"filename": "/src/curl/lib/select.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/sendf.c", "summary": {"functions": {"count": 15, "covered": 11, "percent": 73.33333333333333}, "instantiations": {"count": 15, "covered": 11, "percent": 73.33333333333333}, "lines": {"count": 514, "covered": 296, "percent": 57.58754863813229}, "regions": {"count": 253, "covered": 147, "notcovered": 106, "percent": 58.10276679841897}}}, {"filename": "/src/curl/lib/sendf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/setopt.c", "summary": {"functions": {"count": 4, "covered": 3, "percent": 75}, "instantiations": {"count": 4, "covered": 3, "percent": 75}, "lines": {"count": 2549, "covered": 488, "percent": 19.1447626520204}, "regions": {"count": 991, "covered": 145, "notcovered": 846, "percent": 14.631685166498487}}}, {"filename": "/src/curl/lib/sha256.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 7, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/curl/lib/share.c", "summary": {"functions": {"count": 5, "covered": 2, "percent": 40}, "instantiations": {"count": 5, "covered": 2, "percent": 40}, "lines": {"count": 190, "covered": 10, "percent": 5.263157894736842}, "regions": {"count": 86, "covered": 6, "notcovered": 80, "percent": 6.976744186046512}}}, {"filename": "/src/curl/lib/sigpipe.h", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 6, "covered": 6, "percent": 100}, "lines": {"count": 20, "covered": 20, "percent": 100}, "regions": {"count": 6, "covered": 6, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/slist.c", "summary": {"functions": {"count": 5, "covered": 4, "percent": 80}, "instantiations": {"count": 5, "covered": 4, "percent": 80}, "lines": {"count": 79, "covered": 59, "percent": 74.68354430379746}, "regions": {"count": 40, "covered": 29, "notcovered": 11, "percent": 72.5}}}, {"filename": "/src/curl/lib/smb.c", "summary": {"functions": {"count": 27, "covered": 26, "percent": 96.29629629629629}, "instantiations": {"count": 27, "covered": 26, "percent": 96.29629629629629}, "lines": {"count": 740, "covered": 702, "percent": 94.86486486486486}, "regions": {"count": 406, "covered": 371, "notcovered": 35, "percent": 91.37931034482759}}}, {"filename": "/src/curl/lib/smb.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/smtp.c", "summary": {"functions": {"count": 44, "covered": 40, "percent": 90.9090909090909}, "instantiations": {"count": 44, "covered": 40, "percent": 90.9090909090909}, "lines": {"count": 1323, "covered": 1174, "percent": 88.73771730914588}, "regions": {"count": 674, "covered": 587, "notcovered": 87, "percent": 87.0919881305638}}}, {"filename": "/src/curl/lib/smtp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/socketpair.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/socks.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 787, "covered": 0, "percent": 0}, "regions": {"count": 390, "covered": 0, "notcovered": 390, "percent": 0}}}, {"filename": "/src/curl/lib/speedcheck.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 36, "covered": 10, "percent": 27.77777777777778}, "regions": {"count": 18, "covered": 7, "notcovered": 11, "percent": 38.88888888888889}}}, {"filename": "/src/curl/lib/splay.c", "summary": {"functions": {"count": 4, "covered": 4, "percent": 100}, "instantiations": {"count": 4, "covered": 4, "percent": 100}, "lines": {"count": 203, "covered": 108, "percent": 53.20197044334976}, "regions": {"count": 143, "covered": 59, "notcovered": 84, "percent": 41.25874125874126}}}, {"filename": "/src/curl/lib/splay.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/strcase.c", "summary": {"functions": {"count": 9, "covered": 8, "percent": 88.88888888888889}, "instantiations": {"count": 9, "covered": 8, "percent": 88.88888888888889}, "lines": {"count": 69, "covered": 60, "percent": 86.95652173913044}, "regions": {"count": 59, "covered": 50, "notcovered": 9, "percent": 84.7457627118644}}}, {"filename": "/src/curl/lib/strcase.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/strdup.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 16, "covered": 7, "percent": 43.75}, "regions": {"count": 11, "covered": 5, "notcovered": 6, "percent": 45.45454545454545}}}, {"filename": "/src/curl/lib/strerror.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 403, "covered": 33, "percent": 8.188585607940446}, "regions": {"count": 145, "covered": 11, "notcovered": 134, "percent": 7.586206896551724}}}, {"filename": "/src/curl/lib/strtoofft.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 26, "covered": 26, "percent": 100}, "regions": {"count": 19, "covered": 19, "notcovered": 0, "percent": 100}}}, {"filename": "/src/curl/lib/telnet.c", "summary": {"functions": {"count": 18, "covered": 0, "percent": 0}, "instantiations": {"count": 18, "covered": 0, "percent": 0}, "lines": {"count": 1128, "covered": 0, "percent": 0}, "regions": {"count": 894, "covered": 0, "notcovered": 894, "percent": 0}}}, {"filename": "/src/curl/lib/tftp.c", "summary": {"functions": {"count": 27, "covered": 6, "percent": 22.22222222222222}, "instantiations": {"count": 27, "covered": 6, "percent": 22.22222222222222}, "lines": {"count": 1049, "covered": 199, "percent": 18.970448045757866}, "regions": {"count": 498, "covered": 79, "notcovered": 419, "percent": 15.863453815261044}}}, {"filename": "/src/curl/lib/timeval.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 52, "covered": 37, "percent": 71.15384615384616}, "regions": {"count": 68, "covered": 37, "notcovered": 31, "percent": 54.41176470588235}}}, {"filename": "/src/curl/lib/timeval.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/transfer.c", "summary": {"functions": {"count": 19, "covered": 16, "percent": 84.21052631578947}, "instantiations": {"count": 19, "covered": 16, "percent": 84.21052631578947}, "lines": {"count": 1580, "covered": 1270, "percent": 80.37974683544303}, "regions": {"count": 971, "covered": 788, "notcovered": 183, "percent": 81.15345005149331}}}, {"filename": "/src/curl/lib/transfer.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/url.c", "summary": {"functions": {"count": 50, "covered": 41, "percent": 82}, "instantiations": {"count": 50, "covered": 41, "percent": 82}, "lines": {"count": 3154, "covered": 2036, "percent": 64.55294863665188}, "regions": {"count": 2207, "covered": 1267, "notcovered": 940, "percent": 57.408246488445855}}}, {"filename": "/src/curl/lib/url.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/urlapi-int.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/urlapi.c", "summary": {"functions": {"count": 19, "covered": 18, "percent": 94.73684210526315}, "instantiations": {"count": 19, "covered": 18, "percent": 94.73684210526315}, "lines": {"count": 1308, "covered": 1054, "percent": 80.58103975535168}, "regions": {"count": 1031, "covered": 777, "notcovered": 254, "percent": 75.36372453928225}}}, {"filename": "/src/curl/lib/urldata.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/vauth/cleartext.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 59, "covered": 48, "percent": 81.35593220338984}, "regions": {"count": 26, "covered": 20, "notcovered": 6, "percent": 76.92307692307693}}}, {"filename": "/src/curl/lib/vauth/cram.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 54, "covered": 52, "percent": 96.29629629629629}, "regions": {"count": 18, "covered": 16, "notcovered": 2, "percent": 88.88888888888889}}}, {"filename": "/src/curl/lib/vauth/digest.c", "summary": {"functions": {"count": 13, "covered": 11, "percent": 84.61538461538461}, "instantiations": {"count": 13, "covered": 11, "percent": 84.61538461538461}, "lines": {"count": 747, "covered": 440, "percent": 58.90227576974565}, "regions": {"count": 482, "covered": 265, "notcovered": 217, "percent": 54.9792531120332}}}, {"filename": "/src/curl/lib/vauth/digest.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/vauth/ntlm.c", "summary": {"functions": {"count": 7, "covered": 4, "percent": 57.14285714285714}, "instantiations": {"count": 7, "covered": 4, "percent": 57.14285714285714}, "lines": {"count": 555, "covered": 152, "percent": 27.387387387387385}, "regions": {"count": 191, "covered": 41, "notcovered": 150, "percent": 21.465968586387437}}}, {"filename": "/src/curl/lib/vauth/ntlm.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/vauth/oauth2.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 36, "covered": 0, "percent": 0}, "regions": {"count": 18, "covered": 0, "notcovered": 18, "percent": 0}}}, {"filename": "/src/curl/lib/vauth/vauth.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 26, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/curl/lib/version.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 76, "covered": 74, "percent": 97.36842105263158}, "regions": {"count": 21, "covered": 17, "notcovered": 4, "percent": 80.95238095238095}}}, {"filename": "/src/curl/lib/vtls/openssl.c", "summary": {"functions": {"count": 57, "covered": 20, "percent": 35.08771929824561}, "instantiations": {"count": 57, "covered": 20, "percent": 35.08771929824561}, "lines": {"count": 2927, "covered": 648, "percent": 22.138708575333105}, "regions": {"count": 2350, "covered": 386, "notcovered": 1964, "percent": 16.425531914893618}}}, {"filename": "/src/curl/lib/vtls/vtls.c", "summary": {"functions": {"count": 60, "covered": 19, "percent": 31.666666666666664}, "instantiations": {"count": 60, "covered": 19, "percent": 31.666666666666664}, "lines": {"count": 878, "covered": 186, "percent": 21.184510250569478}, "regions": {"count": 667, "covered": 159, "notcovered": 508, "percent": 23.838080959520237}}}, {"filename": "/src/curl/lib/vtls/vtls.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/warnless.c", "summary": {"functions": {"count": 15, "covered": 7, "percent": 46.666666666666664}, "instantiations": {"count": 15, "covered": 7, "percent": 46.666666666666664}, "lines": {"count": 71, "covered": 33, "percent": 46.478873239436616}, "regions": {"count": 50, "covered": 22, "notcovered": 28, "percent": 44}}}, {"filename": "/src/curl/lib/warnless.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl/lib/wildcard.c", "summary": {"functions": {"count": 3, "covered": 3, "percent": 100}, "instantiations": {"count": 3, "covered": 3, "percent": 100}, "lines": {"count": 32, "covered": 31, "percent": 96.875}, "regions": {"count": 12, "covered": 11, "notcovered": 1, "percent": 91.66666666666666}}}, {"filename": "/src/curl_fuzzer/curl_fuzzer.cc", "summary": {"functions": {"count": 11, "covered": 11, "percent": 100}, "instantiations": {"count": 11, "covered": 11, "percent": 100}, "lines": {"count": 391, "covered": 377, "percent": 96.41943734015345}, "regions": {"count": 202, "covered": 170, "notcovered": 32, "percent": 84.15841584158416}}}, {"filename": "/src/curl_fuzzer/curl_fuzzer.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_fuzzer/curl_fuzzer_callback.cc", "summary": {"functions": {"count": 4, "covered": 4, "percent": 100}, "instantiations": {"count": 4, "covered": 4, "percent": 100}, "lines": {"count": 161, "covered": 136, "percent": 84.472049689441}, "regions": {"count": 71, "covered": 60, "notcovered": 11, "percent": 84.50704225352112}}}, {"filename": "/src/curl_fuzzer/curl_fuzzer_tlv.cc", "summary": {"functions": {"count": 7, "covered": 7, "percent": 100}, "instantiations": {"count": 7, "covered": 7, "percent": 100}, "lines": {"count": 247, "covered": 247, "percent": 100}, "regions": {"count": 470, "covered": 442, "notcovered": 28, "percent": 94.04255319148936}}}, {"filename": "/src/curl_install/include/curl/curl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/nghttp2/nghttp2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/asn1.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/bio.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/conf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/crypto.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/des.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/engine.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/evp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/obj_mac.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/ocsp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/opensslv.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/rsa.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/safestack.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/ssl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/ssl2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/ssl3.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/tls1.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/ui.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/x509.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/x509_vfy.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/openssl/x509v3.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/curl_install/include/zlib.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/includes/nghttp2/nghttp2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/includes/nghttp2/nghttp2ver.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_buf.c", "summary": {"functions": {"count": 30, "covered": 18, "percent": 60}, "instantiations": {"count": 30, "covered": 18, "percent": 60}, "lines": {"count": 458, "covered": 234, "percent": 51.09170305676856}, "regions": {"count": 183, "covered": 97, "notcovered": 86, "percent": 53.00546448087432}}}, {"filename": "/src/nghttp2/lib/nghttp2_buf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_callbacks.c", "summary": {"functions": {"count": 25, "covered": 9, "percent": 36}, "instantiations": {"count": 25, "covered": 9, "percent": 36}, "lines": {"count": 81, "covered": 31, "percent": 38.2716049382716}, "regions": {"count": 28, "covered": 11, "notcovered": 17, "percent": 39.285714285714285}}}, {"filename": "/src/nghttp2/lib/nghttp2_debug.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_frame.c", "summary": {"functions": {"count": 69, "covered": 46, "percent": 66.66666666666666}, "instantiations": {"count": 69, "covered": 46, "percent": 66.66666666666666}, "lines": {"count": 953, "covered": 465, "percent": 48.79328436516264}, "regions": {"count": 315, "covered": 155, "notcovered": 160, "percent": 49.2063492063492}}}, {"filename": "/src/nghttp2/lib/nghttp2_frame.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_hd.c", "summary": {"functions": {"count": 81, "covered": 55, "percent": 67.90123456790124}, "instantiations": {"count": 81, "covered": 55, "percent": 67.90123456790124}, "lines": {"count": 1989, "covered": 1616, "percent": 81.24685771744595}, "regions": {"count": 1043, "covered": 891, "notcovered": 152, "percent": 85.42665388302973}}}, {"filename": "/src/nghttp2/lib/nghttp2_hd.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_hd_huffman.c", "summary": {"functions": {"count": 5, "covered": 5, "percent": 100}, "instantiations": {"count": 5, "covered": 5, "percent": 100}, "lines": {"count": 184, "covered": 170, "percent": 92.3913043478261}, "regions": {"count": 143, "covered": 136, "notcovered": 7, "percent": 95.1048951048951}}}, {"filename": "/src/nghttp2/lib/nghttp2_helper.c", "summary": {"functions": {"count": 12, "covered": 11, "percent": 91.66666666666666}, "instantiations": {"count": 12, "covered": 11, "percent": 91.66666666666666}, "lines": {"count": 237, "covered": 177, "percent": 74.68354430379746}, "regions": {"count": 115, "covered": 85, "notcovered": 30, "percent": 73.91304347826086}}}, {"filename": "/src/nghttp2/lib/nghttp2_helper.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_http.c", "summary": {"functions": {"count": 18, "covered": 15, "percent": 83.33333333333334}, "instantiations": {"count": 18, "covered": 15, "percent": 83.33333333333334}, "lines": {"count": 463, "covered": 309, "percent": 66.73866090712744}, "regions": {"count": 376, "covered": 248, "notcovered": 128, "percent": 65.95744680851064}}}, {"filename": "/src/nghttp2/lib/nghttp2_map.c", "summary": {"functions": {"count": 12, "covered": 11, "percent": 91.66666666666666}, "instantiations": {"count": 12, "covered": 11, "percent": 91.66666666666666}, "lines": {"count": 140, "covered": 92, "percent": 65.71428571428571}, "regions": {"count": 69, "covered": 44, "notcovered": 25, "percent": 63.76811594202898}}}, {"filename": "/src/nghttp2/lib/nghttp2_mem.c", "summary": {"functions": {"count": 10, "covered": 10, "percent": 100}, "instantiations": {"count": 10, "covered": 10, "percent": 100}, "lines": {"count": 36, "covered": 36, "percent": 100}, "regions": {"count": 10, "covered": 10, "notcovered": 0, "percent": 100}}}, {"filename": "/src/nghttp2/lib/nghttp2_outbound_item.c", "summary": {"functions": {"count": 5, "covered": 4, "percent": 80}, "instantiations": {"count": 5, "covered": 4, "percent": 80}, "lines": {"count": 93, "covered": 62, "percent": 66.66666666666666}, "regions": {"count": 32, "covered": 21, "notcovered": 11, "percent": 65.625}}}, {"filename": "/src/nghttp2/lib/nghttp2_outbound_item.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_pq.c", "summary": {"functions": {"count": 13, "covered": 9, "percent": 69.23076923076923}, "instantiations": {"count": 13, "covered": 9, "percent": 69.23076923076923}, "lines": {"count": 141, "covered": 71, "percent": 50.35460992907801}, "regions": {"count": 73, "covered": 31, "notcovered": 42, "percent": 42.465753424657535}}}, {"filename": "/src/nghttp2/lib/nghttp2_priority_spec.c", "summary": {"functions": {"count": 4, "covered": 3, "percent": 75}, "instantiations": {"count": 4, "covered": 3, "percent": 75}, "lines": {"count": 21, "covered": 14, "percent": 66.66666666666666}, "regions": {"count": 20, "covered": 10, "notcovered": 10, "percent": 50}}}, {"filename": "/src/nghttp2/lib/nghttp2_rcbuf.c", "summary": {"functions": {"count": 7, "covered": 5, "percent": 71.42857142857143}, "instantiations": {"count": 7, "covered": 5, "percent": 71.42857142857143}, "lines": {"count": 59, "covered": 48, "percent": 81.35593220338984}, "regions": {"count": 23, "covered": 19, "notcovered": 4, "percent": 82.6086956521739}}}, {"filename": "/src/nghttp2/lib/nghttp2_session.c", "summary": {"functions": {"count": 189, "covered": 124, "percent": 65.60846560846561}, "instantiations": {"count": 189, "covered": 124, "percent": 65.60846560846561}, "lines": {"count": 6806, "covered": 4020, "percent": 59.06553041434029}, "regions": {"count": 3356, "covered": 1973, "notcovered": 1383, "percent": 58.790226460071516}}}, {"filename": "/src/nghttp2/lib/nghttp2_session.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/nghttp2/lib/nghttp2_stream.c", "summary": {"functions": {"count": 50, "covered": 29, "percent": 57.99999999999999}, "instantiations": {"count": 50, "covered": 29, "percent": 57.99999999999999}, "lines": {"count": 734, "covered": 348, "percent": 47.41144414168937}, "regions": {"count": 310, "covered": 132, "notcovered": 178, "percent": 42.58064516129032}}}, {"filename": "/src/nghttp2/lib/nghttp2_submit.c", "summary": {"functions": {"count": 23, "covered": 9, "percent": 39.130434782608695}, "instantiations": {"count": 23, "covered": 9, "percent": 39.130434782608695}, "lines": {"count": 698, "covered": 167, "percent": 23.925501432664756}, "regions": {"count": 292, "covered": 66, "notcovered": 226, "percent": 22.602739726027394}}}, {"filename": "/src/nghttp2/lib/nghttp2_version.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 5, "covered": 5, "percent": 100}, "regions": {"count": 5, "covered": 4, "notcovered": 1, "percent": 80}}}, {"filename": "/src/openssl/crypto/LPdir_unix.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 54, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/openssl/crypto/aes/aes_misc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 7, "covered": 0, "percent": 0}, "regions": {"count": 3, "covered": 0, "notcovered": 3, "percent": 0}}}, {"filename": "/src/openssl/crypto/aes/aes_wrap.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 7, "covered": 0, "percent": 0}, "regions": {"count": 2, "covered": 0, "notcovered": 2, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_bitstr.c", "summary": {"functions": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "instantiations": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "lines": {"count": 184, "covered": 42, "percent": 22.82608695652174}, "regions": {"count": 148, "covered": 24, "notcovered": 124, "percent": 16.216216216216218}}}, {"filename": "/src/openssl/crypto/asn1/a_bool.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 46, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_bytes.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 233, "covered": 0, "percent": 0}, "regions": {"count": 167, "covered": 0, "notcovered": 167, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_d2i_fp.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 199, "covered": 0, "percent": 0}, "regions": {"count": 141, "covered": 0, "notcovered": 141, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_digest.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 34, "covered": 0, "percent": 0}, "regions": {"count": 23, "covered": 0, "notcovered": 23, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_dup.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 21, "covered": 0, "notcovered": 21, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_enum.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 106, "covered": 0, "percent": 0}, "regions": {"count": 91, "covered": 0, "notcovered": 91, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_gentm.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 176, "covered": 0, "percent": 0}, "regions": {"count": 160, "covered": 0, "notcovered": 160, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_i2d_fp.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 79, "covered": 0, "percent": 0}, "regions": {"count": 47, "covered": 0, "notcovered": 47, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_int.c", "summary": {"functions": {"count": 9, "covered": 1, "percent": 11.11111111111111}, "instantiations": {"count": 9, "covered": 1, "percent": 11.11111111111111}, "lines": {"count": 345, "covered": 64, "percent": 18.55072463768116}, "regions": {"count": 266, "covered": 39, "notcovered": 227, "percent": 14.661654135338345}}}, {"filename": "/src/openssl/crypto/asn1/a_mbstr.c", "summary": {"functions": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "instantiations": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "lines": {"count": 277, "covered": 143, "percent": 51.624548736462096}, "regions": {"count": 225, "covered": 102, "notcovered": 123, "percent": 45.33333333333333}}}, {"filename": "/src/openssl/crypto/asn1/a_object.c", "summary": {"functions": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "instantiations": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "lines": {"count": 316, "covered": 91, "percent": 28.79746835443038}, "regions": {"count": 263, "covered": 58, "notcovered": 205, "percent": 22.0532319391635}}}, {"filename": "/src/openssl/crypto/asn1/a_octet.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 9, "covered": 0, "percent": 0}, "regions": {"count": 6, "covered": 0, "notcovered": 6, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_print.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 57, "covered": 0, "percent": 0}, "regions": {"count": 84, "covered": 0, "notcovered": 84, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_set.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 155, "covered": 0, "percent": 0}, "regions": {"count": 175, "covered": 0, "notcovered": 175, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_sign.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 189, "covered": 0, "percent": 0}, "regions": {"count": 143, "covered": 0, "notcovered": 143, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_strex.c", "summary": {"functions": {"count": 14, "covered": 1, "percent": 7.142857142857142}, "instantiations": {"count": 14, "covered": 1, "percent": 7.142857142857142}, "lines": {"count": 452, "covered": 19, "percent": 4.20353982300885}, "regions": {"count": 347, "covered": 13, "notcovered": 334, "percent": 3.7463976945244957}}}, {"filename": "/src/openssl/crypto/asn1/a_strnid.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 94, "covered": 0, "percent": 0}, "regions": {"count": 99, "covered": 0, "notcovered": 99, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_time.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 117, "covered": 0, "percent": 0}, "regions": {"count": 98, "covered": 0, "notcovered": 98, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_type.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 80, "covered": 8, "percent": 10}, "regions": {"count": 90, "covered": 5, "notcovered": 85, "percent": 5.555555555555555}}}, {"filename": "/src/openssl/crypto/asn1/a_utctm.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 184, "covered": 0, "percent": 0}, "regions": {"count": 176, "covered": 0, "notcovered": 176, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/a_utf8.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 151, "covered": 31, "percent": 20.52980132450331}, "regions": {"count": 137, "covered": 25, "notcovered": 112, "percent": 18.248175182481752}}}, {"filename": "/src/openssl/crypto/asn1/a_verify.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 148, "covered": 0, "percent": 0}, "regions": {"count": 106, "covered": 0, "notcovered": 106, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/ameth_lib.c", "summary": {"functions": {"count": 19, "covered": 9, "percent": 47.368421052631575}, "instantiations": {"count": 19, "covered": 9, "percent": 47.368421052631575}, "lines": {"count": 263, "covered": 109, "percent": 41.44486692015209}, "regions": {"count": 169, "covered": 44, "notcovered": 125, "percent": 26.035502958579883}}}, {"filename": "/src/openssl/crypto/asn1/asn1_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/asn1/asn1_gen.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 680, "covered": 0, "percent": 0}, "regions": {"count": 560, "covered": 0, "notcovered": 560, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/asn1_lib.c", "summary": {"functions": {"count": 27, "covered": 8, "percent": 29.629629629629626}, "instantiations": {"count": 27, "covered": 8, "percent": 29.629629629629626}, "lines": {"count": 349, "covered": 124, "percent": 35.53008595988539}, "regions": {"count": 251, "covered": 81, "notcovered": 170, "percent": 32.27091633466135}}}, {"filename": "/src/openssl/crypto/asn1/asn1_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/asn1_par.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 333, "covered": 0, "percent": 0}, "regions": {"count": 322, "covered": 0, "notcovered": 322, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/asn_mime.c", "summary": {"functions": {"count": 24, "covered": 0, "percent": 0}, "instantiations": {"count": 24, "covered": 0, "percent": 0}, "lines": {"count": 743, "covered": 0, "percent": 0}, "regions": {"count": 741, "covered": 0, "notcovered": 741, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/asn_moid.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 69, "covered": 3, "percent": 4.3478260869565215}, "regions": {"count": 52, "covered": 1, "notcovered": 51, "percent": 1.9230769230769231}}}, {"filename": "/src/openssl/crypto/asn1/asn_pack.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 109, "covered": 0, "percent": 0}, "regions": {"count": 96, "covered": 0, "notcovered": 96, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/bio_asn1.c", "summary": {"functions": {"count": 18, "covered": 0, "percent": 0}, "instantiations": {"count": 18, "covered": 0, "percent": 0}, "lines": {"count": 298, "covered": 0, "percent": 0}, "regions": {"count": 183, "covered": 0, "notcovered": 183, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/bio_ndef.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 141, "covered": 0, "percent": 0}, "regions": {"count": 64, "covered": 0, "notcovered": 64, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/d2i_pr.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 97, "covered": 0, "percent": 0}, "regions": {"count": 99, "covered": 0, "notcovered": 99, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/evp_asn1.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 117, "covered": 0, "percent": 0}, "regions": {"count": 92, "covered": 0, "notcovered": 92, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/f_int.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 141, "covered": 0, "percent": 0}, "regions": {"count": 129, "covered": 0, "notcovered": 129, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/f_string.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 135, "covered": 0, "percent": 0}, "regions": {"count": 118, "covered": 0, "notcovered": 118, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/i2d_pr.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 16, "covered": 0, "percent": 0}, "regions": {"count": 17, "covered": 0, "notcovered": 17, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/nsseq.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 8, "covered": 0, "percent": 0}, "regions": {"count": 5, "covered": 0, "notcovered": 5, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/p5_pbe.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 60, "covered": 0, "percent": 0}, "regions": {"count": 51, "covered": 0, "notcovered": 51, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/p5_pbev2.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 178, "covered": 0, "percent": 0}, "regions": {"count": 123, "covered": 0, "notcovered": 123, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/p8_pkey.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 61, "covered": 0, "percent": 0}, "regions": {"count": 55, "covered": 0, "notcovered": 55, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/t_pkey.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 47, "covered": 0, "percent": 0}, "regions": {"count": 49, "covered": 0, "notcovered": 49, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/t_x509.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 433, "covered": 0, "percent": 0}, "regions": {"count": 424, "covered": 0, "notcovered": 424, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/t_x509a.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 45, "covered": 0, "percent": 0}, "regions": {"count": 49, "covered": 0, "notcovered": 49, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/tasn_dec.c", "summary": {"functions": {"count": 13, "covered": 9, "percent": 69.23076923076923}, "instantiations": {"count": 13, "covered": 9, "percent": 69.23076923076923}, "lines": {"count": 1012, "covered": 510, "percent": 50.39525691699605}, "regions": {"count": 816, "covered": 383, "notcovered": 433, "percent": 46.93627450980392}}}, {"filename": "/src/openssl/crypto/asn1/tasn_enc.c", "summary": {"functions": {"count": 10, "covered": 5, "percent": 50}, "instantiations": {"count": 10, "covered": 5, "percent": 50}, "lines": {"count": 533, "covered": 310, "percent": 58.16135084427767}, "regions": {"count": 445, "covered": 227, "notcovered": 218, "percent": 51.01123595505618}}}, {"filename": "/src/openssl/crypto/asn1/tasn_fre.c", "summary": {"functions": {"count": 5, "covered": 4, "percent": 80}, "instantiations": {"count": 5, "covered": 4, "percent": 80}, "lines": {"count": 170, "covered": 130, "percent": 76.47058823529412}, "regions": {"count": 144, "covered": 107, "notcovered": 37, "percent": 74.30555555555556}}}, {"filename": "/src/openssl/crypto/asn1/tasn_new.c", "summary": {"functions": {"count": 8, "covered": 8, "percent": 100}, "instantiations": {"count": 8, "covered": 8, "percent": 100}, "lines": {"count": 250, "covered": 153, "percent": 61.199999999999996}, "regions": {"count": 220, "covered": 124, "notcovered": 96, "percent": 56.36363636363636}}}, {"filename": "/src/openssl/crypto/asn1/tasn_prn.c", "summary": {"functions": {"count": 21, "covered": 0, "percent": 0}, "instantiations": {"count": 21, "covered": 0, "percent": 0}, "lines": {"count": 426, "covered": 0, "percent": 0}, "regions": {"count": 379, "covered": 0, "notcovered": 379, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/tasn_utl.c", "summary": {"functions": {"count": 10, "covered": 8, "percent": 80}, "instantiations": {"count": 10, "covered": 8, "percent": 80}, "lines": {"count": 152, "covered": 83, "percent": 54.60526315789473}, "regions": {"count": 100, "covered": 57, "notcovered": 43, "percent": 56.99999999999999}}}, {"filename": "/src/openssl/crypto/asn1/x_algor.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 58, "covered": 0, "percent": 0}, "regions": {"count": 53, "covered": 0, "notcovered": 53, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_attrib.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 24, "covered": 0, "percent": 0}, "regions": {"count": 27, "covered": 0, "notcovered": 27, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_bignum.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 40, "covered": 0, "notcovered": 40, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_crl.c", "summary": {"functions": {"count": 17, "covered": 0, "percent": 0}, "instantiations": {"count": 17, "covered": 0, "percent": 0}, "lines": {"count": 331, "covered": 0, "percent": 0}, "regions": {"count": 332, "covered": 0, "notcovered": 332, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_info.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 38, "covered": 34, "percent": 89.47368421052632}, "regions": {"count": 24, "covered": 16, "notcovered": 8, "percent": 66.66666666666666}}}, {"filename": "/src/openssl/crypto/asn1/x_long.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 109, "covered": 0, "percent": 0}, "regions": {"count": 55, "covered": 0, "notcovered": 55, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_name.c", "summary": {"functions": {"count": 12, "covered": 8, "percent": 66.66666666666666}, "instantiations": {"count": 12, "covered": 8, "percent": 66.66666666666666}, "lines": {"count": 345, "covered": 218, "percent": 63.18840579710145}, "regions": {"count": 386, "covered": 205, "notcovered": 181, "percent": 53.10880829015544}}}, {"filename": "/src/openssl/crypto/asn1/x_pkey.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 80, "covered": 0, "percent": 0}, "regions": {"count": 101, "covered": 0, "notcovered": 101, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_pubkey.c", "summary": {"functions": {"count": 13, "covered": 1, "percent": 7.6923076923076925}, "instantiations": {"count": 13, "covered": 1, "percent": 7.6923076923076925}, "lines": {"count": 252, "covered": 7, "percent": 2.7777777777777777}, "regions": {"count": 166, "covered": 4, "notcovered": 162, "percent": 2.4096385542168677}}}, {"filename": "/src/openssl/crypto/asn1/x_req.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 10, "covered": 0, "percent": 0}, "regions": {"count": 9, "covered": 0, "notcovered": 9, "percent": 0}}}, {"filename": "/src/openssl/crypto/asn1/x_x509.c", "summary": {"functions": {"count": 10, "covered": 1, "percent": 10}, "instantiations": {"count": 10, "covered": 1, "percent": 10}, "lines": {"count": 142, "covered": 40, "percent": 28.169014084507044}, "regions": {"count": 76, "covered": 13, "notcovered": 63, "percent": 17.105263157894736}}}, {"filename": "/src/openssl/crypto/asn1/x_x509a.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 88, "covered": 0, "percent": 0}, "regions": {"count": 134, "covered": 0, "notcovered": 134, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_cfb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 21, "covered": 0, "notcovered": 21, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_ecb.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 20, "covered": 0, "percent": 0}, "regions": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_enc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 134, "covered": 0, "percent": 0}, "regions": {"count": 94, "covered": 0, "notcovered": 94, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_ofb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 16, "covered": 0, "notcovered": 16, "percent": 0}}}, {"filename": "/src/openssl/crypto/bf/bf_skey.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 51, "covered": 0, "percent": 0}, "regions": {"count": 25, "covered": 0, "notcovered": 25, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/b_dump.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 109, "covered": 0, "percent": 0}, "regions": {"count": 68, "covered": 0, "notcovered": 68, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/b_print.c", "summary": {"functions": {"count": 12, "covered": 6, "percent": 50}, "instantiations": {"count": 12, "covered": 6, "percent": 50}, "lines": {"count": 651, "covered": 254, "percent": 39.01689708141321}, "regions": {"count": 473, "covered": 172, "notcovered": 301, "percent": 36.36363636363637}}}, {"filename": "/src/openssl/crypto/bio/b_sock.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 455, "covered": 0, "percent": 0}, "regions": {"count": 266, "covered": 0, "notcovered": 266, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/bf_buff.c", "summary": {"functions": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "instantiations": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "lines": {"count": 409, "covered": 125, "percent": 30.56234718826406}, "regions": {"count": 302, "covered": 84, "notcovered": 218, "percent": 27.81456953642384}}}, {"filename": "/src/openssl/crypto/bio/bio_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/bio/bio_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/bio_lib.c", "summary": {"functions": {"count": 38, "covered": 15, "percent": 39.473684210526315}, "instantiations": {"count": 38, "covered": 15, "percent": 39.473684210526315}, "lines": {"count": 433, "covered": 194, "percent": 44.80369515011547}, "regions": {"count": 312, "covered": 109, "notcovered": 203, "percent": 34.93589743589743}}}, {"filename": "/src/openssl/crypto/bio/bss_conn.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 456, "covered": 0, "percent": 0}, "regions": {"count": 323, "covered": 0, "notcovered": 323, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/bss_file.c", "summary": {"functions": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "instantiations": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "lines": {"count": 233, "covered": 88, "percent": 37.76824034334764}, "regions": {"count": 193, "covered": 48, "notcovered": 145, "percent": 24.870466321243523}}}, {"filename": "/src/openssl/crypto/bio/bss_mem.c", "summary": {"functions": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "instantiations": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "lines": {"count": 207, "covered": 71, "percent": 34.29951690821256}, "regions": {"count": 140, "covered": 35, "notcovered": 105, "percent": 25}}}, {"filename": "/src/openssl/crypto/bio/bss_null.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 51, "covered": 0, "percent": 0}, "regions": {"count": 38, "covered": 0, "notcovered": 38, "percent": 0}}}, {"filename": "/src/openssl/crypto/bio/bss_sock.c", "summary": {"functions": {"count": 10, "covered": 8, "percent": 80}, "instantiations": {"count": 10, "covered": 8, "percent": 80}, "lines": {"count": 145, "covered": 83, "percent": 57.24137931034483}, "regions": {"count": 88, "covered": 49, "notcovered": 39, "percent": 55.68181818181818}}}, {"filename": "/src/openssl/crypto/bn/asm/x86_64-gcc.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 372, "covered": 0, "percent": 0}, "regions": {"count": 659, "covered": 0, "notcovered": 659, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_add.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 225, "covered": 0, "percent": 0}, "regions": {"count": 132, "covered": 0, "notcovered": 132, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_blind.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 215, "covered": 0, "percent": 0}, "regions": {"count": 173, "covered": 0, "notcovered": 173, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_ctx.c", "summary": {"functions": {"count": 16, "covered": 0, "percent": 0}, "instantiations": {"count": 16, "covered": 0, "percent": 0}, "lines": {"count": 192, "covered": 0, "percent": 0}, "regions": {"count": 110, "covered": 0, "notcovered": 110, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_div.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 237, "covered": 0, "percent": 0}, "regions": {"count": 186, "covered": 0, "notcovered": 186, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/bn/bn_exp.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 1076, "covered": 0, "percent": 0}, "regions": {"count": 895, "covered": 0, "notcovered": 895, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_exp2.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 183, "covered": 0, "percent": 0}, "regions": {"count": 170, "covered": 0, "notcovered": 170, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_gcd.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 567, "covered": 0, "percent": 0}, "regions": {"count": 387, "covered": 0, "notcovered": 387, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_gf2m.c", "summary": {"functions": {"count": 19, "covered": 0, "percent": 0}, "instantiations": {"count": 19, "covered": 0, "percent": 0}, "lines": {"count": 692, "covered": 0, "percent": 0}, "regions": {"count": 551, "covered": 0, "notcovered": 551, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_kron.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 123, "covered": 0, "percent": 0}, "regions": {"count": 93, "covered": 0, "notcovered": 93, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_lib.c", "summary": {"functions": {"count": 30, "covered": 1, "percent": 3.3333333333333335}, "instantiations": {"count": 30, "covered": 1, "percent": 3.3333333333333335}, "lines": {"count": 669, "covered": 3, "percent": 0.4484304932735426}, "regions": {"count": 463, "covered": 3, "notcovered": 460, "percent": 0.6479481641468683}}}, {"filename": "/src/openssl/crypto/bn/bn_mod.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 146, "covered": 0, "percent": 0}, "regions": {"count": 108, "covered": 0, "notcovered": 108, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_mont.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 284, "covered": 0, "percent": 0}, "regions": {"count": 210, "covered": 0, "notcovered": 210, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_mul.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 894, "covered": 0, "percent": 0}, "regions": {"count": 514, "covered": 0, "notcovered": 514, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_nist.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 661, "covered": 0, "percent": 0}, "regions": {"count": 944, "covered": 0, "notcovered": 944, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_prime.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 341, "covered": 0, "percent": 0}, "regions": {"count": 352, "covered": 0, "notcovered": 352, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_prime.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_print.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 309, "covered": 0, "percent": 0}, "regions": {"count": 278, "covered": 0, "notcovered": 278, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_rand.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 161, "covered": 0, "percent": 0}, "regions": {"count": 118, "covered": 0, "notcovered": 118, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_recp.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 169, "covered": 0, "percent": 0}, "regions": {"count": 110, "covered": 0, "notcovered": 110, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_shift.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 155, "covered": 0, "percent": 0}, "regions": {"count": 132, "covered": 0, "notcovered": 132, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_sqr.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 175, "covered": 0, "percent": 0}, "regions": {"count": 90, "covered": 0, "notcovered": 90, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_sqrt.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 341, "covered": 0, "percent": 0}, "regions": {"count": 297, "covered": 0, "notcovered": 297, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/bn_word.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 169, "covered": 0, "percent": 0}, "regions": {"count": 122, "covered": 0, "notcovered": 122, "percent": 0}}}, {"filename": "/src/openssl/crypto/bn/rsaz_exp.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 226, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/buffer/buf_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/buffer/buf_str.c", "summary": {"functions": {"count": 6, "covered": 5, "percent": 83.33333333333334}, "instantiations": {"count": 6, "covered": 5, "percent": 83.33333333333334}, "lines": {"count": 63, "covered": 47, "percent": 74.60317460317461}, "regions": {"count": 49, "covered": 31, "notcovered": 18, "percent": 63.26530612244898}}}, {"filename": "/src/openssl/crypto/buffer/buffer.c", "summary": {"functions": {"count": 5, "covered": 4, "percent": 80}, "instantiations": {"count": 5, "covered": 4, "percent": 80}, "lines": {"count": 109, "covered": 79, "percent": 72.47706422018348}, "regions": {"count": 71, "covered": 43, "notcovered": 28, "percent": 60.56338028169014}}}, {"filename": "/src/openssl/crypto/buildinf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/camellia/cmll_misc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 14, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/camellia/cmll_utl.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 2, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/c_cfb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 21, "covered": 0, "notcovered": 21, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/c_ecb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 17, "covered": 0, "percent": 0}, "regions": {"count": 9, "covered": 0, "notcovered": 9, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/c_enc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 132, "covered": 0, "percent": 0}, "regions": {"count": 160, "covered": 0, "notcovered": 160, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/c_ofb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 16, "covered": 0, "notcovered": 16, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/c_skey.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 92, "covered": 0, "percent": 0}, "regions": {"count": 200, "covered": 0, "notcovered": 200, "percent": 0}}}, {"filename": "/src/openssl/crypto/cast/cast_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/cmac/cm_ameth.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 8, "covered": 0, "percent": 0}, "regions": {"count": 5, "covered": 0, "notcovered": 5, "percent": 0}}}, {"filename": "/src/openssl/crypto/cmac/cm_pmeth.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 73, "covered": 0, "percent": 0}, "regions": {"count": 55, "covered": 0, "notcovered": 55, "percent": 0}}}, {"filename": "/src/openssl/crypto/cmac/cmac.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 166, "covered": 0, "percent": 0}, "regions": {"count": 122, "covered": 0, "notcovered": 122, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_asn1.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 114, "covered": 0, "percent": 0}, "regions": {"count": 80, "covered": 0, "notcovered": 80, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_att.c", "summary": {"functions": {"count": 20, "covered": 0, "percent": 0}, "instantiations": {"count": 20, "covered": 0, "percent": 0}, "lines": {"count": 77, "covered": 0, "percent": 0}, "regions": {"count": 44, "covered": 0, "notcovered": 44, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_dd.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 74, "covered": 0, "percent": 0}, "regions": {"count": 38, "covered": 0, "notcovered": 38, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_enc.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 185, "covered": 0, "percent": 0}, "regions": {"count": 149, "covered": 0, "notcovered": 149, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_env.c", "summary": {"functions": {"count": 28, "covered": 0, "percent": 0}, "instantiations": {"count": 28, "covered": 0, "percent": 0}, "lines": {"count": 795, "covered": 0, "percent": 0}, "regions": {"count": 608, "covered": 0, "notcovered": 608, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/cms/cms_io.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 52, "covered": 0, "percent": 0}, "regions": {"count": 34, "covered": 0, "notcovered": 34, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_kari.c", "summary": {"functions": {"count": 14, "covered": 0, "percent": 0}, "instantiations": {"count": 14, "covered": 0, "percent": 0}, "lines": {"count": 336, "covered": 0, "percent": 0}, "regions": {"count": 299, "covered": 0, "notcovered": 299, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_lib.c", "summary": {"functions": {"count": 28, "covered": 0, "percent": 0}, "instantiations": {"count": 28, "covered": 0, "percent": 0}, "lines": {"count": 505, "covered": 0, "percent": 0}, "regions": {"count": 475, "covered": 0, "notcovered": 475, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_pwri.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 343, "covered": 0, "percent": 0}, "regions": {"count": 216, "covered": 0, "notcovered": 216, "percent": 0}}}, {"filename": "/src/openssl/crypto/cms/cms_sd.c", "summary": {"functions": {"count": 32, "covered": 0, "percent": 0}, "instantiations": {"count": 32, "covered": 0, "percent": 0}, "lines": {"count": 804, "covered": 0, "percent": 0}, "regions": {"count": 841, "covered": 0, "notcovered": 841, "percent": 0}}}, {"filename": "/src/openssl/crypto/comp/c_zlib.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 6, "covered": 5, "percent": 83.33333333333334}, "regions": {"count": 2, "covered": 1, "notcovered": 1, "percent": 50}}}, {"filename": "/src/openssl/crypto/comp/comp_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/comp/comp_lib.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 51, "covered": 0, "percent": 0}, "regions": {"count": 29, "covered": 0, "notcovered": 29, "percent": 0}}}, {"filename": "/src/openssl/crypto/conf/conf_api.c", "summary": {"functions": {"count": 10, "covered": 1, "percent": 10}, "instantiations": {"count": 10, "covered": 1, "percent": 10}, "lines": {"count": 154, "covered": 3, "percent": 1.948051948051948}, "regions": {"count": 218, "covered": 5, "notcovered": 213, "percent": 2.293577981651376}}}, {"filename": "/src/openssl/crypto/conf/conf_def.c", "summary": {"functions": {"count": 19, "covered": 6, "percent": 31.57894736842105}, "instantiations": {"count": 19, "covered": 6, "percent": 31.57894736842105}, "lines": {"count": 537, "covered": 44, "percent": 8.193668528864059}, "regions": {"count": 489, "covered": 25, "notcovered": 464, "percent": 5.112474437627812}}}, {"filename": "/src/openssl/crypto/conf/conf_def.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/conf/conf_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/conf/conf_lib.c", "summary": {"functions": {"count": 22, "covered": 3, "percent": 13.636363636363635}, "instantiations": {"count": 22, "covered": 3, "percent": 13.636363636363635}, "lines": {"count": 228, "covered": 21, "percent": 9.210526315789473}, "regions": {"count": 129, "covered": 11, "notcovered": 118, "percent": 8.527131782945736}}}, {"filename": "/src/openssl/crypto/conf/conf_mall.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 8, "covered": 8, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/conf/conf_mod.c", "summary": {"functions": {"count": 24, "covered": 4, "percent": 16.666666666666664}, "instantiations": {"count": 24, "covered": 4, "percent": 16.666666666666664}, "lines": {"count": 391, "covered": 74, "percent": 18.925831202046037}, "regions": {"count": 317, "covered": 48, "notcovered": 269, "percent": 15.141955835962145}}}, {"filename": "/src/openssl/crypto/constant_time_locl.h", "summary": {"functions": {"count": 14, "covered": 0, "percent": 0}, "instantiations": {"count": 98, "covered": 0, "percent": 0}, "lines": {"count": 42, "covered": 0, "percent": 0}, "regions": {"count": 14, "covered": 0, "notcovered": 14, "percent": 0}}}, {"filename": "/src/openssl/crypto/cpt_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/cryptlib.c", "summary": {"functions": {"count": 36, "covered": 8, "percent": 22.22222222222222}, "instantiations": {"count": 36, "covered": 8, "percent": 22.22222222222222}, "lines": {"count": 370, "covered": 71, "percent": 19.18918918918919}, "regions": {"count": 287, "covered": 28, "notcovered": 259, "percent": 9.75609756097561}}}, {"filename": "/src/openssl/crypto/cryptlib.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/cversion.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 20, "covered": 3, "percent": 15}, "regions": {"count": 26, "covered": 2, "notcovered": 24, "percent": 7.6923076923076925}}}, {"filename": "/src/openssl/crypto/des/cfb64ede.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 158, "covered": 0, "percent": 0}, "regions": {"count": 116, "covered": 0, "notcovered": 116, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/cfb64enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 23, "covered": 0, "notcovered": 23, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/cfb_enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 92, "covered": 0, "percent": 0}, "regions": {"count": 85, "covered": 0, "notcovered": 85, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/des_enc.c", "summary": {"functions": {"count": 5, "covered": 1, "percent": 20}, "instantiations": {"count": 5, "covered": 1, "percent": 20}, "lines": {"count": 267, "covered": 52, "percent": 19.475655430711612}, "regions": {"count": 374, "covered": 83, "notcovered": 291, "percent": 22.192513368983956}}}, {"filename": "/src/openssl/crypto/des/des_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/ecb3_enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 19, "covered": 0, "percent": 0}, "regions": {"count": 9, "covered": 0, "notcovered": 9, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/ecb_enc.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 38, "covered": 17, "percent": 44.73684210526316}, "regions": {"count": 12, "covered": 6, "notcovered": 6, "percent": 50}}}, {"filename": "/src/openssl/crypto/des/ncbc_enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 81, "covered": 0, "percent": 0}, "regions": {"count": 62, "covered": 0, "notcovered": 62, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/ofb64ede.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 44, "covered": 0, "percent": 0}, "regions": {"count": 16, "covered": 0, "notcovered": 16, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/ofb64enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 17, "covered": 0, "notcovered": 17, "percent": 0}}}, {"filename": "/src/openssl/crypto/des/set_key.c", "summary": {"functions": {"count": 7, "covered": 3, "percent": 42.857142857142854}, "instantiations": {"count": 7, "covered": 3, "percent": 42.857142857142854}, "lines": {"count": 107, "covered": 72, "percent": 67.28971962616822}, "regions": {"count": 52, "covered": 27, "notcovered": 25, "percent": 51.92307692307693}}}, {"filename": "/src/openssl/crypto/des/xcbc_enc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 86, "covered": 0, "percent": 0}, "regions": {"count": 66, "covered": 0, "notcovered": 66, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_ameth.c", "summary": {"functions": {"count": 29, "covered": 0, "percent": 0}, "instantiations": {"count": 29, "covered": 0, "percent": 0}, "lines": {"count": 738, "covered": 0, "percent": 0}, "regions": {"count": 595, "covered": 0, "notcovered": 595, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_asn1.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 69, "covered": 0, "percent": 0}, "regions": {"count": 36, "covered": 0, "notcovered": 36, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_check.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 104, "covered": 0, "percent": 0}, "regions": {"count": 162, "covered": 0, "notcovered": 162, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/dh/dh_gen.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 77, "covered": 0, "percent": 0}, "regions": {"count": 71, "covered": 0, "notcovered": 71, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_kdf.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 107, "covered": 0, "percent": 0}, "regions": {"count": 82, "covered": 0, "notcovered": 82, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_key.c", "summary": {"functions": {"count": 9, "covered": 1, "percent": 11.11111111111111}, "instantiations": {"count": 9, "covered": 1, "percent": 11.11111111111111}, "lines": {"count": 172, "covered": 3, "percent": 1.744186046511628}, "regions": {"count": 141, "covered": 1, "notcovered": 140, "percent": 0.7092198581560284}}}, {"filename": "/src/openssl/crypto/dh/dh_lib.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 141, "covered": 0, "percent": 0}, "regions": {"count": 87, "covered": 0, "notcovered": 87, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_pmeth.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 318, "covered": 0, "percent": 0}, "regions": {"count": 223, "covered": 0, "notcovered": 223, "percent": 0}}}, {"filename": "/src/openssl/crypto/dh/dh_rfc5114.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 18, "covered": 0, "percent": 0}, "regions": {"count": 17, "covered": 0, "notcovered": 17, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_ameth.c", "summary": {"functions": {"count": 22, "covered": 0, "percent": 0}, "instantiations": {"count": 22, "covered": 0, "percent": 0}, "lines": {"count": 498, "covered": 0, "percent": 0}, "regions": {"count": 407, "covered": 0, "notcovered": 407, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_asn1.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 68, "covered": 0, "percent": 0}, "regions": {"count": 45, "covered": 0, "notcovered": 45, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/dsa/dsa_gen.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 604, "covered": 0, "percent": 0}, "regions": {"count": 503, "covered": 0, "notcovered": 503, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_key.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 58, "covered": 0, "percent": 0}, "regions": {"count": 48, "covered": 0, "notcovered": 48, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_lib.c", "summary": {"functions": {"count": 12, "covered": 1, "percent": 8.333333333333332}, "instantiations": {"count": 12, "covered": 1, "percent": 8.333333333333332}, "lines": {"count": 197, "covered": 6, "percent": 3.0456852791878175}, "regions": {"count": 121, "covered": 3, "notcovered": 118, "percent": 2.479338842975207}}}, {"filename": "/src/openssl/crypto/dsa/dsa_ossl.c", "summary": {"functions": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "instantiations": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "lines": {"count": 299, "covered": 3, "percent": 1.0033444816053512}, "regions": {"count": 248, "covered": 1, "notcovered": 247, "percent": 0.4032258064516129}}}, {"filename": "/src/openssl/crypto/dsa/dsa_pmeth.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 158, "covered": 0, "percent": 0}, "regions": {"count": 132, "covered": 0, "notcovered": 132, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_sign.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 22, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/dsa/dsa_vrf.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 2, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/dso/dso_dlfcn.c", "summary": {"functions": {"count": 9, "covered": 4, "percent": 44.44444444444444}, "instantiations": {"count": 9, "covered": 4, "percent": 44.44444444444444}, "lines": {"count": 235, "covered": 53, "percent": 22.5531914893617}, "regions": {"count": 212, "covered": 40, "notcovered": 172, "percent": 18.867924528301888}}}, {"filename": "/src/openssl/crypto/dso/dso_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/dso/dso_lib.c", "summary": {"functions": {"count": 21, "covered": 7, "percent": 33.33333333333333}, "instantiations": {"count": 21, "covered": 7, "percent": 33.33333333333333}, "lines": {"count": 321, "covered": 116, "percent": 36.13707165109034}, "regions": {"count": 287, "covered": 96, "notcovered": 191, "percent": 33.44947735191638}}}, {"filename": "/src/openssl/crypto/dso/dso_openssl.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 1, "covered": 1, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ec/ec2_mult.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 318, "covered": 0, "percent": 0}, "regions": {"count": 291, "covered": 0, "notcovered": 291, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec2_oct.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 290, "covered": 0, "percent": 0}, "regions": {"count": 254, "covered": 0, "notcovered": 254, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec2_smpl.c", "summary": {"functions": {"count": 27, "covered": 0, "percent": 0}, "instantiations": {"count": 27, "covered": 0, "percent": 0}, "lines": {"count": 562, "covered": 0, "percent": 0}, "regions": {"count": 412, "covered": 0, "notcovered": 412, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_ameth.c", "summary": {"functions": {"count": 27, "covered": 0, "percent": 0}, "instantiations": {"count": 27, "covered": 0, "percent": 0}, "lines": {"count": 795, "covered": 0, "percent": 0}, "regions": {"count": 678, "covered": 0, "notcovered": 678, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_asn1.c", "summary": {"functions": {"count": 17, "covered": 0, "percent": 0}, "instantiations": {"count": 17, "covered": 0, "percent": 0}, "lines": {"count": 1034, "covered": 0, "percent": 0}, "regions": {"count": 910, "covered": 0, "notcovered": 910, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_curve.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 160, "covered": 0, "percent": 0}, "regions": {"count": 137, "covered": 0, "notcovered": 137, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_cvt.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 81, "covered": 0, "percent": 0}, "regions": {"count": 33, "covered": 0, "notcovered": 33, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ec/ec_key.c", "summary": {"functions": {"count": 26, "covered": 0, "percent": 0}, "instantiations": {"count": 26, "covered": 0, "percent": 0}, "lines": {"count": 412, "covered": 0, "percent": 0}, "regions": {"count": 305, "covered": 0, "notcovered": 305, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_lib.c", "summary": {"functions": {"count": 60, "covered": 0, "percent": 0}, "instantiations": {"count": 60, "covered": 0, "percent": 0}, "lines": {"count": 868, "covered": 0, "percent": 0}, "regions": {"count": 672, "covered": 0, "notcovered": 672, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_mult.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 751, "covered": 0, "percent": 0}, "regions": {"count": 513, "covered": 0, "notcovered": 513, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_oct.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 87, "covered": 0, "percent": 0}, "regions": {"count": 88, "covered": 0, "notcovered": 88, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_pmeth.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 336, "covered": 0, "percent": 0}, "regions": {"count": 282, "covered": 0, "notcovered": 282, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ec_print.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 104, "covered": 0, "percent": 0}, "regions": {"count": 66, "covered": 0, "notcovered": 66, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/eck_prn.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 289, "covered": 0, "percent": 0}, "regions": {"count": 259, "covered": 0, "notcovered": 259, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_mont.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 207, "covered": 0, "percent": 0}, "regions": {"count": 106, "covered": 0, "notcovered": 106, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_nist.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 130, "covered": 0, "percent": 0}, "regions": {"count": 84, "covered": 0, "notcovered": 84, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_nistp224.c", "summary": {"functions": {"count": 41, "covered": 0, "percent": 0}, "instantiations": {"count": 41, "covered": 0, "percent": 0}, "lines": {"count": 1273, "covered": 0, "percent": 0}, "regions": {"count": 405, "covered": 0, "notcovered": 405, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_nistp521.c", "summary": {"functions": {"count": 42, "covered": 0, "percent": 0}, "instantiations": {"count": 42, "covered": 0, "percent": 0}, "lines": {"count": 1596, "covered": 0, "percent": 0}, "regions": {"count": 395, "covered": 0, "notcovered": 395, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_nistputil.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 73, "covered": 0, "percent": 0}, "regions": {"count": 63, "covered": 0, "notcovered": 63, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_nistz256.c", "summary": {"functions": {"count": 21, "covered": 0, "percent": 0}, "instantiations": {"count": 21, "covered": 0, "percent": 0}, "lines": {"count": 886, "covered": 0, "percent": 0}, "regions": {"count": 476, "covered": 0, "notcovered": 476, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_oct.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 347, "covered": 0, "percent": 0}, "regions": {"count": 294, "covered": 0, "notcovered": 294, "percent": 0}}}, {"filename": "/src/openssl/crypto/ec/ecp_smpl.c", "summary": {"functions": {"count": 28, "covered": 0, "percent": 0}, "instantiations": {"count": 28, "covered": 0, "percent": 0}, "lines": {"count": 1244, "covered": 0, "percent": 0}, "regions": {"count": 938, "covered": 0, "notcovered": 938, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdh/ech_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ecdh/ech_kdf.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 44, "covered": 0, "percent": 0}, "regions": {"count": 38, "covered": 0, "notcovered": 38, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdh/ech_key.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 6, "covered": 0, "percent": 0}, "regions": {"count": 4, "covered": 0, "notcovered": 4, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdh/ech_lib.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 129, "covered": 0, "percent": 0}, "regions": {"count": 61, "covered": 0, "notcovered": 61, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdh/ech_ossl.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 112, "covered": 0, "percent": 0}, "regions": {"count": 86, "covered": 0, "notcovered": 86, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_lib.c", "summary": {"functions": {"count": 21, "covered": 0, "percent": 0}, "instantiations": {"count": 21, "covered": 0, "percent": 0}, "lines": {"count": 209, "covered": 0, "percent": 0}, "regions": {"count": 99, "covered": 0, "notcovered": 99, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_ossl.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 383, "covered": 0, "percent": 0}, "regions": {"count": 337, "covered": 0, "notcovered": 337, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_sign.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 30, "covered": 0, "percent": 0}, "regions": {"count": 14, "covered": 0, "notcovered": 14, "percent": 0}}}, {"filename": "/src/openssl/crypto/ecdsa/ecs_vrf.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 31, "covered": 0, "percent": 0}, "regions": {"count": 20, "covered": 0, "notcovered": 20, "percent": 0}}}, {"filename": "/src/openssl/crypto/engine/eng_all.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 41, "covered": 41, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/engine/eng_cnf.c", "summary": {"functions": {"count": 5, "covered": 1, "percent": 20}, "instantiations": {"count": 5, "covered": 1, "percent": 20}, "lines": {"count": 49, "covered": 4, "percent": 8.16326530612245}, "regions": {"count": 59, "covered": 1, "notcovered": 58, "percent": 1.694915254237288}}}, {"filename": "/src/openssl/crypto/engine/eng_ctrl.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 287, "covered": 0, "percent": 0}, "regions": {"count": 254, "covered": 0, "notcovered": 254, "percent": 0}}}, {"filename": "/src/openssl/crypto/engine/eng_dyn.c", "summary": {"functions": {"count": 11, "covered": 2, "percent": 18.181818181818183}, "instantiations": {"count": 11, "covered": 2, "percent": 18.181818181818183}, "lines": {"count": 360, "covered": 28, "percent": 7.777777777777778}, "regions": {"count": 275, "covered": 21, "notcovered": 254, "percent": 7.636363636363637}}}, {"filename": "/src/openssl/crypto/engine/eng_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/engine/eng_fat.c", "summary": {"functions": {"count": 4, "covered": 2, "percent": 50}, "instantiations": {"count": 4, "covered": 2, "percent": 50}, "lines": {"count": 75, "covered": 30, "percent": 40}, "regions": {"count": 75, "covered": 8, "notcovered": 67, "percent": 10.666666666666668}}}, {"filename": "/src/openssl/crypto/engine/eng_init.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 76, "covered": 12, "percent": 15.789473684210526}, "regions": {"count": 59, "covered": 6, "notcovered": 53, "percent": 10.16949152542373}}}, {"filename": "/src/openssl/crypto/engine/eng_lib.c", "summary": {"functions": {"count": 30, "covered": 15, "percent": 50}, "instantiations": {"count": 30, "covered": 15, "percent": 50}, "lines": {"count": 186, "covered": 86, "percent": 46.236559139784944}, "regions": {"count": 113, "covered": 59, "notcovered": 54, "percent": 52.21238938053098}}}, {"filename": "/src/openssl/crypto/engine/eng_list.c", "summary": {"functions": {"count": 12, "covered": 4, "percent": 33.33333333333333}, "instantiations": {"count": 12, "covered": 4, "percent": 33.33333333333333}, "lines": {"count": 276, "covered": 72, "percent": 26.08695652173913}, "regions": {"count": 204, "covered": 55, "notcovered": 149, "percent": 26.96078431372549}}}, {"filename": "/src/openssl/crypto/engine/eng_pkey.c", "summary": {"functions": {"count": 9, "covered": 2, "percent": 22.22222222222222}, "instantiations": {"count": 9, "covered": 2, "percent": 22.22222222222222}, "lines": {"count": 99, "covered": 8, "percent": 8.080808080808081}, "regions": {"count": 97, "covered": 2, "notcovered": 95, "percent": 2.0618556701030926}}}, {"filename": "/src/openssl/crypto/engine/eng_rdrand.c", "summary": {"functions": {"count": 6, "covered": 3, "percent": 50}, "instantiations": {"count": 6, "covered": 3, "percent": 50}, "lines": {"count": 58, "covered": 26, "percent": 44.827586206896555}, "regions": {"count": 41, "covered": 22, "notcovered": 19, "percent": 53.65853658536586}}}, {"filename": "/src/openssl/crypto/engine/eng_table.c", "summary": {"functions": {"count": 13, "covered": 6, "percent": 46.15384615384615}, "instantiations": {"count": 13, "covered": 6, "percent": 46.15384615384615}, "lines": {"count": 186, "covered": 109, "percent": 58.602150537634415}, "regions": {"count": 232, "covered": 117, "notcovered": 115, "percent": 50.43103448275862}}}, {"filename": "/src/openssl/crypto/engine/tb_asnmth.c", "summary": {"functions": {"count": 13, "covered": 2, "percent": 15.384615384615385}, "instantiations": {"count": 13, "covered": 2, "percent": 15.384615384615385}, "lines": {"count": 119, "covered": 18, "percent": 15.126050420168067}, "regions": {"count": 80, "covered": 9, "notcovered": 71, "percent": 11.25}}}, {"filename": "/src/openssl/crypto/engine/tb_cipher.c", "summary": {"functions": {"count": 9, "covered": 2, "percent": 22.22222222222222}, "instantiations": {"count": 9, "covered": 2, "percent": 22.22222222222222}, "lines": {"count": 53, "covered": 15, "percent": 28.30188679245283}, "regions": {"count": 29, "covered": 7, "notcovered": 22, "percent": 24.137931034482758}}}, {"filename": "/src/openssl/crypto/engine/tb_dh.c", "summary": {"functions": {"count": 8, "covered": 2, "percent": 25}, "instantiations": {"count": 8, "covered": 2, "percent": 25}, "lines": {"count": 36, "covered": 11, "percent": 30.555555555555557}, "regions": {"count": 17, "covered": 5, "notcovered": 12, "percent": 29.411764705882355}}}, {"filename": "/src/openssl/crypto/engine/tb_digest.c", "summary": {"functions": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "instantiations": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "lines": {"count": 53, "covered": 18, "percent": 33.9622641509434}, "regions": {"count": 29, "covered": 8, "notcovered": 21, "percent": 27.586206896551722}}}, {"filename": "/src/openssl/crypto/engine/tb_dsa.c", "summary": {"functions": {"count": 8, "covered": 2, "percent": 25}, "instantiations": {"count": 8, "covered": 2, "percent": 25}, "lines": {"count": 36, "covered": 11, "percent": 30.555555555555557}, "regions": {"count": 17, "covered": 5, "notcovered": 12, "percent": 29.411764705882355}}}, {"filename": "/src/openssl/crypto/engine/tb_ecdh.c", "summary": {"functions": {"count": 8, "covered": 1, "percent": 12.5}, "instantiations": {"count": 8, "covered": 1, "percent": 12.5}, "lines": {"count": 36, "covered": 4, "percent": 11.11111111111111}, "regions": {"count": 17, "covered": 3, "notcovered": 14, "percent": 17.647058823529413}}}, {"filename": "/src/openssl/crypto/engine/tb_ecdsa.c", "summary": {"functions": {"count": 8, "covered": 1, "percent": 12.5}, "instantiations": {"count": 8, "covered": 1, "percent": 12.5}, "lines": {"count": 36, "covered": 4, "percent": 11.11111111111111}, "regions": {"count": 17, "covered": 3, "notcovered": 14, "percent": 17.647058823529413}}}, {"filename": "/src/openssl/crypto/engine/tb_pkmeth.c", "summary": {"functions": {"count": 10, "covered": 2, "percent": 20}, "instantiations": {"count": 10, "covered": 2, "percent": 20}, "lines": {"count": 68, "covered": 15, "percent": 22.058823529411764}, "regions": {"count": 37, "covered": 7, "notcovered": 30, "percent": 18.91891891891892}}}, {"filename": "/src/openssl/crypto/engine/tb_rand.c", "summary": {"functions": {"count": 8, "covered": 3, "percent": 37.5}, "instantiations": {"count": 8, "covered": 3, "percent": 37.5}, "lines": {"count": 36, "covered": 14, "percent": 38.88888888888889}, "regions": {"count": 17, "covered": 6, "notcovered": 11, "percent": 35.294117647058826}}}, {"filename": "/src/openssl/crypto/engine/tb_rsa.c", "summary": {"functions": {"count": 8, "covered": 2, "percent": 25}, "instantiations": {"count": 8, "covered": 2, "percent": 25}, "lines": {"count": 36, "covered": 11, "percent": 30.555555555555557}, "regions": {"count": 17, "covered": 5, "notcovered": 12, "percent": 29.411764705882355}}}, {"filename": "/src/openssl/crypto/err/err.c", "summary": {"functions": {"count": 54, "covered": 37, "percent": 68.51851851851852}, "instantiations": {"count": 54, "covered": 37, "percent": 68.51851851851852}, "lines": {"count": 660, "covered": 486, "percent": 73.63636363636363}, "regions": {"count": 598, "covered": 423, "notcovered": 175, "percent": 70.73578595317726}}}, {"filename": "/src/openssl/crypto/err/err_all.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 49, "covered": 49, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/err/err_prn.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 36, "covered": 0, "percent": 0}, "regions": {"count": 14, "covered": 0, "notcovered": 14, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/bio_b64.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 446, "covered": 0, "percent": 0}, "regions": {"count": 321, "covered": 0, "notcovered": 321, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/bio_enc.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 296, "covered": 0, "percent": 0}, "regions": {"count": 183, "covered": 0, "notcovered": 183, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/bio_md.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 157, "covered": 0, "percent": 0}, "regions": {"count": 115, "covered": 0, "notcovered": 115, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/c_all.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 10, "covered": 10, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/evp/c_allc.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 176, "covered": 176, "percent": 100}, "regions": {"count": 115, "covered": 115, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/evp/c_alld.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 49, "covered": 49, "percent": 100}, "regions": {"count": 28, "covered": 28, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/evp/digest.c", "summary": {"functions": {"count": 12, "covered": 5, "percent": 41.66666666666667}, "instantiations": {"count": 12, "covered": 5, "percent": 41.66666666666667}, "lines": {"count": 221, "covered": 78, "percent": 35.294117647058826}, "regions": {"count": 167, "covered": 56, "notcovered": 111, "percent": 33.532934131736525}}}, {"filename": "/src/openssl/crypto/evp/e_aes.c", "summary": {"functions": {"count": 33, "covered": 5, "percent": 15.151515151515152}, "instantiations": {"count": 60, "covered": 32, "percent": 53.333333333333336}, "lines": {"count": 939, "covered": 13, "percent": 1.384451544195953}, "regions": {"count": 678, "covered": 9, "notcovered": 669, "percent": 1.3274336283185841}}}, {"filename": "/src/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c", "summary": {"functions": {"count": 7, "covered": 2, "percent": 28.57142857142857}, "instantiations": {"count": 7, "covered": 2, "percent": 28.57142857142857}, "lines": {"count": 641, "covered": 8, "percent": 1.24804992199688}, "regions": {"count": 310, "covered": 6, "notcovered": 304, "percent": 1.935483870967742}}}, {"filename": "/src/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c", "summary": {"functions": {"count": 7, "covered": 2, "percent": 28.57142857142857}, "instantiations": {"count": 7, "covered": 2, "percent": 28.57142857142857}, "lines": {"count": 682, "covered": 8, "percent": 1.1730205278592376}, "regions": {"count": 317, "covered": 8, "notcovered": 309, "percent": 2.5236593059936907}}}, {"filename": "/src/openssl/crypto/evp/e_bf.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 4, "covered": 0, "percent": 0}, "regions": {"count": 3, "covered": 0, "notcovered": 3, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_camellia.c", "summary": {"functions": {"count": 8, "covered": 1, "percent": 12.5}, "instantiations": {"count": 25, "covered": 18, "percent": 72}, "lines": {"count": 92, "covered": 2, "percent": 2.1739130434782608}, "regions": {"count": 51, "covered": 1, "notcovered": 50, "percent": 1.9607843137254901}}}, {"filename": "/src/openssl/crypto/evp/e_cast.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 4, "covered": 0, "percent": 0}, "regions": {"count": 3, "covered": 0, "notcovered": 3, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_des.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 110, "covered": 0, "percent": 0}, "regions": {"count": 75, "covered": 0, "notcovered": 75, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_des3.c", "summary": {"functions": {"count": 15, "covered": 3, "percent": 20}, "instantiations": {"count": 15, "covered": 3, "percent": 20}, "lines": {"count": 227, "covered": 9, "percent": 3.9647577092511015}, "regions": {"count": 175, "covered": 3, "notcovered": 172, "percent": 1.7142857142857144}}}, {"filename": "/src/openssl/crypto/evp/e_idea.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 23, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_null.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 12, "covered": 0, "percent": 0}, "regions": {"count": 5, "covered": 0, "notcovered": 5, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_rc2.c", "summary": {"functions": {"count": 8, "covered": 2, "percent": 25}, "instantiations": {"count": 8, "covered": 2, "percent": 25}, "lines": {"count": 90, "covered": 6, "percent": 6.666666666666667}, "regions": {"count": 70, "covered": 2, "notcovered": 68, "percent": 2.857142857142857}}}, {"filename": "/src/openssl/crypto/evp/e_rc4.c", "summary": {"functions": {"count": 4, "covered": 2, "percent": 50}, "instantiations": {"count": 4, "covered": 2, "percent": 50}, "lines": {"count": 14, "covered": 6, "percent": 42.857142857142854}, "regions": {"count": 6, "covered": 2, "notcovered": 4, "percent": 33.33333333333333}}}, {"filename": "/src/openssl/crypto/evp/e_rc4_hmac_md5.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 184, "covered": 3, "percent": 1.6304347826086956}, "regions": {"count": 96, "covered": 1, "notcovered": 95, "percent": 1.0416666666666665}}}, {"filename": "/src/openssl/crypto/evp/e_rc5.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 32, "covered": 0, "percent": 0}, "regions": {"count": 30, "covered": 0, "notcovered": 30, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_seed.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 4, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/e_xcbc_d.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 27, "covered": 3, "percent": 11.11111111111111}, "regions": {"count": 21, "covered": 1, "notcovered": 20, "percent": 4.761904761904762}}}, {"filename": "/src/openssl/crypto/evp/encode.c", "summary": {"functions": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "instantiations": {"count": 9, "covered": 5, "percent": 55.55555555555556}, "lines": {"count": 253, "covered": 112, "percent": 44.26877470355731}, "regions": {"count": 159, "covered": 86, "notcovered": 73, "percent": 54.088050314465406}}}, {"filename": "/src/openssl/crypto/evp/evp_cnf.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 35, "covered": 3, "percent": 8.571428571428571}, "regions": {"count": 35, "covered": 1, "notcovered": 34, "percent": 2.857142857142857}}}, {"filename": "/src/openssl/crypto/evp/evp_enc.c", "summary": {"functions": {"count": 24, "covered": 0, "percent": 0}, "instantiations": {"count": 24, "covered": 0, "percent": 0}, "lines": {"count": 516, "covered": 0, "percent": 0}, "regions": {"count": 406, "covered": 0, "notcovered": 406, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/evp_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/evp/evp_key.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 111, "covered": 0, "percent": 0}, "regions": {"count": 102, "covered": 0, "notcovered": 102, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/evp_lib.c", "summary": {"functions": {"count": 31, "covered": 4, "percent": 12.903225806451612}, "instantiations": {"count": 31, "covered": 4, "percent": 12.903225806451612}, "lines": {"count": 217, "covered": 13, "percent": 5.990783410138248}, "regions": {"count": 150, "covered": 8, "notcovered": 142, "percent": 5.333333333333334}}}, {"filename": "/src/openssl/crypto/evp/evp_locl.h", "summary": {"functions": {"count": 5, "covered": 1, "percent": 20}, "instantiations": {"count": 63, "covered": 38, "percent": 60.317460317460316}, "lines": {"count": 48, "covered": 1, "percent": 2.083333333333333}, "regions": {"count": 47, "covered": 1, "notcovered": 46, "percent": 2.127659574468085}}}, {"filename": "/src/openssl/crypto/evp/evp_pbe.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 137, "covered": 0, "percent": 0}, "regions": {"count": 123, "covered": 0, "notcovered": 123, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/evp_pkey.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 125, "covered": 0, "percent": 0}, "regions": {"count": 83, "covered": 0, "notcovered": 83, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/m_dss.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_dss1.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_ecdsa.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_md4.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_md5.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_mdc2.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_ripemd.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_sha.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/m_sha1.c", "summary": {"functions": {"count": 16, "covered": 8, "percent": 50}, "instantiations": {"count": 16, "covered": 8, "percent": 50}, "lines": {"count": 48, "covered": 24, "percent": 50}, "regions": {"count": 16, "covered": 8, "notcovered": 8, "percent": 50}}}, {"filename": "/src/openssl/crypto/evp/m_sigver.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 122, "covered": 0, "percent": 0}, "regions": {"count": 118, "covered": 0, "notcovered": 118, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/m_wp.c", "summary": {"functions": {"count": 4, "covered": 1, "percent": 25}, "instantiations": {"count": 4, "covered": 1, "percent": 25}, "lines": {"count": 12, "covered": 3, "percent": 25}, "regions": {"count": 4, "covered": 1, "notcovered": 3, "percent": 25}}}, {"filename": "/src/openssl/crypto/evp/names.c", "summary": {"functions": {"count": 11, "covered": 4, "percent": 36.36363636363637}, "instantiations": {"count": 11, "covered": 4, "percent": 36.36363636363637}, "lines": {"count": 110, "covered": 51, "percent": 46.36363636363636}, "regions": {"count": 55, "covered": 30, "notcovered": 25, "percent": 54.54545454545454}}}, {"filename": "/src/openssl/crypto/evp/p5_crpt.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 75, "covered": 0, "percent": 0}, "regions": {"count": 66, "covered": 0, "notcovered": 66, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/p5_crpt2.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 200, "covered": 0, "percent": 0}, "regions": {"count": 138, "covered": 0, "notcovered": 138, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/p_lib.c", "summary": {"functions": {"count": 31, "covered": 1, "percent": 3.225806451612903}, "instantiations": {"count": 31, "covered": 1, "percent": 3.225806451612903}, "lines": {"count": 291, "covered": 5, "percent": 1.718213058419244}, "regions": {"count": 242, "covered": 3, "notcovered": 239, "percent": 1.2396694214876034}}}, {"filename": "/src/openssl/crypto/evp/p_sign.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 55, "covered": 0, "percent": 0}, "regions": {"count": 50, "covered": 0, "notcovered": 50, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/p_verify.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 50, "covered": 0, "percent": 0}, "regions": {"count": 47, "covered": 0, "notcovered": 47, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/pmeth_fn.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 229, "covered": 0, "percent": 0}, "regions": {"count": 355, "covered": 0, "notcovered": 355, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/pmeth_gn.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 130, "covered": 0, "percent": 0}, "regions": {"count": 119, "covered": 0, "notcovered": 119, "percent": 0}}}, {"filename": "/src/openssl/crypto/evp/pmeth_lib.c", "summary": {"functions": {"count": 50, "covered": 13, "percent": 26}, "instantiations": {"count": 50, "covered": 13, "percent": 26}, "lines": {"count": 420, "covered": 57, "percent": 13.571428571428571}, "regions": {"count": 296, "covered": 17, "notcovered": 279, "percent": 5.743243243243244}}}, {"filename": "/src/openssl/crypto/ex_data.c", "summary": {"functions": {"count": 24, "covered": 13, "percent": 54.166666666666664}, "instantiations": {"count": 24, "covered": 13, "percent": 54.166666666666664}, "lines": {"count": 296, "covered": 160, "percent": 54.054054054054056}, "regions": {"count": 436, "covered": 224, "notcovered": 212, "percent": 51.37614678899083}}}, {"filename": "/src/openssl/crypto/hmac/hm_ameth.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 52, "covered": 0, "percent": 0}, "regions": {"count": 32, "covered": 0, "notcovered": 32, "percent": 0}}}, {"filename": "/src/openssl/crypto/hmac/hm_pmeth.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 118, "covered": 0, "percent": 0}, "regions": {"count": 75, "covered": 0, "notcovered": 75, "percent": 0}}}, {"filename": "/src/openssl/crypto/hmac/hmac.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 138, "covered": 0, "percent": 0}, "regions": {"count": 124, "covered": 0, "notcovered": 124, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/i_cbc.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 105, "covered": 0, "percent": 0}, "regions": {"count": 202, "covered": 0, "notcovered": 202, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/i_cfb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 20, "covered": 0, "notcovered": 20, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/i_ecb.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 20, "covered": 0, "percent": 0}, "regions": {"count": 9, "covered": 0, "notcovered": 9, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/i_ofb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/i_skey.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 93, "covered": 0, "percent": 0}, "regions": {"count": 33, "covered": 0, "notcovered": 33, "percent": 0}}}, {"filename": "/src/openssl/crypto/idea/idea_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/lhash/lhash.c", "summary": {"functions": {"count": 13, "covered": 11, "percent": 84.61538461538461}, "instantiations": {"count": 13, "covered": 11, "percent": 84.61538461538461}, "lines": {"count": 310, "covered": 239, "percent": 77.09677419354838}, "regions": {"count": 136, "covered": 97, "notcovered": 39, "percent": 71.32352941176471}}}, {"filename": "/src/openssl/crypto/md32_common.h", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 18, "covered": 6, "percent": 33.33333333333333}, "lines": {"count": 91, "covered": 87, "percent": 95.6043956043956}, "regions": {"count": 84, "covered": 58, "notcovered": 26, "percent": 69.04761904761905}}}, {"filename": "/src/openssl/crypto/md4/md4_dgst.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 112, "covered": 112, "percent": 100}, "regions": {"count": 184, "covered": 184, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/md4/md4_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/md5/md5_dgst.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 8, "covered": 8, "percent": 100}, "regions": {"count": 5, "covered": 5, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/md5/md5_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/mdc2/mdc2dgst.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 90, "covered": 0, "percent": 0}, "regions": {"count": 41, "covered": 0, "notcovered": 41, "percent": 0}}}, {"filename": "/src/openssl/crypto/mem.c", "summary": {"functions": {"count": 23, "covered": 5, "percent": 21.73913043478261}, "instantiations": {"count": 23, "covered": 5, "percent": 21.73913043478261}, "lines": {"count": 234, "covered": 42, "percent": 17.94871794871795}, "regions": {"count": 170, "covered": 19, "notcovered": 151, "percent": 11.176470588235295}}}, {"filename": "/src/openssl/crypto/mem_dbg.c", "summary": {"functions": {"count": 21, "covered": 4, "percent": 19.047619047619047}, "instantiations": {"count": 21, "covered": 4, "percent": 19.047619047619047}, "lines": {"count": 490, "covered": 45, "percent": 9.183673469387756}, "regions": {"count": 403, "covered": 25, "notcovered": 378, "percent": 6.20347394540943}}}, {"filename": "/src/openssl/crypto/modes/cbc128.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 135, "covered": 0, "percent": 0}, "regions": {"count": 83, "covered": 0, "notcovered": 83, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/ccm128.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 359, "covered": 0, "percent": 0}, "regions": {"count": 139, "covered": 0, "notcovered": 139, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/cfb128.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 164, "covered": 0, "percent": 0}, "regions": {"count": 85, "covered": 0, "notcovered": 85, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/ctr128.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 165, "covered": 0, "percent": 0}, "regions": {"count": 64, "covered": 0, "notcovered": 64, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/gcm128.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 732, "covered": 0, "percent": 0}, "regions": {"count": 376, "covered": 0, "notcovered": 376, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/modes_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/ofb128.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 55, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/wrap128.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 62, "covered": 0, "percent": 0}, "regions": {"count": 41, "covered": 0, "notcovered": 41, "percent": 0}}}, {"filename": "/src/openssl/crypto/modes/xts128.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 120, "covered": 0, "percent": 0}, "regions": {"count": 35, "covered": 0, "notcovered": 35, "percent": 0}}}, {"filename": "/src/openssl/crypto/o_init.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 5, "covered": 5, "percent": 100}, "regions": {"count": 4, "covered": 4, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/o_time.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 122, "covered": 0, "percent": 0}, "regions": {"count": 50, "covered": 0, "notcovered": 50, "percent": 0}}}, {"filename": "/src/openssl/crypto/objects/o_names.c", "summary": {"functions": {"count": 15, "covered": 5, "percent": 33.33333333333333}, "instantiations": {"count": 15, "covered": 5, "percent": 33.33333333333333}, "lines": {"count": 258, "covered": 87, "percent": 33.72093023255814}, "regions": {"count": 296, "covered": 75, "notcovered": 221, "percent": 25.33783783783784}}}, {"filename": "/src/openssl/crypto/objects/obj_dat.c", "summary": {"functions": {"count": 25, "covered": 8, "percent": 32}, "instantiations": {"count": 25, "covered": 8, "percent": 32}, "lines": {"count": 567, "covered": 87, "percent": 15.343915343915343}, "regions": {"count": 541, "covered": 80, "notcovered": 461, "percent": 14.78743068391867}}}, {"filename": "/src/openssl/crypto/objects/obj_dat.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/objects/obj_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/objects/obj_lib.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 68, "covered": 31, "percent": 45.588235294117645}, "regions": {"count": 51, "covered": 20, "notcovered": 31, "percent": 39.21568627450981}}}, {"filename": "/src/openssl/crypto/objects/obj_xref.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 108, "covered": 0, "percent": 0}, "regions": {"count": 133, "covered": 0, "notcovered": 133, "percent": 0}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_cl.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 219, "covered": 0, "percent": 0}, "regions": {"count": 209, "covered": 0, "notcovered": 209, "percent": 0}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_ht.c", "summary": {"functions": {"count": 14, "covered": 0, "percent": 0}, "instantiations": {"count": 14, "covered": 0, "percent": 0}, "lines": {"count": 402, "covered": 0, "percent": 0}, "regions": {"count": 328, "covered": 0, "notcovered": 328, "percent": 0}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_lib.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 192, "covered": 0, "percent": 0}, "regions": {"count": 118, "covered": 0, "notcovered": 118, "percent": 0}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_prn.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 210, "covered": 0, "percent": 0}, "regions": {"count": 226, "covered": 0, "notcovered": 226, "percent": 0}}}, {"filename": "/src/openssl/crypto/ocsp/ocsp_vfy.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 338, "covered": 0, "percent": 0}, "regions": {"count": 348, "covered": 0, "notcovered": 348, "percent": 0}}}, {"filename": "/src/openssl/crypto/pem/pem_all.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 72, "covered": 0, "percent": 0}, "regions": {"count": 33, "covered": 0, "notcovered": 33, "percent": 0}}}, {"filename": "/src/openssl/crypto/pem/pem_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/pem/pem_info.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 310, "covered": 86, "percent": 27.741935483870968}, "regions": {"count": 294, "covered": 72, "notcovered": 222, "percent": 24.489795918367346}}}, {"filename": "/src/openssl/crypto/pem/pem_lib.c", "summary": {"functions": {"count": 14, "covered": 3, "percent": 21.428571428571427}, "instantiations": {"count": 14, "covered": 3, "percent": 21.428571428571427}, "lines": {"count": 605, "covered": 118, "percent": 19.50413223140496}, "regions": {"count": 476, "covered": 71, "notcovered": 405, "percent": 14.915966386554622}}}, {"filename": "/src/openssl/crypto/pem/pem_oth.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 15, "covered": 0, "percent": 0}, "regions": {"count": 8, "covered": 0, "notcovered": 8, "percent": 0}}}, {"filename": "/src/openssl/crypto/pem/pem_pk8.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 124, "covered": 0, "percent": 0}, "regions": {"count": 81, "covered": 0, "notcovered": 81, "percent": 0}}}, {"filename": "/src/openssl/crypto/pem/pem_pkey.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 163, "covered": 0, "percent": 0}, "regions": {"count": 116, "covered": 0, "notcovered": 116, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_add.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 158, "covered": 0, "percent": 0}, "regions": {"count": 120, "covered": 0, "notcovered": 120, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_attr.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 62, "covered": 0, "percent": 0}, "regions": {"count": 73, "covered": 0, "notcovered": 73, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_crpt.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 49, "covered": 0, "percent": 0}, "regions": {"count": 40, "covered": 0, "notcovered": 40, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_decr.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 92, "covered": 0, "percent": 0}, "regions": {"count": 66, "covered": 0, "notcovered": 66, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_key.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 117, "covered": 0, "percent": 0}, "regions": {"count": 117, "covered": 0, "notcovered": 117, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_kiss.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 210, "covered": 0, "percent": 0}, "regions": {"count": 269, "covered": 0, "notcovered": 269, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_mutl.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 114, "covered": 0, "percent": 0}, "regions": {"count": 111, "covered": 0, "notcovered": 111, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_p8d.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 5, "covered": 0, "percent": 0}, "regions": {"count": 2, "covered": 0, "notcovered": 2, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_p8e.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 38, "covered": 0, "percent": 0}, "regions": {"count": 26, "covered": 0, "notcovered": 26, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/p12_utl.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 76, "covered": 0, "percent": 0}, "regions": {"count": 69, "covered": 0, "notcovered": 69, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs12/pk12err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/pkcs7/pk7_asn1.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 38, "covered": 0, "percent": 0}, "regions": {"count": 27, "covered": 0, "notcovered": 27, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs7/pk7_attr.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 82, "covered": 0, "percent": 0}, "regions": {"count": 82, "covered": 0, "notcovered": 82, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs7/pk7_doit.c", "summary": {"functions": {"count": 24, "covered": 0, "percent": 0}, "instantiations": {"count": 24, "covered": 0, "percent": 0}, "lines": {"count": 1136, "covered": 0, "percent": 0}, "regions": {"count": 1049, "covered": 0, "notcovered": 1049, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs7/pk7_lib.c", "summary": {"functions": {"count": 20, "covered": 0, "percent": 0}, "instantiations": {"count": 20, "covered": 0, "percent": 0}, "lines": {"count": 540, "covered": 0, "percent": 0}, "regions": {"count": 449, "covered": 0, "notcovered": 449, "percent": 0}}}, {"filename": "/src/openssl/crypto/pkcs7/pkcs7err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/pqueue/pqueue.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 137, "covered": 0, "percent": 0}, "regions": {"count": 69, "covered": 0, "notcovered": 69, "percent": 0}}}, {"filename": "/src/openssl/crypto/rand/md_rand.c", "summary": {"functions": {"count": 8, "covered": 5, "percent": 62.5}, "instantiations": {"count": 8, "covered": 5, "percent": 62.5}, "lines": {"count": 405, "covered": 349, "percent": 86.17283950617283}, "regions": {"count": 273, "covered": 231, "notcovered": 42, "percent": 84.61538461538461}}}, {"filename": "/src/openssl/crypto/rand/rand_egd.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 148, "covered": 0, "percent": 0}, "regions": {"count": 75, "covered": 0, "notcovered": 75, "percent": 0}}}, {"filename": "/src/openssl/crypto/rand/rand_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/rand/rand_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/rand/rand_lib.c", "summary": {"functions": {"count": 9, "covered": 4, "percent": 44.44444444444444}, "instantiations": {"count": 9, "covered": 4, "percent": 44.44444444444444}, "lines": {"count": 79, "covered": 25, "percent": 31.645569620253166}, "regions": {"count": 55, "covered": 21, "notcovered": 34, "percent": 38.18181818181819}}}, {"filename": "/src/openssl/crypto/rand/rand_unix.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 133, "covered": 114, "percent": 85.71428571428571}, "regions": {"count": 57, "covered": 37, "notcovered": 20, "percent": 64.91228070175438}}}, {"filename": "/src/openssl/crypto/rand/randfile.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 159, "covered": 0, "percent": 0}, "regions": {"count": 89, "covered": 0, "notcovered": 89, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2_cbc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 161, "covered": 0, "percent": 0}, "regions": {"count": 75, "covered": 0, "notcovered": 75, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2_ecb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 17, "covered": 0, "percent": 0}, "regions": {"count": 8, "covered": 0, "notcovered": 8, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2_skey.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 45, "covered": 0, "percent": 0}, "regions": {"count": 19, "covered": 0, "notcovered": 19, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2cfb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 20, "covered": 0, "notcovered": 20, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc2/rc2ofb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc4/rc4_utl.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 2, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5_ecb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 17, "covered": 0, "percent": 0}, "regions": {"count": 8, "covered": 0, "notcovered": 8, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5_enc.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 140, "covered": 0, "percent": 0}, "regions": {"count": 271, "covered": 0, "notcovered": 271, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5_skey.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 47, "covered": 0, "percent": 0}, "regions": {"count": 50, "covered": 0, "notcovered": 50, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5cfb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 20, "covered": 0, "notcovered": 20, "percent": 0}}}, {"filename": "/src/openssl/crypto/rc5/rc5ofb64.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/crypto/ripemd/rmd_dgst.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 249, "covered": 0, "percent": 0}, "regions": {"count": 841, "covered": 0, "notcovered": 841, "percent": 0}}}, {"filename": "/src/openssl/crypto/ripemd/rmd_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_ameth.c", "summary": {"functions": {"count": 32, "covered": 0, "percent": 0}, "instantiations": {"count": 32, "covered": 0, "percent": 0}, "lines": {"count": 751, "covered": 0, "percent": 0}, "regions": {"count": 780, "covered": 0, "notcovered": 780, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_asn1.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 19, "covered": 0, "percent": 0}, "regions": {"count": 16, "covered": 0, "notcovered": 16, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_crpt.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 122, "covered": 0, "percent": 0}, "regions": {"count": 88, "covered": 0, "notcovered": 88, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_eay.c", "summary": {"functions": {"count": 11, "covered": 1, "percent": 9.090909090909092}, "instantiations": {"count": 11, "covered": 1, "percent": 9.090909090909092}, "lines": {"count": 724, "covered": 3, "percent": 0.4143646408839779}, "regions": {"count": 598, "covered": 1, "notcovered": 597, "percent": 0.16722408026755853}}}, {"filename": "/src/openssl/crypto/rsa/rsa_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/rsa/rsa_gen.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 151, "covered": 0, "percent": 0}, "regions": {"count": 178, "covered": 0, "notcovered": 178, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_lib.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 207, "covered": 0, "percent": 0}, "regions": {"count": 118, "covered": 0, "notcovered": 118, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_none.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 25, "covered": 0, "percent": 0}, "regions": {"count": 17, "covered": 0, "notcovered": 17, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_oaep.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 232, "covered": 0, "percent": 0}, "regions": {"count": 129, "covered": 0, "notcovered": 129, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_pk1.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 196, "covered": 0, "percent": 0}, "regions": {"count": 93, "covered": 0, "notcovered": 93, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_pmeth.c", "summary": {"functions": {"count": 12, "covered": 0, "percent": 0}, "instantiations": {"count": 12, "covered": 0, "percent": 0}, "lines": {"count": 456, "covered": 0, "percent": 0}, "regions": {"count": 439, "covered": 0, "notcovered": 439, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_pss.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 206, "covered": 0, "percent": 0}, "regions": {"count": 166, "covered": 0, "notcovered": 166, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_saos.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 74, "covered": 0, "percent": 0}, "regions": {"count": 51, "covered": 0, "notcovered": 51, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_sign.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 195, "covered": 0, "percent": 0}, "regions": {"count": 182, "covered": 0, "notcovered": 182, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_ssl.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 80, "covered": 0, "percent": 0}, "regions": {"count": 60, "covered": 0, "notcovered": 60, "percent": 0}}}, {"filename": "/src/openssl/crypto/rsa/rsa_x931.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 92, "covered": 0, "percent": 0}, "regions": {"count": 55, "covered": 0, "notcovered": 55, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 106, "covered": 0, "percent": 0}, "regions": {"count": 216, "covered": 0, "notcovered": 216, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed_cbc.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 8, "covered": 0, "percent": 0}, "regions": {"count": 4, "covered": 0, "notcovered": 4, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed_cfb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 4, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed_ecb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 6, "covered": 0, "percent": 0}, "regions": {"count": 4, "covered": 0, "notcovered": 4, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/seed/seed_ofb.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 4, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/sha/sha1_one.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 13, "covered": 0, "percent": 0}, "regions": {"count": 6, "covered": 0, "notcovered": 6, "percent": 0}}}, {"filename": "/src/openssl/crypto/sha/sha256.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 56, "covered": 0, "percent": 0}, "regions": {"count": 12, "covered": 0, "notcovered": 12, "percent": 0}}}, {"filename": "/src/openssl/crypto/sha/sha512.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 171, "covered": 0, "percent": 0}, "regions": {"count": 71, "covered": 0, "notcovered": 71, "percent": 0}}}, {"filename": "/src/openssl/crypto/sha/sha_locl.h", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 204, "covered": 9, "percent": 4.411764705882353}, "regions": {"count": 632, "covered": 6, "notcovered": 626, "percent": 0.949367088607595}}}, {"filename": "/src/openssl/crypto/srp/srp_grps.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/srp/srp_lib.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 254, "covered": 0, "percent": 0}, "regions": {"count": 209, "covered": 0, "notcovered": 209, "percent": 0}}}, {"filename": "/src/openssl/crypto/srp/srp_vfy.c", "summary": {"functions": {"count": 21, "covered": 0, "percent": 0}, "instantiations": {"count": 21, "covered": 0, "percent": 0}, "lines": {"count": 567, "covered": 0, "percent": 0}, "regions": {"count": 511, "covered": 0, "notcovered": 511, "percent": 0}}}, {"filename": "/src/openssl/crypto/stack/stack.c", "summary": {"functions": {"count": 23, "covered": 16, "percent": 69.56521739130434}, "instantiations": {"count": 23, "covered": 16, "percent": 69.56521739130434}, "lines": {"count": 253, "covered": 165, "percent": 65.21739130434783}, "regions": {"count": 194, "covered": 107, "notcovered": 87, "percent": 55.154639175257735}}}, {"filename": "/src/openssl/crypto/ts/ts_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/txt_db/txt_db.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 314, "covered": 0, "percent": 0}, "regions": {"count": 386, "covered": 0, "notcovered": 386, "percent": 0}}}, {"filename": "/src/openssl/crypto/ui/ui_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/ui/ui_lib.c", "summary": {"functions": {"count": 55, "covered": 0, "percent": 0}, "instantiations": {"count": 55, "covered": 0, "percent": 0}, "lines": {"count": 653, "covered": 0, "percent": 0}, "regions": {"count": 465, "covered": 0, "notcovered": 465, "percent": 0}}}, {"filename": "/src/openssl/crypto/ui/ui_locl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/ui/ui_openssl.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 196, "covered": 0, "percent": 0}, "regions": {"count": 124, "covered": 0, "notcovered": 124, "percent": 0}}}, {"filename": "/src/openssl/crypto/uid.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 7, "covered": 0, "percent": 0}, "regions": {"count": 7, "covered": 0, "notcovered": 7, "percent": 0}}}, {"filename": "/src/openssl/crypto/whrlpool/wp_dgst.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 191, "covered": 0, "percent": 0}, "regions": {"count": 97, "covered": 0, "notcovered": 97, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/by_dir.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 290, "covered": 0, "percent": 0}, "regions": {"count": 302, "covered": 0, "notcovered": 302, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/by_file.c", "summary": {"functions": {"count": 5, "covered": 3, "percent": 60}, "instantiations": {"count": 5, "covered": 3, "percent": 60}, "lines": {"count": 180, "covered": 42, "percent": 23.333333333333332}, "regions": {"count": 175, "covered": 40, "notcovered": 135, "percent": 22.857142857142858}}}, {"filename": "/src/openssl/crypto/x509/x509_att.c", "summary": {"functions": {"count": 19, "covered": 0, "percent": 0}, "instantiations": {"count": 19, "covered": 0, "percent": 0}, "lines": {"count": 261, "covered": 0, "percent": 0}, "regions": {"count": 280, "covered": 0, "notcovered": 280, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_cmp.c", "summary": {"functions": {"count": 26, "covered": 2, "percent": 7.6923076923076925}, "instantiations": {"count": 26, "covered": 2, "percent": 7.6923076923076925}, "lines": {"count": 327, "covered": 22, "percent": 6.727828746177369}, "regions": {"count": 278, "covered": 13, "notcovered": 265, "percent": 4.676258992805756}}}, {"filename": "/src/openssl/crypto/x509/x509_d2.c", "summary": {"functions": {"count": 2, "covered": 1, "percent": 50}, "instantiations": {"count": 2, "covered": 1, "percent": 50}, "lines": {"count": 39, "covered": 14, "percent": 35.8974358974359}, "regions": {"count": 39, "covered": 15, "notcovered": 24, "percent": 38.46153846153847}}}, {"filename": "/src/openssl/crypto/x509/x509_def.c", "summary": {"functions": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "instantiations": {"count": 6, "covered": 1, "percent": 16.666666666666664}, "lines": {"count": 18, "covered": 3, "percent": 16.666666666666664}, "regions": {"count": 15, "covered": 2, "notcovered": 13, "percent": 13.333333333333334}}}, {"filename": "/src/openssl/crypto/x509/x509_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/crypto/x509/x509_ext.c", "summary": {"functions": {"count": 27, "covered": 0, "percent": 0}, "instantiations": {"count": 27, "covered": 0, "percent": 0}, "lines": {"count": 83, "covered": 0, "percent": 0}, "regions": {"count": 27, "covered": 0, "notcovered": 27, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_lu.c", "summary": {"functions": {"count": 34, "covered": 13, "percent": 38.23529411764706}, "instantiations": {"count": 34, "covered": 13, "percent": 38.23529411764706}, "lines": {"count": 554, "covered": 167, "percent": 30.144404332129966}, "regions": {"count": 608, "covered": 138, "notcovered": 470, "percent": 22.697368421052634}}}, {"filename": "/src/openssl/crypto/x509/x509_obj.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 123, "covered": 77, "percent": 62.601626016260155}, "regions": {"count": 104, "covered": 63, "notcovered": 41, "percent": 60.57692307692307}}}, {"filename": "/src/openssl/crypto/x509/x509_req.c", "summary": {"functions": {"count": 18, "covered": 0, "percent": 0}, "instantiations": {"count": 18, "covered": 0, "percent": 0}, "lines": {"count": 198, "covered": 0, "percent": 0}, "regions": {"count": 168, "covered": 0, "notcovered": 168, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_trs.c", "summary": {"functions": {"count": 17, "covered": 0, "percent": 0}, "instantiations": {"count": 17, "covered": 0, "percent": 0}, "lines": {"count": 182, "covered": 0, "percent": 0}, "regions": {"count": 209, "covered": 0, "notcovered": 209, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_txt.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 147, "covered": 0, "percent": 0}, "regions": {"count": 134, "covered": 0, "notcovered": 134, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_v3.c", "summary": {"functions": {"count": 15, "covered": 0, "percent": 0}, "instantiations": {"count": 15, "covered": 0, "percent": 0}, "lines": {"count": 180, "covered": 0, "percent": 0}, "regions": {"count": 223, "covered": 0, "notcovered": 223, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509_vfy.c", "summary": {"functions": {"count": 72, "covered": 1, "percent": 1.3888888888888888}, "instantiations": {"count": 72, "covered": 1, "percent": 1.3888888888888888}, "lines": {"count": 2208, "covered": 8, "percent": 0.36231884057971014}, "regions": {"count": 1926, "covered": 2, "notcovered": 1924, "percent": 0.10384215991692627}}}, {"filename": "/src/openssl/crypto/x509/x509_vpm.c", "summary": {"functions": {"count": 35, "covered": 5, "percent": 14.285714285714285}, "instantiations": {"count": 35, "covered": 5, "percent": 14.285714285714285}, "lines": {"count": 386, "covered": 110, "percent": 28.497409326424872}, "regions": {"count": 461, "covered": 87, "notcovered": 374, "percent": 18.872017353579178}}}, {"filename": "/src/openssl/crypto/x509/x509cset.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 88, "covered": 0, "percent": 0}, "regions": {"count": 75, "covered": 0, "notcovered": 75, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509name.c", "summary": {"functions": {"count": 18, "covered": 0, "percent": 0}, "instantiations": {"count": 18, "covered": 0, "percent": 0}, "lines": {"count": 274, "covered": 0, "percent": 0}, "regions": {"count": 288, "covered": 0, "notcovered": 288, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509rset.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 15, "covered": 0, "percent": 0}, "regions": {"count": 16, "covered": 0, "notcovered": 16, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x509type.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 62, "covered": 0, "percent": 0}, "regions": {"count": 57, "covered": 0, "notcovered": 57, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509/x_all.c", "summary": {"functions": {"count": 80, "covered": 0, "percent": 0}, "instantiations": {"count": 80, "covered": 0, "percent": 0}, "lines": {"count": 291, "covered": 0, "percent": 0}, "regions": {"count": 422, "covered": 0, "notcovered": 422, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/ext_dat.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_cache.c", "summary": {"functions": {"count": 7, "covered": 1, "percent": 14.285714285714285}, "instantiations": {"count": 7, "covered": 1, "percent": 14.285714285714285}, "lines": {"count": 179, "covered": 3, "percent": 1.675977653631285}, "regions": {"count": 196, "covered": 3, "notcovered": 193, "percent": 1.530612244897959}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_data.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 50, "covered": 0, "percent": 0}, "regions": {"count": 54, "covered": 0, "notcovered": 54, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_int.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_lib.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 60, "covered": 0, "percent": 0}, "regions": {"count": 64, "covered": 0, "notcovered": 64, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_map.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 59, "covered": 0, "percent": 0}, "regions": {"count": 76, "covered": 0, "notcovered": 76, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_node.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 99, "covered": 0, "percent": 0}, "regions": {"count": 120, "covered": 0, "notcovered": 120, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/pcy_tree.c", "summary": {"functions": {"count": 14, "covered": 0, "percent": 0}, "instantiations": {"count": 14, "covered": 0, "percent": 0}, "lines": {"count": 576, "covered": 0, "percent": 0}, "regions": {"count": 541, "covered": 0, "notcovered": 541, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_akey.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 103, "covered": 0, "percent": 0}, "regions": {"count": 110, "covered": 0, "notcovered": 110, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_alt.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 478, "covered": 0, "percent": 0}, "regions": {"count": 527, "covered": 0, "notcovered": 527, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_bcons.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 5, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_bitst.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 8, "covered": 0, "percent": 0}, "regions": {"count": 6, "covered": 0, "notcovered": 6, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_conf.c", "summary": {"functions": {"count": 27, "covered": 0, "percent": 0}, "instantiations": {"count": 27, "covered": 0, "percent": 0}, "lines": {"count": 304, "covered": 0, "percent": 0}, "regions": {"count": 244, "covered": 0, "notcovered": 244, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_cpols.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 338, "covered": 0, "percent": 0}, "regions": {"count": 410, "covered": 0, "notcovered": 410, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_crld.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 292, "covered": 0, "percent": 0}, "regions": {"count": 348, "covered": 0, "notcovered": 348, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_enum.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 10, "covered": 0, "percent": 0}, "regions": {"count": 7, "covered": 0, "notcovered": 7, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_extku.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 41, "covered": 0, "percent": 0}, "regions": {"count": 61, "covered": 0, "notcovered": 61, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_genn.c", "summary": {"functions": {"count": 7, "covered": 0, "percent": 0}, "instantiations": {"count": 7, "covered": 0, "percent": 0}, "lines": {"count": 132, "covered": 0, "percent": 0}, "regions": {"count": 93, "covered": 0, "notcovered": 93, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_ia5.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 31, "covered": 0, "percent": 0}, "regions": {"count": 30, "covered": 0, "notcovered": 30, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_info.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 93, "covered": 0, "percent": 0}, "regions": {"count": 117, "covered": 0, "notcovered": 117, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_int.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 3, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_lib.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 226, "covered": 0, "percent": 0}, "regions": {"count": 241, "covered": 0, "notcovered": 241, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_ncons.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 358, "covered": 0, "percent": 0}, "regions": {"count": 355, "covered": 0, "notcovered": 355, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_ocsp.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 117, "covered": 0, "percent": 0}, "regions": {"count": 129, "covered": 0, "notcovered": 129, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_pci.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 105, "covered": 0, "percent": 0}, "regions": {"count": 102, "covered": 0, "notcovered": 102, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_pcons.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 8, "covered": 0, "percent": 0}, "regions": {"count": 1, "covered": 0, "notcovered": 1, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_pku.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 14, "covered": 0, "percent": 0}, "regions": {"count": 7, "covered": 0, "notcovered": 7, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_pmaps.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 56, "covered": 0, "percent": 0}, "regions": {"count": 87, "covered": 0, "notcovered": 87, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_prn.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 143, "covered": 0, "percent": 0}, "regions": {"count": 146, "covered": 0, "notcovered": 146, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_purp.c", "summary": {"functions": {"count": 34, "covered": 0, "percent": 0}, "instantiations": {"count": 34, "covered": 0, "percent": 0}, "lines": {"count": 598, "covered": 0, "percent": 0}, "regions": {"count": 670, "covered": 0, "notcovered": 670, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_scts.c", "summary": {"functions": {"count": 6, "covered": 0, "percent": 0}, "instantiations": {"count": 6, "covered": 0, "percent": 0}, "lines": {"count": 186, "covered": 0, "percent": 0}, "regions": {"count": 125, "covered": 0, "notcovered": 125, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_skey.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 69, "covered": 0, "percent": 0}, "regions": {"count": 57, "covered": 0, "notcovered": 57, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_sxnet.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 124, "covered": 0, "percent": 0}, "regions": {"count": 138, "covered": 0, "notcovered": 138, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3_utl.c", "summary": {"functions": {"count": 43, "covered": 0, "percent": 0}, "instantiations": {"count": 43, "covered": 0, "percent": 0}, "lines": {"count": 1020, "covered": 0, "percent": 0}, "regions": {"count": 974, "covered": 0, "notcovered": 974, "percent": 0}}}, {"filename": "/src/openssl/crypto/x509v3/v3err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/e_os.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/e_gost_err.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 26, "covered": 12, "percent": 46.15384615384615}, "regions": {"count": 12, "covered": 5, "notcovered": 7, "percent": 41.66666666666667}}}, {"filename": "/src/openssl/engines/ccgost/e_gost_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost2001.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 375, "covered": 0, "percent": 0}, "regions": {"count": 336, "covered": 0, "notcovered": 336, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost2001_keyx.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 237, "covered": 0, "percent": 0}, "regions": {"count": 129, "covered": 0, "notcovered": 129, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost89.c", "summary": {"functions": {"count": 18, "covered": 0, "percent": 0}, "instantiations": {"count": 18, "covered": 0, "percent": 0}, "lines": {"count": 293, "covered": 0, "percent": 0}, "regions": {"count": 74, "covered": 0, "notcovered": 74, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost94_keyx.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 222, "covered": 0, "percent": 0}, "regions": {"count": 131, "covered": 0, "notcovered": 131, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_ameth.c", "summary": {"functions": {"count": 39, "covered": 1, "percent": 2.564102564102564}, "instantiations": {"count": 39, "covered": 1, "percent": 2.564102564102564}, "lines": {"count": 835, "covered": 45, "percent": 5.389221556886228}, "regions": {"count": 486, "covered": 11, "notcovered": 475, "percent": 2.263374485596708}}}, {"filename": "/src/openssl/engines/ccgost/gost_crypt.c", "summary": {"functions": {"count": 20, "covered": 0, "percent": 0}, "instantiations": {"count": 20, "covered": 0, "percent": 0}, "lines": {"count": 425, "covered": 0, "percent": 0}, "regions": {"count": 232, "covered": 0, "notcovered": 232, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_ctl.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 49, "covered": 0, "percent": 0}, "regions": {"count": 42, "covered": 0, "notcovered": 42, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_eng.c", "summary": {"functions": {"count": 10, "covered": 6, "percent": 60}, "instantiations": {"count": 10, "covered": 6, "percent": 60}, "lines": {"count": 202, "covered": 78, "percent": 38.613861386138616}, "regions": {"count": 144, "covered": 80, "notcovered": 64, "percent": 55.55555555555556}}}, {"filename": "/src/openssl/engines/ccgost/gost_keywrap.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 53, "covered": 0, "percent": 0}, "regions": {"count": 15, "covered": 0, "notcovered": 15, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_lcl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_md.c", "summary": {"functions": {"count": 5, "covered": 0, "percent": 0}, "instantiations": {"count": 5, "covered": 0, "percent": 0}, "lines": {"count": 28, "covered": 0, "percent": 0}, "regions": {"count": 11, "covered": 0, "notcovered": 11, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gost_pmeth.c", "summary": {"functions": {"count": 25, "covered": 1, "percent": 4}, "instantiations": {"count": 25, "covered": 1, "percent": 4}, "lines": {"count": 491, "covered": 57, "percent": 11.608961303462321}, "regions": {"count": 313, "covered": 10, "notcovered": 303, "percent": 3.1948881789137378}}}, {"filename": "/src/openssl/engines/ccgost/gost_sign.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 239, "covered": 0, "percent": 0}, "regions": {"count": 152, "covered": 0, "notcovered": 152, "percent": 0}}}, {"filename": "/src/openssl/engines/ccgost/gosthash.c", "summary": {"functions": {"count": 11, "covered": 0, "percent": 0}, "instantiations": {"count": 11, "covered": 0, "percent": 0}, "lines": {"count": 183, "covered": 0, "percent": 0}, "regions": {"count": 56, "covered": 0, "notcovered": 56, "percent": 0}}}, {"filename": "/src/openssl/engines/e_4758cca.c", "summary": {"functions": {"count": 20, "covered": 5, "percent": 25}, "instantiations": {"count": 20, "covered": 5, "percent": 25}, "lines": {"count": 659, "covered": 59, "percent": 8.952959028831563}, "regions": {"count": 321, "covered": 43, "notcovered": 278, "percent": 13.395638629283487}}}, {"filename": "/src/openssl/engines/e_4758cca_err.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 26, "covered": 16, "percent": 61.53846153846154}, "regions": {"count": 12, "covered": 8, "notcovered": 4, "percent": 66.66666666666666}}}, {"filename": "/src/openssl/engines/e_4758cca_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_aep.c", "summary": {"functions": {"count": 24, "covered": 3, "percent": 12.5}, "instantiations": {"count": 24, "covered": 3, "percent": 12.5}, "lines": {"count": 613, "covered": 85, "percent": 13.866231647634583}, "regions": {"count": 327, "covered": 29, "notcovered": 298, "percent": 8.868501529051988}}}, {"filename": "/src/openssl/engines/e_aep_err.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 26, "covered": 12, "percent": 46.15384615384615}, "regions": {"count": 12, "covered": 5, "notcovered": 7, "percent": 41.66666666666667}}}, {"filename": "/src/openssl/engines/e_aep_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_atalla.c", "summary": {"functions": {"count": 16, "covered": 3, "percent": 18.75}, "instantiations": {"count": 16, "covered": 3, "percent": 18.75}, "lines": {"count": 313, "covered": 78, "percent": 24.920127795527154}, "regions": {"count": 163, "covered": 29, "notcovered": 134, "percent": 17.791411042944784}}}, {"filename": "/src/openssl/engines/e_atalla_err.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 35, "covered": 17, "percent": 48.57142857142857}, "regions": {"count": 13, "covered": 6, "notcovered": 7, "percent": 46.15384615384615}}}, {"filename": "/src/openssl/engines/e_atalla_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_chil.c", "summary": {"functions": {"count": 28, "covered": 5, "percent": 17.857142857142858}, "instantiations": {"count": 28, "covered": 5, "percent": 17.857142857142858}, "lines": {"count": 847, "covered": 104, "percent": 12.278630460448642}, "regions": {"count": 560, "covered": 44, "notcovered": 516, "percent": 7.857142857142857}}}, {"filename": "/src/openssl/engines/e_chil_err.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 35, "covered": 21, "percent": 60}, "regions": {"count": 13, "covered": 9, "notcovered": 4, "percent": 69.23076923076923}}}, {"filename": "/src/openssl/engines/e_chil_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_cswift.c", "summary": {"functions": {"count": 22, "covered": 5, "percent": 22.727272727272727}, "instantiations": {"count": 22, "covered": 5, "percent": 22.727272727272727}, "lines": {"count": 732, "covered": 91, "percent": 12.431693989071038}, "regions": {"count": 455, "covered": 42, "notcovered": 413, "percent": 9.230769230769232}}}, {"filename": "/src/openssl/engines/e_cswift_err.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 35, "covered": 21, "percent": 60}, "regions": {"count": 13, "covered": 9, "notcovered": 4, "percent": 69.23076923076923}}}, {"filename": "/src/openssl/engines/e_cswift_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_nuron.c", "summary": {"functions": {"count": 16, "covered": 3, "percent": 18.75}, "instantiations": {"count": 16, "covered": 3, "percent": 18.75}, "lines": {"count": 195, "covered": 78, "percent": 40}, "regions": {"count": 104, "covered": 29, "notcovered": 75, "percent": 27.884615384615387}}}, {"filename": "/src/openssl/engines/e_nuron_err.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 35, "covered": 17, "percent": 48.57142857142857}, "regions": {"count": 13, "covered": 6, "notcovered": 7, "percent": 46.15384615384615}}}, {"filename": "/src/openssl/engines/e_nuron_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_padlock.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 2, "covered": 2, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/engines/e_sureware.c", "summary": {"functions": {"count": 22, "covered": 4, "percent": 18.181818181818183}, "instantiations": {"count": 22, "covered": 4, "percent": 18.181818181818183}, "lines": {"count": 734, "covered": 123, "percent": 16.7574931880109}, "regions": {"count": 489, "covered": 47, "notcovered": 442, "percent": 9.611451942740286}}}, {"filename": "/src/openssl/engines/e_sureware_err.c", "summary": {"functions": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "instantiations": {"count": 3, "covered": 2, "percent": 66.66666666666666}, "lines": {"count": 35, "covered": 21, "percent": 60}, "regions": {"count": 13, "covered": 9, "notcovered": 4, "percent": 69.23076923076923}}}, {"filename": "/src/openssl/engines/e_sureware_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/e_ubsec.c", "summary": {"functions": {"count": 19, "covered": 3, "percent": 15.789473684210526}, "instantiations": {"count": 19, "covered": 3, "percent": 15.789473684210526}, "lines": {"count": 649, "covered": 69, "percent": 10.631741140215716}, "regions": {"count": 314, "covered": 29, "notcovered": 285, "percent": 9.235668789808917}}}, {"filename": "/src/openssl/engines/e_ubsec_err.c", "summary": {"functions": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "instantiations": {"count": 3, "covered": 1, "percent": 33.33333333333333}, "lines": {"count": 35, "covered": 17, "percent": 48.57142857142857}, "regions": {"count": 13, "covered": 6, "notcovered": 7, "percent": 46.15384615384615}}}, {"filename": "/src/openssl/engines/e_ubsec_err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/aep.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/cswift.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/hw_4758_cca.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/hw_ubsec.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/hwcryptohook.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/engines/vendor_defns/sureware.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/aes.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/asn1.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/asn1_mac.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/asn1t.h", "summary": {"functions": {"count": 9, "covered": 3, "percent": 33.33333333333333}, "instantiations": {"count": 484, "covered": 11, "percent": 2.272727272727273}, "lines": {"count": 28, "covered": 9, "percent": 32.142857142857146}, "regions": {"count": 18, "covered": 6, "notcovered": 12, "percent": 33.33333333333333}}}, {"filename": "/src/openssl/include/openssl/bio.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/blowfish.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/bn.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/cast.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/cms.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/conf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/crypto.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/des.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/dh.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/dsa.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/dso.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/dtls1.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/e_os2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ec.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ecdh.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/engine.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/err.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/evp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/hmac.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/lhash.h", "summary": {"functions": {"count": 4, "covered": 2, "percent": 50}, "instantiations": {"count": 34, "covered": 10, "percent": 29.411764705882355}, "lines": {"count": 14, "covered": 7, "percent": 50}, "regions": {"count": 4, "covered": 2, "notcovered": 2, "percent": 50}}}, {"filename": "/src/openssl/include/openssl/md4.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/md5.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/mdc2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/obj_mac.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/objects.h", "summary": {"functions": {"count": 4, "covered": 2, "percent": 50}, "instantiations": {"count": 26, "covered": 2, "percent": 7.6923076923076925}, "lines": {"count": 18, "covered": 9, "percent": 50}, "regions": {"count": 4, "covered": 2, "notcovered": 2, "percent": 50}}}, {"filename": "/src/openssl/include/openssl/ocsp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/opensslconf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/opensslv.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/pem.h", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 84, "covered": 0, "percent": 0}, "lines": {"count": 36, "covered": 0, "percent": 0}, "regions": {"count": 10, "covered": 0, "notcovered": 10, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/pkcs12.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/pkcs7.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/rc5.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ripemd.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/rsa.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/safestack.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/sha.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/srp.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ssl.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ssl2.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ssl23.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ssl3.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/tls1.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/txt_db.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/ui.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/whrlpool.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/x509.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/x509_vfy.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/include/openssl/x509v3.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/openssl/ssl/bio_ssl.c", "summary": {"functions": {"count": 13, "covered": 0, "percent": 0}, "instantiations": {"count": 13, "covered": 0, "percent": 0}, "lines": {"count": 452, "covered": 0, "percent": 0}, "regions": {"count": 331, "covered": 0, "notcovered": 331, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_both.c", "summary": {"functions": {"count": 28, "covered": 0, "percent": 0}, "instantiations": {"count": 28, "covered": 0, "percent": 0}, "lines": {"count": 1270, "covered": 0, "percent": 0}, "regions": {"count": 723, "covered": 0, "notcovered": 723, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_clnt.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 522, "covered": 0, "percent": 0}, "regions": {"count": 447, "covered": 0, "notcovered": 447, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_lib.c", "summary": {"functions": {"count": 20, "covered": 0, "percent": 0}, "instantiations": {"count": 20, "covered": 0, "percent": 0}, "lines": {"count": 394, "covered": 0, "percent": 0}, "regions": {"count": 210, "covered": 0, "notcovered": 210, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_meth.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 10, "covered": 0, "percent": 0}, "regions": {"count": 13, "covered": 0, "notcovered": 13, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_pkt.c", "summary": {"functions": {"count": 17, "covered": 0, "percent": 0}, "instantiations": {"count": 17, "covered": 0, "percent": 0}, "lines": {"count": 1452, "covered": 0, "percent": 0}, "regions": {"count": 912, "covered": 0, "notcovered": 912, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_srtp.c", "summary": {"functions": {"count": 10, "covered": 0, "percent": 0}, "instantiations": {"count": 10, "covered": 0, "percent": 0}, "lines": {"count": 273, "covered": 0, "percent": 0}, "regions": {"count": 220, "covered": 0, "notcovered": 220, "percent": 0}}}, {"filename": "/src/openssl/ssl/d1_srvr.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 660, "covered": 0, "percent": 0}, "regions": {"count": 557, "covered": 0, "notcovered": 557, "percent": 0}}}, {"filename": "/src/openssl/ssl/s23_clnt.c", "summary": {"functions": {"count": 6, "covered": 4, "percent": 66.66666666666666}, "instantiations": {"count": 6, "covered": 4, "percent": 66.66666666666666}, "lines": {"count": 577, "covered": 320, "percent": 55.45927209705373}, "regions": {"count": 474, "covered": 218, "notcovered": 256, "percent": 45.9915611814346}}}, {"filename": "/src/openssl/ssl/s23_lib.c", "summary": {"functions": {"count": 8, "covered": 3, "percent": 37.5}, "instantiations": {"count": 8, "covered": 3, "percent": 37.5}, "lines": {"count": 92, "covered": 13, "percent": 14.130434782608695}, "regions": {"count": 87, "covered": 5, "notcovered": 82, "percent": 5.747126436781609}}}, {"filename": "/src/openssl/ssl/s23_meth.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 16, "covered": 0, "percent": 0}, "regions": {"count": 17, "covered": 0, "notcovered": 17, "percent": 0}}}, {"filename": "/src/openssl/ssl/s23_pkt.c", "summary": {"functions": {"count": 2, "covered": 2, "percent": 100}, "instantiations": {"count": 2, "covered": 2, "percent": 100}, "lines": {"count": 44, "covered": 36, "percent": 81.81818181818183}, "regions": {"count": 22, "covered": 19, "notcovered": 3, "percent": 86.36363636363636}}}, {"filename": "/src/openssl/ssl/s23_srvr.c", "summary": {"functions": {"count": 3, "covered": 0, "percent": 0}, "instantiations": {"count": 3, "covered": 0, "percent": 0}, "lines": {"count": 453, "covered": 0, "percent": 0}, "regions": {"count": 355, "covered": 0, "notcovered": 355, "percent": 0}}}, {"filename": "/src/openssl/ssl/s3_both.c", "summary": {"functions": {"count": 16, "covered": 8, "percent": 50}, "instantiations": {"count": 16, "covered": 8, "percent": 50}, "lines": {"count": 538, "covered": 214, "percent": 39.77695167286245}, "regions": {"count": 435, "covered": 142, "notcovered": 293, "percent": 32.64367816091954}}}, {"filename": "/src/openssl/ssl/s3_cbc.c", "summary": {"functions": {"count": 9, "covered": 0, "percent": 0}, "instantiations": {"count": 9, "covered": 0, "percent": 0}, "lines": {"count": 550, "covered": 0, "percent": 0}, "regions": {"count": 215, "covered": 0, "notcovered": 215, "percent": 0}}}, {"filename": "/src/openssl/ssl/s3_clnt.c", "summary": {"functions": {"count": 20, "covered": 2, "percent": 10}, "instantiations": {"count": 20, "covered": 2, "percent": 10}, "lines": {"count": 3303, "covered": 92, "percent": 2.785346654556464}, "regions": {"count": 2670, "covered": 58, "notcovered": 2612, "percent": 2.1722846441947565}}}, {"filename": "/src/openssl/ssl/s3_enc.c", "summary": {"functions": {"count": 16, "covered": 3, "percent": 18.75}, "instantiations": {"count": 16, "covered": 3, "percent": 18.75}, "lines": {"count": 737, "covered": 19, "percent": 2.578018995929444}, "regions": {"count": 577, "covered": 15, "notcovered": 562, "percent": 2.5996533795493932}}}, {"filename": "/src/openssl/ssl/s3_lib.c", "summary": {"functions": {"count": 27, "covered": 8, "percent": 29.629629629629626}, "instantiations": {"count": 27, "covered": 8, "percent": 29.629629629629626}, "lines": {"count": 1385, "covered": 224, "percent": 16.173285198555956}, "regions": {"count": 1021, "covered": 103, "notcovered": 918, "percent": 10.088148873653282}}}, {"filename": "/src/openssl/ssl/s3_meth.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 6, "covered": 0, "percent": 0}, "regions": {"count": 5, "covered": 0, "notcovered": 5, "percent": 0}}}, {"filename": "/src/openssl/ssl/s3_pkt.c", "summary": {"functions": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "instantiations": {"count": 11, "covered": 7, "percent": 63.63636363636363}, "lines": {"count": 1515, "covered": 535, "percent": 35.31353135313531}, "regions": {"count": 1083, "covered": 290, "notcovered": 793, "percent": 26.777469990766388}}}, {"filename": "/src/openssl/ssl/s3_srvr.c", "summary": {"functions": {"count": 16, "covered": 0, "percent": 0}, "instantiations": {"count": 16, "covered": 0, "percent": 0}, "lines": {"count": 3192, "covered": 0, "percent": 0}, "regions": {"count": 2464, "covered": 0, "notcovered": 2464, "percent": 0}}}, {"filename": "/src/openssl/ssl/ssl_algs.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 86, "covered": 86, "percent": 100}, "regions": {"count": 22, "covered": 22, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/ssl/ssl_asn1.c", "summary": {"functions": {"count": 2, "covered": 0, "percent": 0}, "instantiations": {"count": 2, "covered": 0, "percent": 0}, "lines": {"count": 482, "covered": 0, "percent": 0}, "regions": {"count": 715, "covered": 0, "notcovered": 715, "percent": 0}}}, {"filename": "/src/openssl/ssl/ssl_cert.c", "summary": {"functions": {"count": 35, "covered": 6, "percent": 17.142857142857142}, "instantiations": {"count": 35, "covered": 6, "percent": 17.142857142857142}, "lines": {"count": 974, "covered": 197, "percent": 20.2258726899384}, "regions": {"count": 902, "covered": 87, "notcovered": 815, "percent": 9.645232815964523}}}, {"filename": "/src/openssl/ssl/ssl_ciph.c", "summary": {"functions": {"count": 31, "covered": 14, "percent": 45.16129032258064}, "instantiations": {"count": 31, "covered": 14, "percent": 45.16129032258064}, "lines": {"count": 1468, "covered": 783, "percent": 53.33787465940054}, "regions": {"count": 1300, "covered": 575, "notcovered": 725, "percent": 44.230769230769226}}}, {"filename": "/src/openssl/ssl/ssl_err.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 9, "covered": 9, "percent": 100}, "regions": {"count": 3, "covered": 3, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/ssl/ssl_err2.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 6, "covered": 6, "percent": 100}, "regions": {"count": 1, "covered": 1, "notcovered": 0, "percent": 100}}}, {"filename": "/src/openssl/ssl/ssl_lib.c", "summary": {"functions": {"count": 171, "covered": 30, "percent": 17.543859649122805}, "instantiations": {"count": 171, "covered": 30, "percent": 17.543859649122805}, "lines": {"count": 2598, "covered": 762, "percent": 29.330254041570434}, "regions": {"count": 2003, "covered": 395, "notcovered": 1608, "percent": 19.720419370943585}}}, {"filename": "/src/openssl/ssl/ssl_locl.h", "summary": {"functions": {"count": 4, "covered": 2, "percent": 50}, "instantiations": {"count": 24, "covered": 2, "percent": 8.333333333333332}, "lines": {"count": 136, "covered": 68, "percent": 50}, "regions": {"count": 6, "covered": 3, "notcovered": 3, "percent": 50}}}, {"filename": "/src/openssl/ssl/ssl_rsa.c", "summary": {"functions": {"count": 27, "covered": 0, "percent": 0}, "instantiations": {"count": 27, "covered": 0, "percent": 0}, "lines": {"count": 879, "covered": 0, "percent": 0}, "regions": {"count": 640, "covered": 0, "notcovered": 640, "percent": 0}}}, {"filename": "/src/openssl/ssl/ssl_sess.c", "summary": {"functions": {"count": 46, "covered": 9, "percent": 19.565217391304348}, "instantiations": {"count": 46, "covered": 9, "percent": 19.565217391304348}, "lines": {"count": 938, "covered": 152, "percent": 16.204690831556505}, "regions": {"count": 656, "covered": 84, "notcovered": 572, "percent": 12.804878048780488}}}, {"filename": "/src/openssl/ssl/ssl_stat.c", "summary": {"functions": {"count": 8, "covered": 0, "percent": 0}, "instantiations": {"count": 8, "covered": 0, "percent": 0}, "lines": {"count": 742, "covered": 0, "percent": 0}, "regions": {"count": 637, "covered": 0, "notcovered": 637, "percent": 0}}}, {"filename": "/src/openssl/ssl/t1_clnt.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 9, "covered": 0, "percent": 0}, "regions": {"count": 13, "covered": 0, "notcovered": 13, "percent": 0}}}, {"filename": "/src/openssl/ssl/t1_enc.c", "summary": {"functions": {"count": 12, "covered": 2, "percent": 16.666666666666664}, "instantiations": {"count": 12, "covered": 2, "percent": 16.666666666666664}, "lines": {"count": 912, "covered": 69, "percent": 7.565789473684211}, "regions": {"count": 780, "covered": 24, "notcovered": 756, "percent": 3.076923076923077}}}, {"filename": "/src/openssl/ssl/t1_ext.c", "summary": {"functions": {"count": 11, "covered": 4, "percent": 36.36363636363637}, "instantiations": {"count": 11, "covered": 4, "percent": 36.36363636363637}, "lines": {"count": 194, "covered": 23, "percent": 11.855670103092782}, "regions": {"count": 139, "covered": 11, "notcovered": 128, "percent": 7.913669064748201}}}, {"filename": "/src/openssl/ssl/t1_lib.c", "summary": {"functions": {"count": 61, "covered": 9, "percent": 14.754098360655737}, "instantiations": {"count": 61, "covered": 9, "percent": 14.754098360655737}, "lines": {"count": 3401, "covered": 396, "percent": 11.643634225227874}, "regions": {"count": 2727, "covered": 247, "notcovered": 2480, "percent": 9.057572423909058}}}, {"filename": "/src/openssl/ssl/t1_meth.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 9, "covered": 0, "percent": 0}, "regions": {"count": 13, "covered": 0, "notcovered": 13, "percent": 0}}}, {"filename": "/src/openssl/ssl/t1_reneg.c", "summary": {"functions": {"count": 4, "covered": 0, "percent": 0}, "instantiations": {"count": 4, "covered": 0, "percent": 0}, "lines": {"count": 140, "covered": 0, "percent": 0}, "regions": {"count": 84, "covered": 0, "notcovered": 84, "percent": 0}}}, {"filename": "/src/openssl/ssl/t1_srvr.c", "summary": {"functions": {"count": 1, "covered": 0, "percent": 0}, "instantiations": {"count": 1, "covered": 0, "percent": 0}, "lines": {"count": 9, "covered": 0, "percent": 0}, "regions": {"count": 13, "covered": 0, "notcovered": 13, "percent": 0}}}, {"filename": "/src/openssl/ssl/tls_srp.c", "summary": {"functions": {"count": 22, "covered": 4, "percent": 18.181818181818183}, "instantiations": {"count": 22, "covered": 4, "percent": 18.181818181818183}, "lines": {"count": 417, "covered": 136, "percent": 32.61390887290168}, "regions": {"count": 260, "covered": 48, "notcovered": 212, "percent": 18.461538461538463}}}, {"filename": "/src/zlib/adler32.c", "summary": {"functions": {"count": 5, "covered": 2, "percent": 40}, "instantiations": {"count": 5, "covered": 2, "percent": 40}, "lines": {"count": 97, "covered": 68, "percent": 70.10309278350515}, "regions": {"count": 140, "covered": 111, "notcovered": 29, "percent": 79.28571428571428}}}, {"filename": "/src/zlib/crc32.c", "summary": {"functions": {"count": 10, "covered": 3, "percent": 30}, "instantiations": {"count": 10, "covered": 3, "percent": 30}, "lines": {"count": 159, "covered": 41, "percent": 25.78616352201258}, "regions": {"count": 106, "covered": 33, "notcovered": 73, "percent": 31.132075471698112}}}, {"filename": "/src/zlib/inffast.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 219, "covered": 210, "percent": 95.8904109589041}, "regions": {"count": 84, "covered": 81, "notcovered": 3, "percent": 96.42857142857143}}}, {"filename": "/src/zlib/inffixed.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/zlib/inflate.c", "summary": {"functions": {"count": 22, "covered": 10, "percent": 45.45454545454545}, "instantiations": {"count": 22, "covered": 10, "percent": 45.45454545454545}, "lines": {"count": 1023, "covered": 744, "percent": 72.72727272727273}, "regions": {"count": 1170, "covered": 894, "notcovered": 276, "percent": 76.41025641025641}}}, {"filename": "/src/zlib/inftrees.c", "summary": {"functions": {"count": 1, "covered": 1, "percent": 100}, "instantiations": {"count": 1, "covered": 1, "percent": 100}, "lines": {"count": 266, "covered": 256, "percent": 96.2406015037594}, "regions": {"count": 109, "covered": 101, "notcovered": 8, "percent": 92.66055045871559}}}, {"filename": "/src/zlib/inftrees.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/zlib/zconf.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/zlib/zlib.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}, {"filename": "/src/zlib/zutil.c", "summary": {"functions": {"count": 5, "covered": 1, "percent": 20}, "instantiations": {"count": 5, "covered": 1, "percent": 20}, "lines": {"count": 45, "covered": 3, "percent": 6.666666666666667}, "regions": {"count": 30, "covered": 2, "notcovered": 28, "percent": 6.666666666666667}}}, {"filename": "/src/zlib/zutil.h", "summary": {"functions": {"count": 0, "covered": 0, "percent": 0}, "instantiations": {"count": 0, "covered": 0, "percent": 0}, "lines": {"count": 0, "covered": 0, "percent": 0}, "regions": {"count": 0, "covered": 0, "notcovered": 0, "percent": 0}}}], "totals": {"functions": {"count": 6666, "covered": 1907, "percent": 28.60786078607861}, "instantiations": {"count": 7495, "covered": 2012, "percent": 26.844563042028017}, "lines": {"count": 197515, "covered": 51027, "percent": 25.834493582765866}, "regions": {"count": 143296, "covered": 30159, "notcovered": 113137, "percent": 21.046644707458686}}}], "type": "llvm.coverage.json.export", "version": "2.0.0"} ================================================ FILE: infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make COPY . $SRC/external-project WORKDIR $SRC/external-project COPY .clusterfuzzlite/build.sh $SRC/ ================================================ FILE: infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make clean # Not strictly necessary, since we are building in a fresh dir. make -j$(nproc) all # Build the fuzz targets. # Copy the fuzzer executables, zip-ed corpora, option and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' # If you have dictionaries. find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' # If you have custom options. ================================================ FILE: infra/cifuzz/test_data/external-project/Makefile ================================================ # Copyright 2017 Google Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # Simple example of a build file that nicely integrates a fuzz target # with the rest of the project. # # We use 'make' as the build system, but these ideas are applicable # to any other build system # By default, use our own standalone_fuzz_target_runner. # This runner does no fuzzing, but simply executes the inputs # provided via parameters. # Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a" # to link the fuzzer(s) against a real fuzzing engine. # # OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE. LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o # Values for CC, CFLAGS, CXX, CXXFLAGS are provided by OSS-Fuzz. # Outside of OSS-Fuzz use the ones you prefer or rely on the default values. # Do not use the -fsanitize=* flags by default. # OSS-Fuzz will use different -fsanitize=* flags for different builds (asan, ubsan, msan, ...) # You may add extra compiler flags like this: CXXFLAGS += -std=c++11 all: do_stuff_fuzzer clean: rm -fv *.a *.o *_fuzzer crash-* *.zip # Fuzz target, links against $LIB_FUZZING_ENGINE, so that # you may choose which fuzzing engine to use. do_stuff_fuzzer: do_stuff_fuzzer.cpp my_api.a standalone_fuzz_target_runner.o ${CXX} ${CXXFLAGS} $< my_api.a ${LIB_FUZZING_ENGINE} -o $@ # The library itself. my_api.a: my_api.cpp my_api.h ${CXX} ${CXXFLAGS} $< -c ar ruv my_api.a my_api.o # The standalone fuzz target runner. standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cpp ================================================ FILE: infra/cifuzz/test_data/external-project/do_stuff_fuzzer.cpp ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "my_api.h" #include // Simple fuzz target for DoStuff(). // See https://llvm.org/docs/LibFuzzer.html for details. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { std::string str(reinterpret_cast(data), size); DoStuff(str); // Disregard the output. return 0; } ================================================ FILE: infra/cifuzz/test_data/external-project/do_stuff_fuzzer.dict ================================================ # A dictionary for more efficient fuzzing of DoStuff(). # If the inputs contain multi-byte tokens, list them here. # See https://llvm.org/docs/LibFuzzer.html#dictionaries "foo" "bar" "ouch" ================================================ FILE: infra/cifuzz/test_data/external-project/my_api.cpp ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Implementation of "my_api". #include "my_api.h" #include // Do some computations with 'str', return the result. // This function contains a bug. Can you spot it? size_t DoStuff(const std::string &str) { std::vector Vec({0, 1, 2, 3, 4}); size_t Idx = 0; if (str.size() > 5) Idx++; if (str.find("foo") != std::string::npos) Idx++; if (str.find("bar") != std::string::npos) Idx++; if (str.find("ouch") != std::string::npos) Idx++; if (str.find("omg") != std::string::npos) Idx++; return Vec[Idx]; } ================================================ FILE: infra/cifuzz/test_data/external-project/my_api.h ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // A library that does ... stuff. // Serves as an example of good fuzz testing and OSS-Fuzz integration. #include size_t DoStuff(const std::string &str); ================================================ FILE: infra/cifuzz/test_data/external-project/standalone_fuzz_target_runner.cpp ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Example of a standalone runner for "fuzz targets". // It reads all files passed as parameters and feeds their contents // one by one into the fuzz target (LLVMFuzzerTestOneInput). // This runner does not do any fuzzing, but allows us to run the fuzz target // on the test corpus (e.g. "do_stuff_test_data") or on a single file, // e.g. the one that comes from a bug report. #include #include #include #include // Forward declare the "fuzz target" interface. // We deliberately keep this inteface simple and header-free. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { std::ifstream in(argv[i]); in.seekg(0, in.end); size_t length = in.tellg(); in.seekg (0, in.beg); std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; // Allocate exactly length bytes so that we reliably catch buffer overflows. std::vector bytes(length); in.read(bytes.data(), bytes.size()); assert(in); LLVMFuzzerTestOneInput(reinterpret_cast(bytes.data()), bytes.size()); std::cout << "Execution successful" << std::endl; } return 0; } ================================================ FILE: infra/cifuzz/test_data/msan_crash_fuzzer_bug_summary.txt ================================================ MemorySanitizer: use-of-uninitialized-value #0 0x52675f in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:13:7 #1 0x45a431 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15 #2 0x45ba46 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:792:3 #3 0x45bed9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:845:3 #4 0x44a4bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6 #5 0x474432 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #6 0x7eff5562683f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f) #7 0x41eab8 in _start (out/do_stuff_fuzzer+0x41eab8) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) Uninitialized value was created by a heap allocation #0 0x4d57ad in malloc /src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:901:3 #1 0x437c07 in operator new(unsigned long) (out/do_stuff_fuzzer+0x437c07) #2 0x45ba46 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:792:3 #3 0x45bed9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:845:3 #4 0x44a4bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6 #5 0x474432 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #6 0x7eff5562683f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f) DEDUP_TOKEN: malloc--operator new(unsigned long)--fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) SUMMARY: ================================================ FILE: infra/cifuzz/test_data/msan_crash_fuzzer_output.txt ================================================ Dictionary: 3 entries INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 1 modules (184 inline 8-bit counters): 184 [0x829300, 0x8293b8), INFO: Loaded 1 PC tables (184 PCs): 184 [0x5dc910,0x5dd490), INFO: 5 files found in /tmp/do_stuff_fuzzer_corpus INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes ==13==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x52675f in LLVMFuzzerTestOneInput /src/cifuzz-example/do_stuff_fuzzer.cpp:13:7 #1 0x45a431 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:599:15 #2 0x45ba46 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:792:3 #3 0x45bed9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:845:3 #4 0x44a4bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6 #5 0x474432 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #6 0x7eff5562683f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f) #7 0x41eab8 in _start (out/do_stuff_fuzzer+0x41eab8) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) Uninitialized value was created by a heap allocation #0 0x4d57ad in malloc /src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:901:3 #1 0x437c07 in operator new(unsigned long) (out/do_stuff_fuzzer+0x437c07) #2 0x45ba46 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:792:3 #3 0x45bed9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:845:3 #4 0x44a4bc in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:906:6 #5 0x474432 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #6 0x7eff5562683f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f) DEDUP_TOKEN: malloc--operator new(unsigned long)--fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) SUMMARY: MemorySanitizer: use-of-uninitialized-value /src/cifuzz-example/do_stuff_fuzzer.cpp:13:7 in LLVMFuzzerTestOneInput Unique heap origins: 65 Stack depot allocated bytes: 4424 Unique origin histories: 29 History depot allocated bytes: 696 Exiting MS: 0 ; base unit: 0000000000000000000000000000000000000000 artifact_prefix='./'; Test unit written to ./crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 Base64: ================================================ FILE: infra/cifuzz/test_data/sarif_utils_msan_stack.txt ================================================ Dictionary: 3 entries 2024-05-07 18:49:02,343 - root - INFO - Fuzzer: do_stuff_fuzzer. Detected bug. INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 1 modules (83 inline 8-bit counters): 83 [0x563ff0e03e98, 0x563ff0e03eeb), INFO: Loaded 1 PC tables (83 PCs): 83 [0x563ff0e03ef0,0x563ff0e04420), INFO: 0 files found in /github/workspace/cifuzz-corpus/do_stuff_fuzzer INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes INFO: A corpus is not provided, starting from an empty corpus #2 INITED cov: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 69Mb #4 NEW cov: 3 ft: 3 corp: 2/3b lim: 4096 exec/s: 0 rss: 69Mb L: 2/2 MS: 2 ChangeBit-InsertByte- ==23==WARNING: MemorySanitizer: use-of-uninitialized-value #0 0x563ff0d278f0 in LLVMFuzzerTestOneInput /src/cifuzz-external-example/do_stuff_fuzzer.cpp:24:1 #1 0x563ff0c24340 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13 #2 0x563ff0c23b65 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7 #3 0x563ff0c25335 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19 #4 0x563ff0c26125 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5 #5 0x563ff0c14436 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6 #6 0x563ff0c40962 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7f4c156ed082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 87b331c034a6458c64ce09c03939e947212e18ce) #8 0x563ff0c055ad in _start (build-out/do_stuff_fuzzer+0x4a5ad) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) Uninitialized value was stored to memory at #0 0x563ff0d278e9 in LLVMFuzzerTestOneInput /src/cifuzz-external-example/do_stuff_fuzzer.cpp #1 0x563ff0c24340 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13 #2 0x563ff0c23b65 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7 #3 0x563ff0c25335 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19 #4 0x563ff0c26125 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5 #5 0x563ff0c14436 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6 #6 0x563ff0c40962 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7f4c156ed082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 87b331c034a6458c64ce09c03939e947212e18ce) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) Uninitialized value was created by a heap deallocation #0 0x563ff0cc7480 in free /src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cpp:218:3 #1 0x563ff0d27800 in LLVMFuzzerTestOneInput /src/cifuzz-external-example/do_stuff_fuzzer.cpp:21:5 #2 0x563ff0c24340 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13 #3 0x563ff0c23b65 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7 #4 0x563ff0c25335 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19 #5 0x563ff0c26125 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5 #6 0x563ff0c14436 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6 #7 0x563ff0c40962 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7f4c156ed082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 87b331c034a6458c64ce09c03939e947212e18ce) DEDUP_TOKEN: __interceptor_free--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) SUMMARY: MemorySanitizer: use-of-uninitialized-value /src/cifuzz-external-example/do_stuff_fuzzer.cpp:24:1 in LLVMFuzzerTestOneInput Unique heap origins: 201 Stack depot allocated bytes: 9764880 Unique origin histories: 181 History depot allocated bytes: 196608 Exiting MS: 5 ShuffleBytes-CopyPart-InsertByte-CopyPart-ManualDict- DE: "bar"-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc 0xa,0x62,0x61,0x72,0xa, \012bar\012 artifact_prefix='/tmp/tmp1tc5b3m2/'; Test unit written to /tmp/tmp1tc5b3m2/crash-c935b6724d7e27401ac9af3773700ca86ac38dea Base64: CmJhcgo= stat::number_of_executed_units: 159 stat::average_exec_per_sec: 0 stat::new_units_added: 1 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 69 ================================================ FILE: infra/cifuzz/test_data/sarif_utils_only_llvmfuzzer_stack.txt ================================================ /github/workspace/build-out/fuzz-bus-label -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpsngf52cy/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bus-label >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82577 inline 8-bit counters): 82573 [0x7fc55e6bedf0, 0x7fc55e6d307d), 4 [0x5e9c28, 0x5e9c2c), 2023-05-04 01:02:55,065 - root - INFO - Not reporting crash in fuzz-bus-label because process timed out. 2023-05-04 01:02:55,069 - root - INFO - Deleting corpus and seed corpus of fuzz-bus-label to save disk. INFO: Loaded 2 PC tables (82577 PCs): 82573 [0x7fc55e6d3080,0x7fc55e815950), 4 [0x5a6c78,0x5a6cb8), INFO: 256 files found in /github/workspace/cifuzz-corpus/fuzz-bus-label INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes INFO: seed corpus: files: 256 min: 1b max: 5242880b total: 30968483b rss: 48Mb #257 INITED cov: 41 ft: 230 corp: 111/4360b exec/s: 0 rss: 73Mb #131072 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 76Mb #262144 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 76Mb #524288 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 77Mb #609082 DONE cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43505 rss: 77Mb Done 609082 runs in 14 second(s) stat::number_of_executed_units: 609082 stat::average_exec_per_sec: 43505 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 77 /github/workspace/build-out/fuzz-bus-label -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpsngf52cy/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bus-label >fuzz-1.log 2>&1 2023-05-04 01:02:55,082 - root - INFO - Deleting fuzz target: fuzz-bus-label. 2023-05-04 01:02:55,083 - root - INFO - Done deleting. 2023-05-04 01:02:55,084 - root - INFO - Fuzzer fuzz-bus-label finished running without reportable crashes. 2023-05-04 01:02:55,084 - root - INFO - Running fuzzer: fuzz-dhcp-server. 2023-05-04 01:02:55,085 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-dhcp-server/public.zip 2023-05-04 01:02:55,088 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:02:55,145 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-dhcp-server/public.zip HTTP/1.1" 200 806749 2023-05-04 01:02:55,350 - root - INFO - Starting fuzzing Fuzzing logs: /github/workspace/build-out/fuzz-dhcp-server -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpyxgwwsvr/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-dhcp-server >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (83640 inline 8-bit counters): 82573 [0x7fe86ff70df0, 0x7fe86ff8507d), 1067 [0x60c638, 0x60ca63), INFO: Loaded 2 PC tables (83640 PCs): 82573 [0x7fe86ff85080,0x7fe8700c7950), 1067 [0x60ca68,0x610d18), INFO: 1153 files found in /github/workspace/cifuzz-corpus/fuzz-dhcp-server INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes INFO: seed corpus: files: 1153 min: 1b max: 5242879b total: 17056071b rss: 50Mb #1155 INITED cov: 577 ft: 1116 corp: 203/54Kb exec/s: 0 rss: 86Mb #1167 NEW cov: 577 ft: 1117 corp: 204/54Kb lim: 1048576 exec/s: 0 rss: 86Mb L: 243/1071 MS: 2 ChangeASCIIInt-CrossOver- #1509 NEW cov: 577 ft: 1118 corp: 205/54Kb lim: 1048576 exec/s: 0 rss: 86Mb L: 243/1071 MS: 2 ChangeBit-CopyPart- #63018 NEW cov: 577 ft: 1119 corp: 206/55Kb lim: 1048576 exec/s: 21006 rss: 86Mb L: 245/1071 MS: 4 InsertByte-ChangeByte-CMP-InsertByte- DE: "2\000\000\000\000\000\000\000"- #65536 pulse cov: 577 ft: 1119 corp: 206/55Kb lim: 1048576 exec/s: 21845 rss: 86Mb Loaded 1024/1155 files from /github/workspace/cifuzz-corpus/fuzz-dhcp-server #99784 NEW cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 19956 rss: 105Mb L: 243/1071 MS: 2 ChangeASCIIInt-ChangeBinInt- #131072 pulse cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 21845 rss: 105Mb #262144 pulse cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 20164 rss: 105Mb #275639 DONE cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 19688 rss: 105Mb ###### Recommended dictionary. ###### "2\000\000\000\000\000\000\000" # Uses: 17879 ###### End of recommended dictionary. ###### Done 275639 runs in 14 second(s) stat::number_of_executed_units: 275639 stat::average_exec_per_sec: 19688 stat::new_units_added: 4 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 105 /github/workspace/build-out/fuzz-dhcp-server -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpyxgwwsvr/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-dhcp-server >fuzz-1.log 2>&1 2023-05-04 01:03:18,374 - root - INFO - Not reporting crash in fuzz-dhcp-server because process timed out. 2023-05-04 01:03:18,377 - root - INFO - Deleting corpus and seed corpus of fuzz-dhcp-server to save disk. 2023-05-04 01:03:18,399 - root - INFO - Deleting fuzz target: fuzz-dhcp-server. 2023-05-04 01:03:18,400 - root - INFO - Done deleting. 2023-05-04 01:03:18,400 - root - INFO - Fuzzer fuzz-dhcp-server finished running without reportable crashes. 2023-05-04 01:03:18,401 - root - INFO - Running fuzzer: fuzz-bcd. 2023-05-04 01:03:18,401 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-bcd/public.zip 2023-05-04 01:03:18,404 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:03:18,582 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-bcd/public.zip HTTP/1.1" 200 2293254 2023-05-04 01:03:18,804 - root - INFO - Starting fuzzing Fuzzing logs: /github/workspace/build-out/fuzz-bcd -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpgvqlyr8q/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bcd >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (83175 inline 8-bit counters): 82573 [0x7f1b5387edf0, 0x7f1b5389307d), 602 [0x5f8718, 0x5f8972), INFO: Loaded 2 PC tables (83175 PCs): 82573 [0x7f1b53893080,0x7f1b539d5950), 602 [0x5f8978,0x5faf18), INFO: 1260 files found in /github/workspace/cifuzz-corpus/fuzz-bcd INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 946175 bytes INFO: seed corpus: files: 1260 min: 1b max: 946175b total: 10373697b rss: 48Mb #1261 INITED cov: 137 ft: 653 corp: 282/1416Kb exec/s: 0 rss: 91Mb #65536 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 32768 rss: 98Mb #131072 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 32768 rss: 98Mb #262144 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 37449 rss: 98Mb #475081 DONE cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 33934 rss: 98Mb Done 475081 runs in 14 second(s) stat::number_of_executed_units: 475081 stat::average_exec_per_sec: 33934 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 98 /github/workspace/build-out/fuzz-bcd -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpgvqlyr8q/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bcd >fuzz-1.log 2>&1 2023-05-04 01:03:41,821 - root - INFO - Not reporting crash in fuzz-bcd because process timed out. 2023-05-04 01:03:41,822 - root - INFO - Deleting corpus and seed corpus of fuzz-bcd to save disk. 2023-05-04 01:03:41,848 - root - INFO - Deleting fuzz target: fuzz-bcd. 2023-05-04 01:03:41,848 - root - INFO - Done deleting. 2023-05-04 01:03:41,848 - root - INFO - Fuzzer fuzz-bcd finished running without reportable crashes. 2023-05-04 01:03:41,848 - root - INFO - Running fuzzer: fuzz-varlink. 2023-05-04 01:03:41,849 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-varlink/public.zip 2023-05-04 01:03:41,852 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:03:41,906 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-varlink/public.zip HTTP/1.1" 200 2586434 2023-05-04 01:03:42,671 - root - INFO - Starting fuzzing 2023-05-04 01:04:05,709 - root - INFO - Not reporting crash in fuzz-varlink because process timed out. Fuzzing logs: /github/workspace/build-out/fuzz-varlink -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpbtf4f932/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-varlink >fuzz-0.log 2>&1 2023-05-04 01:04:05,709 - root - INFO - Deleting corpus and seed corpus of fuzz-varlink to save disk. 2023-05-04 01:04:05,806 - root - INFO - Deleting fuzz target: fuzz-varlink. 2023-05-04 01:04:05,806 - root - INFO - Done deleting. 2023-05-04 01:04:05,806 - root - INFO - Fuzzer fuzz-varlink finished running without reportable crashes. 2023-05-04 01:04:05,806 - root - INFO - Running fuzzer: fuzz-unit-file. 2023-05-04 01:04:05,807 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-unit-file/public.zip 2023-05-04 01:04:05,809 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:04:05,897 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-unit-file/public.zip HTTP/1.1" 200 4999974 2023-05-04 01:04:07,869 - root - INFO - Starting fuzzing 2023-05-04 01:04:09,516 - root - INFO - Fuzzer: fuzz-unit-file. Detected bug. Fuzzing logs: /github/workspace/build-out/fuzz-unit-file -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpjhswtxiw/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-unit-file >fuzz-0.log 2>&1 2023-05-04 01:04:09,517 - root - INFO - Trying to reproduce crash using: /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03. ================== Job 0 exited with exit code 77 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82576 inline 8-bit counters): 82573 [0x7f3b0de4cdf0, 0x7f3b0de6107d), 3 [0x5e9b28, 0x5e9b2b), INFO: Loaded 2 PC tables (82576 PCs): 82573 [0x7f3b0de61080,0x7f3b0dfa3950), 3 [0x5a6af8,0x5a6b28), INFO: 20907 files found in /github/workspace/cifuzz-corpus/fuzz-unit-file INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 604973 bytes INFO: seed corpus: files: 20907 min: 1b max: 604973b total: 16005340b rss: 61Mb ================================================================= ==74==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000005078 at pc 0x0000004ddffa bp 0x7fffeea64fe0 sp 0x7fffeea64fd8 READ of size 4 at 0x602000005078 thread T0 SCARINESS: 27 (4-byte-read-heap-buffer-overflow-far-from-bounds) #0 0x4ddff9 in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 #1 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #2 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #3 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #4 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #5 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #6 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #8 0x41f6ed in _start (build-out/fuzz-unit-file+0x41f6ed) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) 0x602000005078 is located 38 bytes to the right of 2-byte region [0x602000005050,0x602000005052) freed by thread T0 here: #0 0x4a0882 in __interceptor_free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x4ddfb7 in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:29:9 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: __interceptor_free--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) previously allocated by thread T0 here: #0 0x4a0b26 in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3 #1 0x4ddfac in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:28:25 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: malloc--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) SUMMARY: AddressSanitizer: heap-buffer-overflow /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 in LLVMFuzzerTestOneInput Shadow bytes around the buggy address: 0x0c047fff89b0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89c0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89d0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89e0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89f0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd =>0x0c047fff8a00: fa fa 00 02 fa fa 00 02 fa fa fd fa fa fa fa[fa] 0x0c047fff8a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==74==ABORTING MS: 0 ; base unit: 0000000000000000000000000000000000000000 0x61,0x75,0x74,0x6f,0x6d,0x6f,0x75,0x6e,0x74,0x48, automountH artifact_prefix='/tmp/tmpjhswtxiw/'; Test unit written to /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03 Base64: YXV0b21vdW50SA== stat::number_of_executed_units: 314 stat::average_exec_per_sec: 0 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 67 /github/workspace/build-out/fuzz-unit-file -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpjhswtxiw/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-unit-file >fuzz-1.log 2>&1 ================== Job 1 exited with exit code 77 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82576 inline 8-bit counters): 82573 [0x7ff1ba038df0, 0x7ff1ba04d07d), 3 [0x5e9b28, 0x5e9b2b), INFO: Loaded 2 PC tables (82576 PCs): 82573 [0x7ff1ba04d080,0x7ff1ba18f950), 3 [0x5a6af8,0x5a6b28), INFO: 20907 files found in /github/workspace/cifuzz-corpus/fuzz-unit-file INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 604973 bytes INFO: seed corpus: files: 20907 min: 1b max: 604973b total: 16005340b rss: 61Mb ================================================================= ==78==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000005078 at pc 0x0000004ddffa bp 0x7ffc2e6825c0 sp 0x7ffc2e6825b8 READ of size 4 at 0x602000005078 thread T0 SCARINESS: 27 (4-byte-read-heap-buffer-overflow-far-from-bounds) #0 0x4ddff9 in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 #1 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #2 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #3 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #4 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #5 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #6 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #8 0x41f6ed in _start (build-out/fuzz-unit-file+0x41f6ed) DEDUP_TOKEN: LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) 0x602000005078 is located 38 bytes to the right of 2-byte region [0x602000005050,0x602000005052) freed by thread T0 here: #0 0x4a0882 in __interceptor_free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x4ddfb7 in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:29:9 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: __interceptor_free--LLVMFuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) previously allocated by thread T0 here: #0 0x4a0b26 in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3 #1 0x4ddfac in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:28:25 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: malloc--samLLVM2FuzzerTestOneInput --fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) SUMMARY: AddressSanitizer: heap-buffer-overflow /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 in samsamLLVM2FuzzerTestOneInput Shadow bytes around the buggy address: 0x0c047fff89b0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89c0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89d0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89e0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89f0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd =>0x0c047fff8a00: fa fa 00 02 fa fa 00 02 fa fa fd fa fa fa fa[fa] 0x0c047fff8a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==78==ABORTING MS: 0 ; base unit: 0000000000000000000000000000000000000000 0x61,0x75,0x74,0x6f,0x6d,0x6f,0x75,0x6e,0x74,0x48, automountH artifact_prefix='/tmp/tmpjhswtxiw/'; Test unit written to /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03 Base64: YXV0b21vdW50SA== stat::number_of_executed_units: 314 stat::average_exec_per_sec: 0 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 68 ================================================ FILE: infra/cifuzz/test_data/sarif_utils_systemd_stack.txt ================================================ /github/workspace/build-out/fuzz-bus-label -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpsngf52cy/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bus-label >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82577 inline 8-bit counters): 82573 [0x7fc55e6bedf0, 0x7fc55e6d307d), 4 [0x5e9c28, 0x5e9c2c), 2023-05-04 01:02:55,065 - root - INFO - Not reporting crash in fuzz-bus-label because process timed out. 2023-05-04 01:02:55,069 - root - INFO - Deleting corpus and seed corpus of fuzz-bus-label to save disk. INFO: Loaded 2 PC tables (82577 PCs): 82573 [0x7fc55e6d3080,0x7fc55e815950), 4 [0x5a6c78,0x5a6cb8), INFO: 256 files found in /github/workspace/cifuzz-corpus/fuzz-bus-label INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes INFO: seed corpus: files: 256 min: 1b max: 5242880b total: 30968483b rss: 48Mb #257 INITED cov: 41 ft: 230 corp: 111/4360b exec/s: 0 rss: 73Mb #131072 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 76Mb #262144 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 76Mb #524288 pulse cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43690 rss: 77Mb #609082 DONE cov: 41 ft: 230 corp: 111/4360b lim: 1048576 exec/s: 43505 rss: 77Mb Done 609082 runs in 14 second(s) stat::number_of_executed_units: 609082 stat::average_exec_per_sec: 43505 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 77 /github/workspace/build-out/fuzz-bus-label -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpsngf52cy/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bus-label >fuzz-1.log 2>&1 2023-05-04 01:02:55,082 - root - INFO - Deleting fuzz target: fuzz-bus-label. 2023-05-04 01:02:55,083 - root - INFO - Done deleting. 2023-05-04 01:02:55,084 - root - INFO - Fuzzer fuzz-bus-label finished running without reportable crashes. 2023-05-04 01:02:55,084 - root - INFO - Running fuzzer: fuzz-dhcp-server. 2023-05-04 01:02:55,085 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-dhcp-server/public.zip 2023-05-04 01:02:55,088 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:02:55,145 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-dhcp-server/public.zip HTTP/1.1" 200 806749 2023-05-04 01:02:55,350 - root - INFO - Starting fuzzing Fuzzing logs: /github/workspace/build-out/fuzz-dhcp-server -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpyxgwwsvr/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-dhcp-server >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (83640 inline 8-bit counters): 82573 [0x7fe86ff70df0, 0x7fe86ff8507d), 1067 [0x60c638, 0x60ca63), INFO: Loaded 2 PC tables (83640 PCs): 82573 [0x7fe86ff85080,0x7fe8700c7950), 1067 [0x60ca68,0x610d18), INFO: 1153 files found in /github/workspace/cifuzz-corpus/fuzz-dhcp-server INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 1048576 bytes INFO: seed corpus: files: 1153 min: 1b max: 5242879b total: 17056071b rss: 50Mb #1155 INITED cov: 577 ft: 1116 corp: 203/54Kb exec/s: 0 rss: 86Mb #1167 NEW cov: 577 ft: 1117 corp: 204/54Kb lim: 1048576 exec/s: 0 rss: 86Mb L: 243/1071 MS: 2 ChangeASCIIInt-CrossOver- #1509 NEW cov: 577 ft: 1118 corp: 205/54Kb lim: 1048576 exec/s: 0 rss: 86Mb L: 243/1071 MS: 2 ChangeBit-CopyPart- #63018 NEW cov: 577 ft: 1119 corp: 206/55Kb lim: 1048576 exec/s: 21006 rss: 86Mb L: 245/1071 MS: 4 InsertByte-ChangeByte-CMP-InsertByte- DE: "2\000\000\000\000\000\000\000"- #65536 pulse cov: 577 ft: 1119 corp: 206/55Kb lim: 1048576 exec/s: 21845 rss: 86Mb Loaded 1024/1155 files from /github/workspace/cifuzz-corpus/fuzz-dhcp-server #99784 NEW cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 19956 rss: 105Mb L: 243/1071 MS: 2 ChangeASCIIInt-ChangeBinInt- #131072 pulse cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 21845 rss: 105Mb #262144 pulse cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 20164 rss: 105Mb #275639 DONE cov: 577 ft: 1120 corp: 207/55Kb lim: 1048576 exec/s: 19688 rss: 105Mb ###### Recommended dictionary. ###### "2\000\000\000\000\000\000\000" # Uses: 17879 ###### End of recommended dictionary. ###### Done 275639 runs in 14 second(s) stat::number_of_executed_units: 275639 stat::average_exec_per_sec: 19688 stat::new_units_added: 4 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 105 /github/workspace/build-out/fuzz-dhcp-server -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpyxgwwsvr/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-dhcp-server >fuzz-1.log 2>&1 2023-05-04 01:03:18,374 - root - INFO - Not reporting crash in fuzz-dhcp-server because process timed out. 2023-05-04 01:03:18,377 - root - INFO - Deleting corpus and seed corpus of fuzz-dhcp-server to save disk. 2023-05-04 01:03:18,399 - root - INFO - Deleting fuzz target: fuzz-dhcp-server. 2023-05-04 01:03:18,400 - root - INFO - Done deleting. 2023-05-04 01:03:18,400 - root - INFO - Fuzzer fuzz-dhcp-server finished running without reportable crashes. 2023-05-04 01:03:18,401 - root - INFO - Running fuzzer: fuzz-bcd. 2023-05-04 01:03:18,401 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-bcd/public.zip 2023-05-04 01:03:18,404 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:03:18,582 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-bcd/public.zip HTTP/1.1" 200 2293254 2023-05-04 01:03:18,804 - root - INFO - Starting fuzzing Fuzzing logs: /github/workspace/build-out/fuzz-bcd -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpgvqlyr8q/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bcd >fuzz-0.log 2>&1 ================== Job 0 exited with exit code 0 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (83175 inline 8-bit counters): 82573 [0x7f1b5387edf0, 0x7f1b5389307d), 602 [0x5f8718, 0x5f8972), INFO: Loaded 2 PC tables (83175 PCs): 82573 [0x7f1b53893080,0x7f1b539d5950), 602 [0x5f8978,0x5faf18), INFO: 1260 files found in /github/workspace/cifuzz-corpus/fuzz-bcd INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 946175 bytes INFO: seed corpus: files: 1260 min: 1b max: 946175b total: 10373697b rss: 48Mb #1261 INITED cov: 137 ft: 653 corp: 282/1416Kb exec/s: 0 rss: 91Mb #65536 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 32768 rss: 98Mb #131072 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 32768 rss: 98Mb #262144 pulse cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 37449 rss: 98Mb #475081 DONE cov: 137 ft: 653 corp: 282/1416Kb lim: 946175 exec/s: 33934 rss: 98Mb Done 475081 runs in 14 second(s) stat::number_of_executed_units: 475081 stat::average_exec_per_sec: 33934 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 98 /github/workspace/build-out/fuzz-bcd -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpgvqlyr8q/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-bcd >fuzz-1.log 2>&1 2023-05-04 01:03:41,821 - root - INFO - Not reporting crash in fuzz-bcd because process timed out. 2023-05-04 01:03:41,822 - root - INFO - Deleting corpus and seed corpus of fuzz-bcd to save disk. 2023-05-04 01:03:41,848 - root - INFO - Deleting fuzz target: fuzz-bcd. 2023-05-04 01:03:41,848 - root - INFO - Done deleting. 2023-05-04 01:03:41,848 - root - INFO - Fuzzer fuzz-bcd finished running without reportable crashes. 2023-05-04 01:03:41,848 - root - INFO - Running fuzzer: fuzz-varlink. 2023-05-04 01:03:41,849 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-varlink/public.zip 2023-05-04 01:03:41,852 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:03:41,906 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-varlink/public.zip HTTP/1.1" 200 2586434 2023-05-04 01:03:42,671 - root - INFO - Starting fuzzing 2023-05-04 01:04:05,709 - root - INFO - Not reporting crash in fuzz-varlink because process timed out. Fuzzing logs: /github/workspace/build-out/fuzz-varlink -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpbtf4f932/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-varlink >fuzz-0.log 2>&1 2023-05-04 01:04:05,709 - root - INFO - Deleting corpus and seed corpus of fuzz-varlink to save disk. 2023-05-04 01:04:05,806 - root - INFO - Deleting fuzz target: fuzz-varlink. 2023-05-04 01:04:05,806 - root - INFO - Done deleting. 2023-05-04 01:04:05,806 - root - INFO - Fuzzer fuzz-varlink finished running without reportable crashes. 2023-05-04 01:04:05,806 - root - INFO - Running fuzzer: fuzz-unit-file. 2023-05-04 01:04:05,807 - root - INFO - Downloading corpus from OSS-Fuzz: https://storage.googleapis.com/systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-unit-file/public.zip 2023-05-04 01:04:05,809 - urllib3.connectionpool - DEBUG - Starting new HTTPS connection (1): storage.googleapis.com:443 2023-05-04 01:04:05,897 - urllib3.connectionpool - DEBUG - https://storage.googleapis.com:443 "GET /systemd-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/systemd_fuzz-unit-file/public.zip HTTP/1.1" 200 4999974 2023-05-04 01:04:07,869 - root - INFO - Starting fuzzing 2023-05-04 01:04:09,516 - root - INFO - Fuzzer: fuzz-unit-file. Detected bug. Fuzzing logs: /github/workspace/build-out/fuzz-unit-file -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpjhswtxiw/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-unit-file >fuzz-0.log 2>&1 2023-05-04 01:04:09,517 - root - INFO - Trying to reproduce crash using: /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03. ================== Job 0 exited with exit code 77 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82576 inline 8-bit counters): 82573 [0x7f3b0de4cdf0, 0x7f3b0de6107d), 3 [0x5e9b28, 0x5e9b2b), INFO: Loaded 2 PC tables (82576 PCs): 82573 [0x7f3b0de61080,0x7f3b0dfa3950), 3 [0x5a6af8,0x5a6b28), INFO: 20907 files found in /github/workspace/cifuzz-corpus/fuzz-unit-file INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 604973 bytes INFO: seed corpus: files: 20907 min: 1b max: 604973b total: 16005340b rss: 61Mb ================================================================= ==74==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000005078 at pc 0x0000004ddffa bp 0x7fffeea64fe0 sp 0x7fffeea64fd8 READ of size 4 at 0x602000005078 thread T0 SCARINESS: 27 (4-byte-read-heap-buffer-overflow-far-from-bounds) #0 0x4ddff9 in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 #1 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #2 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #3 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #4 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #5 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #6 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #8 0x41f6ed in _start (build-out/fuzz-unit-file+0x41f6ed) DEDUP_TOKEN: samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) 0x602000005078 is located 38 bytes to the right of 2-byte region [0x602000005050,0x602000005052) freed by thread T0 here: #0 0x4a0882 in __interceptor_free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x4ddfb7 in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:29:9 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: __interceptor_free--samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) previously allocated by thread T0 here: #0 0x4a0b26 in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3 #1 0x4ddfac in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:28:25 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7f3b0ce20082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: malloc--samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) SUMMARY: AddressSanitizer: heap-buffer-overflow /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 in samLLVM2FuzzerTestOneInput Shadow bytes around the buggy address: 0x0c047fff89b0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89c0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89d0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89e0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89f0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd =>0x0c047fff8a00: fa fa 00 02 fa fa 00 02 fa fa fd fa fa fa fa[fa] 0x0c047fff8a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==74==ABORTING MS: 0 ; base unit: 0000000000000000000000000000000000000000 0x61,0x75,0x74,0x6f,0x6d,0x6f,0x75,0x6e,0x74,0x48, automountH artifact_prefix='/tmp/tmpjhswtxiw/'; Test unit written to /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03 Base64: YXV0b21vdW50SA== stat::number_of_executed_units: 314 stat::average_exec_per_sec: 0 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 67 /github/workspace/build-out/fuzz-unit-file -timeout=25 -rss_limit_mb=2560 -len_control=0 -seed=1337 -artifact_prefix=/tmp/tmpjhswtxiw/ -max_total_time=13 -print_final_stats=1 /github/workspace/cifuzz-corpus/fuzz-unit-file >fuzz-1.log 2>&1 ================== Job 1 exited with exit code 77 ============ INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1337 INFO: Loaded 2 modules (82576 inline 8-bit counters): 82573 [0x7ff1ba038df0, 0x7ff1ba04d07d), 3 [0x5e9b28, 0x5e9b2b), INFO: Loaded 2 PC tables (82576 PCs): 82573 [0x7ff1ba04d080,0x7ff1ba18f950), 3 [0x5a6af8,0x5a6b28), INFO: 20907 files found in /github/workspace/cifuzz-corpus/fuzz-unit-file INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 604973 bytes INFO: seed corpus: files: 20907 min: 1b max: 604973b total: 16005340b rss: 61Mb ================================================================= ==78==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000005078 at pc 0x0000004ddffa bp 0x7ffc2e6825c0 sp 0x7ffc2e6825b8 READ of size 4 at 0x602000005078 thread T0 SCARINESS: 27 (4-byte-read-heap-buffer-overflow-far-from-bounds) #0 0x4ddff9 in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 #1 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #2 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #3 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #4 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #5 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #6 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #7 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) #8 0x41f6ed in _start (build-out/fuzz-unit-file+0x41f6ed) DEDUP_TOKEN: samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long)--fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) 0x602000005078 is located 38 bytes to the right of 2-byte region [0x602000005050,0x602000005052) freed by thread T0 here: #0 0x4a0882 in __interceptor_free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x4ddfb7 in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:29:9 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: __interceptor_free--samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) previously allocated by thread T0 here: #0 0x4a0b26 in malloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3 #1 0x4ddfac in samLLVM2FuzzerTestOneInput /work/build/../../src/systemd/src/core/fuzz-unit-file.c:28:25 #2 0x4fc653 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:611:15 #3 0x4fbe3a in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:514:3 #4 0x4fdca4 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:826:7 #5 0x4fded9 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector >&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:857:3 #6 0x4ed53f in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:912:6 #7 0x516b92 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10 #8 0x7ff1b900c082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) DEDUP_TOKEN: malloc--samLLVM2FuzzerTestOneInput--fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) SUMMARY: AddressSanitizer: heap-buffer-overflow /work/build/../../src/systemd/src/core/fuzz-unit-file.c:30:16 in samsamLLVM2FuzzerTestOneInput Shadow bytes around the buggy address: 0x0c047fff89b0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89c0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89d0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89e0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd 0x0c047fff89f0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd =>0x0c047fff8a00: fa fa 00 02 fa fa 00 02 fa fa fd fa fa fa fa[fa] 0x0c047fff8a10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c047fff8a50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==78==ABORTING MS: 0 ; base unit: 0000000000000000000000000000000000000000 0x61,0x75,0x74,0x6f,0x6d,0x6f,0x75,0x6e,0x74,0x48, automountH artifact_prefix='/tmp/tmpjhswtxiw/'; Test unit written to /tmp/tmpjhswtxiw/crash-7be9e0f3a71d95f8d5e67c5a9d84273d6f4e3c03 Base64: YXV0b21vdW50SA== stat::number_of_executed_units: 314 stat::average_exec_per_sec: 0 stat::new_units_added: 0 stat::slowest_unit_time_sec: 0 stat::peak_rss_mb: 68 ================================================ FILE: infra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined ================================================ [File too large to display: 13.7 MB] ================================================ FILE: infra/cifuzz/test_helpers.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Contains convenient helpers for writing tests.""" import contextlib import os import sys import shutil import tempfile from unittest import mock import config_utils import docker import workspace_utils INFRA_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # pylint: disable=wrong-import-position,import-error sys.path.append(INFRA_DIR) import helper # TODO(metzman): Get rid of these decorators. @mock.patch('config_utils._is_dry_run', return_value=True) @mock.patch('platform_config.BasePlatformConfig.project_src_path', return_value=None) @mock.patch('os.path.basename', return_value=None) def _create_config(config_cls, _, __, ___, **kwargs): """Creates a config object from |config_cls| and then sets every attribute that is a key in |kwargs| to the corresponding value. Asserts that each key in |kwargs| is an attribute of config.""" with mock.patch('config_utils.BaseConfig.validate', return_value=True): config = config_cls() for key, value in kwargs.items(): assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key setattr(config, key, value) return config def create_build_config(**kwargs): """Wrapper around _create_config for build configs.""" return _create_config(config_utils.BuildFuzzersConfig, **kwargs) def create_run_config(**kwargs): """Wrapper around _create_config for run configs.""" return _create_config(config_utils.RunFuzzersConfig, **kwargs) def create_workspace(workspace_path='/workspace'): """Returns a workspace located at |workspace_path| ('/workspace' by default).""" config = create_run_config(workspace=workspace_path) return workspace_utils.Workspace(config) def patch_environ(testcase_obj, env=None, empty=False, runner=False): """Patch environment. |testcase_obj| is the unittest.TestCase that contains tests. |env|, if specified, is a dictionary of environment variables to start from. If |empty| is True then the new patched environment will be empty. If |runner| is True then the necessary environment variables will be set to run the scripts from base-runner.""" if env is None: env = {} patcher = mock.patch.dict(os.environ, env) testcase_obj.addCleanup(patcher.stop) patcher.start() if empty: for key in os.environ.copy(): del os.environ[key] if runner: # Add the scripts for base-runner to the path since the wont be in # /usr/local/bin on host machines during testing. base_runner_dir = os.path.join(INFRA_DIR, 'base-images', 'base-runner') os.environ['PATH'] = (os.environ.get('PATH', '') + os.pathsep + base_runner_dir) if 'GOPATH' not in os.environ: # A GOPATH must be set or else the coverage script fails, even for getting # the coverage of non-Go programs. os.environ['GOPATH'] = '/root/go' @contextlib.contextmanager def temp_dir_copy(directory): """Context manager that yields a temporary copy of |directory|.""" with tempfile.TemporaryDirectory() as temp_dir: temp_copy_path = os.path.join(temp_dir, os.path.basename(directory)) shutil.copytree(directory, temp_copy_path) yield temp_copy_path @contextlib.contextmanager def docker_temp_dir(): """Returns a temporary a directory that is useful for use with docker. On cleanup this contextmanager uses docker to delete the directory's contents so that if anything is owned by root it can be deleted (which tempfile.TemporaryDirectory() cannot do) by non-root users.""" with tempfile.TemporaryDirectory() as temp_dir: yield temp_dir helper.docker_run([ '-v', f'{temp_dir}:/temp_dir', '-t', docker.BASE_BUILDER_TAG, '/bin/bash', '-c', 'rm -rf /temp_dir/*' ]) ================================================ FILE: infra/cifuzz/workspace_utils.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Module for representing the workspace directory which CIFuzz uses.""" import os import shutil class Workspace: """Class representing the workspace directory.""" def __init__(self, config): self.workspace = config.workspace def initialize_dir(self, directory): # pylint: disable=no-self-use """Creates directory if it doesn't already exist, otherwise does nothing.""" os.makedirs(directory, exist_ok=True) @property def repo_storage(self): """The parent directory for repo storage.""" return os.path.join(self.workspace, 'storage') @property def out(self): """The out directory used for storing the fuzzer build built by build_fuzzers.""" # Don't use 'out' because it needs to be used by artifacts. return os.path.join(self.workspace, 'build-out') @property def work(self): """The directory used as the work directory for the fuzzer build/run.""" return os.path.join(self.workspace, 'work') @property def artifacts(self): """The directory used to store artifacts for download by CI-system users.""" # This is hardcoded by a lot of clients, so we need to use this. return os.path.join(self.workspace, 'out', 'artifacts') @property def clusterfuzz_build(self): """The directory where builds from ClusterFuzz are stored.""" return os.path.join(self.workspace, 'cifuzz-prev-build') @property def clusterfuzz_coverage(self): """The directory where builds from ClusterFuzz are stored.""" return os.path.join(self.workspace, 'cifuzz-prev-coverage') @property def coverage_report(self): """The directory where coverage reports generated by cifuzz are put.""" return os.path.join(self.workspace, 'cifuzz-coverage') @property def corpora(self): """The directory where corpora from ClusterFuzz are stored.""" return os.path.join(self.workspace, 'cifuzz-corpus') @property def pruned_corpora(self): """The directory where pruned corpora are stored.""" return os.path.join(self.workspace, 'cifuzz-pruned-corpus') @property def sarif(self): """The directory where sarif files are stored.""" return os.path.join(self.workspace, 'cifuzz-sarif') def make_repo_for_sarif(self, repo_manager): """Copies the repo over for the sarif upload GitHub action.""" return shutil.copytree(repo_manager.repo_dir, self.sarif, symlinks=True) ================================================ FILE: infra/common_utils.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Common utilities for OSS-Fuzz infrastructure.""" import logging import os import re import shlex import subprocess import constants OSS_FUZZ_DIR = os.environ.get( 'OSS_FUZZ_DIR', os.path.abspath(os.path.dirname(os.path.dirname(__file__)))) BUILD_DIR = os.path.join(OSS_FUZZ_DIR, 'build') BASE_RUNNER_IMAGE = 'gcr.io/oss-fuzz-base/base-runner' BASE_IMAGES = { 'generic': [ 'gcr.io/oss-fuzz-base/base-image', 'gcr.io/oss-fuzz-base/base-clang', 'gcr.io/oss-fuzz-base/base-builder', BASE_RUNNER_IMAGE, 'gcr.io/oss-fuzz-base/base-runner-debug', ], 'go': ['gcr.io/oss-fuzz-base/base-builder-go'], 'javascript': ['gcr.io/oss-fuzz-base/base-builder-javascript'], 'jvm': ['gcr.io/oss-fuzz-base/base-builder-jvm'], 'python': ['gcr.io/oss-fuzz-base/base-builder-python'], 'rust': ['gcr.io/oss-fuzz-base/base-builder-rust'], 'ruby': ['gcr.io/oss-fuzz-base/base-builder-ruby'], 'swift': ['gcr.io/oss-fuzz-base/base-builder-swift'], } PROJECT_LANGUAGE_REGEX = re.compile(r'\s*language\s*:\s*([^\s]+)') BASE_OS_VERSION_REGEX = re.compile(r'\s*base_os_version\s*:\s*([^\s]+)') logger = logging.getLogger(__name__) def get_project_build_subdir(project, subdir_name): """Creates the |subdir_name| subdirectory of the |project| subdirectory in |BUILD_DIR| and returns its path.""" directory = os.path.join(BUILD_DIR, subdir_name, project) os.makedirs(directory, exist_ok=True) return directory def get_out_dir(project=''): """Creates and returns path to /out directory for the given project (if specified).""" return get_project_build_subdir(project, 'out') class Project: """Class representing a project that is in OSS-Fuzz or an external project (ClusterFuzzLite user).""" def __init__( self, project_name_or_path, is_external=False, build_integration_path=constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH): self.is_external = is_external if self.is_external: self.path = os.path.abspath(project_name_or_path) self.name = os.path.basename(self.path) self.build_integration_path = os.path.join(self.path, build_integration_path) else: self.name = project_name_or_path self.path = os.path.join(OSS_FUZZ_DIR, 'projects', self.name) self.build_integration_path = self.path @property def dockerfile_path(self): """Returns path to the project Dockerfile.""" return os.path.join(self.build_integration_path, 'Dockerfile') @property def language(self): """Returns project language.""" project_yaml_path = os.path.join(self.build_integration_path, 'project.yaml') if not os.path.exists(project_yaml_path): logger.warning('No project.yaml. Assuming c++.') return constants.DEFAULT_LANGUAGE with open(project_yaml_path) as file_handle: content = file_handle.read() for line in content.splitlines(): match = PROJECT_LANGUAGE_REGEX.match(line) if match: return match.group(1) logger.warning('Language not specified in project.yaml. Assuming c++.') return constants.DEFAULT_LANGUAGE @property def base_os_version(self): """Returns the project's base OS version.""" project_yaml_path = os.path.join(self.build_integration_path, 'project.yaml') if not os.path.exists(project_yaml_path): return 'legacy' with open(project_yaml_path) as file_handle: content = file_handle.read() for line in content.splitlines(): match = BASE_OS_VERSION_REGEX.match(line) if match: return match.group(1) return 'legacy' @property def coverage_extra_args(self): """Returns project coverage extra args.""" project_yaml_path = os.path.join(self.build_integration_path, 'project.yaml') if not os.path.exists(project_yaml_path): logger.warning('project.yaml not found: %s.', project_yaml_path) return '' with open(project_yaml_path) as file_handle: content = file_handle.read() coverage_flags = '' read_coverage_extra_args = False # Pass the yaml file and extract the value of the coverage_extra_args key. # This is naive yaml parsing and we do not handle comments at this point. for line in content.splitlines(): if read_coverage_extra_args: # Break reading coverage args if a new yaml key is defined. if len(line) > 0 and line[0] != ' ': break coverage_flags += line if 'coverage_extra_args' in line: read_coverage_extra_args = True # Include the first line only if it's not a multi-line value. if 'coverage_extra_args: >' not in line: coverage_flags += line.replace('coverage_extra_args: ', '') return coverage_flags @property def out(self): """Returns the out dir for the project. Creates it if needed.""" return get_out_dir(self.name) @property def work(self): """Returns the out dir for the project. Creates it if needed.""" return get_project_build_subdir(self.name, 'work') @property def corpus(self): """Returns the out dir for the project. Creates it if needed.""" return get_project_build_subdir(self.name, 'corpus') def is_base_image(image_name): """Checks if the image name is a base image.""" return os.path.exists(os.path.join('infra', 'base-images', image_name)) def check_project_exists(project): """Checks if a project exists.""" if os.path.exists(project.path): return True if project.is_external: descriptive_project_name = project.path else: descriptive_project_name = project.name logger.error('"%s" does not exist.', descriptive_project_name) return False def get_command_string(command): """Returns a shell escaped command string.""" return ' '.join(shlex.quote(part) for part in command) def docker_build(build_args): """Calls `docker build`.""" command = ['docker', 'build'] command.extend(build_args) logger.info('Running: %s.', get_command_string(command)) try: subprocess.check_call(command) except subprocess.CalledProcessError: logger.error('Docker build failed.') return False return True def docker_pull(image): """Call `docker pull`.""" command = ['docker', 'pull', image] logger.info('Running: %s', get_command_string(command)) try: subprocess.check_call(command) except subprocess.CalledProcessError: logger.error('Docker pull failed.') return False return True def pull_images(language=None): """Pulls base images used to build projects in language lang (or all if lang is None).""" for base_image_lang, base_images in BASE_IMAGES.items(): if (language is None or base_image_lang == 'generic' or base_image_lang == language): for base_image in base_images: if not docker_pull(base_image): return False return True def build_image_impl(project, cache=True, pull=False, architecture='x86_64'): """Builds image.""" image_name = project.name if is_base_image(image_name): image_project = 'oss-fuzz-base' docker_build_dir = os.path.join(OSS_FUZZ_DIR, 'infra', 'base-images', image_name) dockerfile_path = os.path.join(docker_build_dir, 'Dockerfile') else: if not check_project_exists(project): return False dockerfile_path = project.dockerfile_path docker_build_dir = project.path image_project = 'oss-fuzz' if pull and not pull_images(project.language): return False build_args = [] image_name = 'gcr.io/%s/%s' % (image_project, image_name) if architecture == 'aarch64': build_args += [ 'buildx', 'build', '--platform', 'linux/arm64', '--progress', 'plain', '--load', ] if not cache: build_args.append('--no-cache') build_args += ['-t', image_name, '--file', dockerfile_path] build_args.append(docker_build_dir) if architecture == 'aarch64': command = ['docker'] + build_args subprocess.check_call(command) return True return docker_build(build_args) ================================================ FILE: infra/constants.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Constants for OSS-Fuzz.""" DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH = '.clusterfuzzlite' DEFAULT_LANGUAGE = 'c++' DEFAULT_SANITIZER = 'address' DEFAULT_ARCHITECTURE = 'x86_64' DEFAULT_ENGINE = 'libfuzzer' LANGUAGES = [ 'c', 'c++', 'go', 'javascript', 'jvm', 'python', 'rust', 'swift', 'ruby', ] LANGUAGES_WITH_COVERAGE_SUPPORT = [ 'c', 'c++', 'go', 'jvm', 'python', 'rust', 'swift', 'javascript', 'ruby' ] SANITIZERS = [ 'address', 'none', 'memory', 'undefined', 'thread', 'coverage', 'introspector', 'hwaddress', ] ARCHITECTURES = ['i386', 'x86_64', 'aarch64'] ENGINES = ['libfuzzer', 'afl', 'honggfuzz', 'centipede', 'none', 'wycheproof'] ================================================ FILE: infra/experimental/SystemSan/Makefile ================================================ .POSIX: CXX = clang++ CFLAGS = -std=c++17 -Wall -Wextra -O3 -g3 -Werror all: SystemSan target target_file target_dns SystemSan: SystemSan.cpp inspect_dns.cpp inspect_utils.cpp $(CXX) $(CFLAGS) -lpthread -o $@ $^ # Needs atheris. python-test: all ./SystemSan python shell_injection_poc_fuzzer.py target: target.cpp $(CXX) $(CFLAGS) -fsanitize=address,fuzzer -o $@ $^ target_file: target_file.cpp $(CXX) $(CFLAGS) -fsanitize=address,fuzzer -o $@ $^ target_dns: target_dns.cpp $(CXX) $(CFLAGS) -fsanitize=address,fuzzer -o $@ $^ test: all vuln.dict ./SystemSan ./target -dict=vuln.dict ./SystemSan ./target_file -dict=vuln.dict ./SystemSan ./target_dns -dict=vuln.dict pytorch-lightning-1.5.10: cp SystemSan.cpp PoEs/pytorch-lightning-1.5.10/; \ cd PoEs/pytorch-lightning-1.5.10/; \ docker build . --tag syssan_pytorch-lightning; \ docker run -t systemsan_pytorch-lightning:latest; node-shell-quote-v1.7.3: cp SystemSan.cpp PoEs/node-shell-quote-v1.7.3/; \ cd PoEs/node-shell-quote-v1.7.3/; \ docker build . --tag systemsan_node-shell-quote; \ docker run -t systemsan_node-shell-quote:latest; clean: rm -f SystemSan /tmp/tripwire target target_file target_dns ================================================ FILE: infra/experimental/SystemSan/PoEs/node-shell-quote-v1.7.3/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Build and run the proof of error in shell-quote v1.7.3. FROM gcr.io/oss-fuzz-base/base-builder RUN apt update && \ apt install -y \ vim \ npm && \ git clone \ --depth 1 \ https://github.com/substack/node-shell-quote.git && \ npm config set @gitlab-org:registry \ https://gitlab.com/api/v4/packages/npm/ COPY ./build.sh $SRC RUN ./build.sh COPY . $SRC RUN make SystemSan CMD ["make", "run"] ================================================ FILE: infra/experimental/SystemSan/PoEs/node-shell-quote-v1.7.3/Makefile ================================================ .POSIX: CXX = clang++ CFLAGS = -std=c++17 -Wall -Wextra -O3 -g3 SystemSan: SystemSan.cpp $(CXX) $(CFLAGS) -lpthread -o $@ $^ run: clean SystemSan target.js ./SystemSan jsfuzz ./target.js clean: rm -f SystemSan /tmp/tripwire ================================================ FILE: infra/experimental/SystemSan/PoEs/node-shell-quote-v1.7.3/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). npm install ./node-shell-quote/ # Build fuzzers. npm i -g @gitlab-org/jsfuzz ================================================ FILE: infra/experimental/SystemSan/PoEs/node-shell-quote-v1.7.3/target.js ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Exploit shell quote with fuzzer's input as a parameter of echo. * This PoC is extended from a report in GitHub Advisory Database: * https://github.com/advisories/GHSA-g4rg-993r-mgx7 * The original report records a shell injection exploit in shell-quote v1.7.2, * we show that a similar shell corruption exploit still persists in v1.7.3, * after a commit that intends to fix the original exploit. * */ /* Fuzz the target program with buf generated by Jsfuzz. */ function fuzz(buf) { buf = String(buf) const childProcess = require('child_process'); const shellQuote = require('shell-quote'); childProcess.execSync(shellQuote.quote(['echo', buf])); } /* Run Jsfuzz. */ module.exports = { fuzz }; ================================================ FILE: infra/experimental/SystemSan/PoEs/pytorch-lightning-1.5.10/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Build and run the proof of error in pytorch-lightning. FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt update && \ apt install -y vim && \ git clone \ --depth 1 \ --branch 1.5.10 \ https://github.com/PyTorchLightning/pytorch-lightning.git COPY ./build.sh $SRC RUN ./build.sh COPY . $SRC RUN make SystemSan CMD ["make", "run"] ================================================ FILE: infra/experimental/SystemSan/PoEs/pytorch-lightning-1.5.10/Makefile ================================================ .POSIX: CXX = clang++ CFLAGS = -std=c++17 -Wall -Wextra -O3 -g3 SystemSan: SystemSan.cpp $(CXX) $(CFLAGS) -lpthread -o $@ $^ run: clean SystemSan fuzz_pytorch_lightning.py ./SystemSan ./fuzz_pytorch_lightning.py -dict=vuln.dict clean: rm -f SystemSan /tmp/tripwire ================================================ FILE: infra/experimental/SystemSan/PoEs/pytorch-lightning-1.5.10/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). cd pytorch-lightning pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: infra/experimental/SystemSan/PoEs/pytorch-lightning-1.5.10/fuzz_pytorch_lightning.py ================================================ #!/usr/local/bin/python3 # # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Exploit pytorch lightning with fuzzer's input as a random env variable. This PoC is extended from a report in GitHub Advisory Database: https://github.com/advisories/GHSA-r5qj-cvf9-p85h The original report documents an exploit using a specific environment variable, we show a way to achieve the same exploit with an arbitrary env variable. """ import os import sys import atheris with atheris.instrument_imports(): from pytorch_lightning import Trainer from pytorch_lightning.utilities.argparse import parse_env_variables def prepare_fuzzing_input(data): """Prepare the data needed by the exploit with input data from fuzzers.""" data = data.replace(b'\0', b'') env_name = 'AN_ARBITRARY_ENV_NAME' return data, env_name def exploit_target(env_value, env_name): """This target is based on a snippet from the official documentation of `parse_env_variables`: https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.utilities.argparse.html # pylint: disable=line-too-long It might not be the most realistic example, but serves as a PoC to show that SystemSan works for Python.""" os.environb[env_name.encode()] = env_value parse_env_variables(Trainer, template=env_name) def TestOneInput(data): # pylint: disable=invalid-name """Exploit the target only with input data from fuzzers.""" env_value, env_name = prepare_fuzzing_input(data) exploit_target(env_value, env_name) def main(): """Fuzz target with atheris.""" atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == '__main__': main() ================================================ FILE: infra/experimental/SystemSan/PoEs/pytorch-lightning-1.5.10/vuln.dict ================================================ "os.system('/tmp/tripwire')" ================================================ FILE: infra/experimental/SystemSan/README.md ================================================ # System Sanitizers We use `ptrace` to instrument system calls made by the target program to detect various vulnerabilities. ## Command injection This detector currently works by - Checking if `execve` is called with `/tmp/tripwire` (which comes from our dictionary). - Checking if `execve` is invoking a shell with invalid syntax. This is likely caused by our input. ## Arbitrary file open TODO: documentation. ## Proof of concept ### Cleanup Note this will delete /tmp/tripwire if it exists. ```shell make clean ``` ### Run test Note this will overwrite /tmp/tripwire if it exists. ```shell make test ``` Look for one of the following lines: > ===BUG DETECTED: Shell injection=== which indicates the detection of executing the planted `/tmp/tripwire`. > ===BUG DETECTED: Shell corruption=== which indicates the detection of executing a syntactic erroneous command. ### Command injection PoC in Python with `pytorch-lightning` With `SystemSan`, [`Artheris`](https://github.com/google/atheris) can detect a shell injection bug in [version v1.5.10 of `pytorch-lightning`](https://github.com/PyTorchLightning/pytorch-lightning/tree/1.5.0). ```shell make pytorch-lightning-1.5.10 ``` ### Command injection PoC in JavaScript with `shell-quote` With `SystemSan`, [`Jsfuzz`](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/jsfuzz) can detect a shell corrpution bug in [the latest version (v1.7.3) of `shell-quote`](https://github.com/substack/node-shell-quote) without any seed. ```shell make node-shell-quote-v1.7.3 ``` This is based on [a shell injection exploit report](https://wh0.github.io/2021/10/28/shell-quote-rce-exploiting.html) of [version v1.7.2 of `shell-quote`](https://github.com/substack/node-shell-quote/tree/v1.7.2). `SystemSan` can also discover the same shell injection bug with a corpus file containing: ``` `:`/tmp/tripwire``:` ``` ## Trophies - - ================================================ FILE: infra/experimental/SystemSan/SystemSan.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A detector that uses ptrace to identify shell injection vulnerabilities. */ /* C standard library */ #include #include #include #include /* POSIX */ #include #include #include #include /* Linux */ #include #include #include #include #include #include #include #include #include #include #include "inspect_utils.h" #include "inspect_dns.h" #define DEBUG_LOGS 0 #if DEBUG_LOGS #define debug_log(...) \ do { \ fprintf(stderr, __VA_ARGS__); \ fflush(stdout); \ fputc('\n', stderr); \ } while (0) #else #define debug_log(...) #endif #define fatal_log(...) \ do { \ fprintf(stderr, __VA_ARGS__); \ fputc('\n', stderr); \ exit(EXIT_FAILURE); \ } while (0) // The magic string that we'll use to detect full control over the command // executed. const std::string kTripWire = "/tmp/tripwire"; // Shell injection bug confirmed with /tmp/tripwire. const std::string kInjectionError = "Shell injection"; // Shell corruption bug detected based on syntax error. const std::string kCorruptionError = "Shell corruption"; // The magic string that we'll use to detect arbitrary file open const std::string kFzAbsoluteDirectory = "/fz/"; // Arbitrary file open in /fz/ const std::string kArbitraryFileOpenError = "Arbitrary file open"; // Assuming only shorter (than this constant) top dir are legitly used. constexpr int kRootDirMaxLength = 16; // The PID of the root process we're fuzzing. pid_t g_root_pid; // Map of a PID/TID its PID/TID creator and wether it ran exec. std::map root_pids; // Assuming the longest pathname is "/bin/bash". constexpr int kShellPathnameLength = 20; // Syntax error messages of each shell. const std::map> kShellSyntaxErrors = { {"bash", { ": command not found", // General ": syntax error", // Unfinished " or ' or ` or if, leading | or ; ": missing `]'", // Unfinished [ ": event not found", // ! leads large numbers ": No such file or directory", // Leading < or / }}, {"csh", { ": Command not found.", // General ": Missing }.", // Unfinished { "Too many ('s.", // Unfinished ( "Invalid null command.", // Leading | or < or > "Missing name for redirect.", // Single < or > ": No match.", // Leading ? or [ or * "Modifier failed.", // Leading ^ "No previous left hand side.", // A ^ ": No such job.", // Leading % ": No current job.", // A % ": Undefined variable.", // Containing $ ": Event not found.", // ! leads large numbers // TODO: Make this more specific. "Unmatched", // Unfinished " or ' or `, leading ; }}, {"dash", { "not found", // General "Syntax error", // Unfinished " or ' or ` or if, leading | or ; or & "missing ]", // Unfinished [ "No such file", // Leading < }}, {"zsh", { ": command not found", // General ": syntax error", // Unfinished " or ' or ` ": ']' expected", // Unfinished [ ": no such file or directory", // Leading < or / ": parse error near", // Leading |, or & ": no such user or named directory", // Leading ~ }}, }; // Shells used by Processes. std::map g_shell_pids; struct Tracee { pid_t pid; bool syscall_enter = true; Tracee(pid_t pid) : pid(pid) {} }; pid_t run_child(char **argv) { // Run the program under test with its args as a child process pid_t pid = fork(); switch (pid) { case -1: fatal_log("Fork failed: %s", strerror(errno)); case 0: raise(SIGSTOP); execvp(argv[0], argv); fatal_log("execvp: %s", strerror(errno)); } return pid; } // Construct a string with the memory specified in a register. std::string read_string(pid_t pid, unsigned long reg, unsigned long length) { auto memory = read_memory(pid, reg, length); if (!memory.size()) { return ""; } std::string content(reinterpret_cast(memory.data()), std::min(memory.size(), length)); return content; } void inspect_for_injection(pid_t pid, const user_regs_struct ®s) { // Inspect a PID's registers for the sign of shell injection. std::string path = read_string(pid, regs.rdi, kTripWire.length()); if (!path.length()) { return; } debug_log("inspecting"); if (path == kTripWire) { report_bug(kInjectionError, pid); } } std::string get_pathname(pid_t pid, const user_regs_struct ®s) { // Parse the pathname from the memory specified in the RDI register. std::string pathname = read_string(pid, regs.rdi, kShellPathnameLength); debug_log("Pathname is %s (len %lu)\n", pathname.c_str(), pathname.length()); return pathname; } std::string match_shell(std::string binary_pathname); // Identify the exact shell behind sh std::string identify_sh(std::string path) { char shell_pathname[kShellPathnameLength]; auto written = readlink(path.c_str(), shell_pathname, kShellPathnameLength - 1); if (written == -1) { std::cerr << "Cannot query which shell is behind sh: readlink failed on " << path << ": " << strerror(errno) << "\n"; std::cerr << "Assuming the shell is dash\n"; return "dash"; } shell_pathname[written] = '\0'; debug_log("sh links to %s\n", shell_pathname); std::string shell_pathname_str(shell_pathname); return match_shell(shell_pathname_str); } std::string match_shell(std::string binary_pathname) { // Identify the name of the shell used in the pathname. if (!binary_pathname.length()) { return ""; } // We use c_str() to accept only the null terminated string. std::string binary_name = binary_pathname.substr( binary_pathname.find_last_of("/") + 1).c_str(); debug_log("Binary is %s (%lu)\n", binary_name.c_str(), binary_name.length()); for (const auto &item : kShellSyntaxErrors) { std::string known_shell = item.first; if (binary_name == "sh") { debug_log("Matched sh: Needs to identify which specific shell it is.\n"); return identify_sh(binary_pathname); } if (binary_name == known_shell) { debug_log("Matched %s\n", binary_name.c_str()); return known_shell; } } return ""; } std::string get_shell(pid_t pid, const user_regs_struct ®s) { // Get shell name used in a process. std::string binary_pathname = get_pathname(pid, regs); return match_shell(binary_pathname); } void match_error_pattern(std::string buffer, std::string shell, pid_t pid) { auto error_patterns = kShellSyntaxErrors.at(shell); for (const auto &pattern : error_patterns) { if (buffer.find(pattern) != std::string::npos) { std::cerr << "--- Found a sign of shell corruption ---\n" << buffer.c_str() << "\n----------------------------------------\n"; // If a shell corruption error happens, kill its parent. auto parent = root_pids[pid]; while (!parent.ran_exec) { if (parent.parent_tid == g_root_pid) { break; } parent = root_pids[parent.parent_tid]; } report_bug(kCorruptionError, parent.parent_tid); } } } void inspect_for_corruption(pid_t pid, const user_regs_struct ®s) { // Inspect a PID's registers for shell corruption. std::string buffer = read_string(pid, regs.rsi, regs.rdx); debug_log("Write buffer: %s\n", buffer.c_str()); match_error_pattern(buffer, g_shell_pids[pid], pid); } void log_file_open(std::string path, int flags, pid_t pid) { report_bug(kArbitraryFileOpenError, pid); std::cerr << "===File opened: " << path.c_str() << ", flags = " << flags << ","; switch (flags & 3) { case O_RDONLY: std::cerr << "O_RDONLY"; break; case O_WRONLY: std::cerr << "O_WRONLY"; break; case O_RDWR: std::cerr << "O_RDWR"; break; default: std::cerr << "unknown"; } std::cerr << "===\n"; } bool has_unprintable(const std::string &value) { for (size_t i = 0; i < value.length(); i++) { if (value[i] & 0x80) { return true; } } return false; } void inspect_for_arbitrary_file_open(pid_t pid, const user_regs_struct ®s) { // Inspect a PID's register for the sign of arbitrary file open. std::string path = read_string(pid, regs.rsi, kRootDirMaxLength); if (!path.length()) { return; } if (path.substr(0, kFzAbsoluteDirectory.length()) == kFzAbsoluteDirectory) { log_file_open(path, regs.rdx, pid); return; } if (path[0] == '/' && path.length() > 1) { std::string path_absolute_topdir = path; size_t root_dir_end = path.find('/', 1); if (root_dir_end != std::string::npos) { path_absolute_topdir = path.substr(0, root_dir_end); } if (has_unprintable(path_absolute_topdir)) { struct stat dirstat; if (stat(path_absolute_topdir.c_str(), &dirstat) != 0) { log_file_open(path, regs.rdx, pid); } } } } int trace(std::map pids) { unsigned long exit_status = 0; while (!pids.empty()) { std::vector new_pids; auto it = pids.begin(); while (it != pids.end()) { auto pid = it->first; auto &tracee = it->second; int status = 0; int result = waitpid(pid, &status, __WALL | WNOHANG); if (result == -1) { it = pids.erase(it); continue; } if (result == 0) { // Nothing to report yet. ++it; continue; } if (WIFEXITED(status) || WIFSIGNALED(status)) { debug_log("%d exited", pid); it = pids.erase(it); // Remove pid from the watchlist when it exits g_shell_pids.erase(pid); root_pids.erase(pid); continue; } // ptrace sets 0x80 for syscalls (with PTRACE_O_TRACESYSGOOD set). bool is_syscall = WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80); int sig = 0; if (!is_syscall) { // Handle generic signal. siginfo_t siginfo; if (ptrace(PTRACE_GETSIGINFO, pid, nullptr, &siginfo) == -1) { debug_log("ptrace(PTRACE_GETSIGINFO, %d): %s", pid, strerror(errno)); continue; } sig = siginfo.si_signo; debug_log("forwarding signal %d to %d", sig, pid); } if ((status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXIT << 8)))) { debug_log("%d exiting", pid); if (pid == g_root_pid) { if (ptrace(PTRACE_GETEVENTMSG, pid, 0, &exit_status) == -1) { debug_log("ptrace(PTRACE_GETEVENTMSG, %d): %s", pid, strerror(errno)); } debug_log("got exit status from root process: %lu", exit_status); } if (ptrace(PTRACE_DETACH, pid, 0, 0) == -1) { debug_log("ptrace(PTRACE_DETACH, %d): %s", pid, strerror(errno)); } continue; } if (WIFSTOPPED(status) && (status >> 8 == (SIGTRAP | (PTRACE_EVENT_CLONE << 8)) || status >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8)) || status >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)))) { long new_pid; if (ptrace(PTRACE_GETEVENTMSG, pid, 0, &new_pid) == -1) { debug_log("ptrace(PTRACE_GETEVENTMSG, %d): %s", pid, strerror(errno)); continue; } debug_log("forked %ld", new_pid); new_pids.push_back(new_pid); root_pids.emplace(new_pid, ThreadParent(pid)); } if (is_syscall) { user_regs_struct regs; if (ptrace(PTRACE_GETREGS, pid, 0, ®s) == -1) { debug_log("ptrace(PTRACE_GETREGS, %d): %s", pid, strerror(errno)); continue; } if (tracee.syscall_enter) { if (regs.orig_rax == __NR_execve) { // This is a new process. auto parent = root_pids[pid]; parent.ran_exec = true; root_pids[pid] = parent; inspect_for_injection(pid, regs); std::string shell = get_shell(pid, regs); if (shell != "") { debug_log("Shell parsed: %s", shell.c_str()); g_shell_pids.insert(std::make_pair(pid, shell)); } } inspect_dns_syscalls(pid, regs); if (regs.orig_rax == __NR_openat) { // TODO(metzman): Re-enable this once we have config/flag support. // inspect_for_arbitrary_file_open(pid, regs); } if (regs.orig_rax == __NR_write && g_shell_pids.find(pid) != g_shell_pids.end()) { debug_log("Inspecting the `write` buffer of shell process %d.", pid); inspect_for_corruption(pid, regs); } } // TODO: Check for commands with invalid syntax passed to /bin/sh and // other shells. // TODO: It's possible the process we're fuzzing can communicate with // another process to execute code. Our check wouldn't catch this // currently. tracee.syscall_enter = !tracee.syscall_enter; } if (ptrace(PTRACE_SYSCALL, pid, nullptr, sig) == -1) { debug_log("ptrace(PTRACE_SYSCALL, %d): %s", pid, strerror(errno)); continue; } ++it; } for (const auto &pid : new_pids) { pids.emplace(pid, Tracee(pid)); } } return static_cast(exit_status >> 8); } int main(int argc, char **argv) { if (argc <= 1) { fatal_log("Expecting at least one arguments, received %d", argc - 1); } // Create an executable tripwire file, as programs may check for existence // before actually calling exec. std::ofstream tripwire(kTripWire); tripwire.close(); chmod(kTripWire.c_str(), 0755); pid_t pid = run_child(argv + 1); long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXIT; if (ptrace(PTRACE_SEIZE, pid, nullptr, options) == -1) { fatal_log("ptrace(PTRACE_SEIZE): %s", strerror(errno)); } if (waitpid(pid, nullptr, __WALL) == -1) { fatal_log("waitpid: %s", strerror(errno)); } if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1) { fatal_log("ptrace(PTRACE_SYSCALL): %s", strerror(errno)); } g_root_pid = pid; std::map pids; pids.emplace(pid, Tracee(pid)); root_pids.emplace(pid, ThreadParent(pid)); return trace(pids); } ================================================ FILE: infra/experimental/SystemSan/inspect_dns.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A detector that uses ptrace to identify shell injection vulnerabilities. */ /* POSIX */ #include #include /* Linux */ #include #include #include #include #include "inspect_utils.h" // Arbitrary domain name resolution. const std::string kArbitraryDomainNameResolution = "Arbitrary domain name resolution"; // Global constant for one file descriptor about of a DNS socket int kFdDns = 0; const size_t kDnsHeaderLen = 12; void inspect_for_arbitrary_dns_connect(pid_t pid, const user_regs_struct ®s) { auto memory = read_memory(pid, regs.rsi, sizeof(struct sockaddr_in)); if (memory.size()) { struct sockaddr_in * sa = reinterpret_cast(memory.data()); if (sa->sin_family == AF_INET && htons(sa->sin_port) == 53) { // save file descriptor for later sendmmsg kFdDns = regs.rdi; } } } struct DnsHeader { uint16_t tx_id; uint16_t flags; uint16_t questions; uint16_t answers; uint16_t nameservers; uint16_t additional; }; struct DnsHeader parse_dns_header(std::vector data) { struct DnsHeader h; h.tx_id = (((uint16_t) data[0]) << 8) | ((uint16_t) data[1]); h.flags = (((uint16_t) data[2]) << 8) | ((uint16_t) data[3]); h.questions = (((uint16_t) data[4]) << 8) | ((uint16_t) data[5]); h.answers = (((uint16_t) data[6]) << 8) | ((uint16_t) data[7]); h.nameservers = (((uint16_t) data[8]) << 8) | ((uint16_t) data[9]); h.additional = (((uint16_t) data[10]) << 8) | ((uint16_t) data[11]); return h; } bool dns_flags_standard_query(uint16_t flags) { if ((flags & 0x8000) == 0) { // Query, not response. if (((flags & 0x7800) >> 11) == 0) { // Opcode 0 is standard query. if ((flags & 0x0200) == 0) { // Message is not truncated. if ((flags & 0x0040) == 0) { // Z-bit reserved flag is unset. return true; } } } } return false; } struct DnsRequest { // Start of name in the byte vector. size_t offset; // End of name in the byte vector. size_t end; // Length of top level domain. uint8_t tld_size; // Number of levels/dots in domain name. size_t nb_levels; // DNS type like A is 1. uint16_t dns_type; // DNS class like IN is 1. uint16_t dns_class; }; struct DnsRequest parse_dns_request(std::vector data, size_t offset) { struct DnsRequest r; r.offset = offset; r.tld_size = 0; r.nb_levels = 0; while(offset < data.size()) { uint8_t rlen = uint8_t(data[offset]); if (rlen == 0) { offset++; break; } r.nb_levels++; offset += rlen+1; r.tld_size = rlen; } if (offset <= 4 + data.size()) { r.end = offset; r.dns_type = (((uint16_t) data[offset]) << 8) | ((uint16_t) data[offset+1]); r.dns_class = (((uint16_t) data[offset+2]) << 8) | ((uint16_t) data[offset+3]); } else { r.end = data.size(); } return r; } void log_dns_request(struct DnsRequest r, std::vector data) { size_t offset = r.offset; std::cerr << "===Domain resolved: "; while(offset < r.end) { uint8_t rlen = uint8_t(data[offset]); if (rlen == 0) { break; } std::cerr << '.'; for (uint8_t i = 1; i < rlen+1; i++) { std::cerr << (char) data[offset + i]; } offset += rlen+1; } std::cerr << "===\n"; std::cerr << "===DNS request type: " << r.dns_type << ", class: " << r.dns_class << "===\n"; } void inspect_for_arbitrary_dns_pkt(std::vector data, pid_t pid) { if (data.size() < kDnsHeaderLen + 1) { return; } struct DnsHeader h = parse_dns_header(data); if (h.questions != 1) { return; } if (h.answers != 0 || h.nameservers != 0) { return; } if (!dns_flags_standard_query(h.flags)) { return; } struct DnsRequest req = parse_dns_request(data, kDnsHeaderLen); // Alert if the top level domain is only one character and // if there is more than just the TLD. if (req.tld_size == 1 && req.nb_levels > 1 && req.end < data.size()) { report_bug(kArbitraryDomainNameResolution, pid); log_dns_request(req, data); } } void inspect_for_arbitrary_dns_fdbuffer(pid_t pid, const user_regs_struct ®s) { if (kFdDns > 0 && kFdDns == (int) regs.rdi) { auto memory = read_memory(pid, regs.rsi, regs.rdx); if (memory.size()) { inspect_for_arbitrary_dns_pkt(memory, pid); } } } void inspect_for_arbitrary_dns_iov(pid_t pid, unsigned long iov) { auto memory = read_memory(pid, iov, sizeof(struct iovec)); if (memory.size()) { struct iovec * iovec = reinterpret_cast(memory.data()); memory = read_memory(pid, (unsigned long) iovec->iov_base, iovec->iov_len); if (memory.size()) { inspect_for_arbitrary_dns_pkt(memory, pid); } } } void inspect_for_arbitrary_dns_sendmsg(pid_t pid, const user_regs_struct ®s) { if (kFdDns > 0 && kFdDns == (int) regs.rdi) { auto memory = read_memory(pid, regs.rsi, sizeof(struct msghdr)); if (memory.size()) { struct msghdr * msg = reinterpret_cast(memory.data()); if (msg->msg_iovlen == 1) { inspect_for_arbitrary_dns_iov(pid, (unsigned long) msg->msg_iov); } } } } void inspect_for_arbitrary_dns_sendmmsg(pid_t pid, const user_regs_struct ®s) { if (kFdDns > 0 && kFdDns == (int) regs.rdi) { auto memory = read_memory(pid, regs.rsi, sizeof(struct mmsghdr)); if (memory.size()) { struct mmsghdr * msg = reinterpret_cast(memory.data()); if (msg->msg_hdr.msg_iovlen == 1) { inspect_for_arbitrary_dns_iov(pid, (unsigned long) msg->msg_hdr.msg_iov); } } } } void inspect_dns_syscalls(pid_t pid, const user_regs_struct ®s) { switch (regs.orig_rax) { case __NR_connect: inspect_for_arbitrary_dns_connect(pid, regs); break; case __NR_close: if (kFdDns > 0 && kFdDns == (int) regs.rdi) { // reset DNS file descriptor on close kFdDns = 0; } break; case __NR_sendmmsg: inspect_for_arbitrary_dns_sendmmsg(pid, regs); break; case __NR_sendmsg: inspect_for_arbitrary_dns_sendmsg(pid, regs); break; case __NR_sendto: // fallthrough case __NR_write: inspect_for_arbitrary_dns_fdbuffer(pid, regs); } } ================================================ FILE: infra/experimental/SystemSan/inspect_dns.h ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A detector that uses ptrace to identify DNS arbitrary resolutions. */ /* POSIX */ #include /* Linux */ #include void inspect_dns_syscalls(pid_t pid, const user_regs_struct ®s); ================================================ FILE: infra/experimental/SystemSan/inspect_utils.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A detector that uses ptrace to identify DNS arbitrary resolutions. */ /* C standard library */ #include /* POSIX */ #include /* Linux */ #include #include #include #include #include #include "inspect_utils.h" extern pid_t g_root_pid; extern std::map root_pids; std::vector read_memory(pid_t pid, unsigned long long address, size_t size) { std::vector memory; for (size_t i = 0; i < size; i += sizeof(long)) { long word = ptrace(PTRACE_PEEKTEXT, pid, address + i, 0); if (word == -1) { return memory; } std::byte *word_bytes = reinterpret_cast(&word); memory.insert(memory.end(), word_bytes, word_bytes + sizeof(long)); } return memory; } void report_bug(std::string bug_type, pid_t tid) { // Report the bug found based on the bug code. std::cerr << "===BUG DETECTED: " << bug_type.c_str() << "===\n"; // Rely on sanitizers/libFuzzer to produce a stacktrace by sending SIGABRT // to the root process. // Note: this may not be reliable or consistent if shell injection happens // in an async way. // Find the thread group id, that is the pid. pid_t pid = tid; auto parent = root_pids[tid]; while (!parent.ran_exec) { // Find the first parent which ran exec syscall. if (parent.parent_tid == g_root_pid) { break; } pid = parent.parent_tid; parent = root_pids[parent.parent_tid]; } tgkill(pid, tid, SIGABRT); } ================================================ FILE: infra/experimental/SystemSan/inspect_utils.h ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A detector that uses ptrace to identify DNS arbitrary resolutions. */ /* POSIX */ #include #include #include // Structure to know which thread id triggered the bug. struct ThreadParent { // Parent thread ID, ie creator. pid_t parent_tid; // Current thread ID ran exec to become another process. bool ran_exec = false; ThreadParent() : parent_tid(0) {} ThreadParent(pid_t tid) : parent_tid(tid) {} }; std::vector read_memory(pid_t pid, unsigned long long address, size_t size); void report_bug(std::string bug_type, pid_t tid); ================================================ FILE: infra/experimental/SystemSan/target.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A sample target program under test, * /tmp/tripwire or other commands will be injected into its shell command */ #include #include #include extern "C" int LLVMFuzzerTestOneInput(char* data, size_t size) { std::string str(data, size); std::cout << "INPUT" << str << std::endl; system(str.c_str()); return 0; } ================================================ FILE: infra/experimental/SystemSan/target_dns.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(char* data, size_t size) { std::string str(data, size); std::cout << "INPUT" << str << std::endl; struct addrinfo *result = NULL; getaddrinfo(str.c_str(), NULL, NULL, &result); if (result) { freeaddrinfo(result); } return 0; } ================================================ FILE: infra/experimental/SystemSan/target_file.cpp ================================================ /* * Copyright 2022 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* A sample target program under test, * /tmp/tripwire or other commands will be injected into its shell command */ #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(char* data, size_t size) { std::string str(data, size); std::cout << "INPUT" << str << std::endl; FILE *fp = fopen(str.c_str(), "r"); if (fp) { fclose(fp); } return 0; } ================================================ FILE: infra/experimental/SystemSan/vuln.dict ================================================ "/tmp/tripwire" "/fz/" "f.z" ================================================ FILE: infra/experimental/chronos/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/cloud-builders/gcloud RUN apt-get update && apt-get install -y jq ================================================ FILE: infra/experimental/chronos/README.md ================================================ # Chronos: rebuilding OSS-Fuzz harnesses using cached builds Chronos is a utility tooling to enable fast re-building of OSS-Fuzz projects and analysis of projects' testing infrastructure. This is used by projects, e.g. [OSS-Fuzz-gen](https://github.com/google/oss-fuzz-gen) to help speed up valuation processes during fuzzing harness generation. At the core, Chronos relies on caching containers after project build, in order to enable fast rebuilding of a project following minor patches, and also enable running of the tests in a given project. To support this, Chronos creates a snapshot of a the docker container given project post build completion. This means that all `.o` files, generated configuations etc. persist in the docker container. These artifacts are then leverage for future "replay builds" where only a minor part of the project has changed, e.g. due to some patching on the project. This patching could be e.g. minor adjustments to the fuzzing harness source code e.g. by [oss-fuzz-gen](https://github.com/google/oss-fuzz-gen). As such, at the core of Chronos are cached containers that are generated by taking a snapshot of the container of a project post project build. Chronos is focused on two features, rebuilding projects fast and running the tests of a given project. ## Chronos features: fast rebuilding and running the tests of a project ### CLI interface for Chronos The default route to validating Chronos is using the CLI available in `infra/experimental/chronos/manager.py` ### Chronos feature: Fast rebuilding Chronos enables rebuilding projects efficiently in contexts where only a small patch needs to be evalualted in the target. This is achieved by running a replay build script in the build container, similarly to how a regular `build_fuzzers` command would run, but with the caveat that the replay build script only performs a subset of the operations of the original `build.sh`. The replay build scripts are constructed in two ways: manually or automatically. #### Option 1: Automated rebuilds Chronos support automated rebuilding. This is meant as a generic mechanism to enable Chronos support for projects by default. This is achieved by: 1. Calling into a `replay_build.sh` script during the building inside the container [here](https://github.com/google/oss-fuzz/blob/206656447b213fb04901d15122692d8dd4d45312/infra/base-images/base-builder/compile#L292-L296) 2. The `replay_build.sh` calls into `make_build_replayable.py`: [here](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/replay_build.sh) 3. `make_build_replayable.py` adjusts the build environment to wrap around common commands, to avoid performing a complete run of `build.sh`: [here](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/make_build_replayable.py). The automated rebuilding works in combination with [Ccache](https://ccache.dev/), in order to facilitate cachine of e.g. `.o` files. This means that during rebuild mode as long as we have a cacche, we don't need to e.g. run `configure` again and will only have to rebuild the changed source code. #### Option 2: Manually provided replay builds `replay_build.sh` above, is simply just a wrapper script around `build.sh` that aims to enable fast rebuilding of the project. This `replay_build.sh` can, however, be overwritten in the Dockerfile of the project's builder image to support a custom approach to fast rebuilding. Two examples of this is [php](https://github.com/google/oss-fuzz/blob/206656447b213fb04901d15122692d8dd4d45312/projects/php/replay_build.sh#L1) and [ffmpeg](https://github.com/google/oss-fuzz/blob/master/projects/ffmpeg/replay_build.sh#L1). Providing a manual `replay_build.sh` is likely more efficient at build time and can help speed up the process. Automated replay build scripts can also be erroneous. #### Testing the validity of a replay build The Chronos manager can use the `manager.py` to validate the validity of a replay build for a given project: ```sh python3 infra/experimental/chronos/manager.py check-replay tinyobjloader ``` If the above command fails for the relevant project, then the replay build feature does not work for the given project. ### Chronos feature: Running tests of a project The second part of Chronos is a feature to enable running the tests of a given project. This is done by way of a script `run_tests.sh`. Samples of this script include [jsonnet](https://github.com/google/oss-fuzz/blob/master/projects/jsonnet/run_tests.sh#L1) and [tinyobjloader](https://github.com/google/oss-fuzz/blob/master/projects/tinyobjloader/run_tests.sh#L1). #### Run tests constraints 1. The `run_tests.sh` main task is to run the tests of a project and return `0` upon success and non-null otherwise. 2. The `run_tests.sh` script must leave the main repository in the state as it was prior to the execution of `run_tests.sh` relative to `git diff` (or similar diff features of other version control systems). #### Testing the validity of run_tests.sh The Chronos manager can use the `manager.py` to validate the validity of a `run_tests.sh` script: ```sh python3 infra/experimental/chronos/manager.py check-tests json-c ``` ### Constraints imposed on replay_build.sh and run_tests.sh At the core of chronos are the two scripts `replay_build.sh` and `run_tests.sh`. We have a default mechanism for `replay_build.sh` so it's not strictly necessary to have a custom one, although it will likely improve speed and maybe correctness by providing one. There are three stages of the Chronos workflow: 1. The cached containers represent the state of a build container after a successful project build. 2. The `replay_build.sh` is able to rebuild a given project from the state of a cached container. 3. The `run_tests.sh` script is able to run the tests of a given project. This should be able to succeed following the running of a `replay_build.sh`. The stages (2) and (3) must both support running without network connectivity. Specifically, this means that the `replay_build.sh` must not do tasks e.g. fetch dependencies, download corpus, or anything of this nature. Similarly, the `run_tests.sh` must be able to operate completely in a closed network environment. ## Pre-built images. Chronos cached images are build daily, and pre-built images are available at: - `us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/-ofg-cached-address` - `us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/-ofg-cached-coverage` They can be used as drop-in replacements for the usual `gcr.io/oss-fuzz/` images. ================================================ FILE: infra/experimental/chronos/build_all.sh ================================================ #!/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build all C/C++ projects. c_project_yaml=$(find projects/ -name project.yaml -exec grep -l 'language: c' {} \;) projs=$(echo $c_project_yaml | xargs dirname | xargs basename -a | sort) cd infra/experimental/chronos for proj in $projs; do if [ ! -f ../../../projects/$proj/Dockerfile ]; then # Incomplete integration. echo "Skipping $proj as it's incomplete." continue fi echo ./build_on_cloudbuild.sh $proj c ./build_on_cloudbuild.sh $proj c done ================================================ FILE: infra/experimental/chronos/build_cache_local.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ _PROJECT=$1 _FUZZING_LANGUAGE=$2 _SANITIZER=${3:-address} BASE=$PWD # Final image is either ccache or replay script, depending on which worked. FINAL_IMAGE_NAME=us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-${_SANITIZER} # Always build an image with ccache. CCACHE_IMAGE_NAME=us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-ccache-${_SANITIZER} # Step 1: build the base image cd projects/${_PROJECT} docker build -t gcr.io/oss-fuzz/${_PROJECT} . # Step 2: create a container where `compile` has run which enables ccaching # and also generates a replay build script. cd ${BASE} mkdir -p ccaches/${_PROJECT} mkdir -p build/out/${_PROJECT} B_START=$SECONDS docker container rm -f ${_PROJECT}-origin-${_SANITIZER} docker run \ --env=SANITIZER=${_SANITIZER} \ --env=CCACHE_DIR=/workspace/ccache \ --env=FUZZING_LANGUAGE=${_FUZZING_LANGUAGE} \ --env=CAPTURE_REPLAY_SCRIPT=1 \ --name=${_PROJECT}-origin-${_SANITIZER} \ -v=$PWD/ccaches/${_PROJECT}/ccache:/workspace/ccache \ -v=$PWD/build/out/${_PROJECT}/:/out/ \ gcr.io/oss-fuzz/${_PROJECT} \ /bin/bash -c \ "export PATH=/ccache/bin:\$PATH && compile && cp -n /usr/local/bin/replay_build.sh \$SRC/" B_TIME=$(($SECONDS - $B_START)) # Step 3: save (commit, locally) the cached container as an image docker container commit -c "ENV REPLAY_ENABLED=1" -c "ENV CAPTURE_REPLAY_SCRIPT=" ${_PROJECT}-origin-${_SANITIZER} $FINAL_IMAGE_NAME # If the project has declared its own replay_build.sh, assume that's the # approach to use and we're done. if [ -f projects/${_PROJECT}/replay_build.sh ]; then echo "Has project-specfied replay build script." exit 0 fi # Step 4: save the list of executables created from a vanilla build. This is # needed for validating if replay and ccaching works. # notes: run a shell the container with e.g. # `docker run --entrypoint /bin/bash -it local/ossfuzz/htslib-origin-address` executables_vanilla="$(find ./build/out/${_PROJECT} -executable -type f | sort)" # Step 5: Build with replay enabled, and validate the executables are the same # in terms of naming. # Note that an important step is removing everything in $OUT/ which is done # in the docker command. R_START=$SECONDS docker run \ --rm \ --env=SANITIZER=${_SANITIZER} \ --env=FUZZING_LANGUAGE=${_FUZZING_LANGUAGE} \ -v=$PWD/build/out/${_PROJECT}/:/out/ \ --name=${_PROJECT}-origin-${_SANITIZER}-replay-recached \ $FINAL_IMAGE_NAME \ /bin/bash -c \ "export PATH=/ccache/bin:\$PATH && rm -rf /out/* && compile" R_TIME=$(($SECONDS - $R_START)) # Step 6: Extract the newly build executables executables_replay="$(find ./build/out/${_PROJECT}/ -executable -type f | sort)" echo "Executables vanilla: " echo ${executables_vanilla} echo "------------------------------------------------------" echo "Executables replay: " echo ${executables_replay} REPLAY_WORKED= # Step 7: match executables from vanilla builds and replay builds. # If this step is successful, then the process can exit as it's ready. if [[ "$executables_replay" == "$executables_vanilla" ]] then REPLAY_WORKED=1 if [ -z "${RUN_ALL+1}" ]; then echo "${_PROJECT}: Replay worked." echo "${_PROJECT}: Compile times: Vanilla=${B_TIME}; Replay=${R_TIME};" exit 0 fi else echo "${_PROJECT}: Replay did not work" R_TIME="N/A" fi # Step 8: prepare Dockerfile for ccache cp -rf ccaches/${_PROJECT}/ccache ./projects/${_PROJECT}/ccache-cache infra/experimental/chronos/prepare-ccache ${_PROJECT} cd projects/${_PROJECT} # Step 9: Build an image with CCache's new items (modifications are done on the # dockerfile) docker build -t $CCACHE_IMAGE_NAME . cd ${BASE} # Step 10: Run a `compile` with ccache's image. # Run the ccache build A_START=$SECONDS docker run \ --rm \ --env=SANITIZER=${_SANITIZER} \ --env=FUZZING_LANGUAGE=${_FUZZING_LANGUAGE} \ --name=${_PROJECT}-origin-${_SANITIZER}-recached \ -v=$PWD/build/out/${_PROJECT}/:/out/ \ $CCACHE_IMAGE_NAME \ /bin/bash -c \ "export PATH=/ccache/bin:\$PATH && rm -rf /out/* && compile" A_TIME=$(($SECONDS - $A_START)) # Step 11: extract the executables from the ccache build executables_ccache="$(find ./build/out/${_PROJECT}/ -executable -type f | sort)" # Step 12: validate the ccache builds are successful if [[ "$executables_ccache" == "$executables_vanilla" ]] then echo "${_PROJECT}: Compile times: Vanilla=${B_TIME}; Replay=${R_TIME}; CCache=${A_TIME};" if [[ -z "${REPLAY_WORKED}" || ${R_TIME} -gt ${A_TIME} ]]; then if [ ${R_TIME} -gt ${A_TIME} ]; then echo "Replay was slower than ccache." fi # Replay didn't work or was slower, so make the default "cached" image use the ccache one. docker image tag \ $CCACHE_IMAGE_NAME \ $FINAL_IMAGE_NAME fi exit 0 else echo "${_PROJECT}: Replay and ccaching did not work." exit 1 fi ================================================ FILE: infra/experimental/chronos/build_on_cloudbuild.sh ================================================ #!/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=$1 FUZZING_LANGUAGE=$2 gcloud builds submit "https://github.com/google/oss-fuzz" \ --async \ --git-source-revision=master \ --config=cloudbuild.yaml \ --substitutions=_PROJECT=$PROJECT,_FUZZING_LANGUAGE=$FUZZING_LANGUAGE \ --project=oss-fuzz \ --region=us-central1 ================================================ FILE: infra/experimental/chronos/check_tests.sh ================================================ #!/bin/bash # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Module for validating "run_tests.sh" of a given project. Before the run_tests.sh # script is run, a cached container image is first built. We assume here that the # replay is working for the target project. # (TODO): make sure this works for both replay_build.sh and ccached rebuilds. # currently the focus is on replay_build.sh. _PROJECT=$1 _FUZZING_LANGUAGE=$2 _SANITIZER=${3:-address} BASE=$PWD # Final image is either ccache or replay script, depending on which worked. FINAL_IMAGE_NAME=us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-${_SANITIZER} # Step 1: build the base image cd projects/${_PROJECT} docker build -t gcr.io/oss-fuzz/${_PROJECT} . # Step 2: create a container where `compile` has run which enables ccaching # and also generates a replay build script. cd ${BASE} mkdir -p ccaches/${_PROJECT} mkdir -p build/out/${_PROJECT} # Clean up existing images. docker container rm -f ${_PROJECT}-origin-${_SANITIZER} docker run \ --env=SANITIZER=${_SANITIZER} \ --env=CCACHE_DIR=/workspace/ccache \ --env=FUZZING_LANGUAGE=${_FUZZING_LANGUAGE} \ --env=CAPTURE_REPLAY_SCRIPT=1 \ --name=${_PROJECT}-origin-${_SANITIZER} \ -v=$PWD/ccaches/${_PROJECT}/ccache:/workspace/ccache \ -v=$PWD/build/out/${_PROJECT}/:/out/ \ gcr.io/oss-fuzz/${_PROJECT} \ /bin/bash -c \ "export PATH=/ccache/bin:\$PATH && compile && cp -n /usr/local/bin/replay_build.sh \$SRC/" # Step 3: save (commit, locally) the cached container as an image docker container commit -c "ENV REPLAY_ENABLED=1" -c "ENV CAPTURE_REPLAY_SCRIPT=" ${_PROJECT}-origin-${_SANITIZER} $FINAL_IMAGE_NAME T_START=$SECONDS # Step 4: run the actual run_tests.sh script in the container. docker run \ --rm \ --network none \ -ti \ us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-address /bin/bash -c 'chmod +x /src/run_tests.sh && /src/run_tests.sh' T_END=$SECONDS T_TOTAL_TIME=$(($T_END - $T_START)) echo "--------------------------------------------------------" echo "Total time taken to replay tests: $T_TOTAL_TIME" ================================================ FILE: infra/experimental/chronos/chronos.sh ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This script records the ENV and commands needed for fuzz target recompilation. # It intercepts bash commands to save: 1) the ENV variable values before # building the fuzz target (`recompile_env.sh`) and 2) all subsequent bash # commands from that point (`recompile`). Combined with Docker, this setup # allows for recompiling the fuzz target without rebuilding the entire project. # Usage: # 1. Set FUZZ_TARGET (e.g., in project's Dockerfile) # 2. Source this file before compiling the fuzz target (e.g., source chronos.sh # at the beginning of project's build.sh). export START_RECORDING="false" RECOMPILE_ENV="/usr/local/bin/recompile_env.sh" # Initialize the recompile script as compile in case Chronos did not trap any # command containing the fuzz target. initialize_recompile_script() { export RECOMPILE_SCRIPT="/usr/local/bin/recompile" cp "/usr/local/bin/compile" "$RECOMPILE_SCRIPT" } reset_recompile_script() { rm "$RECOMPILE_SCRIPT" echo "#!/bin/bash" > "$RECOMPILE_SCRIPT" echo "source $RECOMPILE_ENV" >> "$RECOMPILE_SCRIPT" chmod +x "$RECOMPILE_SCRIPT" } # Execute or record command for recompilation. execute_or_record_command() { record_command() { echo "cd \"$(pwd)\"" >> "$RECOMPILE_SCRIPT" echo "$@" >> "$RECOMPILE_SCRIPT" } # Check if any element in the command array contains the FUZZ_TARGET. if [[ "$BASH_COMMAND" == *"$FUZZ_TARGET"* ]]; then export START_RECORDING="true" # Save all environment variables, excluding read-only ones reset_recompile_script declare -p | grep -Ev 'declare -[^ ]*r[^ ]*' > "$RECOMPILE_ENV" fi if [[ "$START_RECORDING" == "true" ]]; then record_command "$BASH_COMMAND" echo "Recorded execution of: $BASH_COMMAND" fi } main() { # Initialize. initialize_recompile_script # Set up trap for DEBUG to intercept commands. trap 'execute_or_record_command' DEBUG # Enable extended debugging mode shopt -s extdebug # Ensure trap works in subshells and functions. set -T } main ================================================ FILE: infra/experimental/chronos/cloudbuild.yaml ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # CloudBuild for generating Chronos-cached images. # Supports building by way of ccache now. # High-level steps: # 1) Build image for project # 2) Run an ASAN build and store ccache # 3) Copy ccache cache to host and copy into project's OSS-Fuzz folder # 4) Build image for project and copy ccache in, storing image as *-ofg-cache-address # 5) Run an coverage build and store ccache # 6) Copy ccache cache to host and copy into project's OSS-Fuzz folder # 7) Build image for project and copy ccache in, storing image as *-ofg-cache-coverage # TODO (David): add support for use of dedicated replay_build.sh steps: - name: 'gcr.io/cloud-builders/docker' entrypoint: /bin/bash args: - /workspace/infra/experimental/chronos/build_cache_local.sh - ${_PROJECT} - ${_FUZZING_LANGUAGE} - address env: - RUN_ALL=1 - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-ccache-address allowFailure: true - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-address allowFailure: true - name: 'gcr.io/cloud-builders/docker' entrypoint: /bin/bash args: - /workspace/infra/experimental/chronos/build_cache_local.sh - ${_PROJECT} - ${_FUZZING_LANGUAGE} - memory env: - RUN_ALL=1 allowFailure: true # MSan is finicky, so let this fail. - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-ccache-memory allowFailure: true - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-memory allowFailure: true - name: 'gcr.io/cloud-builders/docker' entrypoint: /bin/bash args: - /workspace/infra/experimental/chronos/build_cache_local.sh - ${_PROJECT} - ${_FUZZING_LANGUAGE} - coverage env: - RUN_ALL=1 - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-cached-coverage allowFailure: true - name: 'gcr.io/cloud-builders/docker' args: - push - us-central1-docker.pkg.dev/oss-fuzz/oss-fuzz-gen/${_PROJECT}-ofg-ccache-coverage allowFailure: true timeout: 72000s # 20 hours, same as build_lib.py logsBucket: oss-fuzz-gcb-logs tags: - ${_PROJECT} - chronos options: pool: name: projects/oss-fuzz/locations/us-central1/workerPools/buildpool-chronos ================================================ FILE: infra/experimental/chronos/cloudbuild_all.yaml ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # CloudBuild for generating Chronos-cached images. steps: - name: 'gcr.io/cloud-builders/docker' args: - build - -t - gcloud - . dir: infra/experimental/chronos - name: 'gcloud' args: - infra/experimental/chronos/build_all.sh entrypoint: /bin/bash timeout: 1800s serviceAccount: 'projects/oss-fuzz/serviceAccounts/llm-eval@oss-fuzz.iam.gserviceaccount.com' options: logging: CLOUD_LOGGING_ONLY tags: - chronos-all ================================================ FILE: infra/experimental/chronos/e2e-replay-build.sh ================================================ #!/usr/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Sample projects: simd, wt, libheif, htslib PROJECT=liblouis LOG=replay-${PROJECT}.txt OUT1=replay-out-${PROJECT}-1 OUT2=replay-out-${PROJECT}-2 python infra/helper.py build_image --no-pull "$PROJECT" # AddressSanitizer. mkdir -p build/out/${PROJECT} echo "start" >> ${LOG} echo $(date +%Y:%m:%d:%H:%M:%S) >> ${LOG} # Remove container name we are about to use. docker container rm "${PROJECT}-origin-asan" # Build once, clean container if needed docker run -v $PWD/build/out/${PROJECT}:/out \ -ti --entrypoint="/bin/sh" \ --env FUZZING_LANGUAGE=c --env SANITIZER="address" \ --name "${PROJECT}-origin-asan" \ "gcr.io/oss-fuzz/${PROJECT}" -c "compile" # Copy outs and log data cp -rf $PWD/build/out/${PROJECT} ${OUT1} rm -rf $PWD/build/out/${PROJECT} ls -la $PWD/build/out/ >> ${LOG} echo "next" >> ${LOG} echo $(date +%Y:%m:%d:%H:%M:%S) >> ${LOG} docker commit "${PROJECT}-origin-asan" "gcr.io/oss-fuzz/${PROJECT}-ofg-cached-asan" # Run the replay command docker run -v $PWD/build/out/${PROJECT}:/out \ -e REPLAY_ENABLED=1 -ti --entrypoint="/bin/sh" \ --env FUZZING_LANGUAGE=c --env SANITIZER="address" \ "gcr.io/oss-fuzz/${PROJECT}-ofg-cached-asan" -c "compile" echo "finish" >> ${LOG} echo $(date +%Y:%m:%d:%H:%M:%S) >> ${LOG} cp -rf $PWD/build/out/${PROJECT} ${OUT2} # Now match the artifacts SUCCESS=$(infra/experimental/chronos/match_artifacts $OUT1 $OUT2) if [[ $SUCCESS -eq 0 ]]; then echo "SUCCESS REPLAY" >> ${LOG} else echo "FAIL REPLAY" >> ${LOG} fi ================================================ FILE: infra/experimental/chronos/match_artifacts.sh ================================================ #!/usr/bin/bash -eux # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CMP1=$1 CMP2=$2 for exec1 in $(find $CMP1/ -type f -executable); do base=$(basename $exec1) exec2=$CMP2/${base} if [ ! -f ${exec2} ]; then exit 1 fi comparison=$(cmp --silent $exec1 $exec2; echo $?) if [[ $comparison -ne 0 ]]; then exit 1 fi done exit 0 ================================================ FILE: infra/experimental/chronos/prepare-ccache ================================================ #!/usr/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=$1 { echo "COPY ccache-cache/ /ccache/cache"; echo "ENV PATH=\"/ccache/bin:\$PATH\"" } >> "projects/$PROJECT/Dockerfile" ================================================ FILE: infra/experimental/chronos/prepare-replay-rebuild ================================================ #!/usr/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=$1 { echo "ENV REPLAY_ENABLED=1"; } >> "projects/$PROJECT/Dockerfile" ================================================ FILE: infra/experimental/chronos/requirements.txt ================================================ tree-sitter==0.25.1 tree-sitter-cpp==0.23.4 requests==2.32.5 ================================================ FILE: infra/experimental/contrib/arvo/LICENSE ================================================ BSD 2-Clause License Copyright (c) 2022, The ARVO AUTHORS Copyright (c) 2023, The Arizona Board of Regents All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: infra/experimental/contrib/arvo/__init__.py ================================================ ================================================ FILE: infra/experimental/contrib/arvo/arvo_data.py ================================================ """ARVO data management module. This module provides data management functions for ARVO reproducer, including configuration mappings and Docker/build script fixes. """ from pathlib import Path from typing import Any, Dict, Tuple from datetime import datetime from hacks import get_project_hack from arvo_utils import (DockerfileModifier, CHANGED_KEY, CHANGED_TYPE, GLOBAL_STR_REPLACE, UPDATE_TABLE) def update_resource_info(item_name: str, item_url: str, item_type: str) -> Tuple[str, str, str]: """Update resource information based on configuration tables. Args: item_name: Name of the resource item. item_url: URL of the resource. item_type: Type of the resource. Returns: Tuple of (updated_name, updated_url, updated_type). """ if item_name in CHANGED_KEY: item_name = CHANGED_KEY[item_name] if item_name in UPDATE_TABLE: resource_type = CHANGED_TYPE.get(item_name, 'git') return item_name, UPDATE_TABLE[item_name], resource_type else: return item_name, item_url, item_type def dockerfile_cleaner(dockerfile_path: str | Path) -> None: """Clean dockerfile by removing git branch-specific arguments. Args: dockerfile_path: Path to the Dockerfile to clean. """ dft = DockerfileModifier(dockerfile_path) dft.replace(r'(--single-branch\s+)', "") # --single-branch dft.replace(r'(--branch\s+\S+\s+|-b\s\S+\s+|--branch=\S+\s+)', "") # remove --branch or -b dft.flush() def fix_dockerfile(dockerfile_path: str | Path, project: str | None = None, commit_date: datetime | None = None) -> bool: """Fix the dockerfile for specific projects and general issues. Args: dockerfile_path: Path to the Dockerfile to fix. project: Name of the project for project-specific fixes. commit_date: Target commit date (required for some projects like GDAL). Returns: True if fixes were applied successfully, False otherwise. """ dockerfile_cleaner(dockerfile_path) dft = DockerfileModifier(dockerfile_path) # Some dockerfile forgets to apt update before apt install # and we have to install/set ca-certificate/git sslVerify to avoid # certificates issues # TODO: improve regex dft.replace_once( r'RUN apt', "RUN apt update -y && apt install git ca-certificates -y && " "git config --global http.sslVerify false && " "git config --global --add safe.directory '*'\nRUN apt") dft.str_replace_all(GLOBAL_STR_REPLACE) # Apply project-specific hacks that solve building/compiling problems if project: hack = get_project_hack(project) if hack: # Pass commit_date to the hack if it needs it if hasattr(hack, 'set_commit_date') and commit_date: hack.set_commit_date(commit_date) if not hack.apply_dockerfile_fixes(dft): return False dft.clean_comments() return dft.flush() def fix_build_script(file_path: Path, project_name: str) -> bool: """Fix the build script for specific projects. Args: file_path: Path to the build script file. project_name: Name of the project. Returns: True if fixes were applied successfully, False otherwise. """ if not file_path.exists(): return True dft = DockerfileModifier(file_path) # Apply project-specific build script hacks hack = get_project_hack(project_name) if hack and not hack.apply_build_script_fixes(dft): return False return dft.flush() def extra_scripts(project_name: str, source_dir: Path) -> bool: """Execute extra scripts for specific projects. This function allows us to modify build.sh scripts and other stuff to modify the compiling setting. Args: project_name: Name of the project. source_dir: Path to the source directory. Returns: True if scripts executed successfully, False otherwise. """ # Apply project-specific extra fixes hack = get_project_hack(project_name) if hack and not hack.apply_extra_fixes(source_dir): return False return True def special_component(project_name: str, item_key: str, item: Dict[str, Any], dockerfile: str | Path) -> bool: """Check if a component requires special handling. TODO: Theoretically, we can remove this func since other parts gonna handle the submodule, but not tested. These components are submodules, but their info are in srcmap. Args: project_name: Name of the project. item_key: Key of the item in srcmap. item: Item data from srcmap. dockerfile: Path to the dockerfile. Returns: True if component should be skipped, False otherwise. """ # These components are submodules, but their info are in srcmap if project_name == 'libressl' and item_key == '/src/libressl/openbsd': return False if project_name == 'gnutls' and item_key == '/src/gnutls/nettle': # Just Ignore since we have submodule update --init with open(dockerfile, encoding='utf-8') as f: dt = f.read() if item['rev'] not in dt: return True else: return False return False def skip_component(project_name: str, item_name: str) -> bool: """Check if a component should be skipped during processing. TODO: solve the submodule problem in a decent way Args: project_name: Name of the project. item_name: Name of the item/component. Returns: True if component should be skipped, False otherwise. """ NO_OPERATION = ( "/src", "/src/LPM/external.protobuf/src/external.protobuf", "/src/libprotobuf-mutator/build/external.protobuf/src/external.protobuf", ) item_name = item_name.strip(" ") # Special for skia, Skip since they are done by submodule init if project_name in ['skia', 'skia-ftz']: if item_name.startswith("/src/skia/"): return True if item_name in NO_OPERATION: return True return False if __name__ == "__main__": pass ================================================ FILE: infra/experimental/contrib/arvo/arvo_reproducer.py ================================================ # ARVO reproducer # Paper: https://arxiv.org/abs/2408.02153 # ARVO Implementation: https://github.com/n132/ARVO # Neil — May 5, 2025 — Seattle, USA # Jordi — July 30, 2025 """ARVO reproducer module. This module reproduces a vulnerability and its fix on OSS-Fuzz. Login gcloud: $ gcloud auth application-default login Classes: BuildData: Named tuple for build configuration data. Functions: Main reproducing functions and utilities for OSS-Fuzz vulnerability reproduction. """ import argparse import json import logging import os import re import subprocess import tempfile import time from bisect import bisect_right from datetime import datetime from pathlib import Path from typing import Any from urllib.parse import parse_qs, urlparse import requests from dateutil.parser import parse from google.cloud import storage from dataclasses import dataclass from arvo_data import (extra_scripts, fix_build_script, fix_dockerfile, skip_component, special_component, update_resource_info) from arvo_utils import (DockerfileModifier, VersionControlTool, check_call, clean_dir, clone, docker_build, docker_run, execute, hg_clone, leave_ret, svn_clone, OSS_ERR, OSS_OUT, OSS_WORK, PNAME_TABLE) # Global storage client storage_client: storage.Client | None = None @dataclass class BuildData: project_name: str engine: str sanitizer: str architecture: str def parse_oss_fuzz_report(report_text: bytes, local_id: int) -> dict[str, Any] | bool: """Parse OSS-Fuzz report text and extract relevant information. Args: report_text: Raw report text as bytes. local_id: Local ID of the issue. Returns: Dictionary containing parsed report data, or False if parsing fails. """ text = report_text.decode( 'unicode_escape', errors='ignore') # decode escaped unicode like \u003d def extract(pattern: str, default: str = '') -> str: """Extract information using regex pattern.""" match = re.search(pattern, text) if not match: if default == '': logging.error(f"FAILED to PARSE {pattern} {local_id=}") exit(1) else: return default return match.group(1).strip() result = { "project": extract(r'(?:Target|Project):\s*(\S+)', 'NOTFOUND'), "job_type": extract(r'Job Type:\s*(\S+)'), "platform": extract(r'Platform Id:\s*(\S+)', 'linux'), "crash_type": extract(r'Crash Type:\s*(.+)'), "crash_address": extract(r'Crash Address:\s*(\S+)'), "severity": extract(r'Security Severity:\s*(\w+)', 'Medium'), "regressed": extract(r'(?:Regressed|Crash Revision):\s*(https?://\S+)', "NO_REGRESS"), "reproducer": extract(r'(?:Minimized Testcase|Reproducer Testcase|Download).*:' r'\s*(https?://\S+)'), "verified_fixed": extract(r'(?:fixed in|Fixed:)\s*(https?://\S+revisions\S+)', 'NO_FIX'), "localId": local_id } sanitizer_map = { "address (ASAN)": "address", "memory (MSAN)": "memory", "undefined (UBSAN)": "undefined", "asan": "address", "msan": "memory", "ubsan": "undefined", } fuzz_target = extract(r'(?:Fuzz Target|Fuzz target binary):\s*(\S+)', 'NOTFOUND') if len(result['job_type'].split("_")) == 2: return False else: result['sanitizer'] = sanitizer_map[result['job_type'].split("_")[1]] if fuzz_target != 'NOTFOUND': result['fuzz_target'] = fuzz_target if result['project'] == "NOTFOUND": result['project'] = result['job_type'].split("_")[-1] return result def fetch_issue(local_id: int | str) -> dict[str, Any] | bool: """Fetch issue information from OSS-Fuzz tracker. Args: local_id: Local ID of the issue to fetch. Returns: Dictionary containing issue information, or False if fetch fails. """ # TODO: Replace this with proper issue tracker API calls url = (f'https://issues.oss-fuzz.com/action/issues/{local_id}/' f'events?currentTrackerId=391') session = requests.Session() # Step 1: Get the token from the cookie session.get("https://issues.oss-fuzz.com/") xsrf_token = session.cookies.get("XSRF_TOKEN") headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'en,zh-CN;q=0.9,zh;q=0.8,ar;q=0.7', 'priority': 'u=1, i', 'referer': 'https://issues.oss-fuzz.com/', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Google Chrome";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Linux"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36', 'X-XSRF-Token': xsrf_token } response = session.get(url, headers=headers) raw_text = response.content try: result = parse_oss_fuzz_report(raw_text, int(local_id)) except Exception: logging.error(f"FAIL on {local_id}, skip") return False return result def parse_job_type(job_type: str) -> dict[str, Any]: """Parse job type string into components. Args: job_type: Job type string from OSS-Fuzz. Returns: Dictionary containing parsed job type components. """ parts = job_type.split('_') remainder = [] parsed = {} while len(parts) > 0: part = parts.pop(0) if part in ['afl', 'honggfuzz', 'libfuzzer']: parsed['engine'] = part elif part in ['asan', 'ubsan', 'msan']: parsed['sanitizer'] = part elif part == 'i386': parsed['arch'] = part elif part == 'untrusted': parsed['untrusted'] = True else: remainder.append(part) if len(remainder) > 0: parsed['project'] = '_'.join(remainder) if 'arch' not in parsed: parsed['arch'] = 'x86_64' if 'engine' not in parsed: parsed['engine'] = 'none' if 'untrusted' not in parsed: parsed['untrusted'] = False return parsed def download_build_artifacts(metadata: dict[str, Any], url: str, outdir: Path) -> list[str] | bool: """Download build artifacts from Google Cloud Storage. Args: metadata: Issue metadata containing build information. url: URL to download artifacts from. outdir: Output directory for downloaded files. Returns: List of downloaded file paths on success, False on failure. """ global storage_client if storage_client is None: storage_client = storage.Client() bucket_map = { "libfuzzer_address_i386": "clusterfuzz-builds-i386", "libfuzzer_memory_i386": "clusterfuzz-builds-i386", "libfuzzer_undefined_i386": "clusterfuzz-builds-i386", "libfuzzer_address": "clusterfuzz-builds", "libfuzzer_memory": "clusterfuzz-builds", "libfuzzer_undefined": "clusterfuzz-builds", "afl_address": "clusterfuzz-builds-afl", "honggfuzz_address": "clusterfuzz-builds-honggfuzz", } sanitizer_map = { "address (ASAN)": "address", "memory (MSAN)": "memory", "undefined (UBSAN)": "undefined", "asan": "address", "msan": "memory", "ubsan": "undefined", "address": "address", "memory": "memory", "undefined": "undefined", None: "", } job_name = metadata["job_type"] job = parse_job_type(job_name) # These don't have any build artifacts if job['untrusted'] or job['engine'] == 'none': return False # Prefer the info from the job name, since the metadata # format has changed several times. if 'project' in metadata: project = metadata["project"] else: project = job['project'] if 'sanitizer' in metadata: sanitizer = sanitizer_map[metadata["sanitizer"]] assert sanitizer == sanitizer_map[job['sanitizer']] else: sanitizer = sanitizer_map[job['sanitizer']] fuzzer = job['engine'] bucket_string = f"{fuzzer}_{sanitizer}" if job['arch'] == 'i386': bucket_string += '_i386' assert bucket_string in bucket_map bucket_name = bucket_map[bucket_string] # Grab the revision from the URL urlparams = parse_qs(urlparse(url).query) if 'revision' in urlparams: revision = urlparams['revision'][0] elif 'range' in urlparams: revision = urlparams['range'][0].split(':')[1] else: return False zip_name = f'{project}-{sanitizer}-{revision}.zip' srcmap_name = f'{project}-{sanitizer}-{revision}.srcmap.json' zip_path = f'{project}/{zip_name}' srcmap_path = f'{project}/{srcmap_name}' downloaded_files = [] bucket = storage_client.bucket(bucket_name) for path, name in [(srcmap_path, srcmap_name)]: download_path = outdir / name if download_path.exists(): logging.info(f'Skipping {name} (already exists)') downloaded_files.append(download_path) continue blob = bucket.blob(path) if not blob.exists(): logging.info(f'Skipping {name} (not found)') continue blob.download_to_filename(str(download_path)) logging.info(f'Downloaded {name}') downloaded_files.append(download_path) return [str(f) for f in downloaded_files] def get_project_name(issue: dict[str, Any], srcmap: str | Path) -> str | bool: """Get project name from issue and srcmap data. Args: issue: Issue dictionary containing project information. srcmap: Path to the srcmap file. Returns: Project name on success, False on failure. """ if 'project' not in issue: logging.error("[FAILED] to get project field in issue") return False else: project_name = issue['project'] if project_name in PNAME_TABLE: return PNAME_TABLE[project_name] # handling special cases with open(srcmap, encoding='utf-8') as f: info1 = json.load(f) expected_name = "/src/" + project_name if expected_name in info1: return project_name else: logging.error( f"Failed to locate the main component, plz add that to pname_table") return False def get_language(project_dir: Path) -> str | bool: """Get programming language from project.yaml file. Args: project_dir: Path to the project directory. Returns: Language string on success, False on failure. """ project_yaml = project_dir / "project.yaml" if not project_yaml.exists(): return False with open(project_yaml, encoding='utf-8') as f: content = f.read() matches = re.findall(r'language\s*:\s*([^\s]+)', content) if len(matches) != 1: logging.error(f"[!] Get more than one languages") return False return str(matches[0]) def get_sanitizer(fuzzer_sanitizer: str) -> str | bool: """Convert fuzzer sanitizer short name to full name. Args: fuzzer_sanitizer: Short sanitizer name (asan, msan, ubsan). Returns: Full sanitizer name on success, False on failure. """ sanitizer_map = {'asan': "address", 'msan': 'memory', 'ubsan': 'undefined'} return sanitizer_map.get(fuzzer_sanitizer, False) def download_poc(issue: dict[str, Any], path: Path, name: str) -> Path | bool: """Download proof-of-concept file from issue. Args: issue: Issue dictionary containing reproducer URL. path: Directory to save the POC file. name: Name for the downloaded file. Returns: Path to downloaded file on success, False on failure. """ session = requests.Session() url = issue['reproducer'] response = session.head(url, allow_redirects=True) if response.status_code != 200: return False reproducer_path = path / name response = session.get(url) if response.status_code != 200: return False reproducer_path.write_bytes(response.content) return reproducer_path def prepare_ossfuzz(project_name: str, commit_date: str | datetime) -> tuple[Path, Path] | bool: """Prepare OSS-Fuzz repository for the specified project and date. Args: project_name: Name of the project. commit_date: Target commit date or commit hash. Returns: Tuple of (temp_dir, project_dir) on success, False on failure. """ # 1. Clone OSS Fuzz tmp_dir = clone("https://github.com/google/oss-fuzz.git", name="oss-fuzz") if tmp_dir is False: return False # 2. Get the Commit Close to Commit_Date tmp_oss_fuzz_dir = tmp_dir / "oss-fuzz" if isinstance(commit_date, str): oss_fuzz_commit = commit_date else: # Remove the cmd variable and use the list directly result = execute([ 'git', 'log', '--before=' + commit_date.isoformat(), '-n1', '--format=%H' ], tmp_oss_fuzz_dir) if result.success and result.output: oss_fuzz_commit = result.output.strip() else: oss_fuzz_commit = False if oss_fuzz_commit is False: cmd = ['git', 'log', '--reverse', '--format=%H'] result = execute(cmd, tmp_oss_fuzz_dir) if result.success and result.output: oss_fuzz_commit = result.output.splitlines()[0].strip() else: oss_fuzz_commit = False if oss_fuzz_commit is False: logging.error('Failed to get oldest oss-fuzz commit') return leave_ret(False, tmp_dir) # 3. Reset OSS Fuzz gt = VersionControlTool(tmp_oss_fuzz_dir) if not gt.reset(oss_fuzz_commit): logging.error("Failed to Reset OSS-Fuzz") return leave_ret(False, tmp_dir) # 4. Locate Project Dir tmp_list = [x for x in tmp_oss_fuzz_dir.iterdir() if x.is_dir()] if tmp_oss_fuzz_dir / "projects" in tmp_list: proj_dir = tmp_oss_fuzz_dir / "projects" / project_name elif tmp_oss_fuzz_dir / "targets" in tmp_list: proj_dir = tmp_oss_fuzz_dir / "targets" / project_name else: logging.error(f"Failed to locate the project({project_name}) in oss-fuzz") return leave_ret(False, tmp_dir) return (tmp_dir, proj_dir) def rebase_dockerfile(dockerfile_path: str | Path, commit_date: str) -> bool: """Rebase dockerfile to use historical base image. Args: dockerfile_path: Path to the Dockerfile to rebase. commit_date: Target commit date for base image. Returns: True if rebase succeeded, False otherwise. """ def _get_base(date: str, repo: str = "gcr.io/oss-fuzz-base/base-builder") -> str: """Get base image hash for the specified date.""" cache_name = repo.split("/")[-1] cache_file = f"/tmp/{cache_name}_cache.json" cache_ttl = 86400 # 24 hours result_json = [] if os.path.exists(cache_file) and ( time.time() - os.path.getmtime(cache_file)) < cache_ttl: with open(cache_file, 'r', encoding='utf-8') as f: result_json = json.load(f) else: cmd = [ "gcloud", "container", "images", "list-tags", repo, "--format=json", "--sort-by=timestamp" ] result = execute(cmd) if result.success and result.output: result_json = json.loads(result.output) with open(cache_file, 'w', encoding='utf-8') as f: f.write(json.dumps(result_json, indent=4)) else: return "" timestamps = [] for item in result_json: timestamps.append(int(parse(item['timestamp']['datetime']).timestamp())) target_ts = int(parse(date).timestamp()) return result_json[bisect_right(timestamps, target_ts - 1) - 1]['digest'].split(":")[1] # Load the Dockerfile try: with open(dockerfile_path, encoding='utf-8') as f: data = f.read() except IOError: logging.error(f"No such a dockerfile: {dockerfile_path}") return False # Locate the Repo match = re.search(r'FROM .*', data) if match is None: logging.error("Failed to get the base-image: {dockerfile_path}") return False else: repo = match[0][5:] if "@sha256" in repo: repo = repo.split("@sha256")[0] if repo == 'ossfuzz/base-builder' or repo == 'ossfuzz/base-libfuzzer': repo = "gcr.io/oss-fuzz-base/base-builder" if ":" in repo: repo = repo.split(":")[0] image_hash = _get_base(commit_date, repo) # We insert update since some old dockerfile doesn't have that line data = re.sub( r"FROM .*", f"FROM {repo}@sha256:" + image_hash + "\nRUN apt-get update -y\n", data) with open(dockerfile_path, 'w', encoding='utf-8') as f: f.write(data) return True def update_revision_info(dockerfile: str | Path, src_path: str, item: dict[str, Any], commit_date: datetime | Path, approximate: str) -> bool: """Update revision information in dockerfile. Args: dockerfile: Path to the dockerfile. src_path: Source path in the dockerfile. item: Item information containing URL, revision, and type. commit_date: Target commit date or path for replacement mode. approximate: Approximation direction ('+' or '-'). Returns: True if update succeeded, False otherwise. """ item_url = item['url'] item_rev = item['rev'] item_type = item['type'] dft = DockerfileModifier(dockerfile) if item_url.startswith("http:"): keyword = item_url[4:] elif item_url.startswith("https:"): keyword = item_url[5:] else: keyword = item_url hits, line_count = dft.get_line(keyword) # mismatch if len(hits) != 1: return False line = hits[0] if item_type == 'git': pattern = re.compile(rf"{item_type}\s+clone") elif item_type == 'hg': pattern = re.compile(rf"{item_type}\s+clone") elif item_type == 'svn': pattern = re.compile(rf"RUN\s+svn\s+(co|checkout)+") else: logging.error("NOT supported protocol") return False if len(pattern.findall(line)) != 1: # mismatch return False if isinstance(commit_date, Path): rep_path = commit_date # Replace mode: for bisection # Replace the original line with ADD/COPY command # Then RUN init/update the submodule dft.replace_line_at(line_count - 1, f"ADD {rep_path.name} {src_path}") dft.insert_line_at( line_count, f"RUN bash -cx 'pushd {src_path} ;(git submodule init && " f"git submodule update --force) ;popd'") dft.flush() return True else: # Insertion Mode if item_type == "git": if approximate == '-': dft.insert_line_at( line_count, f"RUN bash -cx 'pushd {src_path} ; " f"(git reset --hard {item_rev}) || " f"(commit=$(git log --before='{commit_date.isoformat()}' " f"--format='%H' -n1) && " f"git reset --hard $commit || exit 99) ; " f"(git submodule init && git submodule update --force) ;popd'") else: dft.insert_line_at( line_count, f"RUN bash -cx 'pushd {src_path} ; " f"(git reset --hard {item_rev}) || " f"(commit=$(git log --since='{commit_date.isoformat()}' " f"--format='%H' --reverse | head -n1) && " f"git reset --hard $commit || exit 99) ; " f"(git submodule init && git submodule update --force) ;popd'") elif item_type == 'hg': # TODO: support approximate dft.insert_line_at( line_count, f'RUN bash -cx "pushd {src_path} ; ' f'(hg update --clean -r {item_rev} && ' f'hg purge --config extensions.purge=)|| exit 99 ; popd"') elif item_type == "svn": # TODO: support approximate dft.replace(pattern, f"RUN svn checkout -r {item_rev}") else: logging.error("Failed to support {item_type}") return False dft.flush() return True def build_fuzzers_impl(local_id: int | str, project_dir: Path, engine: str, sanitizer: str, architecture: str, source_path: Path | None, mount_path: Path | None = None, no_dump: bool = False, custom_script: list[str] | None = None) -> bool: """Build fuzzers using Docker. Args: local_id: Local ID for logging and output directories. project_dir: Path to the project directory. engine: Fuzzing engine to use. sanitizer: Sanitizer to use. architecture: Target architecture. source_path: Path to source code. mount_path: Mount path for source code in container. no_dump: Whether to suppress log output. custom_script: Additional custom script commands. Returns: True if build succeeded, False otherwise. """ if custom_script is None: custom_script = [] # Set the LogFile log_file = OSS_ERR / f"{local_id}_Image.log" logging.info(f"Check the output in file: {log_file}") # Clean The WORK/OUT DIR project_out = OSS_OUT / f"{local_id}_OUT" project_work = OSS_WORK / f"{local_id}_WORK" if project_out.exists(): check_call(["sudo", "rm", "-rf", str(project_out)]) if project_work.exists(): check_call(["sudo", "rm", "-rf", str(project_work)]) project_out.mkdir() project_work.mkdir() args = [ '-t', f'gcr.io/oss-fuzz/{local_id}', '--file', str(project_dir / "Dockerfile"), str(project_dir) ] if not docker_build(args, log_file=log_file): logging.error(f"Failed to build DockerImage") return False # Build Succeed, Try Compiling if log_file and log_file.exists(): os.remove(str(log_file)) env = [ 'FUZZING_ENGINE=' + engine, 'SANITIZER=' + sanitizer, 'ARCHITECTURE=' + architecture, 'FUZZING_LANGUAGE=' + str(get_language(project_dir)), ] command = sum([['-e', x] for x in env], []) # Mount the Source/Dependencies (we try to replace this with # modifying dockerfile) if source_path and mount_path: for item in source_path.iterdir(): command += ['-v', f'{item}:{mount_path / item.name}'] # Mount out/work dir command += [ '-v', f'{project_out}:/out', '-v', f'{project_work}:/work', '-t', f'gcr.io/oss-fuzz/{local_id}' ] # supports for submodule tracker command += custom_script if not no_dump: log_file = OSS_ERR / f"{local_id}_Compile.log" logging.info(f"Check the output in file: {str(log_file)}") else: log_file = None result = docker_run(command, log_file=log_file) if not result: logging.error('Failed to Build Targets') return False else: if log_file and log_file.exists() and str(log_file) != "/dev/null": os.remove(str(log_file)) logging.info(f"OUT: {project_out}") return True def build_fuzzer_with_source(local_id: int | str, project_name: str, srcmap: str | Path, sanitizer: str, engine: str, arch: str, commit_date: datetime, issue: dict[str, Any], tag: str) -> bool: """Build fuzzer with source code from srcmap. Args: local_id: Local ID for the build. project_name: Name of the project. srcmap: Path to the srcmap file. sanitizer: Sanitizer to use. engine: Fuzzing engine. arch: Target architecture. commit_date: Target commit date. issue: Issue information. tag: Build tag ('fix' or 'vul'). Returns: True if build succeeded, False otherwise. """ # Build source_dir with open(srcmap, encoding='utf-8') as f: srcmap_items = json.loads(f.read()) if ("/src" in srcmap_items and srcmap_items['/src']['url'] == 'https://github.com/google/oss-fuzz.git'): result = prepare_ossfuzz(project_name, srcmap_items['/src']['rev']) else: result = prepare_ossfuzz(project_name, commit_date) if not result: return False else: tmp_dir, project_dir = result dockerfile = project_dir / 'Dockerfile' logging.info(f"dockerfile: {dockerfile}") build_data = BuildData(sanitizer=sanitizer, architecture=arch, engine=engine, project_name=project_name) # Step ZERO: Rebase Dockerfiles if not rebase_dockerfile(dockerfile, str(commit_date).replace(" ", "-")): logging.error( f"build_fuzzer_with_source: Failed to Rebase Dockerfile, {local_id}") return leave_ret(False, tmp_dir) # Step ONE: Fix Dockerfiles if not fix_dockerfile(dockerfile, project_name, commit_date): logging.error( f"build_fuzzer_with_source: Failed to Fix Dockerfile, {local_id}") return leave_ret(False, tmp_dir) # Step TWO: Prepare Dependencies with open(srcmap, encoding='utf-8') as f: data = json.loads(f.read()) source_dir = Path(tempfile.mkdtemp()) src = source_dir / "src" src.mkdir(parents=True, exist_ok=True) docker_volume = [] unsorted = list(data.keys()) sorted_keys = sorted(unsorted, key=len) main_component = get_project_name(issue, srcmap) if main_component is False: return leave_ret(False, tmp_dir) force_no_err_dump = "/src/xz" in sorted_keys # Handle Srcmap Info for item_key in sorted_keys: # logging.info(f"Prepare Dependency: {x}") if skip_component(project_name, item_key): continue if tag == 'fix' and main_component == item_key: approximate = '+' else: approximate = '-' new_data = {} new_data['rev'] = data[item_key]['rev'] new_key, new_data['url'], new_data['type'] = update_resource_info( item_key, data[item_key]['url'], data[item_key]['type']) del data[item_key] data[new_key] = new_data item_name = new_key item_url = data[new_key]['url'] item_type = data[new_key]['type'] item_rev = data[new_key]['rev'] item_name = "/".join(item_name.split("/")[2:]) if special_component(project_name, new_key, data[new_key], dockerfile): continue if (item_name == 'aflplusplus' and item_url == 'https://github.com/AFLplusplus/AFLplusplus.git'): continue if (item_name == 'libfuzzer' and 'llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer' in item_url): continue # Broken Revision if item_rev == "" or item_rev == "UNKNOWN": logging.error(f"Broken Meta: No Revision Provided") return leave_ret(False, [tmp_dir, source_dir]) # Ignore not named dependencies if it's not main if item_name.strip(" ") == "" and len(data.keys()) == 1: logging.error(f"Broken Meta: Found Not Named Dep") return leave_ret(False, [tmp_dir, source_dir]) # Broken type if item_type not in ['git', 'svn', 'hg']: logging.error(f"Broken Meta: No support for {item_type}") return leave_ret(False, [tmp_dir, source_dir]) # Try to perform checkout in dockerfile, # which could make reproducing more reliable if update_revision_info(dockerfile, new_key, data[new_key], commit_date, approximate): continue # Prepare the dependencies and record them. We'll use -v to mount them # to the docker container if item_type == 'git': clone_result = clone(item_url, item_rev, src, item_name, commit_date=commit_date) if clone_result is False: logging.error(f"[!] build_from_srcmap: Failed to clone & checkout " f"[{local_id}]: {item_name}") return leave_ret(False, [tmp_dir, source_dir]) elif clone_result is None: command = (f'git log --before="{commit_date.isoformat()}" ' f'-n 1 --format="%H"') result = subprocess.run(command, stdout=subprocess.PIPE, text=True, shell=True, cwd=src / item_name) commit_hash = result.stdout.strip() if not check_call(['git', "reset", '--hard', commit_hash], cwd=src / item_name): logging.error(f"[!] build_from_srcmap: Failed to clone & checkout " f"[{local_id}]: {item_name}") return leave_ret(False, [tmp_dir, source_dir]) docker_volume.append(new_key) elif item_type == 'svn': if not svn_clone(item_url, item_rev, src, item_name): logging.error( f"[!] build_from_srcmap/svn: Failed clone & checkout: {item_name}") return leave_ret(False, [tmp_dir, source_dir]) docker_volume.append(new_key) elif item_type == 'hg': if not hg_clone(item_url, item_rev, src, item_name): logging.error( f"[!] build_from_srcmap/hg: Failed clone & checkout: {item_name}") return leave_ret(False, [tmp_dir, source_dir]) docker_volume.append(new_key) else: logging.error(f"Failed to support {item_type}") exit(1) # Step Three: Extra Scripts if not extra_scripts(project_name, source_dir): logging.error(f"Failed to Run ExtraScripts, {local_id}") return leave_ret(False, [tmp_dir, source_dir]) if not fix_build_script(project_dir / "build.sh", project_name): logging.error(f"Failed to Fix Build.sh, {local_id}") return leave_ret(False, [tmp_dir, source_dir]) # Let's Build It result = build_fuzzers_impl(local_id, project_dir=project_dir, engine=build_data.engine, sanitizer=build_data.sanitizer, architecture=build_data.architecture, source_path=source_dir / "src", mount_path=Path("/src"), no_dump=force_no_err_dump) # we need sudo since the docker container root touched the folder check_call(["sudo", "rm", "-rf", str(source_dir)]) return leave_ret(result, tmp_dir) def build_from_srcmap(srcmap: Path, issue: dict[str, Any], tag: str) -> bool: """Build fuzzer from srcmap file. Args: srcmap: Path to the srcmap file. issue: Issue dictionary. tag: Build tag ('fix' or 'vul'). Returns: True if build succeeded, False otherwise. """ # Get Basic Information fuzzer_info = issue['job_type'].split("_") engine = fuzzer_info[0] sanitizer = get_sanitizer(fuzzer_info[1]) arch = 'i386' if fuzzer_info[2] == 'i386' else 'x86_64' # Get Issue Date issue_date = srcmap.name.split(".")[0].split("-")[-1] commit_date = datetime.strptime(issue_date + " +0000", '%Y%m%d%H%M %z') if 'issue' not in issue: issue['issue'] = {'localId': issue['localId']} if engine not in ['libfuzzer', 'afl', 'honggfuzz', 'centipede']: logging.error("Failed to get engine") return False if sanitizer is False: logging.error("Failed to get Sanitizer") return False return build_fuzzer_with_source(issue['issue']['localId'], issue['project'], srcmap, sanitizer, engine, arch, commit_date, issue, tag) def arvo_reproducer(local_id: int | str, tag: str) -> bool: """Main ARVO reproducer function. Args: local_id: Local ID of the vulnerability. tag: Version tag ('fix' or 'vul'). Returns: True if reproduction succeeded, False otherwise. """ logging.info(f"Working on {local_id}") # 1. Fetch the basic info for the vulnerability issue = fetch_issue(local_id) # TODO, refactor a fast way if not issue: logging.error(f"Failed to get the srcmap or issue for {local_id}") return False tmpdir = Path(tempfile.mkdtemp()) srcmap_url = issue['regressed'] if tag == 'vul' else issue['verified_fixed'] srcmap_files = download_build_artifacts(issue, srcmap_url, tmpdir) if not srcmap_files: logging.error(f"Failed to get the srcmap for {local_id}") return False srcmap = Path(srcmap_files[0]) # Early issues don't have 'project' field. Set project for issues that # didn't have it. if 'project' not in issue: issue['project'] = issue['fuzzer'].split("_")[1] # 2. Download the PoC logging.info("Downloading PoC") case_dir = Path(tempfile.mkdtemp()) try: case_path = download_poc(issue, case_dir, "crash_case") except Exception: logging.error(f"Failed to Download the Reproducer") return False logging.info(f"POC: {case_path}") if not case_path or not case_path.exists(): logging.error(f"Failed to Download the Reproducer") return False # 3. Build the Vulnerable Software logging.info("Building the Binary") result = build_from_srcmap(srcmap, issue, tag) if not result: logging.error(f"Failed to build old fuzzers from srcmap") return False return True def main() -> None: """Main function.""" parser = argparse.ArgumentParser(description='Reproduce ') parser.add_argument('--issueId', help='The issueId of the found vulnerability ' 'https://issues.oss-fuzz.com/', required=True) parser.add_argument('--version', default='fix', help="The fixed version or vulnerable version") args = parser.parse_args() # In this script, localId == issueId arvo_reproducer(args.issueId, args.version) if __name__ == "__main__": main() ================================================ FILE: infra/experimental/contrib/arvo/arvo_reproducer_test.py ================================================ """Test module for ARVO reproducer functionality. This module contains functional tests for the ARVO reproducer components: 1. The functionality of reproducer components. 2. The building of a project's fuzzers from a vulnerability found on OSS-Fuzz. """ import shutil import tempfile import unittest import warnings from datetime import datetime from pathlib import Path from typing import Dict, Any from arvo_reproducer import (arvo_reproducer, download_poc, fetch_issue, prepare_ossfuzz, rebase_dockerfile) from arvo_utils import execute # Suppress Google auth warnings warnings.filterwarnings("ignore", category=UserWarning, module="google.auth._default") # Test constants REPRODUCE_TEST_LOCAL_ID = 42487096 UNITTEST_LOCAL_ID = 42498388 class ArvoReproducingTest(unittest.TestCase): """Test class for ARVO reproducer functionality.""" def test_reproduce(self) -> None: """Test the complete reproduction process.""" result = arvo_reproducer(REPRODUCE_TEST_LOCAL_ID, 'vul') self.assertEqual(result, True) case_dir = Path(tempfile.mkdtemp()) issue = fetch_issue(REPRODUCE_TEST_LOCAL_ID) # TODO, refactor a fast way download_poc(issue, case_dir, "crash_case") (case_dir / "stderr").touch() with open(case_dir / "stderr", 'wb') as f: execute([ f'/tmp/{REPRODUCE_TEST_LOCAL_ID}_OUT/set_eval_fuzzer', str(case_dir / "crash_case") ], stdout=f, stderr=f) with open(case_dir / "stderr", 'rb') as f: crash_info = f.read() self.assertEqual( b"SUMMARY: AddressSanitizer: heap-buffer-overflow " in crash_info, True) shutil.rmtree(case_dir) class ArvoUnitTests(unittest.TestCase): """Unit tests for individual ARVO reproducer components.""" def test_fetch_issue(self) -> None: """Test if we can get issues from OSS-Fuzz.""" expected_issue_cve_2021_38593: Dict[str, Any] = { 'project': 'qt', 'job_type': 'libfuzzer_asan_i386_qt', 'platform': 'linux', 'crash_type': 'UNKNOWN WRITE', 'crash_address': '0x10000000', 'severity': 'High', 'regressed': 'https://oss-fuzz.com/revisions?job=libfuzzer_asan_i386_qt&' 'range=202106240616:202106250624', 'reproducer': 'https://oss-fuzz.com/download?testcase_id=6379642528333824', 'verified_fixed': 'https://oss-fuzz.com/revisions?job=libfuzzer_asan_i386_qt&' 'range=202107280604:202107290609', 'localId': 42498388, 'sanitizer': 'address', 'fuzz_target': 'qtsvg_svg_qsvgrenderer_render' } issue = fetch_issue(UNITTEST_LOCAL_ID) self.assertEqual(expected_issue_cve_2021_38593, issue) def test_download_poc(self) -> None: """Test if we can download proof-of-concept files.""" issue = fetch_issue(UNITTEST_LOCAL_ID) case_dir = Path(tempfile.mkdtemp()) result = download_poc(issue, case_dir, "crash_case") self.assertEqual(result.name, "crash_case") shutil.rmtree(case_dir) def test_rebase_dockerfile(self) -> None: """Test if we can get the historical dockerfile and rebase it.""" commit_date = datetime.strptime("202409200607" + " +0000", '%Y%m%d%H%M %z') result = prepare_ossfuzz("libxml2", commit_date) commit_date_str = str(commit_date).replace(" ", "-") rebase_result = rebase_dockerfile(result[1] / "Dockerfile", commit_date_str) self.assertEqual(rebase_result, True) shutil.rmtree(result[0]) if __name__ == '__main__': unittest.main() ================================================ FILE: infra/experimental/contrib/arvo/arvo_utils.py ================================================ """ARVO utilities module. This module provides utility functions for ARVO reproducer including: - Command execution functions - Version control operations - Docker operations - File system utilities - Dockerfile modification tools """ import json import os import logging import re import shutil import subprocess import tempfile import warnings from datetime import datetime from pathlib import Path from typing import Any, Dict, List, Tuple import pytz from dataclasses import dataclass def load_repo_map(file_name: str) -> Dict[str, Any]: """Load repository mapping from JSON file. Args: file_name: Name of the JSON file to load. Returns: Dictionary containing the loaded JSON data. """ json_path = os.path.join(os.path.dirname(__file__), file_name) with open(json_path, encoding='utf-8') as f: return json.load(f) # Configuration constants - Order matters GLOBAL_STR_REPLACE = load_repo_map("string_replacement.json") UPDATE_TABLE = load_repo_map("component_fixes.json") # Global constants OSS_OUT = OSS_WORK = OSS_ERR = Path("/tmp") # Only include non git project CHANGED_TYPE = {'/src/graphicsmagick': 'hg'} CHANGED_KEY = { '/src/mdbtools/test': '/src/mdbtools', } PNAME_TABLE = { 'libpng-proto': "libprotobuf-mutator", 'pcapplusplus': "PcapPlusPlus", 'skia-ftz': 'skia', } # Configure logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # Suppress Google auth warnings warnings.filterwarnings("ignore", category=UserWarning, module="google.auth._default") @dataclass class CommandResult: success: bool output: bytes | None returncode: int def execute(cmd: List[str], cwd: Path = Path("/tmp"), stdout: int = subprocess.PIPE, stderr: int = subprocess.PIPE) -> CommandResult: """ Execute a command and return its result. Args: cmd: Command to execute as a list of strings. cwd: Working directory for the command. stdout: Stdout redirection target. stderr: Stderr redirection target. Returns: CommandResult: with success, output, and returncode. success is True if returncode==0, regardless of output. output is the stdout bytes if present, else None. """ try: result = subprocess.run(cmd, cwd=cwd, stderr=stderr, stdout=stdout, check=False) output = result.stdout if result.stdout and result.stdout.strip( ) != b'' else None return CommandResult(success=(result.returncode == 0), output=output, returncode=result.returncode) except (subprocess.SubprocessError, OSError): return CommandResult(success=False, output=None, returncode=-1) def check_call(cmd: List[str], cwd: Path = Path("/tmp"), stdout: int = subprocess.PIPE, stderr: int = subprocess.PIPE) -> bool: """Execute a command and return success status. Args: cmd: Command to execute as a list of strings. cwd: Working directory for the command. stdout: Stdout redirection target. stderr: Stderr redirection target. Returns: True if command succeeded, False otherwise. """ try: result = subprocess.run(cmd, cwd=cwd, stderr=stderr, stdout=stdout, check=False) return result.returncode == 0 except (subprocess.SubprocessError, OSError): return False def _git_pull(cwd: Path) -> bool: """Pull latest changes from git repository. Args: cwd: Path to the git repository. Returns: True if pull succeeded, False otherwise. """ with open("/dev/null", 'w', encoding='utf-8') as f: return check_call(['git', 'pull'], cwd=cwd, stderr=f, stdout=f) def _hg_pull(cwd: Path) -> bool: """Pull latest changes from mercurial repository. Args: cwd: Path to the mercurial repository. Returns: True if pull succeeded, False otherwise. """ with open("/dev/null", 'w', encoding='utf-8') as f: return check_call(['hg', 'pull'], cwd=cwd, stderr=f, stdout=f) def _svn_pull(cwd: Path) -> bool: """Update SVN repository to latest revision. Args: cwd: Path to the SVN repository. Returns: True if update succeeded, False otherwise. """ with open("/dev/null", 'w', encoding='utf-8') as f: return check_call(['svn', 'update'], cwd=cwd, stderr=f, stdout=f) def clone(url: str, commit: str | None = None, dest: str | Path | None = None, name: str | None = None, main_repo: bool = False, commit_date: datetime | None = None) -> Path | bool: """Clone a git repository and optionally checkout a specific commit. Args: url: Repository URL to clone. commit: Specific commit to checkout. dest: Destination directory for cloning. name: Name for the cloned repository directory. main_repo: Whether this is the main repository. commit_date: Date of the commit for fallback checkout. Returns: Path to cloned repository on success, False on failure. """ def _git_clone(url: str, dest: Path, name: str | None) -> bool: """Helper function to perform git clone operation.""" cmd = ['git', 'clone', url] if name is not None: cmd.append(name) if not check_call(cmd, dest): return False return True def _check_out(commit: str, path: Path) -> bool: """Helper function to checkout a specific commit.""" with open('/dev/null', 'w', encoding='utf-8') as f: return check_call(['git', "reset", '--hard', commit], cwd=path, stdout=f) dest_path = Path(dest) if dest else Path(tempfile.mkdtemp()) if not _git_clone(url, dest_path, name): logging.error(f"[!] - clone: Failed to clone {url}") return False if commit: logging.info(f"Checkout to commit {commit}") repo_name = list(dest_path.iterdir())[0] if name is None else name repo_path = dest_path / repo_name if _check_out(commit, repo_path): return dest_path else: if main_repo: logging.error(f"[!] - clone: Failed to checkout {repo_name}") return False else: if commit_date is None: logging.warning( f"[!] - clone: Failed to checkout {repo_name} but it's not the main component, using the latest version" ) return dest_path logging.warning( "[!] Failed to checkout, try a version before required commit") cmd = [ "git", "log", f"--before='{commit_date.isoformat()}'", "--format='%H'", "-n1" ] fallback_result = execute(cmd, repo_path) if fallback_result.success and fallback_result.output: fallback_commit = fallback_result.output.decode().strip("'") logging.info(f"Checkout to {fallback_commit}") if _check_out(fallback_commit, repo_path): return dest_path logging.error(f"[!] - clone: Failed to checkout {repo_name}") return False return dest_path def svn_clone(url: str, commit: str | None = None, dest: str | Path | None = None, rename: str | None = None) -> Path | bool: """Clone an SVN repository and optionally checkout a specific revision. Args: url: SVN repository URL. commit: Specific revision to checkout. dest: Destination directory. rename: Name for the cloned directory. Returns: Path to cloned repository on success, False on failure. """ def _svn_clone(url: str, dest: Path, name: str | None = None) -> bool: """Helper function to perform SVN checkout operation.""" cmd = ["svn", "co", url] if name: cmd.append(name) if not check_call(cmd, dest): return False return True tmp_path = Path(dest) if dest else Path(tempfile.mkdtemp()) if not _svn_clone(url, tmp_path, rename): logging.error(f"[!] - svn_clone: Failed to clone {url}") return False if commit: repo_name = rename if rename else list(tmp_path.iterdir())[0] repo_path = tmp_path / repo_name if not check_call(['svn', "up", '--force', '-r', commit], cwd=repo_path): return False return tmp_path def hg_clone(url: str, commit: str | None = None, dest: str | Path | None = None, rename: str | None = None) -> Path | bool: """Clone a Mercurial repository and optionally checkout a specific commit. Args: url: Mercurial repository URL. commit: Specific commit to checkout. dest: Destination directory. rename: Name for the cloned directory. Returns: Path to cloned repository on success, False on failure. """ def _hg_clone(url: str, dest: Path, name: str | None = None) -> bool: """Helper function to perform hg clone operation.""" cmd = ["hg", "clone", url] if name: cmd.append(name) if not check_call(cmd, dest): return False return True tmp_path = Path(dest) if dest else Path(tempfile.mkdtemp()) if not _hg_clone(url, tmp_path, rename): logging.error(f"[!] - hg_clone: Failed to clone {url}") return False if commit: repo_name = rename if rename else list(tmp_path.iterdir())[0] repo_path = tmp_path / repo_name if not (check_call(['hg', "update", '--clean', '-r', commit], cwd=repo_path) and check_call(['hg', "purge", '--config', 'extensions.purge='], cwd=repo_path)): return False return tmp_path class DockerfileModifier: """A class for modifying Dockerfile content with various text operations.""" def __init__(self, path: str | Path) -> None: """ Initialize the DockerfileModifier. This constructor loads the Dockerfile content and performs a clean up: - Removes all comment lines (lines starting with #) - Removes line continuations (backslash-newline) - Collapses multiple blank lines into a single blank line This normalization makes further text processing and modifications more robust and predictable. Args: path: Path to the Dockerfile to modify. """ self.path = Path(path) with open(self.path, encoding='utf-8') as f: self.content = f.read() # Clean up the content comments = re.compile(r'^\s*#.*\n', re.MULTILINE) self.content = comments.sub("", self.content) self.content = self.content.replace("\\\n", "") blank_line = re.compile(r'\n(\s)*\n', re.MULTILINE) self.content = blank_line.sub("\n", self.content) def flush(self) -> bool: """Write the modified content back to the file. Returns: True if write succeeded, False otherwise. """ try: with open(self.path, 'w', encoding='utf-8') as f: f.write(self.content) return True except IOError: return False def str_replace(self, old: str, new: str) -> None: """Replace all occurrences of old string with new string. Args: old: String to replace. new: Replacement string. """ self.content = self.content.replace(old, new) def str_replace_all(self, pairs: Dict[str, str]) -> None: """Replace multiple string pairs. Args: pairs: Dictionary of old -> new string mappings. """ for key, value in pairs.items(): self.str_replace(key, value) def replace_line_at(self, pos: int, line: str) -> None: """Replace the line at specified position. Args: pos: Line position (0-indexed). line: New line content. """ lines = self.content.split("\n") if 0 <= pos < len(lines): lines[pos] = line self.content = "\n".join(lines) def replace(self, old: str, new: str, flags: int = 0) -> None: """Replace using regular expressions. Args: old: Regular expression pattern. new: Replacement string. flags: Regular expression flags. """ self.content = re.sub(old, new, self.content, flags=flags) def replace_once(self, old: str, new: str) -> None: """Replace first occurrence using regular expressions. Args: old: Regular expression pattern. new: Replacement string. """ self.content = re.sub(old, new, self.content, count=1) def insert_line_before(self, target: str, newline: str) -> bool | None: """Insert a new line before the target line. Args: target: Target line to find. newline: New line to insert. Returns: None if target not found, otherwise inserts the line. """ line_num = self.locate_str(target) if line_num is False: return False self.insert_line_at(line_num, newline) return None def insert_line_after(self, target: str, newline: str) -> bool | None: """Insert a new line after the target line. Args: target: Target line to find. newline: New line to insert. Returns: None if target not found, otherwise inserts the line. """ line_num = self.locate_str(target) if line_num is False: return False self.insert_line_at(line_num + 1, newline) return None def insert_line_at(self, pos: int, line: str) -> None: """Insert a line at specified position. Args: pos: Position to insert at. line: Line content to insert. """ lines = self.content.split("\n") lines.insert(pos, line) self.content = "\n".join(lines) def remove_range(self, starts: int, ends: int) -> None: """Remove lines in the specified range. Args: starts: Start line number (inclusive). ends: End line number (exclusive). """ lines = self.content.split("\n") new_lines = [] for num, line in enumerate(lines): if not (starts <= num < ends): new_lines.append(line) self.content = '\n'.join(new_lines) def clean_comments(self) -> None: """Remove comment lines from the content.""" pattern = re.compile(r'^#.*', re.MULTILINE) self.content = pattern.sub('', self.content) newline_pattern = re.compile(r'^\n', re.MULTILINE) self.content = newline_pattern.sub('', self.content) def locate_str(self, keyword: str) -> int | bool: """Find the line number containing the keyword. Args: keyword: Keyword to search for. Returns: Line number if found, False otherwise. """ lines = self.content.split("\n") for line_num, line in enumerate(lines): if keyword in line: return line_num return False def get_line(self, keyword: str) -> Tuple[List[str], int]: """Get lines containing the keyword and the last line number. Args: keyword: Keyword to search for. Returns: Tuple of (matching_lines, last_line_number). """ lines = self.content.split("\n") matching_lines = [] last_line_num = 0 for line_num, line in enumerate(lines, 1): if keyword in line: matching_lines.append(line) last_line_num = line_num if len(matching_lines) < 2: return matching_lines, last_line_num # Use regex for more precise matching pattern = re.compile(rf"{keyword}(\s.*$|$)") matching_lines = [] last_line_num = 0 for line_num, line in enumerate(lines, 1): if pattern.search(line): matching_lines.append(line) last_line_num = line_num return matching_lines, last_line_num class VersionControlTool: """A unified interface for version control operations (git, hg, svn).""" def __init__(self, repo_path: str | Path, vc_type: str = 'git', revision: str | None = None, latest: bool = False) -> None: """Initialize the VersionControlTool. Args: repo_path: Path to the repository or URL to clone. vc_type: Version control type ('git', 'hg', 'svn'). revision: Specific revision to checkout. latest: Whether to pull latest changes. Raises: ValueError: If vc_type is not supported. """ if vc_type not in ['git', 'hg', 'svn']: raise ValueError(f'VersionControlTool: Does not support {vc_type}') self.type = vc_type repo_path_obj = Path(repo_path) if isinstance(repo_path, str) else repo_path if not repo_path_obj.exists(): repo_path_obj = self.clone(str(repo_path), revision) if not repo_path_obj: raise RuntimeError(f'VersionControlTool: Failed to init {repo_path}') self.repo = repo_path_obj self.name = self.repo.name if latest and not self.pull(): raise RuntimeError(f'VersionControlTool: Failed to Update {repo_path}') def pull(self) -> bool: """Pull latest changes from the repository. Returns: True if pull succeeded, False otherwise. """ if self.type == 'git': return _git_pull(self.repo) elif self.type == 'hg': return _hg_pull(self.repo) else: return _svn_pull(self.repo) def clone(self, url: str, revision: str | None = None) -> Path | bool: """Clone the repository. Args: url: Repository URL to clone. revision: Specific revision to checkout. Returns: Path to cloned repository on success, False on failure. """ if self.type == 'git': repo = clone(url, revision) if repo is not False: self.repo = list(repo.iterdir())[0] return self.repo elif self.type == 'hg': repo = hg_clone(url, revision) if repo is not False: self.repo = list(repo.iterdir())[0] return self.repo else: repo = svn_clone(url, revision) if repo is not False: self.repo = list(repo.iterdir())[0] return self.repo return False def commit_date(self, commit: str) -> str | bool: """Get the date of a specific commit. Args: commit: Commit hash or revision. Returns: Formatted date string on success, False on failure. """ def time_reformat(original_str: str) -> str: """Reformat time string to standard format.""" original_dt = datetime.strptime(original_str, "%Y-%m-%d %H:%M:%S %z") utc_dt = original_dt.astimezone(pytz.utc) return utc_dt.strftime("%Y%m%d%H%M") if self.type == 'git': result = execute(['git', 'show', '-s', '--format=%ci', commit], self.repo) if result.success and result.output: return time_reformat(result.output.decode()) elif self.type == 'hg': result = execute(['hg', 'log', '-r', commit, '--template', '{date}'], self.repo) if result.success and result.output: timestamp = int(result.output.decode().split(".")[0]) return datetime.utcfromtimestamp(timestamp).strftime('%Y%m%d%H%M') else: result = execute(['svn', 'log', '-r', commit, '-q'], self.repo) if result.success and result.output: lines = result.output.decode().split('\n') if len(lines) > 1: date_part = lines[1].split(' | ')[2].split(' (')[0] return time_reformat(date_part) return False def reset(self, commit: str) -> bool: """Reset the repository to a specific commit. Args: commit: Commit hash or revision to reset to. Returns: True if reset succeeded, False otherwise. """ if self.type == 'git': cmd = ['git', 'reset', '--hard', commit] with open('/dev/null', 'w', encoding='utf-8') as f: return check_call(cmd, self.repo, stdout=f) elif self.type == 'hg': cmd1 = ['hg', 'update', '--clean', '-r', commit] cmd2 = ['hg', "purge", '--config', 'extensions.purge='] return (check_call(cmd1, self.repo) and check_call(cmd2, self.repo)) elif self.type == "svn": return check_call(['svn', "up", '--force', '-r', commit], cwd=self.repo) return False def docker_build(args: List[str], log_file: Path | None = None) -> bool: """Build a Docker image. Args: args: Arguments for docker build command. log_file: Optional log file to write output. Returns: True if build succeeded, False otherwise. """ cmd = ['docker', 'build'] cmd.extend(args) logging.info("Docker Build: \n" + " ".join(cmd)) if log_file: with open(log_file, 'w', encoding='utf-8') as f: result = check_call(cmd, stderr=f, stdout=f) f.write("\n" + " ".join(cmd) + "\n") return result else: return check_call(cmd) def docker_run(args: List[str], rm: bool = True, log_file: Path | None = None) -> bool: """Run a Docker container. Args: args: Arguments for docker run command. rm: Whether to automatically remove the container when it exits. log_file: Optional log file to write output. Returns: True if run succeeded, False otherwise. """ if rm: cmd = ['docker', 'run', '--rm', '--privileged'] else: cmd = ['docker', 'run', '--privileged'] cmd.extend(args) logging.info("Docker Run: \n" + " ".join(cmd)) if log_file: with open(log_file, 'w', encoding='utf-8') as f: result = check_call(cmd, stdout=f, stderr=f) f.write("\n" + " ".join(cmd) + "\n") return result else: return check_call(cmd) def clean_dir(directory: Path) -> bool: """Remove a directory and all its contents. Args: directory: Directory to remove. Returns: True if removal succeeded, False otherwise. """ if not directory.exists(): return True try: shutil.rmtree(directory) return True except OSError: logging.warning(f"[FAILED] to remove tmp file {directory}") return False def leave_ret(return_val: Any, tmp_dirs: Path | list[Path]) -> Any: """ Clean up temporary directories and return a value. This function is used to ensure that any temporary directories created during the execution of a process are properly removed before returning a result. It accepts either a single Path or a list of Paths, and attempts to remove each directory (and its contents) using clean_dir. This helps prevent resource leaks and keeps the filesystem clean after temporary work is done. Args: return_val: Value to return after cleanup. tmp_dirs: Temporary directory or list of directories to clean up. Returns: The return_val parameter, after cleanup is performed. """ if isinstance(tmp_dirs, list): for tmp_dir in tmp_dirs: clean_dir(tmp_dir) else: clean_dir(tmp_dirs) return return_val if __name__ == "__main__": pass ================================================ FILE: infra/experimental/contrib/arvo/component_fixes.json ================================================ { "/src/freetype2": "https://github.com/freetype/freetype2", "/src/freetype": "https://github.com/freetype/freetype", "/src/pcre2": "https://github.com/PCRE2Project/pcre2", "/src/skia/third_party/externals/libjpeg-turbo": "https://github.com/libjpeg-turbo/libjpeg-turbo.git", "/src/radare2-regressions": "https://github.com/rlaemmert/radare2-regressions.git", "/src/x264": "https://code.videolan.org/videolan/x264.git", "/src/x265": "https://bitbucket.org/multicoreware/x265_git.git", "/src/vorbis": "https://gitlab.xiph.org/xiph/vorbis.git", "/src/theora": "https://gitlab.xiph.org/xiph/theora.git", "/src/opus": "https://gitlab.xiph.org/xiph/opus.git", "/src/ogg": "https://gitlab.xiph.org/xiph/ogg.git", "/src/libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", "/src/wireshark": "https://github.com/wireshark/wireshark.git", "/src/kimageformats": "https://invent.kde.org/frameworks/kimageformats.git", "/src/extra-cmake-modules": "https://invent.kde.org/frameworks/extra-cmake-modules.git", "/src/kcodecs": "https://github.com/KDE/kcodecs.git", "/src/karchive": "https://invent.kde.org/frameworks/karchive.git", "/src/libtheora": "https://gitlab.xiph.org/xiph/theora.git", "/src/libva": "https://github.com/intel/libva.git", "/src/libssh2": "https://github.com/libssh2/libssh2.git", "/src/quickjs": "https://github.com/bellard/quickjs", "/src/lwan": "https://github.com/lpereira/lwan.git", "/src/graphicsmagick": "https://foss.heptapod.net/graphicsmagick/graphicsmagick", "/src/llvm": "https://github.com/llvm/llvm-project.git", "/src/pcre": "https://github.com/PhilipHazel/pcre2", "/src/gnulib": "https://github.com/coreutils/gnulib.git", "/src/net-snmp": "https://github.com/net-snmp/net-snmp.git", "/src/harfbuzz": "https://github.com/harfbuzz/harfbuzz.git", "/src/matio": "https://github.com/tbeu/matio.git", "/src/aspell": "https://github.com/gnuaspell/aspell.git", "/src/libsndfile": "https://github.com/libsndfile/libsndfile.git", "/src/poppler": "https://gitlab.freedesktop.org/poppler/poppler.git", "/src/gdal/poppler": "https://gitlab.freedesktop.org/poppler/poppler.git", "/src/gdal/curl": "https://github.com/curl/curl.git", "/src/ghostpdl": "https://cgit.ghostscript.com/ghostpdl.git", "/src/cryptofuzz": "https://github.com/MozillaSecurity/cryptofuzz.git", "/src/python-library-fuzzers": "https://github.com/hugovk/python-library-fuzzers.git", "/src/libmicrohttpd": "https://git.gnunet.org/libmicrohttpd.git" } ================================================ FILE: infra/experimental/contrib/arvo/hacks/__init__.py ================================================ """Project-specific hacks for fixing Dockerfiles and build scripts. This module contains project-specific fixes that solve building/compiling problems for various OSS-Fuzz projects. Each project has its own module with dedicated hack functions. """ import importlib from abc import ABC, abstractmethod from pathlib import Path try: from ..arvo_utils import DockerfileModifier except ImportError: # Fallback for when module is imported directly from arvo_utils import DockerfileModifier class ProjectHack(ABC): """Base class for project-specific hacks.""" def __init__(self): self.commit_date = None def set_commit_date(self, commit_date): """Set the commit date for hacks that need it.""" self.commit_date = commit_date @abstractmethod def apply_dockerfile_fixes(self, dft: DockerfileModifier) -> bool: """Apply project-specific fixes to a Dockerfile. Args: dft: DockerfileModifier instance for the project's Dockerfile. Returns: True if fixes were applied successfully, False otherwise. """ pass def apply_build_script_fixes(self, dft: DockerfileModifier) -> bool: """Apply project-specific fixes to a build script. Args: dft: DockerfileModifier instance for the project's build script. Returns: True if fixes were applied successfully, False otherwise. """ # Default implementation - no build script fixes return True def apply_extra_fixes(self, source_dir: Path) -> bool: """Apply extra project-specific fixes that require file system operations. Args: source_dir: Path to the source directory. Returns: True if fixes were applied successfully, False otherwise. """ # Default implementation - no extra fixes return True def get_project_hack(project_name: str) -> ProjectHack | None: """Get a project hack instance by name using dynamic import.""" try: # Try to import the module for this project module = importlib.import_module(f".{project_name}", __name__) # Look for a class that ends with 'Hack' and is a subclass of ProjectHack for attr_name in dir(module): attr = getattr(module, attr_name) if (isinstance(attr, type) and issubclass(attr, ProjectHack) and attr != ProjectHack): return attr() # If no hack class found, return None return None except ImportError: # No hack module for this project return None # Helper functions that can be reused across projects def x265_fix(dft: DockerfileModifier) -> None: """Apply x265-specific fixes to the dockerfile modifier. This is a common fix used by multiple projects that depend on x265. The order of these replacements matters. """ dft.replace( r'RUN\shg\sclone\s.*bitbucket.org/multicoreware/x265\s*(x265)*', "RUN git clone " "https://bitbucket.org/multicoreware/x265_git.git x265\n") dft.replace( r'RUN\shg\sclone\s.*hg\.videolan\.org/x265\s*(x265)*', "RUN git clone " "https://bitbucket.org/multicoreware/x265_git.git x265\n") ================================================ FILE: infra/experimental/contrib/arvo/hacks/cryptofuzz.py ================================================ """Cryptofuzz project-specific hacks.""" from . import ProjectHack class CryptofuzzHack(ProjectHack): """Hacks for the Cryptofuzz project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix Cryptofuzz Dockerfile issues.""" # Fix libressl update script dft.insert_line_before( "RUN cd $SRC/libressl && ./update.sh", "RUN sed -n -i '/^# setup source paths$/,$p' $SRC/libressl/update.sh") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/dlplibs.py ================================================ """DLPLibs project-specific hacks.""" from . import ProjectHack class DLPLibsHack(ProjectHack): """Hacks for the DLPLibs project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix DLPLibs Dockerfile issues.""" dft.replace(r"ADD", '# ADD') dft.replace(r"RUN wget", '#RUN wget') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/duckdb.py ================================================ """DuckDB project-specific hacks.""" from . import ProjectHack class DuckDBHack(ProjectHack): """Hacks for the DuckDB project.""" def apply_dockerfile_fixes(self, dft) -> bool: """No Dockerfile fixes needed for DuckDB.""" return True def apply_build_script_fixes(self, dft) -> bool: """Fix DuckDB build script issues.""" dft.replace(r'^make$', 'make -j`nproc`\n') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/ffmpeg.py ================================================ """FFmpeg project-specific hacks.""" from . import ProjectHack, x265_fix class FFmpegHack(ProjectHack): """Hacks for the FFmpeg project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix FFmpeg Dockerfile issues.""" # Apply x265 fixes x265_fix(dft) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/ghostscript.py ================================================ """Ghostscript project-specific hacks.""" from . import ProjectHack class GhostscriptHack(ProjectHack): """Hacks for the Ghostscript project.""" def apply_dockerfile_fixes(self, dft) -> bool: """No Dockerfile fixes needed for Ghostscript.""" return True def apply_build_script_fixes(self, dft) -> bool: """Fix Ghostscript build script issues.""" old = r"mv \$SRC\/freetype freetype" new = "cp -r $SRC/freetype freetype" dft.replace(old, new) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/gnutls.py ================================================ """GnuTLS project-specific hacks.""" from . import ProjectHack class GnuTLSHack(ProjectHack): """Hacks for the GnuTLS project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix GnuTLS Dockerfile issues.""" dft.str_replace(" libnettle6 ", " ") dft.replace(r".*client_corpus_no_fuzzer_mode.*", "") dft.replace(r".*server_corpus_no_fuzzer_mode.*", "") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/graphicsmagick.py ================================================ """GraphicsMagick project-specific hacks.""" from . import ProjectHack, x265_fix class GraphicsMagickHack(ProjectHack): """Hacks for the GraphicsMagick project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix GraphicsMagick Dockerfile issues.""" # Fix mercurial clone with retry logic dft.replace( r'RUN hg clone .* graphicsmagick', 'RUN (CMD="hg clone --insecure ' 'https://foss.heptapod.net/graphicsmagick/graphicsmagick ' 'graphicsmagick" && ' 'for x in `seq 1 100`; do $($CMD); ' 'if [ $? -eq 0 ]; then break; fi; done)') # Apply x265 fixes x265_fix(dft) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/imagemagick.py ================================================ """ImageMagick project-specific hacks.""" from pathlib import Path from . import ProjectHack class ImageMagickHack(ProjectHack): """Hacks for the ImageMagick project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix ImageMagick Dockerfile issues.""" # Fix heic corpus download issue dft.replace(r'RUN svn .*heic_corpus.*', "RUN mkdir /src/heic_corpus && touch /src/heic_corpus/XxX") return True def apply_extra_fixes(self, source_dir: Path) -> bool: """Apply extra ImageMagick-specific fixes.""" # TODO: Improve this hack target = (source_dir / "src" / "imagemagick" / "Magick++" / "fuzz" / "build.sh") if target.exists(): with open(target, encoding='utf-8') as f: lines = f.readlines() for x in range(3): if lines and "zip" in lines[-x - 1]: del lines[-x - 1] with open(target, 'w', encoding='utf-8') as f: f.write("\n".join(lines)) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/jbig2dec.py ================================================ """JBIG2DEC project-specific hacks.""" from . import ProjectHack class JBIG2DECHack(ProjectHack): """Hacks for the JBIG2DEC project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix JBIG2DEC Dockerfile issues.""" dft.replace(r'RUN cd tests .*', "") return True def apply_build_script_fixes(self, dft) -> bool: """Fix JBIG2DEC build script issues.""" dft.replace('unzip.*', 'exit 0') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/lcms.py ================================================ """LCMS project-specific hacks.""" from . import ProjectHack class LCMSHack(ProjectHack): """Hacks for the LCMS project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix LCMS Dockerfile issues.""" # TODO: improve this tmp patch dft.replace(r'#add more seeds from the testbed dir.*\n', "") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/libheif.py ================================================ """LibHeif project-specific hacks.""" from . import ProjectHack, x265_fix class LibHeifHack(ProjectHack): """Hacks for the LibHeif project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix LibHeif Dockerfile issues.""" # Apply x265 fixes x265_fix(dft) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/libredwg.py ================================================ """LibreDWG project-specific hacks.""" from . import ProjectHack class LibreDWGHack(ProjectHack): """Hacks for the LibreDWG project.""" def apply_dockerfile_fixes(self, dft) -> bool: """No Dockerfile fixes needed for LibreDWG.""" return True def apply_build_script_fixes(self, dft) -> bool: """Fix LibreDWG build script issues.""" dft.replace(r'^make$', 'make -j`nproc`\n') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/libreoffice.py ================================================ """LibreOffice project-specific hacks.""" from . import ProjectHack class LibreOfficeHack(ProjectHack): """Hacks for the LibreOffice project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix LibreOffice Dockerfile issues.""" # Fix setup script and disable various commands dft.str_replace( 'RUN ./bin/oss-fuzz-setup.sh', "RUN sed -i 's|svn export --force -q https://github.com|" "#svn export --force -q https://github.com|g' " "./bin/oss-fuzz-setup.sh") dft.str_replace('RUN svn export', '# RUN svn export') dft.str_replace('ADD ', '# ADD ') dft.str_replace('RUN zip', '# RUN zip') dft.str_replace('RUN mkdir afl-testcases', "# RUN mkdir afl-testcases") dft.str_replace( 'RUN ./bin/oss-fuzz-setup.sh', "# RUN ./bin/oss-fuzz-setup.sh") # Avoid downloading not related stuff return True def apply_build_script_fixes(self, dft) -> bool: """Fix LibreOffice build script issues.""" # If you don't want to destroy your life. # Please leave this project alone. too hard to fix and the compiling # takes several hours line = '$SRC/libreoffice/bin/oss-fuzz-build.sh' dft.insert_line_before( line, "sed -i 's/make fuzzers/make fuzzers -i/g' " "$SRC/libreoffice/bin/oss-fuzz-build.sh") dft.insert_line_before( line, "sed -n -i '/#starting corpuses/q;p' " "$SRC/libreoffice/bin/oss-fuzz-build.sh") dft.insert_line_before( line, r"sed -n -i '/pushd instdir\/program/q;p' " r"$SRC/libreoffice/bin/oss-fuzz-build.sh") dft.insert_line_before( line, 'echo "pushd instdir/program && mv *fuzzer $OUT" >> ' '$SRC/libreoffice/bin/oss-fuzz-build.sh') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/libyang.py ================================================ """LibYang project-specific hacks.""" from . import ProjectHack class LibYangHack(ProjectHack): """Hacks for the LibYang project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix LibYang Dockerfile issues.""" dft.str_replace( 'RUN git clone https://github.com/PCRE2Project/pcre2 pcre2 &&', "RUN git clone https://github.com/PCRE2Project/pcre2 pcre2\n" "RUN ") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/lwan.py ================================================ """Lwan project-specific hacks.""" from . import ProjectHack class LwanHack(ProjectHack): """Hacks for the Lwan project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix Lwan Dockerfile issues.""" dft.str_replace('git://github.com/lpereira/lwan', 'https://github.com/lpereira/lwan.git') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/openh264.py ================================================ """OpenH264 project-specific hacks.""" from . import ProjectHack class OpenH264Hack(ProjectHack): """Hacks for the OpenH264 project.""" def apply_dockerfile_fixes(self, dft) -> bool: """No Dockerfile fixes needed for OpenH264.""" return True def apply_build_script_fixes(self, dft) -> bool: """Fix OpenH264 build script issues.""" lines = dft.content.split("\n") starts = -1 ends = -1 for num, line in enumerate(lines): if "# prepare corpus" in line: starts = num elif "# build" in line: ends = num break if starts != -1 and ends != -1: dft.remove_range(starts, ends) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/quickjs.py ================================================ """QuickJS project-specific hacks.""" from . import ProjectHack class QuickJSHack(ProjectHack): """Hacks for the QuickJS project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix QuickJS Dockerfile issues.""" dft.str_replace('https://github.com/horhof/quickjs', 'https://github.com/bellard/quickjs') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/radare2.py ================================================ """Radare2 project-specific hacks.""" from . import ProjectHack class Radare2Hack(ProjectHack): """Hacks for the Radare2 project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix Radare2 Dockerfile issues.""" dft.str_replace("https://github.com/radare/radare2-regressions", 'https://github.com/rlaemmert/radare2-regressions.git') return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/skia.py ================================================ """Skia project-specific hacks.""" from . import ProjectHack class SkiaHack(ProjectHack): """Hacks for the Skia project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix Skia Dockerfile issues.""" # Comment out wget commands and fix build script dft.str_replace('RUN wget', "# RUN wget") dft.insert_line_after('COPY build.sh $SRC/', "RUN sed -i 's/cp.*zip.*//g' $SRC/build.sh") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/uwebsockets.py ================================================ """uWebSockets project-specific hacks.""" from . import ProjectHack class UWebSocketsHack(ProjectHack): """Hacks for the uWebSockets project.""" def apply_dockerfile_fixes(self, dft) -> bool: """No Dockerfile fixes needed for uWebSockets.""" return True def apply_build_script_fixes(self, dft) -> bool: """Fix uWebSockets build script issues.""" # https://github.com/alexhultman/zlib -> https://github.com/madler/zlib.git script = "sed -i 's/alexhultman/madler/g' fuzzing/Makefile" dft.insert_line_at(0, script) return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/wireshark.py ================================================ """Wireshark project-specific hacks.""" from . import ProjectHack class WiresharkHack(ProjectHack): """Hacks for the Wireshark project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix Wireshark Dockerfile issues.""" dft.replace(r"RUN git clone .*wireshark.*", "") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/wolfssl.py ================================================ """WolfSSL project-specific hacks.""" from . import ProjectHack class WolfSSLHack(ProjectHack): """Hacks for the WolfSSL project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix WolfSSL Dockerfile issues.""" # Replace gsutil cp command with a simple touch and zip dft.str_replace( 'RUN gsutil cp ' 'gs://wolfssl-backup.clusterfuzz-external.appspot.com/' 'corpus/libFuzzer/wolfssl_cryptofuzz-disable-fastmath/public.zip ' '$SRC/corpus_wolfssl_disable-fastmath.zip', "RUN touch 0xdeadbeef && " "zip $SRC/corpus_wolfssl_disable-fastmath.zip 0xdeadbeef") return True ================================================ FILE: infra/experimental/contrib/arvo/hacks/yara.py ================================================ """YARA project-specific hacks.""" from . import ProjectHack class YARAHack(ProjectHack): """Hacks for the YARA project.""" def apply_dockerfile_fixes(self, dft) -> bool: """Fix YARA Dockerfile issues.""" if 'bison' not in dft.content: dft.insert_line_before( "RUN git clone https://github.com/VirusTotal/yara.git", "RUN apt install -y bison") return True ================================================ FILE: infra/experimental/contrib/arvo/string_replacement.json ================================================ { "http://download.icu-project.org/files/icu4c/59.1/": "https://github.com/unicode-org/icu/releases/download/release-59-1/", "git://git.gnome.org/libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", "svn co svn://vcs.exim.org/pcre2/code/trunk pcre2": "git clone https://github.com/PCRE2Project/pcre2 pcre2", "https://git.savannah.nongnu.org/r/freetype/freetype2": "https://github.com/freetype/freetype2", "https://git.savannah.gnu.org/git/freetype/freetype2.git": "https://github.com/freetype/freetype2", "git://git.sv.nongnu.org/freetype/freetype2.git": "https://github.com/freetype/freetype2", "ftp://ftp.unidata.ucar.edu/pub/netcdf/netcdf-4.4.1.1.tar.gz": "-L http://ppmcore.mpi-cbg.de/upload/netcdf-4.4.1.1.tar.gz", "RUN curl http": "RUN curl -L http", "&& curl http": "&& curl -L http", "https://github.com/01org/libva": "https://github.com/intel/libva.git", "https://github.com/intel/libva\n": "https://github.com/intel/libva.git\n", "http://www.zlib.net/zlib-1.2.11.tar.gz": "https://www.zlib.net/fossils/zlib-1.2.11.tar.gz", "https://jannau.net/dav1d_fuzzer_seed_corpus.zip": "https://download.videolan.org/pub/videolan/testing/contrib/dav1d/dav1d_fuzzer_seed_corpus.zip", "git://git.xiph.org/ogg.git": "https://gitlab.xiph.org/xiph/ogg.git", "https://github.com/xiph/ogg.git": "https://gitlab.xiph.org/xiph/ogg.git", "git://git.xiph.org/opus.git": "https://gitlab.xiph.org/xiph/opus.git", "git://git.xiph.org/theora.git": "https://gitlab.xiph.org/xiph/theora.git", "git://git.xiph.org/vorbis.git": "https://gitlab.xiph.org/xiph/vorbis.git", "svn co http://svn.xiph.org/trunk/ogg": "git clone https://gitlab.xiph.org/xiph/ogg.git", "git://git.videolan.org/git/x264.git": "https://code.videolan.org/videolan/x264.git", "http://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz": "https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz", "https://downloads.apache.org/maven/maven-3/3.6.3/binaries/": "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/", "https://downloads.apache.org/maven/maven-3/3.8.6/binaries/": "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/", "https://downloads.apache.org/maven/maven-3/3.8.5/binaries/": "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/", "https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/": "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/", "https://dlcdn.apache.org/maven/maven-3/3.8.5/binaries/": "https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/", "https://opus-codec.org/static/testvectors/opus_testvectors.tar.gz": "http://opus-codec.org/static/testvectors/opus_testvectors.tar.gz", "https://anongit.freedesktop.org/git/harfbuzz.git": "https://github.com/harfbuzz/harfbuzz.git", "git://anongit.kde.org/extra-cmake-modules": "https://invent.kde.org/frameworks/extra-cmake-modules.git", "git://anongit.kde.org/kimageformats": "https://invent.kde.org/frameworks/kimageformats.git", "git://anongit.kde.org/karchive": "https://invent.kde.org/frameworks/karchive.git", "git://git.savannah.gnu.org/gnulib.git": "https://github.com/coreutils/gnulib.git", "svn co http://llvm.org/svn/llvm-project/llvm/trunk": "git clone https://github.com/llvm/llvm-project.git", "svn co svn://vcs.exim.org/pcre/code/trunk": "git clone https://github.com/PhilipHazel/pcre2", "https://github.com/cmeister2/libssh2.git": "https://github.com/libssh2/libssh2.git", "git://git.code.sf.net/p/matio/matio": "https://github.com/tbeu/matio.git", "https://github.com/cmeister2/aspell.git": "https://github.com/gnuaspell/aspell.git", "https://github.com/erikd/libsndfile.git": "https://github.com/libsndfile/libsndfile.git", "https://anongit.freedesktop.org/git/poppler/poppler.git": "https://gitlab.freedesktop.org/poppler/poppler.git", "https://gitlab.freedesktop.org/ceyhunalp/poppler.git": "https://gitlab.freedesktop.org/poppler/poppler.git", "git.ghostscript.com/ghostpdl.git": "cgit.ghostscript.com/ghostpdl.git", "https://github.com/guidovranken/cryptofuzz\n": "https://github.com/MozillaSecurity/cryptofuzz.git\n", "https://gnunet.org/git": "https://git.gnunet.org", " --depth 1": "", " --depth=1": "", " --depth ": " --jobs ", " --recursive ": " " } ================================================ FILE: infra/experimental/mcp/.gitignore ================================================ .venv __pycache__ ================================================ FILE: infra/experimental/mcp/README.md ================================================ # OSS-Fuzz MCP This is an experimental implementation of an MCP server that enables use of OSS-Fuzz tools. You can use it to solve various common OSS-Fuzz tasks. At this stage, this is purely experimental code. ## Threat model for running This is experimental code and has an open threat model. By design, the MCP server executes untrusted code. As such, when running this tool you should assume you will be running untrusted code on your machine. You should only run this in a trusted environment and on a trusted network. In practice, this means you must run this in a heavily sandboxed environment, and from a security perspective if you run this tool you will run untrusted code in your environment. This code does not run in OSS-Fuzz production services and is not part of the tooling that runs our continuous fuzzing of open source projects. ## Running the Service ```sh python3.12 -m venv .venv . .venv/bin/active python3 -m pip install -r ./requirements.txt # Start server in one terminal python3 ./oss_fuzz_server.py # Start client python3 ./client.py fix-build --projects abseil-py ``` ================================================ FILE: infra/experimental/mcp/client.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Client for OSS-Fuzz MCP server.""" import asyncio import os import shutil import logging import random import subprocess import argparse import time import sys import httpx import pathlib from pydantic_ai import Agent from pydantic_ai.mcp import MCPServerStdio import config as oss_fuzz_mcp_config # Configure logging logging.basicConfig( level=logging.INFO, format="[CLIENT] %(asctime)s - %(name)s - %(levelname)s - %(message)s", stream=sys.stderr) logger = logging.getLogger("mcp-server") MCP_SERVER_URL = "http://localhost:8000/sse" OSS_FUZZ_SYSTEM_PROMPT = f"""You are an expert software security engineer that is specialized in OSS-Fuzz. OSS-Fuzz is a framework for managing fuzzing of projects, including building the projects, writing fuzzing harnesses, and running the fuzzing harnesses. An OSS-Fuzz project in general consists of a Dockerfile, a build.sh script, and a project.yaml file. The Dockerfile is used to build the project and the build.sh script is used to build the fuzzing harnesses. The project.yaml file holds metadata. OSS-Fuzz builds the projects inside a container and links the fuzzing harnesses inside the container. The fuzzer executables, and relevant files, are copied to the $OUT directory. There are three key tasks in OSS-Fuzz: 1. Fixing broken OSS-Fuzz projects. Sometimes the OSS-Fuzz projects fail to build, which is likely either a broken Dockerfile, broken build.sh or broken fuzzing harness source codes. This often need to be fixed. 2. Creating new OSS-Fuzz projects. This is done by creating a new Dockerfile, build.sh, project.yaml and also fuzzing harnesses. This requires studying the project source code and coming up with a set up where the fuzzing harnesses exist in the OSS-Fuzz project directory structure. 3. Improving the code coverage of existing OSS-Fuzz projects by adding new fuzzing harnesses or extending existing ones. You are an expert in completing the above tasks. The OSS-Fuzz source code is available at {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}. The various OSS-Fuzz projects are available in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects. You have access to the MCP tools, which allow you to read and write files, run commands, and interact with the OSS-Fuzz framework. You must use these tools to complete the tasks. Each OSS-Fuzz project targets fuzzing of a relevant open source project. Often you need to look at the source code of this project, which exists in {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/"the project name"/... This source code is a local version of the project and *not* the paths that exist in the container. You should not adjust the files in this directory, but only read and study them. In case you need to add changes to the source code, then these should be done directly by way of the Dockerfile and build.sh script. Inside the container, in general the fuzzing harness is placed at $SRC/harness_name... and the project code is in $SRC/project_name. A sample structure for an OSS-Fuzz project is rapidjson (located at {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/rapidjson/)) which has the following relevant files: Dockerfile: ``` FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y make autoconf automake libtool cmake libgtest-dev RUN git clone --depth 1 https://github.com/Tencent/rapidjson.git rapidjson WORKDIR rapidjson COPY *.sh fuzzer.cpp $SRC/ ``` build.sh ``` export CXXFLAGS="$CXXFLAGS -pthread" if [[ $CFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi if [[ $CFLAGS = *sanitize=address* ]] then export CXXFLAGS="$CXXFLAGS -DASAN" fi # First build library and tests, which is needed for OSS-Fuzz's Chronos. mkdir build cd build cmake ../ make -j$(nproc) cd ../ # Build fuzz harness. $CXX $CXXFLAGS -D_GLIBCXX_DEBUG -I $SRC/rapidjson/include $SRC/fuzzer.cpp $LIB_FUZZING_ENGINE -o $OUT/fuzzer ``` fuzzer.cpp ``` #include #include #include #include #include #ifdef MSAN extern "C" {{ void __msan_check_mem_is_initialized(const volatile void *x, size_t size); }} #endif template void fuzzWithFlags(const std::string &s) {{ /* Parse input to rapidjson::Document */ rapidjson::Document document; rapidjson::ParseResult pr = document.Parse(s.c_str()); if ( !pr ) {{ return; }} /* Convert from rapidjson::Document to string */ rapidjson::StringBuffer sb; rapidjson::PrettyWriter writer(sb); document.Accept(writer); std::string str = sb.GetString(); #ifdef MSAN if ( str.size() ) {{ __msan_check_mem_is_initialized(str.data(), str.size()); }} #endif }} extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {{ const std::string s(data, data + size); fuzzWithFlags(s); fuzzWithFlags(s); fuzzWithFlags(s); fuzzWithFlags(s); return 0; }} ``` OSS-Fuzz supports multiple languages: - C - C++ - Go - Python - Java """ async def run_agent_loop(prompt: str) -> list: """ Performs a run with the LLM. Args: prompt: The user's message Returns: List of Nodes each a step in agent execution. """ nodes = [] try: server = MCPServerStdio( 'python3', [str(pathlib.Path(__file__).parent.resolve()) + '/oss_fuzz_server.py'], timeout=5200.0) agent = Agent(model="openai:gpt-4", toolsets=[server], retries=30) # Run the agent with the MCP server context logger.info('Starting agent run') async with agent.iter(prompt) as agent_run: logger.info('Agent run started') async for node in agent_run: logger.info('Running node [%d] %s', len(nodes), node.__class__.__name__) time.sleep(3) nodes.append(node) except Exception as e: logger.info('Error during agent run: %s', e) sys.exit(1) return nodes def initialize_oss_fuzz() -> None: """ Initialize the OSS-Fuzz environment by cloning the OSS-Fuzz repository. """ if not os.path.exists(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR): logger.info('Cloning OSS-Fuzz repository...') subprocess.check_call( f'git clone https://github.com/google/oss-fuzz.git {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}', shell=True) os.makedirs(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, exist_ok=True) def _get_oss_fuzz_filetree(project_name: str) -> str: """Gets the file tree for a given OSS-Fuzz project.""" project_dir = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', project_name) if not os.path.isdir(project_dir): logger.warning('Project directory does not exist: %s', project_dir) return '' file_tree = [] for root, _, files in os.walk(project_dir): for fname in files: file_tree.append(os.path.join(project_dir, root, fname)) return '\n'.join(file_tree) def _get_upstream_repo(project_name: str) -> str: """Gets the upstream repository URL for a given project.""" project_yaml = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', project_name, 'project.yaml') if not os.path.exists(project_yaml): logger.warning('Project YAML does not exist: %s', project_yaml) return '' with open(project_yaml, 'r', encoding='utf-8') as f: project_data = f.read() main_repo = '' for line in project_data.split('\n'): if line.startswith('main_repo'): main_repo = line.replace('main_repo: ', '').strip() return main_repo def _detect_language(project_name: str) -> str: """Gets the likely language of a project, using file extension count.""" project_src = os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name) if not os.path.isdir(project_src): return '' languages = { 'c++': 0, 'c': 0, 'python': 0, 'jvm': 0, 'go': 0, } for _, _, fnames in os.walk(project_src): for fname in fnames: _, file_extension = os.path.splitext(fname) if file_extension in ['.c++', '.cpp', '.cc', '.hpp', '.h']: languages['c++'] += 1 if file_extension in ['.c', '.h']: languages['c'] += 1 if file_extension in ['.py']: languages['python'] += 1 if file_extension in ['.java']: languages['jvm'] += 1 if file_extension in ['.go']: languages['go'] += 1 max_language = max(languages, key=languages.get) # If max language is C, make sure it's not equal to C++ in the event only header files were counted. # In that scenario, we will consider only header files to be C++. if max_language == 'c' and languages['c'] == languages['c++']: max_language = 'c++' return max_language def prepare_oss_fuzz_project(project_name: str) -> bool: """Gets the main repo of an OSS-Fuzz project and clones it into our caching folder.""" # check the project yaml. project_yaml = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', project_name, 'project.yaml') if not os.path.exists(project_yaml): logger.warning('Project YAML does not exist: %s', project_yaml) return False if os.path.isdir( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name)): return True with open(project_yaml, 'r', encoding='utf-8') as f: project_data = f.read() main_repo = '' for line in project_data.split('\n'): if line.startswith('main_repo'): main_repo = line.replace('main_repo: ', '').strip() if not main_repo: raise Exception('No main_repo found in project.yaml') logger.info('Main repo: %s', main_repo) try: subprocess.check_call( 'git clone ' + main_repo + ' ' + os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name), shell=True, timeout=60 * 10) except subprocess.CalledProcessError as e: logger.info(f"Error cloning project {project_name}: {e}") return False except subprocess.TimeoutExpired: logger.info(f"Cloning project {project_name} timed out.") return False return os.path.isdir( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name)) async def does_project_build(project: str) -> bool: """Runs OSS-Fuzz build_fuzzers and check_build to validate if project is successful""" try: subprocess.check_call( f'python3 {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/infra/helper.py build_fuzzers ' + project, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, timeout=60 * 20) except subprocess.CalledProcessError: return False except subprocess.TimeoutExpired: logger.info(f"Building project {project} timed out.") return False try: subprocess.check_call( f'python3 {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/infra/helper.py check_build ' + project, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, timeout=60 * 10) except subprocess.CalledProcessError: return False except subprocess.TimeoutExpired: logger.info(f"Checking build for project {project} timed out.") return False return True async def fix_project_build(project: str, max_tries: int = 3): """Runs an agent to fix the build of an OSS-Fuzz project.""" project_language = _detect_language(project) extra_project_text = "" upstream_repo = _get_upstream_repo(project) if upstream_repo: extra_project_text += f"The upstream repository targeted by the OSS-Fuzz project is {upstream_repo}.\n" if project_language == 'python': extra_project_text += 'For Python projects, installing packages by way of pip should be done using `python3 -m pip ...` in the OSS-Fuzz build container.\n' oss_fuzz_filetree = _get_oss_fuzz_filetree(project) if oss_fuzz_filetree: extra_project_text += f'The files in the OSS-Fuzz project for {project} are:\n{oss_fuzz_filetree}\n' nodes = [] for _attempt in range(max_tries): logger.info('Attempt %d to fix project %s', _attempt + 1, project) nodes += await run_agent_loop( f"""Fix the OSS-Fuzz project {project} that currently has a broken build. Use the build logs from OSS-Fuzz's project {project} and determine why it fails, then proceed to adjust Dockerfile and build.sh scripts until the project builds. The OSS-Fuzz project {project} targets a project written in {project_language}. {extra_project_text} You should edit the files directly in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/ Once the project builds, then you must ensure the project passes OSS-Fuzz's "fuzzer-check". Do not stop testing new Dockerfile and build.sh scripts until the "fuzzer-check" passes. If you need access to the files of the project that is being built, then this is available at the path {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project}/ The files in {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project}/ are a copy for read-only purposes, and not the files that will exist in the build environment. In order to change files in the build environment, you must modify or create files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/. Use file operations tools to inspect the files. However, only modify and adjust the files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/... Some rules: - Do not change the ENTRYPOINT of the Dockerfile, it must remain as it is. - Do not adjust the Dockerfile so it copies files from the {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project}/... directory, as this is not the path that exists in the container. - You can add new files into the build environment by creating them in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/ and copying them into the environment by adjusting {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/Dockerfile. - The "fuzzer-check" must pass. - Continue adjusting the files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/ until "fuzzer-check" passes. """) fix_success = await does_project_build(project) if fix_success: logger.info('Project %s build fixed successfully.', project) break return nodes, fix_success def _get_all_broken_oss_fuzz_projects(language: str = '') -> list[str]: """Gets the projects that are failing to build in OSS-Fuzz.""" OSS_FUZZ_BUILD_STATUS_URL = 'https://oss-fuzz-build-logs.storage.googleapis.com' FUZZ_BUILD_JSON = 'status.json' fuzz_build_url = OSS_FUZZ_BUILD_STATUS_URL + '/' + FUZZ_BUILD_JSON raw_fuzz_builds = httpx.get(fuzz_build_url) if raw_fuzz_builds.status_code != 200: raise Exception( f"Failed to fetch OSS-Fuzz build status: {raw_fuzz_builds.status_code}") fuzz_builds = raw_fuzz_builds.json() broken_projects = [] for project in fuzz_builds.get('projects', []): if len(project.get('history', [])) <= 4: continue history = project['history'] # Ensure the latest three build are failing, as we don't want to "fix" projects # that spurious fail. This happens due to network issues, for example. if history[0]['success'] or history[1]['success'] or history[2]['success']: continue # Make sure the project actually exists in the OSS-Fuzz repository. # We need to do this because Clusterfuzz may keep some projects rolling # withouth them being in OSS-Fuzz any longer. project_path = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', project['name']) if not os.path.exists(project_path): continue if language: # Check which language project_yaml = os.path.join(project_path, 'project.yaml') if not os.path.exists(project_yaml): logger.info( f"Project {project['name']} does not have a project.yaml file, skipping." ) continue with open(project_yaml, 'r', encoding='utf-8') as f: project_data = f.read() project_language = '' for line in project_data.split('\n'): if line.startswith('language:'): project_language = line.replace('language:', '').strip().lower() break if project_language != language.lower(): continue broken_projects = [project['name']] + broken_projects return broken_projects async def add_run_tests_command(project_name: str): """Adds a run-tests.sh command for a specific OSS-Fuzz project.""" project_path = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', project_name) if not os.path.exists(project_path): logger.warning("Project %s does not exist in OSS-Fuzz.", project_name) return if not prepare_oss_fuzz_project(project_name): logger.warning("Failed to prepare OSS-Fuzz project %s.", project_name) return run_tests_path = os.path.join(project_path, 'run_tests.sh') if not os.path.exists(run_tests_path): with open(run_tests_path, 'w', encoding='utf-8') as f: f.write("#!/bin/bash\n") f.write("echo 'Running tests for project: {}'\n".format(project_name)) dockerfile_path = os.path.join(project_path, 'Dockerfile') if not os.path.exists(dockerfile_path): logger.info(f"Dockerfile does not exist for project {project_name}.") return with open(dockerfile_path, 'r', encoding='utf-8') as f: if 'run_tests.sh' not in f.read(): should_add = True else: should_add = False if should_add: with open(dockerfile_path, 'a', encoding='utf-8') as f: f.write("COPY run_tests.sh $SRC/\n") f.write("RUN chmod +x $SRC/run_tests.sh\n") os.chmod(run_tests_path, 0o755) await run_agent_loop(f""" You are an expert software security engineer that is specialized in OSS-Fuzz. You are tasked with adding a run_tests.sh script to an OSS-Fuzz project. This script should run the tests of the project, and ensure that the project is working correctly. The run_tests.sh script should be placed in the project directory at {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/run_tests.sh. You must ensure that the run_tests.sh script is executable and runs the tests of the project. The run_tests.sh script should be placed in the project directory at {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/run_tests.sh. You must ensure that the run_tests.sh script is executable and runs the tests of the project. You should assume the run_tests.sh script runs after the project is build, and that the starting working directory of the run_tests.sh script is the WORKDIR of the Dockerfile ($SRC if not otherwise specified). Your task is to fix the run_tests.sh script for {project_name} so it runs the tests of the project and also passes the `run-tests-check`. You are working on the OSS-Fuzz project {project_name}. You must ensure the check `run-tests-check` passes! Continue creating a new run_tests.sh script until the check passes. You must adjust the file in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/run_tests.sh to execute the tests. You must run the `run-tests-check` after adjusting the script.""") async def expand_existing_project(project_name: str): """Expands existing coverage harnesses of a given project.""" if not prepare_oss_fuzz_project(project_name): logger.info('Failed to prepare %s. Exiting.', project_name) return nodes = await run_agent_loop( f"""You are a security engineer that is an expert in fuzzing development, and your goal is to expand on the fuzzing harnesses of OSS-Fuzz project {project_name}. Use the tools to understand the fuzzing harnesses of the {project_name}'s OSS-Fuzz integration. You should edit the files directly in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/.... A copy of the source code of {project_name} is available at {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project_name}/... This is a read-only copy and you should not modify the files in this directory. Instead, you should only modify the files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/ and you should do so to the extend that the fuzzing extensions are successful. Use file operations tools to inspect the files. However, only modify and adjust the files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/... Use coverage tooling to understand if there are improvements in code coverage. You can both add new fuzzing harnesses or modify existing, by writing files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/... Some rules: - Do not change the ENTRYPOINT of the Dockerfile, it must remain as it is. - Do not adjust the Dockerfile so it copies files from the {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project_name}/... directory, as this is not the path that exists in the container. - If you need to add files to the project directory when inside the container, then add them to the {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/ folder and copy via the Dockerfile. - The "fuzzer-check" must pass. - Continue adjusting the files in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project_name}/ until "fuzzer-check" passes. """) if nodes: _log_nodes(f'responses-expand-{project_name}.log', nodes) def _log_nodes(logfile, nodes, header_text=''): """Logs the nodes to a specified logfile.""" with open(logfile, 'a', encoding='utf-8') as f: if header_text: f.write(header_text + '\n') for node in nodes: f.write(str(node)) f.write('\n') f.write('-' * 55 + '\n') async def fix_oss_fuzz_projects(projects_to_fix=None, max_projects_to_fix=4, language='', max_tries=3): """Fixes the build of a list of OSS-Fuzz projects.""" if projects_to_fix is None: # Get list of all OSS-Fuzz projects that are broken. broken_oss_fuzz_projects = _get_all_broken_oss_fuzz_projects(language) random.shuffle(broken_oss_fuzz_projects) logger.info('Total number of broken OSS-Fuzz projects: %d', len(broken_oss_fuzz_projects)) if len(broken_oss_fuzz_projects) > max_projects_to_fix: broken_oss_fuzz_projects = broken_oss_fuzz_projects[:max_projects_to_fix] else: broken_oss_fuzz_projects = projects_to_fix logger.info('Projects to fix: %s', broken_oss_fuzz_projects) if not broken_oss_fuzz_projects: logger.info('No broken OSS-Fuzz projects to fix.') return responses = [] for project in broken_oss_fuzz_projects: logger.info('Trying to fix project: %s', project) try: if not prepare_oss_fuzz_project(project): continue except: continue nodes, fix_success = await fix_project_build(project, max_tries) responses.append({'project': project, 'fix_success': fix_success}) if nodes: _log_nodes(f'responses-fix-build-{project}.json', nodes, header_text=f'Fixed build: {fix_success}') async def initiate_project_creation(project: str, project_repo: str, language: str): """Runs an agent to create an OSS-Fuzz project.""" if language == 'go': extra_text = """ A sample build.sh script for a Go OSS-Fuzz project is: ```sh mv $SRC/fuzz_pageparser.go $SRC/hugo/parser/pageparser/ compile_go_fuzzer github.com/gohugoio/hugo/parser/pageparser FuzzParseFrontMatterAndContent FuzzParseFrontMatterAndContent ``` and a sample go fuzzer is: ```go package pageparser import "bytes" func FuzzParseFrontMatterAndContent(data []byte) int { ParseFrontMatterAndContent(bytes.NewReader(data)) return 1 } ``` You must use the `compile_go_fuzzer` command which exists inside the OSS-Fuzz container. To debug semantics of this if needed, you should build the project and extract the logs. The first argument to `compile_go_fuzzer` is the package path, and the second argument is the fuzzer name. The `compile_go_fuzzer` source code is as follows: ```go path=$1 function=$2 fuzzer=$3 tags="-tags gofuzz" if [[ $# -eq 4 ]]; then tags="-tags $4" fi # makes directory change temporary ( cd $GOPATH/src/$path || true # in the case we are in the right directory, with go.mod but no go.sum go mod tidy || true # project was downloaded with go get if go list fails go list $tags $path || { cd $GOPATH/pkg/mod/ && cd `echo $path | cut -d/ -f1-3 | awk '{print $1"@*"}'`; } || cd - # project does not have go.mod if go list fails again go list $tags $path || { go mod init $path && go mod tidy ;} if [[ $SANITIZER = *coverage* ]]; then fuzzed_package=`go list $tags -f '{{.Name}}' $path` abspath=`go list $tags -f {{.Dir}} $path` cd $abspath cp $GOPATH/ossfuzz_coverage_runner.go ./"${function,,}"_test.go sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go # The repo is the module path/name, which is already created above in case it doesn't exist, # but not always the same as the module path. This is necessary to handle SIV properly. fuzzed_repo=$(go list $tags -f {{.Module}} "$path") abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo` # give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath # Additional packages for which to get coverage. pkgaddcov="" # to prevent bash from failing about unbound variable GO_COV_ADD_PKG_SET=${GO_COV_ADD_PKG:-} if [[ -n "${GO_COV_ADD_PKG_SET}" ]]; then pkgaddcov=","$GO_COV_ADD_PKG abspath_repo=`go list -m $tags -f {{.Dir}} $GO_COV_ADD_PKG || go list $tags -f {{.Dir}} $GO_COV_ADD_PKG` echo "s=^$GO_COV_ADD_PKG"="$abspath_repo"= >> $OUT/$fuzzer.gocovpath fi go test -run Test${function}Corpus -v $tags -coverpkg $fuzzed_repo/...$pkgaddcov -c -o $OUT/$fuzzer $path else # Compile and instrument all Go files relevant to this fuzz target. echo "Running go-fuzz $tags -func $function -o $fuzzer.a $path" go-fuzz $tags -func $function -o $fuzzer.a $path # Link Go code ($fuzzer.a) with fuzzing engine to produce fuzz target binary. $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer fi ) ``` I am only showing the source code of `compile_go_fuzzer` here for your reference. You should just use it directly as a command `compile_go_fuzzer` as shown above in the `build.sh`. """ else: extra_text = "" target_goal = '' if language in ['c', 'c++']: target_goal = """The goal is to make sure we have a decent code coverage of the target project. Make sure the coverage of the target is above 10% in terms of line coverage. Use the tools available to extract code coverage of the project when you're creating the harness, and either add more fuzzing harnesses to the project or extend the harness to cover more functions.""" nodes = await run_agent_loop( f"""You are an expert software security engineer and you are tasked with creating an OSS-Fuzz project. I have set up an initial project structure at {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/. This structure includes a Dockerfile, build.sh, and project.yaml file. The Dockerfile clones the target project repository ({project_repo}) and the build.sh file is empty. Your task is to fill in the empty build.sh file with the necessary commands to build the project. The Dockerfile should set up the relevant dependencies, but it should continue to inherit FROM the base builder image as already set. You should: (1) fix the build.sh so it builds the project correctly, using CC, CXX, CFLAGS and CXXFLAGS for compilation. (2) add at least one fuzzing harness. This should be added in the {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/ directory and copied into the contained using the Dockerfile, where it will be build by the build.sh script. You must ensure when the fuzzing harness is linked that the $LIB_FUZZING_ENGINE environment variable is included in the link command. The build.sh script must make sure to copy out the fuzzers build to the $OUT/ directory. You must continue this session until the OSS-Fuzz project {project} builds correctly and the \"fuzzer-check\" must pass. This is a project in the {language} programming language, so you must ensure the fuzzing harness is written in {language} and the build.sh script is set up to compile the project. {extra_text} The project repository source code is available at {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project}/. This source code is a local version of the project and *not* the paths that exist in the container. You should not adjust the files in this directory, but only read them. In case you need to add changes to the source code, then these should be done directly by way of the Dockerfile and build.sh script. Inside the container, in general the fuzzing harness is placed at $SRC/harness_name... and the project code is in $SRC/project_name. You must add at least one fuzzing harness to the OSS-Fuzz project {project}, and ensure it fully works. Use the file reading and writing tools to create the necessary files in the {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/{project}/ directory. Then, run the build_fuzzers and check_build commands to ensure the project builds correctly. Repeat this until the project builds successfully and the fuzzer-check passes. The project must build success fully and the fuzzer-check must pass. If they do not pass, then you must refine the OSS-Fuzz project until it does. {target_goal} """) fix_success = await does_project_build(project) if nodes: _log_nodes(f'responses-{project}.json', nodes, header_text=f'initialization: {fix_success}') if not fix_success: logger.info('Project %s still does not build, trying to fix again.', project) fix_nodes, fix_success = await fix_project_build(project) if fix_nodes: _log_nodes(f'responses-fix-build-{project}.json', fix_nodes, header_text=f'fixed: {fix_success}') return nodes, fix_success def prepare_new_oss_fuzz_project(project_name: str, project_url: str) -> bool: """Gets the main repo of an OSS-Fuzz project and clones it into our caching folder.""" if os.path.isdir( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name)): return True try: subprocess.check_call( 'git clone ' + project_url + ' ' + os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, project_name), shell=True, timeout=60 * 10) except subprocess.CalledProcessError as e: logger.info("Error cloning project %s: %s", project_name, e) return False except subprocess.TimeoutExpired: logger.info("Cloning project %s timed out.", project_name) return False return os.path.isdir( f'{oss_fuzz_mcp_config.BASE_PROJECTS_DIR}/{project_name}') async def create_oss_fuzz_integration_for_project(project_url: str, project_language: str): """Creates an integration for a specific OSS-Fuzz project.""" # This function would typically create a new MCP tool for the project # and register it with the MCP server. # For now, we will just print the project URL. logger.info(f"Creating OSS-Fuzz integration for project: {project_url}") # Here you would implement the logic to create the integration. oss_fuzz_project_name = project_url.split('/')[-1].lower() if not oss_fuzz_project_name: raise ValueError("Project URL does not contain a valid project name.") oss_fuzz_path = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'projects', oss_fuzz_project_name) if os.path.isdir(oss_fuzz_path): shutil.rmtree(oss_fuzz_path) prepare_new_oss_fuzz_project(oss_fuzz_project_name, project_url) if not project_language: project_language = _detect_language(oss_fuzz_project_name) logger.info('Project %s language: %s', oss_fuzz_project_name, project_language) if not project_language: logger.info('Could not detect language for project %s, exiting') return os.makedirs(oss_fuzz_path) dockerfile_path = os.path.join(oss_fuzz_path, 'Dockerfile') build_sh_path = os.path.join(oss_fuzz_path, 'build.sh') project_yaml_path = os.path.join(oss_fuzz_path, 'project.yaml') base_image = '' project_language = project_language.lower() if project_language == 'c': base_image = 'gcr.io/oss-fuzz-base/base-builder' elif project_language == 'c++': base_image = 'gcr.io/oss-fuzz-base/base-builder' elif project_language == 'go': base_image = 'gcr.io/oss-fuzz-base/base-builder-go' # Dockerfile with open(dockerfile_path, 'w') as f: dockerfile_content = f""" FROM {base_image} RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone {project_url} /src/{oss_fuzz_project_name} WORKDIR /src/{oss_fuzz_project_name} COPY build.sh $SRC/build.sh """ f.write(dockerfile_content) # Build script with open(build_sh_path, 'w') as f: build_sh_content = f"""#!/bin/bash -eux # Empty build script for now. This needs to be filled with the actual build commands.""" f.write(build_sh_content) # Project YAML with open(project_yaml_path, 'w') as f: project_yaml_content = f"""\ homepage: "{project_url}" language: {project_language} primary_contact: "david@adalogics.com" main_repo: "{project_url}" """ f.write(project_yaml_content) # First, create a template setup for the project. # Use a local directory with the project clone, await initiate_project_creation(oss_fuzz_project_name, project_url, project_language) def parse_arguments(): """Parse command line arguments.""" parser = argparse.ArgumentParser(description="OSS-Fuzz MCP Client") subparsers = parser.add_subparsers(dest='command') # Fix builds command fix_builds = subparsers.add_parser( 'fix-builds', help='Fix the builds of OSS-Fuzz projects that are currently broken.') fix_builds.add_argument( '--max_attempts', type=int, default=3, help='Maximum number of attempts to fix each project (default: 3)') fix_builds.add_argument('--max-projects', type=int, default=4, help='Maximum number of projects to fix (default: 4)') fix_builds.add_argument('--language', help='Filter projects by language (e.g., c, c++, go)', default='') fix_builds.add_argument( '--projects', nargs='*', help= 'List of specific projects to fix. If not provided, random broken projects will be selected.' ) # Create initial OSS-Fuzz project command. create_project = subparsers.add_parser( 'create-project', help= 'Create an initial OSS-Fuzz project with a given repository URL and language.' ) create_project.add_argument( 'project_url', type=str, help='The URL of the project repository to create an OSS-Fuzz project for.' ) create_project.add_argument( '--language', type=str, default='', help='The programming language of the project (e.g., c, c++, go).') # Command to add run_tests.sh add_run_tests_parser = subparsers.add_parser( 'run-tests', help='Add run-tests.sh command for specific project') add_run_tests_parser.add_argument( 'project_name', type=str, help='The name of the project to add run-tests.sh command for.') expand_existing = subparsers.add_parser( 'expand-existing', help='Expand existing OSS-Fuzz project') expand_existing.add_argument('project_name', type=str, help='The name of the project to expand.') return parser.parse_args() async def main(): """Main function to demonstrate the client usage""" args = parse_arguments() initialize_oss_fuzz() if args.command == 'fix-builds': await fix_oss_fuzz_projects(args.projects, args.max_projects, args.language, args.max_attempts) elif args.command == 'create-project': logger.info('Creating OSS-Fuzz project for URL: %s', args.project_url) await create_oss_fuzz_integration_for_project(args.project_url, args.language) elif args.command == 'run-tests': await add_run_tests_command(args.project_name) elif args.command == 'expand-existing': await expand_existing_project(args.project_name) if __name__ == "__main__": asyncio.run(main()) ================================================ FILE: infra/experimental/mcp/config.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ BASE_DIR = '/var/tmp/oss-fuzz-mcp' BASE_PROJECTS_DIR = f'{BASE_DIR}/projects' BASE_OSS_FUZZ_DIR = f'{BASE_DIR}/oss-fuzz' BASE_TMP_LOGS = f'{BASE_DIR}/tmp-logs' ================================================ FILE: infra/experimental/mcp/oss_fuzz_server.py ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """MCP server for OSS-Fuzz.""" import logging import os import shutil import sys import json import time import subprocess from mcp.server.fastmcp import FastMCP import config as oss_fuzz_mcp_config TARGET_PROJECT = '' # Configure logging logging.basicConfig( level=logging.INFO, format= "[SERVER] %(asctime)s - %(name)s - '%(module)s - %(funcName)s - %(levelname)s - %(message)s", stream=sys.stderr) logger = logging.getLogger("mcp-server") # Create an MCP server with a name mcp = FastMCP("OSS-Fuzz tools with relevant file system utilities.") FILE_ACCESS_ERROR = f"""Error: Cannot access directories outside of the base directory. Remember, all paths accessible by you must be prefixed with {oss_fuzz_mcp_config.BASE_DIR}. Further: 1) For project source code, this is available within {oss_fuzz_mcp_config.BASE_PROJECTS_DIR}. 2) For access to OSS-Fuzz project files, these are accessible in {oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR}/projects/PROJECT_NAME/. """ def _internal_delay(): """Forced delay to control LLM limits""" time.sleep(2) def clone_oss_fuzz_if_it_does_not_exist(): """Clones OSS-Fuzz if it does not already exist.""" target = oss_fuzz_mcp_config.BASE_PROJECTS_DIR if os.path.isdir(target): logger.info('OSS-Fuzz already exists') return repo_url = "https://github.com/google/oss-fuzz" try: subprocess.check_call(["git", "clone", repo_url, target], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=oss_fuzz_mcp_config.BASE_DIR) except subprocess.CalledProcessError: logger.info('Error cloning OSS-Fuzz') def _prepare_target_project(): """Prepares the target OSS-Fuzz project by copying it to the OSS-Fuzz projects directory.""" global TARGET_PROJECT clone_oss_fuzz_if_it_does_not_exist() project_name = os.path.basename(TARGET_PROJECT) # Copy over the project files if needed. if os.path.isdir( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name)): shutil.rmtree( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name)) shutil.copytree( TARGET_PROJECT, os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name)) return project_name @mcp.tool() async def check_if_oss_fuzz_project_builds() -> bool: """ Checks if the OSS-Fuzz project being worked on builds successfully. Returns: True if the project builds successfully, False otherwise """ project_name = _prepare_target_project() logger.info("Checking if OSS-Fuzz project '%s' builds successfully...", project_name) try: logger.info('Building OSS-Fuzz project: %s', project_name) subprocess.check_call('python3 infra/helper.py build_fuzzers ' + project_name, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, timeout=60 * 20) return True except subprocess.CalledProcessError as e: logger.info("Build failed for project '%s': {%s}", project_name, str(e)) return False except subprocess.TimeoutExpired: logger.info(f"Building project {project_name} timed out.") return False def shorten_logs_if_needed(log_string: str) -> str: """ Shortens the log string if it exceeds a certain length. Args: log_string: The log string to potentially shorten Returns: The original log string if it's short enough, or a shortened version """ max_length = 5000 # Define a maximum length for logs if len(log_string) > max_length: return log_string[:1000] + '... [truncated] ' + log_string[-3700:] return log_string @mcp.tool() async def build_and_get_build_logs_from_oss_fuzz() -> str: """ Retrieves build logs for an OSS-Fuzz project. This is useful when changes have been made to the project and you want to see the build output. Returns: A string containing the build logs for the project """ project_name = _prepare_target_project() logger.info("Retrieving build logs for OSS-Fuzz project '%s'...", project_name) os.makedirs(oss_fuzz_mcp_config.BASE_TMP_LOGS, exist_ok=True) target_logs = os.path.join(oss_fuzz_mcp_config.BASE_TMP_LOGS, 'build-log.txt') if os.path.isfile(target_logs): os.remove(target_logs) log_stdout = open(target_logs, 'w', encoding='utf-8') try: logger.info("Building OSS-Fuzz project: '%s'", project_name) subprocess.check_call('python3 infra/helper.py build_fuzzers ' + project_name, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=log_stdout, stderr=subprocess.STDOUT, timeout=60 * 20) except subprocess.CalledProcessError as e: logger.info("Build failed for project '%s': {%s}", project_name, str(e)) except subprocess.TimeoutExpired: logger.info(f"Building project {project_name} timed out.") with open(target_logs, 'r', encoding='utf-8') as f: logs = f.read() logs_to_return = shorten_logs_if_needed(logs) logger.info("Build logs for project '%s': {%s}", project_name, logs_to_return) return logs_to_return #@mcp.tool() async def get_sample_artifacts_from_oss_fuzz_project( language: str) -> dict[str, str]: """ Retrieves sample artifacts, Dockerfile and builds, for a specific language from OSS-Fuzz projects. Args: language: The programming language for which to retrieve sample artifacts Returns: A dictionary containing the Dockerfile and build script. """ logger.info("Retrieving sample artifacts for OSS-Fuzz project language: %s", language) if language == 'go': project_name = 'go-dns' elif language == 'c': project_name = 'cjson' elif language == 'cpp': project_name = 'htslib' elif language == 'java': project_name = 'guava' else: return f"Error: Unsupported language '{language}'. Supported languages are: go, c, cpp, java." logger.info("Retrieving sample artifacts for OSS-Fuzz project '%s'...", project_name) dockerfile_path = os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name, 'Dockerfile') build_script_path = os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name, 'build.sh') if not os.path.isfile(dockerfile_path) or not os.path.isfile( build_script_path): return f"Error: Sample artifacts for project '{project_name}' not found." with open(dockerfile_path, 'r', encoding='utf-8') as f: dockerfile = f.read() with open(build_script_path, 'r', encoding='utf-8') as f: build_script = f.read() artifacts = {"Dockerfile": dockerfile, "build.sh": build_script} logger.info("Sample artifacts retrieved successfully for project '%s'.", project_name) return artifacts #@mcp.tool() async def check_run_tests( project_name) -> str: #, build_sh, dockerfile) -> str: """ OSS-Fuzz tool that performs "run-tests-check" on an OSS-Fuzz project. Use this tool to verify `run_tests.sh` scripts. Checks if an OSS-Fuzz project's tests run correctly. This check should only be applied after the project builds successfully. This check is needed for an OSS-Fuzz project to be in a good state. Args: project_name: Name of the OSS-Fuzz project to check Returns: The logs from building the project with custom artifacts. """ clone_oss_fuzz_if_it_does_not_exist() logger.info( "Checking if OSS-Fuzz project '%s' builds with custom artifacts...", project_name) os.makedirs(oss_fuzz_mcp_config.BASE_TMP_LOGS, exist_ok=True) target_logs = os.path.join(oss_fuzz_mcp_config.BASE_TMP_LOGS, 'check-fuzz-run-tests-log.txt') if os.path.isfile(target_logs): os.remove(target_logs) log_stdout = open(target_logs, 'w', encoding='utf-8') try: subprocess.check_call( f'infra/experimental/chronos/check_tests.sh {project_name} c++', cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=log_stdout, stderr=subprocess.STDOUT, timeout=60 * 20) except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e: logger.info("Build failed for project '%s': {%s}", project_name, str(e)) log_stdout.write("\n\nrun-tests.sh failed!!\n") with open(target_logs, 'r', encoding='utf-8') as f: logs = f.read() logs_to_return = shorten_logs_if_needed(logs) logger.info("run-tests.sh logs for project '%s': {%s}", project_name, logs_to_return) return logs_to_return with open(target_logs, 'r', encoding='utf-8') as f: logs = f.read() logs_to_return = shorten_logs_if_needed(logs) logger.info("run-tests.sh for project '%s': {%s}", project_name, logs_to_return) return logs_to_return @mcp.tool() async def check_oss_fuzz_fuzzers() -> str: """ Performs "fuzzer-check" on an OSS-Fuzz project with custom artifacts. Checks if the OSS-Fuzz project's fuzzers run correctly with custom artifacts. This check should only be applied after the project builds successfully. This check is needed for an OSS-Fuzz project to be in a good state. Returns: The build logs from building the project with custom artifacts. """ project_name = _prepare_target_project() logger.info( "Checking if OSS-Fuzz project '%s' builds and fuzzers pass check_build", project_name) os.makedirs(oss_fuzz_mcp_config.BASE_TMP_LOGS, exist_ok=True) target_logs = os.path.join(oss_fuzz_mcp_config.BASE_TMP_LOGS, 'check-fuzz-build-log.txt') if os.path.isfile(target_logs): os.remove(target_logs) log_stdout = open(target_logs, 'w', encoding='utf-8') try: subprocess.check_call('python3 infra/helper.py build_fuzzers ' + project_name, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=log_stdout, stderr=subprocess.STDOUT, timeout=60 * 20) except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e: logger.info("Build failed for project '%s': {%s}", project_name, str(e)) log_stdout.write("\n\nBuild failed!!\n") with open(target_logs, 'r', encoding='utf-8') as f: logs = f.read() logs_to_return = shorten_logs_if_needed(logs) logger.info("Build logs for project '%s': {%s}", project_name, logs_to_return) return logs_to_return check_target_logs = os.path.join(oss_fuzz_mcp_config.BASE_TMP_LOGS, 'check-fuzz-run-log.txt') if os.path.isfile(check_target_logs): os.remove(check_target_logs) log_stdout = open(check_target_logs, 'w', encoding='utf-8') try: subprocess.check_call('python3 infra/helper.py check_build ' + project_name, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=log_stdout, stderr=subprocess.STDOUT, timeout=60 * 30) log_stdout.write("\n\nChecking fuzzers succeeded.\n") except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e: logger.info("Check failed for project '%s': {%s}", project_name, str(e)) log_stdout.write("\n\nChecking fuzzers failed!!\n") with open(check_target_logs, 'r', encoding='utf-8') as f: logs = f.read() logs_to_return = shorten_logs_if_needed(logs) logger.info("Check fuzzers for project '%s': {%s}", project_name, logs_to_return) return logs_to_return # File operating utilities #@mcp.tool() async def list_files(path: str = "") -> str: """List all files in the specified directory. Args: path: Optional subdirectory path relative to the base directory """ _internal_delay() target_dir = os.path.normpath(path) if not target_dir.startswith(oss_fuzz_mcp_config.BASE_DIR): return FILE_ACCESS_ERROR logger.info("Listing files in directory: %s", target_dir) try: files = os.listdir(target_dir) file_info = [] for file in files: full_path = os.path.join(target_dir, file) is_dir = os.path.isdir(full_path) size = os.path.getsize(full_path) if not is_dir else "-" file_type = "Directory" if is_dir else "File" file_info.append({"name": file, "type": file_type, "size": size}) return_val = json.dumps(file_info, indent=2) return return_val except Exception as e: return f"Error listing files: {str(e)}" #@mcp.tool() async def get_file_size(file_path) -> str: """Get the size of a file. Args: file_path: Path to the file relative to the base directory Returns: The size of the file in bytes or an error message. """ _internal_delay() target_file = os.path.normpath(file_path) if not target_file.startswith(oss_fuzz_mcp_config.BASE_DIR): return FILE_ACCESS_ERROR logger.info("Getting file size: %s", target_file) try: if not os.path.isfile(target_file): return f"Error: File does not exist or is not a file: {file_path}" size = os.path.getsize(target_file) return f"File size of {file_path}: {size} bytes" except Exception as e: return f"Error getting file size: {str(e)}" #@mcp.tool() async def read_file(file_path: str, start_idx: int, end_idx: int) -> str: """Read the contents of a file. Will read a maximum of 3000 characters to control size of content. Use arguments to control which part of file to read. Args: file_path: Path to the file relative to the base directory start_idx: character index to start reading from end_idx: character index to stop reading (exclusive). If set to -1 will read until the end of the file Returns: The contents of the file or an error message. """ _internal_delay() target_file = os.path.normpath(file_path) if not target_file.startswith(oss_fuzz_mcp_config.BASE_DIR): return FILE_ACCESS_ERROR logger.info("Reading file: %s", target_file) try: if not os.path.isfile(target_file): return f"Error: File does not exist or is not a file: {file_path}" with open(target_file, 'r', encoding='utf-8') as f: content = f.read() except Exception as e: return f"Error reading file: {str(e)}" if end_idx == -1: end_idx = len(content) buffer_size_to_read = end_idx - start_idx if buffer_size_to_read <= 0: return f"Error: Invalid indices. Negative size asked for: {buffer_size_to_read}" if buffer_size_to_read > 3000: return f"Error: Requested size too large: {buffer_size_to_read}. Maximum is 3000 characters." try: return content[start_idx:end_idx] except Exception as e: return f"Error extracting content: {str(e)}" #@mcp.tool() async def write_file(file_path: str, content: str) -> str: """Write content to a file. Args: file_path: Path to the file relative to the base directory content: Content to write to the file """ _internal_delay() logger.info("Writing to file: %s", file_path) target_file = os.path.normpath(file_path) if not target_file.startswith(oss_fuzz_mcp_config.BASE_DIR): return FILE_ACCESS_ERROR try: # Create directory if it doesn't exist os.makedirs(os.path.dirname(target_file), exist_ok=True) with open(target_file, 'w') as f: f.write(content) return f"Successfully wrote to {file_path}" except Exception as e: return f"Error writing to file: {str(e)}" #@mcp.tool() async def delete_file(file_path: str) -> str: """Delete a file. Args: file_path: Path to the file relative to the base directory """ _internal_delay() logger.info("Deleting file: %s", file_path) target_file = os.path.normpath(file_path) if not target_file.startswith(oss_fuzz_mcp_config.BASE_DIR): return FILE_ACCESS_ERROR try: if not os.path.exists(target_file): return f"Error: File does not exist: {file_path}" if os.path.isdir(target_file): os.rmdir(target_file) return f"Successfully deleted directory: {file_path}" else: os.remove(target_file) return f"Successfully deleted file: {file_path}" except Exception as e: return f"Error deleting file: {str(e)}" #@mcp.tool() async def search_project_filename(project_name: str, filename: str) -> str: """ Searches for a filename inside the project directory. Args: project_name: Name of the OSS-Fuzz project to search in filename: The filename to search for Returns: A string containing the paths of the files with the relevant filename, or an error message. """ _internal_delay() logger.info('Searching for filename "%s" in project "%s"...', filename, project_name) if '/' in filename: return "Error: Filename should not contain directory separators, only basename." files_found = [] for root, dirs, files in os.walk( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name)): for fname in files: if fname == filename: full_path = os.path.join(root, fname) files_found.append(full_path) return '\n'.join( files_found ) if files_found else f'No files named "{filename}" found in project "{project_name}".' #@mcp.tool() async def search_project_file_content(project_name: str, search_term: str) -> str: """ Searches for a term in the content of files inside the project directory. Args: project_name: Name of the OSS-Fuzz project to search in. search_term: The term to search for in the file contents. Returns: A string containing the paths of the files that contain the search term and the line in the file the term is found, or an error message if no files are found. """ _internal_delay() logger.info('Searching for term "%s" in project "%s"...', search_term, project_name) files_found = [] for root, _, files in os.walk( os.path.join(oss_fuzz_mcp_config.BASE_PROJECTS_DIR, 'projects', project_name)): for fname in files: full_path = os.path.join(root, fname) with open(full_path, 'r', encoding='utf-8') as f: content = f.read() if search_term in content: for lineno, line in enumerate(content.split('\n')): if search_term in line: files_found.append(f'{full_path}:{lineno}') return '\n'.join( files_found ) if files_found else f'No files containing "{search_term}" found in project "{project_name}".' #@mcp.tool() async def get_coverage_of_oss_fuzz_project(project_name): """ Gets the code coverage information for an OSS-Fuzz project. Args: project_name: Name of the OSS-Fuzz project Returns: A string containing the code coverage information, or an error message. """ _internal_delay() logger.info('Getting coverage for project "%s"...', project_name) os.makedirs(oss_fuzz_mcp_config.BASE_TMP_LOGS, exist_ok=True) target_logs = os.path.join(oss_fuzz_mcp_config.BASE_TMP_LOGS, 'build-log.txt') if os.path.isfile(target_logs): os.remove(target_logs) log_stdout = open(target_logs, 'w', encoding='utf-8') try: logger.info("Building OSS-Fuzz project: '%s'", project_name) subprocess.check_call( 'python3 infra/helper.py introspector --coverage-only --seconds=10 ' + project_name, cwd=oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, shell=True, stdout=log_stdout, stderr=subprocess.STDOUT, timeout=60 * 20) except subprocess.CalledProcessError as e: logger.info("Build failed for project '%s': {%s}", project_name, str(e)) except subprocess.TimeoutExpired: logger.info(f"Building project {project_name} timed out.") # Extract coverage if we have it. coverage_info_file = os.path.join(oss_fuzz_mcp_config.BASE_OSS_FUZZ_DIR, 'build', 'out', project_name, 'report', 'linux', 'summary.json') if not os.path.isfile(coverage_info_file): return f"Error: Coverage information not found for project '{project_name}'." with open(coverage_info_file, 'r', encoding='utf-8') as f: oss_fuzz_cov_dict = json.load(f) refined_cov_dict = { 'file-coverage': [], 'total-coverage': { 'lines': { 'count': oss_fuzz_cov_dict['data'][0]['totals']['lines']['count'], 'covered': oss_fuzz_cov_dict['data'][0]['totals']['lines']['covered'], 'percent': oss_fuzz_cov_dict['data'][0]['totals']['lines']['percent'] }, 'functions': { 'count': oss_fuzz_cov_dict['data'][0]['totals']['functions']['count'], 'covered': oss_fuzz_cov_dict['data'][0]['totals']['functions'] ['covered'], 'percent': oss_fuzz_cov_dict['data'][0]['totals']['functions']['percent'] } } } for file_cov in oss_fuzz_cov_dict['data'][0]['files']: refined_cov_dict['file-coverage'].append({ 'filename': file_cov['filename'], 'lines': { 'count': file_cov['summary']['lines']['count'], 'covered': file_cov['summary']['lines']['covered'], 'percent': file_cov['summary']['lines']['percent'] }, 'functions': { 'count': file_cov['summary']['functions']['count'], 'covered': file_cov['summary']['functions']['covered'], 'percent': file_cov['summary']['functions']['percent'] } }) logger.info('Refined coverage dict: %s', json.dumps(refined_cov_dict, indent=2)) return json.dumps(refined_cov_dict, indent=2) def start_mcp_server(): """Starts the MCP server.""" global TARGET_PROJECT oss_fuzz_target = sys.argv[1] TARGET_PROJECT = oss_fuzz_target logger.info('OSS-Fuzz MCP server target: %s', oss_fuzz_target) try: logger.info("Starting MCP server.") mcp.run(transport="stdio") except KeyboardInterrupt: logger.info("Caught KeyboardInterrupt.") logger.info('Server shut down.') if __name__ == "__main__": start_mcp_server() ================================================ FILE: infra/experimental/mcp/requirements.txt ================================================ openai==1.97.0 pydantic_ai==0.4.10 logfire ================================================ FILE: infra/experimental/sanitizers/ExecSan/README.md ================================================ # Moved This has moved to . ================================================ FILE: infra/helper.py ================================================ #!/usr/bin/env python # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Helper script for OSS-Fuzz users. Can do common tasks like building projects/fuzzers, running them etc.""" from __future__ import print_function from multiprocessing.dummy import Pool as ThreadPool import argparse import datetime import errno import logging import os import re import shlex import shutil import subprocess import sys import tempfile import urllib.request import constants import templates import chronos.manager import common_utils # Forward reference common functions. We do this because they are used # throughout the infra and to avoid breakages we declare them here. # TODO(David): clean this up. OSS_FUZZ_DIR = common_utils.OSS_FUZZ_DIR Project = common_utils.Project docker_build = common_utils.docker_build build_image_impl = common_utils.build_image_impl pull_images = common_utils.pull_images def _get_base_runner_image(args, debug=False): """Returns the base runner image to use.""" image = common_utils.BASE_RUNNER_IMAGE if debug: image += '-debug' tag = 'latest' if hasattr(args, 'base_image_tag') and args.base_image_tag: tag = args.base_image_tag elif hasattr(args, 'project') and args.project: if args.project.base_os_version != 'legacy': tag = args.project.base_os_version return f'{image}:{tag}' VALID_PROJECT_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+$') MAX_PROJECT_NAME_LENGTH = 26 CORPUS_URL_FORMAT = ( 'gs://{project_name}-corpus.clusterfuzz-external.appspot.com/libFuzzer/' '{fuzz_target}/') CORPUS_BACKUP_URL_FORMAT = ( 'gs://{project_name}-backup.clusterfuzz-external.appspot.com/corpus/' 'libFuzzer/{fuzz_target}/') HTTPS_CORPUS_BACKUP_URL_FORMAT = ( 'https://storage.googleapis.com/{project_name}-backup.clusterfuzz-external' '.appspot.com/corpus/libFuzzer/{fuzz_target}/public.zip') LANGUAGE_REGEX = re.compile(r'[^\s]+') WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)') # Regex to match special chars in project name. SPECIAL_CHARS_REGEX = re.compile('[^a-zA-Z0-9_-]') LANGUAGE_TO_BASE_BUILDER_IMAGE = { 'c': 'base-builder', 'c++': 'base-builder', 'go': 'base-builder-go', 'javascript': 'base-builder-javascript', 'jvm': 'base-builder-jvm', 'python': 'base-builder-python', 'ruby': 'base-builder-ruby', 'rust': 'base-builder-rust', 'swift': 'base-builder-swift' } ARM_BUILDER_NAME = 'oss-fuzz-buildx-builder' CLUSTERFUZZLITE_ENGINE = 'libfuzzer' CLUSTERFUZZLITE_ARCHITECTURE = 'x86_64' CLUSTERFUZZLITE_FILESTORE_DIR = 'filestore' CLUSTERFUZZLITE_DOCKER_IMAGE = 'gcr.io/oss-fuzz-base/cifuzz-run-fuzzers' INDEXER_PREBUILT_URL = ('https://clusterfuzz-builds.storage.googleapis.com/' 'oss-fuzz-artifacts/indexer') logger = logging.getLogger(__name__) if sys.version_info[0] >= 3: raw_input = input # pylint: disable=invalid-name # pylint: disable=too-many-lines def main(): # pylint: disable=too-many-branches,too-many-return-statements """Gets subcommand from program arguments and does it. Returns 0 on success 1 on error.""" logging.basicConfig(level=logging.INFO) parser = get_parser() args = parse_args(parser) # Need to do this before chdir. # TODO(https://github.com/google/oss-fuzz/issues/6758): Get rid of chdir. if hasattr(args, 'testcase_path'): args.testcase_path = _get_absolute_path(args.testcase_path) # Note: this has to happen after parse_args above as parse_args needs to know # the original CWD for external projects. os.chdir(common_utils.OSS_FUZZ_DIR) if not os.path.exists(common_utils.BUILD_DIR): os.mkdir(common_utils.BUILD_DIR) # We have different default values for `sanitizer` depending on the `engine`. # Some commands do not have `sanitizer` argument, so `hasattr` is necessary. if hasattr(args, 'sanitizer') and not args.sanitizer: if args.project.language == 'javascript': args.sanitizer = 'none' else: args.sanitizer = constants.DEFAULT_SANITIZER if args.command == 'generate': result = generate(args) elif args.command == 'build_image': result = build_image(args) elif args.command == 'build_fuzzers': result = build_fuzzers(args) elif args.command == 'fuzzbench_build_fuzzers': result = fuzzbench_build_fuzzers(args) elif args.command == 'fuzzbench_run_fuzzer': result = fuzzbench_run_fuzzer(args) elif args.command == 'fuzzbench_measure': result = fuzzbench_measure(args) elif args.command == 'check_build': result = check_build(args) elif args.command == 'download_corpora': result = download_corpora(args) elif args.command == 'run_fuzzer': result = run_fuzzer(args) elif args.command == 'coverage': result = coverage(args) elif args.command == 'introspector': result = introspector(args) elif args.command == 'reproduce': result = reproduce(args) elif args.command == 'shell': result = shell(args) elif args.command == 'pull_images': result = common_utils.pull_images() elif args.command == 'index': result = index(args) elif args.command == 'run_clusterfuzzlite': result = run_clusterfuzzlite(args) elif args.command == 'check-tests': chronos.manager.cmd_dispatcher_check_tests(args) result = 0 elif args.command == 'check-replay': chronos.manager.cmd_dispatcher_check_replay(args) result = 0 else: # Print help string if no arguments provided. parser.print_help() result = False return bool_to_retcode(result) def bool_to_retcode(boolean): """Returns 0 if |boolean| is Truthy, 0 is the standard return code for a successful process execution. Returns 1 otherwise, indicating the process failed.""" return 0 if boolean else 1 def parse_args(parser, args=None): """Parses |args| using |parser| and returns parsed args. Also changes |args.build_integration_path| to have correct default behavior.""" # Use default argument None for args so that in production, argparse does its # normal behavior, but unittesting is easier. parsed_args = parser.parse_args(args) project = getattr(parsed_args, 'project', None) if not project: return parsed_args # Use hacky method for extracting attributes so that ShellTest works. # TODO(metzman): Fix this. is_external = getattr(parsed_args, 'external', False) parsed_args.project = common_utils.Project(parsed_args.project, is_external) return parsed_args def _add_external_project_args(parser): parser.add_argument( '--external', help='Is project external?', default=False, action='store_true', ) def get_parser(): # pylint: disable=too-many-statements,too-many-locals """Returns an argparse parser.""" parser = argparse.ArgumentParser('helper.py', description='oss-fuzz helpers') subparsers = parser.add_subparsers(dest='command') generate_parser = subparsers.add_parser( 'generate', help='Generate files for new project.') generate_parser.add_argument('project') generate_parser.add_argument('--language', default=constants.DEFAULT_LANGUAGE, choices=LANGUAGE_TO_BASE_BUILDER_IMAGE.keys(), help='Project language.') _add_external_project_args(generate_parser) build_image_parser = subparsers.add_parser('build_image', help='Build an image.') build_image_parser.add_argument('project') build_image_parser.add_argument('--pull', action='store_true', help='Pull latest base image.') _add_architecture_args(build_image_parser) build_image_parser.add_argument('--cache', action='store_true', default=False, help='Use docker cache when building image.') build_image_parser.add_argument('--no-pull', action='store_true', help='Do not pull latest base image.') _add_external_project_args(build_image_parser) build_fuzzers_parser = subparsers.add_parser( 'build_fuzzers', help='Build fuzzers for a project.') _add_architecture_args(build_fuzzers_parser) _add_engine_args(build_fuzzers_parser) _add_sanitizer_args(build_fuzzers_parser) _add_environment_args(build_fuzzers_parser) _add_external_project_args(build_fuzzers_parser) build_fuzzers_parser.add_argument('project') build_fuzzers_parser.add_argument('source_path', help='path of local source', nargs='?') build_fuzzers_parser.add_argument('--mount_path', dest='mount_path', help='path to mount local source in ' '(defaults to WORKDIR)') build_fuzzers_parser.add_argument('--clean', dest='clean', action='store_true', help='clean existing artifacts.') build_fuzzers_parser.add_argument('--no-clean', dest='clean', action='store_false', help='do not clean existing artifacts ' '(default).') build_fuzzers_parser.set_defaults(clean=False) fuzzbench_build_fuzzers_parser = subparsers.add_parser( 'fuzzbench_build_fuzzers') _add_architecture_args(fuzzbench_build_fuzzers_parser) fuzzbench_build_fuzzers_parser.add_argument('--engine') _add_sanitizer_args(fuzzbench_build_fuzzers_parser) _add_environment_args(fuzzbench_build_fuzzers_parser) _add_external_project_args(fuzzbench_build_fuzzers_parser) fuzzbench_build_fuzzers_parser.add_argument('project') check_build_parser = subparsers.add_parser( 'check_build', help='Checks that fuzzers execute without errors.') _add_architecture_args(check_build_parser) _add_engine_args(check_build_parser, choices=constants.ENGINES) _add_sanitizer_args(check_build_parser, choices=constants.SANITIZERS) _add_environment_args(check_build_parser) _add_base_image_tag_args(check_build_parser) check_build_parser.add_argument('project', help='name of the project or path (external)') check_build_parser.add_argument('fuzzer_name', help='name of the fuzzer', nargs='?') _add_external_project_args(check_build_parser) index_parser = subparsers.add_parser('index', help='Index project.') index_parser.add_argument( '--targets', help='Allowlist of targets to index (comma-separated).') index_parser.add_argument('--dev', action='store_true', help=('Use development versions of scripts and ' 'indexer.')) index_parser.add_argument('--shell', action='store_true', help='Run /bin/bash instead of the indexer.') index_parser.add_argument('--docker_arg', help='Additional docker argument to pass through ' '(can be specified multiple times).', nargs='*', action='extend') index_parser.add_argument('project', help='Project') index_parser.add_argument( 'extra_args', nargs='*', help='Additional args to pass through to the Docker entrypoint.') _add_architecture_args(index_parser) _add_environment_args(index_parser) run_fuzzer_parser = subparsers.add_parser( 'run_fuzzer', help='Run a fuzzer in the emulated fuzzing environment.') _add_architecture_args(run_fuzzer_parser) _add_engine_args(run_fuzzer_parser) _add_sanitizer_args(run_fuzzer_parser) _add_environment_args(run_fuzzer_parser) _add_base_image_tag_args(run_fuzzer_parser) _add_external_project_args(run_fuzzer_parser) run_fuzzer_parser.add_argument( '--corpus-dir', help='directory to store corpus for the fuzz target') run_fuzzer_parser.add_argument('project', help='name of the project or path (external)') run_fuzzer_parser.add_argument('fuzzer_name', help='name of the fuzzer') run_fuzzer_parser.add_argument('fuzzer_args', help='arguments to pass to the fuzzer', nargs='*') fuzzbench_run_fuzzer_parser = subparsers.add_parser('fuzzbench_run_fuzzer') _add_architecture_args(fuzzbench_run_fuzzer_parser) fuzzbench_run_fuzzer_parser.add_argument('--engine') _add_sanitizer_args(fuzzbench_run_fuzzer_parser) _add_environment_args(fuzzbench_run_fuzzer_parser) _add_external_project_args(fuzzbench_run_fuzzer_parser) fuzzbench_run_fuzzer_parser.add_argument( '--corpus-dir', help='directory to store corpus for the fuzz target') fuzzbench_run_fuzzer_parser.add_argument( 'project', help='name of the project or path (external)') fuzzbench_run_fuzzer_parser.add_argument('fuzzer_name', help='name of the fuzzer') fuzzbench_run_fuzzer_parser.add_argument( 'fuzzer_args', help='arguments to pass to the fuzzer', nargs='*') fuzzbench_measure_parser = subparsers.add_parser('fuzzbench_measure') fuzzbench_measure_parser.add_argument( 'project', help='name of the project or path (external)') fuzzbench_measure_parser.add_argument('engine_name', help='name of the fuzzer') fuzzbench_measure_parser.add_argument('fuzz_target_name', help='name of the fuzzer') coverage_parser = subparsers.add_parser( 'coverage', help='Generate code coverage report for the project.') coverage_parser.add_argument('--no-corpus-download', action='store_true', help='do not download corpus backup from ' 'OSS-Fuzz; use corpus located in ' 'build/corpus///') coverage_parser.add_argument('--no-serve', action='store_true', help='do not serve a local HTTP server.') coverage_parser.add_argument('--port', default='8008', help='specify port for' ' a local HTTP server rendering coverage report') coverage_parser.add_argument('--fuzz-target', help='specify name of a fuzz ' 'target to be run for generating coverage ' 'report') coverage_parser.add_argument('--corpus-dir', help='specify location of corpus' ' to be used (requires --fuzz-target argument)') coverage_parser.add_argument('--public', action='store_true', help='if set, will download public ' 'corpus using wget') coverage_parser.add_argument('project', help='name of the project or path (external)') coverage_parser.add_argument('extra_args', help='additional arguments to ' 'pass to llvm-cov utility.', nargs='*') _add_external_project_args(coverage_parser) _add_architecture_args(coverage_parser) _add_base_image_tag_args(coverage_parser) introspector_parser = subparsers.add_parser( 'introspector', help='Run a complete end-to-end run of ' 'fuzz introspector. This involves (1) ' 'building the fuzzers with ASAN; (2) ' 'running all fuzzers; (3) building ' 'fuzzers with coverge; (4) extracting ' 'coverage; (5) building fuzzers using ' 'introspector') introspector_parser.add_argument('project', help='name of the project') introspector_parser.add_argument('--seconds', help='number of seconds to run fuzzers', default=10) introspector_parser.add_argument('source_path', help='path of local source', nargs='?') introspector_parser.add_argument( '--public-corpora', help='if specified, will use public corpora for code coverage', default=False, action='store_true') introspector_parser.add_argument( '--private-corpora', help='if specified, will use private corpora', default=False, action='store_true') introspector_parser.add_argument( '--coverage-only', action='store_true', help='if specified, will only collect coverage.') download_corpora_parser = subparsers.add_parser( 'download_corpora', help='Download all corpora for a project.') download_corpora_parser.add_argument('--fuzz-target', nargs='+', help='specify name of a fuzz target') download_corpora_parser.add_argument('--public', action='store_true', help='if set, will download public ' 'corpus using wget') download_corpora_parser.add_argument( 'project', help='name of the project or path (external)') reproduce_parser = subparsers.add_parser('reproduce', help='Reproduce a crash.') reproduce_parser.add_argument('--valgrind', action='store_true', help='run with valgrind') reproduce_parser.add_argument('project', help='name of the project or path (external)') reproduce_parser.add_argument('fuzzer_name', help='name of the fuzzer') reproduce_parser.add_argument('testcase_path', help='path of local testcase') reproduce_parser.add_argument('fuzzer_args', help='arguments to pass to the fuzzer', nargs='*') _add_environment_args(reproduce_parser) _add_external_project_args(reproduce_parser) _add_architecture_args(reproduce_parser) _add_base_image_tag_args(reproduce_parser) shell_parser = subparsers.add_parser( 'shell', help='Run /bin/bash within the builder container.') shell_parser.add_argument('project', help='name of the project or path (external)') shell_parser.add_argument('source_path', help='path of local source', nargs='?') _add_architecture_args(shell_parser) _add_engine_args(shell_parser) _add_sanitizer_args(shell_parser) _add_environment_args(shell_parser) _add_external_project_args(shell_parser) _add_base_image_tag_args(shell_parser) run_clusterfuzzlite_parser = subparsers.add_parser( 'run_clusterfuzzlite', help='Run ClusterFuzzLite on a project.') _add_sanitizer_args(run_clusterfuzzlite_parser) _add_environment_args(run_clusterfuzzlite_parser) run_clusterfuzzlite_parser.add_argument('project') run_clusterfuzzlite_parser.add_argument('--clean', dest='clean', action='store_true', help='clean existing artifacts.') run_clusterfuzzlite_parser.add_argument( '--no-clean', dest='clean', action='store_false', help='do not clean existing artifacts ' '(default).') run_clusterfuzzlite_parser.add_argument('--branch', default='master', required=True) _add_external_project_args(run_clusterfuzzlite_parser) run_clusterfuzzlite_parser.set_defaults(clean=False) subparsers.add_parser('pull_images', help='Pull base images.') check_test_parser = subparsers.add_parser( 'check-tests', help='Checks run_test.sh for specific project.') check_test_parser.add_argument( 'project', type=str, help='The name of the project to check (e.g., "libpng").', ) check_test_parser.add_argument( '--stop-on-failure', action='store_true', help='If set, will stop integrity checks on first failure.') _add_sanitizer_args(check_test_parser) check_test_parser.add_argument( '--container-output', choices=['silent', 'file', 'stdout'], default='stdout', help='How to handle output from the container. ') check_test_parser.add_argument( '--run-full-cache-replay', action='store_true', help= 'If set, will run the full cache replay instead of just checking the script.' ) check_test_parser.add_argument( '--integrity-check', action='store_true', help= 'Setting `integrity_check` enables a check that validates if the `run_test.sh` modifies '\ 'the source control of the project will be performed. That is we want to ensure '\ 'e.g. `git diff ./` has the same output before and after `run_tests.sh`. The `run_test.sh` '\ 'must not change the underlying project source, and if it does it should reset the changes ' \ 'before exiting.' ) check_replay_parser = subparsers.add_parser( 'check-replay', help='Checks if the replay script works for a specific project.') check_replay_parser.add_argument('project', help='The name of the project to check.') _add_sanitizer_args(check_replay_parser) check_replay_parser.add_argument( '--integrity-check', action='store_true', help='If set, will test the integrity of the replay script. The integrity check' \ 'will run the build a number of times where each time the source code of the ' \ 'project is patched with a different patch to validate. The goal is to ensure ' \ 'the replay script correctly builds the target source code when code modifications ' \ 'are made. The patches will perform three main tasks:\n' \ '1) A control test to ensure it is working as is.\n' \ '2) A control test to check that we rebuild when white noise is included.\n' \ '3) A set of bad patches that should cause the build to fail.') return parser def _check_fuzzer_exists(project, fuzzer_name, args, architecture='x86_64'): """Checks if a fuzzer exists.""" platform = 'linux/arm64' if architecture == 'aarch64' else 'linux/amd64' command = ['docker', 'run', '--rm', '--platform', platform] command.extend(['-v', '%s:/out:z' % project.out]) command.append(_get_base_runner_image(args)) command.extend(['/bin/bash', '-c', 'test -f /out/%s' % fuzzer_name]) try: subprocess.check_call(command) except subprocess.CalledProcessError: logger.error('%s does not seem to exist. Please run build_fuzzers first.', fuzzer_name) return False return True def _normalized_name(name): """Return normalized name with special chars like slash, colon, etc normalized to hyphen(-). This is important as otherwise these chars break local and cloud storage paths.""" return SPECIAL_CHARS_REGEX.sub('-', name).strip('-') def _get_absolute_path(path): """Returns absolute path with user expansion.""" return os.path.abspath(os.path.expanduser(path)) def _add_architecture_args(parser, choices=None): """Adds common architecture args.""" if choices is None: choices = constants.ARCHITECTURES parser.add_argument('--architecture', default=constants.DEFAULT_ARCHITECTURE, choices=choices) def _add_engine_args(parser, choices=None): """Adds common engine args.""" if choices is None: choices = constants.ENGINES parser.add_argument('--engine', default=constants.DEFAULT_ENGINE, choices=choices) def _add_sanitizer_args(parser, choices=None): """Adds common sanitizer args.""" if choices is None: choices = constants.SANITIZERS parser.add_argument('--sanitizer', default=None, choices=choices, help='the default is "address"') def _add_environment_args(parser): """Adds common environment args.""" parser.add_argument('-e', action='append', help="set environment variable e.g. VAR=value") def _add_base_image_tag_args(parser): """Adds base image tag arg.""" parser.add_argument('--base-image-tag', help='The tag of the base-runner image to use.') def _env_to_docker_args(env_list): """Turns envirnoment variable list into docker arguments.""" return sum([['-e', v] for v in env_list], []) def workdir_from_lines(lines, default='/src'): """Gets the WORKDIR from the given lines.""" for line in reversed(lines): # reversed to get last WORKDIR. match = re.match(WORKDIR_REGEX, line) if match: workdir = match.group(1) workdir = workdir.replace('$SRC', '/src') if not os.path.isabs(workdir): workdir = os.path.join('/src', workdir) return os.path.normpath(workdir) return default def _workdir_from_dockerfile(project): """Parses WORKDIR from the Dockerfile for the given project.""" with open(project.dockerfile_path) as file_handle: lines = file_handle.readlines() return workdir_from_lines(lines, default=os.path.join('/src', project.name)) def prepare_aarch64_emulation(): """Run some necessary commands to use buildx to build AArch64 targets using QEMU emulation on an x86_64 host.""" subprocess.check_call( ['docker', 'buildx', 'create', '--name', ARM_BUILDER_NAME]) subprocess.check_call(['docker', 'buildx', 'use', ARM_BUILDER_NAME]) def docker_run(run_args, *, print_output=True, architecture='x86_64'): """Calls `docker run`.""" platform = 'linux/arm64' if architecture == 'aarch64' else 'linux/amd64' command = [ 'docker', 'run', '--privileged', '--shm-size=2g', '--platform', platform ] if os.getenv('OSS_FUZZ_SAVE_CONTAINERS_NAME'): command.append('--name') command.append(os.getenv('OSS_FUZZ_SAVE_CONTAINERS_NAME')) else: command.append('--rm') # Support environments with a TTY. if sys.stdin.isatty(): command.append('-i') command.extend(run_args) logger.info('Running: %s.', common_utils.get_command_string(command)) stdout = None if not print_output: stdout = open(os.devnull, 'w') try: subprocess.check_call(command, stdout=stdout, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: return False return True def build_image(args): """Builds docker image.""" if args.pull and args.no_pull: logger.error('Incompatible arguments --pull and --no-pull.') return False if args.pull: pull = True elif args.no_pull: pull = False else: y_or_n = raw_input('Pull latest base images (compiler/runtime)? (y/N): ') pull = y_or_n.lower() == 'y' if pull: logger.info('Pulling latest base images...') else: logger.info('Using cached base images...') # If build_image is called explicitly, don't use cache. if common_utils.build_image_impl(args.project, cache=args.cache, pull=pull, architecture=args.architecture): return True return False def build_fuzzers_impl( # pylint: disable=too-many-arguments,too-many-locals,too-many-branches project, clean, engine, sanitizer, architecture, env_to_add, source_path, mount_path=None, child_dir='', build_project_image=True): """Builds fuzzers.""" if build_project_image and not common_utils.build_image_impl( project, architecture=architecture): return False project_out = os.path.join(project.out, child_dir) if clean: logger.info('Cleaning existing build artifacts.') # Clean old and possibly conflicting artifacts in project's out directory. docker_run([ '-v', f'{project_out}:/out', '-t', f'gcr.io/oss-fuzz/{project.name}', '/bin/bash', '-c', 'rm -rf /out/*' ], architecture=architecture) docker_run([ '-v', '%s:/work' % project.work, '-t', 'gcr.io/oss-fuzz/%s' % project.name, '/bin/bash', '-c', 'rm -rf /work/*' ], architecture=architecture) else: logger.info('Keeping existing build artifacts as-is (if any).') env = [ 'FUZZING_ENGINE=' + engine, 'SANITIZER=' + sanitizer, 'ARCHITECTURE=' + architecture, 'PROJECT_NAME=' + project.name, 'HELPER=True', ] _add_oss_fuzz_ci_if_needed(env) if project.language: env.append('FUZZING_LANGUAGE=' + project.language) if env_to_add: env += env_to_add command = _env_to_docker_args(env) if source_path: workdir = _workdir_from_dockerfile(project) if mount_path: command += [ '-v', '%s:%s' % (_get_absolute_path(source_path), mount_path), ] else: if workdir == '/src': logger.error('Cannot use local checkout with "WORKDIR: /src".') return False command += [ '-v', '%s:%s' % (_get_absolute_path(source_path), workdir), ] command += [ '-v', f'{project_out}:/out', '-v', f'{project.work}:/work', f'gcr.io/oss-fuzz/{project.name}' ] if sys.stdin.isatty(): command.insert(-1, '-t') result = docker_run(command, architecture=architecture) if not result: logger.error('Building fuzzers failed.') return False return True def run_clusterfuzzlite(args): """Runs ClusterFuzzLite on a local repo.""" if not os.path.exists(CLUSTERFUZZLITE_FILESTORE_DIR): os.mkdir(CLUSTERFUZZLITE_FILESTORE_DIR) try: with tempfile.TemporaryDirectory() as workspace: if args.external: project_src_path = os.path.join(workspace, args.project.name) shutil.copytree(args.project.path, project_src_path) build_command = [ '--tag', 'gcr.io/oss-fuzz-base/cifuzz-run-fuzzers', '--file', 'infra/run_fuzzers.Dockerfile', 'infra' ] if not common_utils.docker_build(build_command): return False filestore_path = os.path.abspath(CLUSTERFUZZLITE_FILESTORE_DIR) docker_run_command = [] if args.external: docker_run_command += [ '-e', f'PROJECT_SRC_PATH={project_src_path}', ] else: docker_run_command += [ '-e', f'OSS_FUZZ_PROJECT_NAME={args.project.name}', ] docker_run_command += [ '-v', f'{filestore_path}:{filestore_path}', '-v', f'{workspace}:{workspace}', '-e', f'FILESTORE_ROOT_DIR={filestore_path}', '-e', f'WORKSPACE={workspace}', '-e', f'REPOSITORY={args.project.name}', '-e', 'CFL_PLATFORM=standalone', '--entrypoint', '', '-v', '/var/run/docker.sock:/var/run/docker.sock', CLUSTERFUZZLITE_DOCKER_IMAGE, 'python3', '/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py', ] return docker_run(docker_run_command) except PermissionError as error: logger.error('PermissionError: %s.', error) # Tempfile can't delete the workspace because of a permissions issue. This # is because docker creates files in the workspace that are owned by root # but this process is probably being run as another user. Use a docker image # to delete the temp directory (workspace) so that we have permission. docker_run([ '-v', f'{workspace}:{workspace}', '--entrypoint', '', CLUSTERFUZZLITE_DOCKER_IMAGE, 'rm', '-rf', os.path.join(workspace, '*') ]) return False def build_fuzzers(args): """Builds fuzzers.""" if args.engine == 'centipede' and args.sanitizer != 'none': # Centipede always requires separate binaries for sanitizers: # An unsanitized binary, which Centipede requires for fuzzing. # A sanitized binary, placed in the child directory. sanitized_binary_directories = ( ('none', ''), (args.sanitizer, f'__centipede_{args.sanitizer}'), ) else: # Generally, a fuzzer only needs one sanitized binary in the default dir. sanitized_binary_directories = ((args.sanitizer, ''),) return all( build_fuzzers_impl(args.project, args.clean, args.engine, sanitizer, args.architecture, args.e, args.source_path, mount_path=args.mount_path, child_dir=child_dir) for sanitizer, child_dir in sanitized_binary_directories) def fuzzbench_build_fuzzers(args): """Builds fuzz targets with an arbitrary fuzzer from FuzzBench.""" with tempfile.TemporaryDirectory() as tmp_dir: tmp_dir = os.path.abspath(tmp_dir) fuzzbench_path = os.path.join(tmp_dir, 'fuzzbench') subprocess.run([ 'git', 'clone', 'https://github.com/google/fuzzbench', '--depth', '1', fuzzbench_path ], check=True) env = [ f'FUZZBENCH_PATH={fuzzbench_path}', 'OSS_FUZZ_ON_DEMAND=1', f'PROJECT={args.project.name}' ] tag = f'gcr.io/oss-fuzz/{args.project.name}' subprocess.run([ 'docker', 'tag', 'gcr.io/oss-fuzz-base/base-builder-fuzzbench', 'gcr.io/oss-fuzz-base/base-builder' ], check=True) common_utils.build_image_impl(args.project) assert common_utils.docker_build([ '--tag', tag, '--build-arg', f'parent_image={tag}', '--file', os.path.join(fuzzbench_path, 'fuzzers', args.engine, 'builder.Dockerfile'), os.path.join(fuzzbench_path, 'fuzzers', args.engine) ]) return build_fuzzers_impl(args.project, False, args.engine, args.sanitizer, args.architecture, env, source_path=fuzzbench_path, mount_path=fuzzbench_path, build_project_image=False) def _add_oss_fuzz_ci_if_needed(env): """Adds value of |OSS_FUZZ_CI| environment variable to |env| if it is set.""" oss_fuzz_ci = os.getenv('OSS_FUZZ_CI') if oss_fuzz_ci: env.append('OSS_FUZZ_CI=' + oss_fuzz_ci) def check_build(args): """Checks that fuzzers in the container execute without errors.""" # Access the property to trigger validation early. _ = args.project.base_os_version if not common_utils.check_project_exists(args.project): return False if (args.fuzzer_name and not _check_fuzzer_exists( args.project, args.fuzzer_name, args, args.architecture)): return False env = [ 'FUZZING_ENGINE=' + args.engine, 'SANITIZER=' + args.sanitizer, 'ARCHITECTURE=' + args.architecture, 'FUZZING_LANGUAGE=' + args.project.language, 'HELPER=True', ] _add_oss_fuzz_ci_if_needed(env) if args.e: env += args.e run_args = _env_to_docker_args(env) + [ '-v', f'{args.project.out}:/out', '-t', _get_base_runner_image(args) ] if args.fuzzer_name: run_args += ['test_one.py', args.fuzzer_name] else: run_args.append('test_all.py') result = docker_run(run_args, architecture=args.architecture) if result: logger.info('Check build passed.') else: logger.error('Check build failed.') return result def _get_fuzz_targets(project): """Returns names of fuzz targest build in the project's /out directory.""" fuzz_targets = [] for name in os.listdir(project.out): if name.startswith('afl-'): continue if name == 'centipede': continue if name.startswith('jazzer_'): continue if name == 'llvm-symbolizer': continue path = os.path.join(project.out, name) # Python and JVM fuzz targets are only executable for the root user, so # we can't use os.access. if os.path.isfile(path) and (os.stat(path).st_mode & 0o111): fuzz_targets.append(name) return fuzz_targets def _get_latest_corpus(project, fuzz_target, base_corpus_dir): """Downloads the latest corpus for the given fuzz target.""" corpus_dir = os.path.join(base_corpus_dir, fuzz_target) os.makedirs(corpus_dir, exist_ok=True) if not fuzz_target.startswith(project.name + '_'): fuzz_target = '%s_%s' % (project.name, fuzz_target) # Normalise fuzz target name. fuzz_target = _normalized_name(fuzz_target) corpus_backup_url = CORPUS_BACKUP_URL_FORMAT.format(project_name=project.name, fuzz_target=fuzz_target) command = ['gsutil', 'ls', corpus_backup_url] # Don't capture stderr. We want it to print in real time, in case gsutil is # asking for two-factor authentication. corpus_listing = subprocess.Popen(command, stdout=subprocess.PIPE) output, _ = corpus_listing.communicate() # Some fuzz targets (e.g. new ones) may not have corpus yet, just skip those. if corpus_listing.returncode: logger.warning('Corpus for %s not found:\n', fuzz_target) return if output: latest_backup_url = output.splitlines()[-1] archive_path = corpus_dir + '.zip' command = ['gsutil', '-q', 'cp', latest_backup_url, archive_path] subprocess.check_call(command) command = ['unzip', '-q', '-o', archive_path, '-d', corpus_dir] subprocess.check_call(command) os.remove(archive_path) else: # Sync the working corpus copy if a minimized backup is not available. corpus_url = CORPUS_URL_FORMAT.format(project_name=project.name, fuzz_target=fuzz_target) command = ['gsutil', '-m', '-q', 'rsync', '-R', corpus_url, corpus_dir] subprocess.check_call(command) def _get_latest_public_corpus(args, fuzzer): """Downloads the public corpus""" target_corpus_dir = "build/corpus/%s" % args.project.name if not os.path.isdir(target_corpus_dir): os.makedirs(target_corpus_dir) target_zip = os.path.join(target_corpus_dir, fuzzer + ".zip") project_qualified_fuzz_target_name = fuzzer qualified_name_prefix = args.project.name + '_' if not fuzzer.startswith(qualified_name_prefix): project_qualified_fuzz_target_name = qualified_name_prefix + fuzzer download_url = HTTPS_CORPUS_BACKUP_URL_FORMAT.format( project_name=args.project.name, fuzz_target=project_qualified_fuzz_target_name) cmd = ['wget', download_url, '-O', target_zip] try: with open(os.devnull, 'w') as stdout: subprocess.check_call(cmd, stdout=stdout) except OSError: logger.error('Failed to download corpus') target_fuzzer_dir = os.path.join(target_corpus_dir, fuzzer) if not os.path.isdir(target_fuzzer_dir): os.mkdir(target_fuzzer_dir) target_corpus_dir = os.path.join(target_corpus_dir, fuzzer) try: with open(os.devnull, 'w') as stdout: subprocess.check_call( ['unzip', '-q', '-o', target_zip, '-d', target_fuzzer_dir], stdout=stdout) except OSError: logger.error('Failed to unzip corpus') # Remove the downloaded zip os.remove(target_zip) return True def download_corpora(args): """Downloads most recent corpora from GCS for the given project.""" if not common_utils.check_project_exists(args.project): return False if args.public: logger.info("Downloading public corpus") try: with open(os.devnull, 'w') as stdout: subprocess.check_call(['wget', '--version'], stdout=stdout) except OSError: logger.error('wget not found') return False else: try: with open(os.devnull, 'w') as stdout: subprocess.check_call(['gsutil', '--version'], stdout=stdout) except OSError: logger.error('gsutil not found. Please install it from ' 'https://cloud.google.com/storage/docs/gsutil_install') return False if args.fuzz_target: fuzz_targets = args.fuzz_target else: fuzz_targets = _get_fuzz_targets(args.project) if not fuzz_targets: logger.error( 'Fuzz targets not found. Please build project first ' '(python3 infra/helper.py build_fuzzers %s) so that download_corpora ' 'can automatically identify targets.', args.project.name) return False corpus_dir = args.project.corpus def _download_for_single_target(fuzz_target): try: if args.public: _get_latest_public_corpus(args, fuzz_target) else: _get_latest_corpus(args.project, fuzz_target, corpus_dir) return True except Exception as error: # pylint:disable=broad-except logger.error('Corpus download for %s failed: %s.', fuzz_target, str(error)) return False logger.info('Downloading corpora for %s project to %s.', args.project.name, corpus_dir) thread_pool = ThreadPool() return all(thread_pool.map(_download_for_single_target, fuzz_targets)) def coverage(args): # pylint: disable=too-many-branches """Generates code coverage using clang source based code coverage.""" if args.corpus_dir and not args.fuzz_target: logger.error( '--corpus-dir requires specifying a particular fuzz target using ' '--fuzz-target') return False if not common_utils.check_project_exists(args.project): return False if args.project.language not in constants.LANGUAGES_WITH_COVERAGE_SUPPORT: logger.error( 'Project is written in %s, coverage for it is not supported yet.', args.project.language) return False if (not args.no_corpus_download and not args.corpus_dir and not args.project.is_external): if not download_corpora(args): return False extra_cov_args = ( f'{args.project.coverage_extra_args.strip()} {" ".join(args.extra_args)}') env = [ 'FUZZING_ENGINE=libfuzzer', 'HELPER=True', 'FUZZING_LANGUAGE=%s' % args.project.language, 'PROJECT=%s' % args.project.name, 'SANITIZER=coverage', 'COVERAGE_EXTRA_ARGS=%s' % extra_cov_args, 'ARCHITECTURE=' + args.architecture, ] if not args.no_serve: env.append(f'HTTP_PORT={args.port}') run_args = _env_to_docker_args(env) if args.port: run_args.extend([ '-p', '%s:%s' % (args.port, args.port), ]) if args.corpus_dir: if not os.path.exists(args.corpus_dir): logger.error('The path provided in --corpus-dir argument does not ' 'exist.') return False corpus_dir = os.path.realpath(args.corpus_dir) run_args.extend(['-v', '%s:/corpus/%s' % (corpus_dir, args.fuzz_target)]) else: run_args.extend(['-v', '%s:/corpus' % args.project.corpus]) run_args.extend([ '-v', '%s:/out' % args.project.out, '-t', _get_base_runner_image(args), ]) run_args.append('coverage') if args.fuzz_target: run_args.append(args.fuzz_target) result = docker_run(run_args, architecture=args.architecture) if result: logger.info('Successfully generated clang code coverage report.') else: logger.error('Failed to generate clang code coverage report.') return result def _introspector_prepare_corpus(args): """Helper function for introspector runs to generate corpora.""" parser = get_parser() # Generate corpus, either by downloading or running fuzzers. if args.private_corpora or args.public_corpora: corpora_command = ['download_corpora'] if args.public_corpora: corpora_command.append('--public') corpora_command.append(args.project.name) if not download_corpora(parse_args(parser, corpora_command)): logger.error('Failed to download corpora') return False else: fuzzer_targets = _get_fuzz_targets(args.project) for fuzzer_name in fuzzer_targets: # Make a corpus directory. fuzzer_corpus_dir = args.project.corpus + f'/{fuzzer_name}' if not os.path.isdir(fuzzer_corpus_dir): os.makedirs(fuzzer_corpus_dir) run_fuzzer_command = [ 'run_fuzzer', '--sanitizer', 'address', '--corpus-dir', fuzzer_corpus_dir, args.project.name, fuzzer_name ] parsed_args = parse_args(parser, run_fuzzer_command) parsed_args.fuzzer_args = [ f'-max_total_time={args.seconds}', '-detect_leaks=0' ] # Continue even if run command fails, because we do not have 100% # accuracy in fuzz target detection, i.e. we might try to run something # that is not a target. run_fuzzer(parsed_args) return True def introspector(args): """Runs a complete end-to-end run of introspector.""" parser = get_parser() args_to_append = [] if args.source_path: args_to_append.append(_get_absolute_path(args.source_path)) # Build fuzzers with ASAN. build_fuzzers_command = [ 'build_fuzzers', '--sanitizer=address', args.project.name ] + args_to_append if not build_fuzzers(parse_args(parser, build_fuzzers_command)): logger.error('Failed to build project with ASAN') return False if not _introspector_prepare_corpus(args): return False # Build code coverage. build_fuzzers_command = [ 'build_fuzzers', '--sanitizer=coverage', args.project.name ] + args_to_append if not build_fuzzers(parse_args(parser, build_fuzzers_command)): logger.error('Failed to build project with coverage instrumentation') return False # Collect coverage. coverage_command = [ 'coverage', '--no-corpus-download', '--port', '', args.project.name ] if not coverage(parse_args(parser, coverage_command)): logger.error('Failed to extract coverage') return False logger.info('Coverage collected for %s', args.project.name) if args.coverage_only: logger.info('Coverage-only enabled, finishing now.') return True # Build introspector. build_fuzzers_command = [ 'build_fuzzers', '--sanitizer=introspector', args.project.name ] + args_to_append if not build_fuzzers(parse_args(parser, build_fuzzers_command)): logger.error('Failed to build project with introspector') return False introspector_dst = os.path.join(args.project.out, "introspector-report/inspector") shutil.rmtree(introspector_dst, ignore_errors=True) shutil.copytree(os.path.join(args.project.out, "inspector"), introspector_dst) # Copy the coverage reports into the introspector report. dst_cov_report = os.path.join(introspector_dst, "covreport") shutil.copytree(os.path.join(args.project.out, "report"), dst_cov_report) # Copy per-target coverage reports src_target_cov_report = os.path.join(args.project.out, "report_target") for target_cov_dir in os.listdir(src_target_cov_report): dst_target_cov_report = os.path.join(dst_cov_report, target_cov_dir) shutil.copytree(os.path.join(src_target_cov_report, target_cov_dir), dst_target_cov_report) logger.info('Introspector run complete. Report in %s', introspector_dst) logger.info( 'To browse the report, run: `python3 -m http.server 8008 --directory %s`' 'and navigate to localhost:8008/fuzz_report.html in your browser', introspector_dst) return True def run_fuzzer(args): """Runs a fuzzer in the container.""" if not common_utils.check_project_exists(args.project): return False if not _check_fuzzer_exists(args.project, args.fuzzer_name, args, args.architecture): return False env = [ 'FUZZING_ENGINE=' + args.engine, 'SANITIZER=' + args.sanitizer, 'RUN_FUZZER_MODE=interactive', 'HELPER=True', ] if args.e: env += args.e run_args = _env_to_docker_args(env) if args.corpus_dir: if not os.path.exists(args.corpus_dir): logger.error('The path provided in --corpus-dir argument does not exist') return False corpus_dir = os.path.realpath(args.corpus_dir) run_args.extend([ '-v', '{corpus_dir}:/tmp/{fuzzer}_corpus'.format(corpus_dir=corpus_dir, fuzzer=args.fuzzer_name) ]) run_args.extend([ '-v', '%s:/out' % args.project.out, '-t', _get_base_runner_image(args), 'run_fuzzer', args.fuzzer_name, ] + args.fuzzer_args) return docker_run(run_args, architecture=args.architecture) def fuzzbench_run_fuzzer(args): """Runs a fuzz target built by fuzzbench in the container.""" if not common_utils.check_project_exists(args.project): return False env = [ 'FUZZING_ENGINE=' + args.engine, 'SANITIZER=' + args.sanitizer, 'RUN_FUZZER_MODE=interactive', 'HELPER=True', f'FUZZ_TARGET={args.fuzzer_name}', f'BENCHMARK={args.project.name}', 'TRIAL_ID=1', 'EXPERIMENT_TYPE=bug', ] if args.e: env += args.e run_args = _env_to_docker_args(env) if args.corpus_dir: if not os.path.exists(args.corpus_dir): logger.error('The path provided in --corpus-dir argument does not exist') return False corpus_dir = os.path.realpath(args.corpus_dir) run_args.extend([ '-v', '{corpus_dir}:/tmp/{fuzzer}_corpus'.format(corpus_dir=corpus_dir, fuzzer=args.fuzzer_name) ]) with tempfile.TemporaryDirectory() as tmp_dir: tmp_dir = os.path.abspath(tmp_dir) fuzzbench_path = os.path.join(tmp_dir, 'fuzzbench') subprocess.run([ 'git', 'clone', 'https://github.com/google/fuzzbench', '--depth', '1', fuzzbench_path ], check=True) run_args.extend([ '-v', f'{args.project.out}:/out', '-v', f'{fuzzbench_path}:{fuzzbench_path}', '-e', f'FUZZBENCH_PATH={fuzzbench_path}', f'gcr.io/oss-fuzz/{args.project.name}', 'fuzzbench_run_fuzzer', args.fuzzer_name, ] + args.fuzzer_args) return docker_run(run_args, architecture=args.architecture) def fuzzbench_measure(args): """Measure results from fuzzing with fuzzbench.""" if not common_utils.check_project_exists(args.project): return False with tempfile.TemporaryDirectory() as tmp_dir: tmp_dir = os.path.abspath(tmp_dir) fuzzbench_path = os.path.join(tmp_dir, 'fuzzbench') subprocess.run([ 'git', 'clone', 'https://github.com/google/fuzzbench', '--depth', '1', fuzzbench_path ], check=True) run_args = [ '-v', f'{args.project.out}:/out', '-v', f'{fuzzbench_path}:{fuzzbench_path}', '-e', f'FUZZBENCH_PATH={fuzzbench_path}', '-e', 'EXPERIMENT_TYPE=bug', '-e', f'FUZZ_TARGET={args.fuzz_target_name}', '-e', f'FUZZER={args.engine_name}', '-e', f'BENCHMARK={args.project.name}', f'gcr.io/oss-fuzz/{args.project.name}', 'fuzzbench_measure' ] return docker_run(run_args, architecture='x86_64') def reproduce(args): """Reproduces a specific test case from a specific project.""" return reproduce_impl(args.project, args.fuzzer_name, args.valgrind, args.e, args.fuzzer_args, args.testcase_path, args, args.architecture) def reproduce_impl( # pylint: disable=too-many-arguments project, fuzzer_name, valgrind, env_to_add, fuzzer_args, testcase_path, args, architecture='x86_64', run_function=docker_run): """Reproduces a specific test case.""" if not common_utils.check_project_exists(project): return False if not _check_fuzzer_exists(project, fuzzer_name, args, architecture): return False debugger = '' env = ['HELPER=True', 'ARCHITECTURE=' + architecture] use_debug_image = bool(valgrind) image_name = _get_base_runner_image(args, debug=use_debug_image) if valgrind: debugger = 'valgrind --tool=memcheck --track-origins=yes --leak-check=full' if debugger: env += ['DEBUGGER=' + debugger] if env_to_add: env.extend(env_to_add) run_args = _env_to_docker_args(env) + [ '-v', '%s:/out' % project.out, '-v', '%s:/testcase' % _get_absolute_path(testcase_path), '-t', image_name, 'reproduce', fuzzer_name, '-runs=100', ] + fuzzer_args return run_function(run_args, architecture=architecture) def _validate_project_name(project_name): """Validates |project_name| is a valid OSS-Fuzz project name.""" if len(project_name) > MAX_PROJECT_NAME_LENGTH: logger.error( 'Project name needs to be less than or equal to %d characters.', MAX_PROJECT_NAME_LENGTH) return False if not VALID_PROJECT_NAME_REGEX.match(project_name): logger.info('Invalid project name: %s.', project_name) return False return True def _validate_language(language): if not LANGUAGE_REGEX.match(language): logger.error('Invalid project language %s.', language) return False return True def _create_build_integration_directory(directory): """Returns True on successful creation of a build integration directory. Suitable for OSS-Fuzz and external projects.""" try: os.makedirs(directory) except OSError as error: if error.errno != errno.EEXIST: raise logger.error('%s already exists.', directory) return False return True def _template_project_file(filename, template, template_args, directory): """Templates |template| using |template_args| and writes the result to |directory|/|filename|. Sets the file to executable if |filename| is build.sh.""" file_path = os.path.join(directory, filename) with open(file_path, 'w') as file_handle: file_handle.write(template % template_args) if filename == 'build.sh': os.chmod(file_path, 0o755) def generate(args): """Generates empty project files.""" return _generate_impl(args.project, args.language) def _get_current_datetime(): """Returns this year. Needed for mocking.""" return datetime.datetime.now() def _base_builder_from_language(language): """Returns the base builder for the specified language.""" return LANGUAGE_TO_BASE_BUILDER_IMAGE[language] def _generate_impl(project, language): """Implementation of generate(). Useful for testing.""" if project.is_external: # External project. project_templates = templates.EXTERNAL_TEMPLATES else: # Internal project. if not _validate_project_name(project.name): return False project_templates = templates.TEMPLATES if not _validate_language(language): return False directory = project.build_integration_path if not _create_build_integration_directory(directory): return False logger.info('Writing new files to: %s.', directory) template_args = { 'project_name': project.name, 'base_builder': _base_builder_from_language(language), 'language': language, 'year': _get_current_datetime().year } for filename, template in project_templates.items(): _template_project_file(filename, template, template_args, directory) return True def index(args): """Runs the indexer on the project.""" if not args.project.is_external and not common_utils.check_project_exists( args.project): return False image_name = f'gcr.io/oss-fuzz/{args.project.name}' if not common_utils.build_image_impl( args.project, cache=True, pull=False, architecture=args.architecture): logger.error('Failed to build project image for indexer.') return False env = [ f'ARCHITECTURE={args.architecture}', 'HELPER=True', f'PROJECT_NAME={args.project.name}', 'INDEXER_BUILD=1', ] if args.e: env.extend(args.e) run_args = _env_to_docker_args(env) run_args.extend([ '-v', f'{args.project.out}:/out', '-v', f'{args.project.work}:/work', '-t', ]) if args.docker_arg: run_args.extend(args.docker_arg) if args.dev: indexer_dir = os.path.join(os.path.dirname(__file__), 'base-images', 'base-builder', 'indexer') indexer_binary_path = os.path.join(indexer_dir, 'indexer') if not os.path.exists(indexer_binary_path): print('Indexer binary does not exist, pulling prebuilt.') with urllib.request.urlopen(INDEXER_PREBUILT_URL) as resp, \ open(indexer_binary_path, 'wb') as f: shutil.copyfileobj(resp, f) os.chmod(indexer_binary_path, 0o755) run_args.extend(['-v', f'{indexer_dir}:/opt/indexer']) run_args.append(image_name) if args.shell: run_args.append('/bin/bash') else: run_args.append('/opt/indexer/index_build.py') if args.targets: run_args.extend(['--targets', args.targets]) run_args.extend(args.extra_args) logger.info(f'Running indexer for project: {args.project.name}') result = docker_run(run_args, architecture=args.architecture) if result: logger.info('Indexer completed successfully.') else: logger.error('Indexer failed.') return result def shell(args): """Runs a shell within a docker image.""" # Access the property to trigger validation early. _ = args.project.base_os_version if not common_utils.build_image_impl(args.project): return False env = [ 'FUZZING_ENGINE=' + args.engine, 'SANITIZER=' + args.sanitizer, 'ARCHITECTURE=' + args.architecture, 'HELPER=True', f'PROJECT_NAME={args.project.name}' ] if args.project.name != 'base-runner-debug': env.append('FUZZING_LANGUAGE=' + args.project.language) if args.e: env += args.e if common_utils.is_base_image(args.project.name): image_project = 'oss-fuzz-base' out_dir = common_utils.get_out_dir() else: image_project = 'oss-fuzz' out_dir = args.project.out run_args = _env_to_docker_args(env) if args.source_path: workdir = _workdir_from_dockerfile(args.project) run_args.extend([ '-v', '%s:%s' % (_get_absolute_path(args.source_path), workdir), ]) run_args.extend([ '-v', '%s:/out' % out_dir, '-v', '%s:/work' % args.project.work, '-t', 'gcr.io/%s/%s' % (image_project, args.project.name), '/bin/bash' ]) docker_run(run_args, architecture=args.architecture) return True if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/helper_test.py ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for helper.py""" import datetime import os import tempfile import unittest from unittest import mock from pyfakefs import fake_filesystem_unittest import constants import helper import common_utils import templates # pylint: disable=no-self-use,protected-access class ShellTest(unittest.TestCase): """Tests 'shell' command.""" @mock.patch('helper.docker_run') @mock.patch('helper.build_image_impl') def test_base_runner_debug(self, _, __): """Tests that shell base-runner-debug works as intended.""" image_name = 'base-runner-debug' unparsed_args = ['shell', image_name] parser = helper.get_parser() args = helper.parse_args(parser, unparsed_args) args.sanitizer = 'address' result = helper.shell(args) self.assertTrue(result) class BuildImageImplTest(unittest.TestCase): """Tests for build_image_impl.""" @mock.patch('common_utils.docker_build') def test_no_cache(self, mock_docker_build): """Tests that cache=False is handled properly.""" image_name = 'base-image' common_utils.build_image_impl(common_utils.Project(image_name), cache=False) self.assertIn('--no-cache', mock_docker_build.call_args_list[0][0][0]) @mock.patch('common_utils.docker_build') @mock.patch('common_utils.pull_images') def test_pull(self, mock_pull_images, _): """Tests that pull=True is handled properly.""" image_name = 'base-image' project = common_utils.Project(image_name, is_external=True) self.assertTrue(common_utils.build_image_impl(project, pull=True)) mock_pull_images.assert_called_with('c++') @mock.patch('common_utils.docker_build') def test_base_image(self, mock_docker_build): """Tests that build_image_impl works as intended with a base-image.""" image_name = 'base-image' self.assertTrue( common_utils.build_image_impl(common_utils.Project(image_name))) build_dir = os.path.join(common_utils.OSS_FUZZ_DIR, 'infra/base-images/base-image') mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz-base/base-image', '--file', os.path.join(build_dir, 'Dockerfile'), build_dir ]) @mock.patch('common_utils.docker_build') def test_oss_fuzz_project(self, mock_docker_build): """Tests that build_image_impl works as intended with an OSS-Fuzz project.""" project_name = 'example' self.assertTrue( common_utils.build_image_impl(common_utils.Project(project_name))) build_dir = os.path.join(common_utils.OSS_FUZZ_DIR, 'projects', project_name) mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz/example', '--file', os.path.join(build_dir, 'Dockerfile'), build_dir ]) @mock.patch('common_utils.docker_build') def test_external_project(self, mock_docker_build): """Tests that build_image_impl works as intended with a non-OSS-Fuzz project.""" with tempfile.TemporaryDirectory() as temp_dir: project_src_path = os.path.join(temp_dir, 'example') os.mkdir(project_src_path) build_integration_path = 'build-integration' project = common_utils.Project( project_src_path, is_external=True, build_integration_path=build_integration_path) self.assertTrue(common_utils.build_image_impl(project)) mock_docker_build.assert_called_with([ '-t', 'gcr.io/oss-fuzz/example', '--file', os.path.join(project_src_path, build_integration_path, 'Dockerfile'), project_src_path ]) class GenerateImplTest(fake_filesystem_unittest.TestCase): """Tests for _generate_impl.""" PROJECT_NAME = 'newfakeproject' PROJECT_LANGUAGE = 'python' def setUp(self): self.maxDiff = None # pylint: disable=invalid-name self.setUpPyfakefs() self.fs.add_real_directory(helper.OSS_FUZZ_DIR) def _verify_templated_files(self, template_dict, directory, language): template_args = { 'project_name': self.PROJECT_NAME, 'year': 2021, 'base_builder': helper._base_builder_from_language(language), 'language': language, } for filename, template in template_dict.items(): file_path = os.path.join(directory, filename) with open(file_path, 'r') as file_handle: contents = file_handle.read() self.assertEqual(contents, template % template_args) @mock.patch('helper._get_current_datetime', return_value=datetime.datetime(year=2021, month=1, day=1)) def test_generate_oss_fuzz_project(self, _): """Tests that the correct files are generated for an OSS-Fuzz project.""" helper._generate_impl(helper.Project(self.PROJECT_NAME), self.PROJECT_LANGUAGE) self._verify_templated_files( templates.TEMPLATES, os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME), self.PROJECT_LANGUAGE) def test_generate_external_project(self): """Tests that the correct files are generated for a non-OSS-Fuzz project.""" build_integration_path = '/newfakeproject/build-integration' helper._generate_impl( helper.Project('/newfakeproject/', is_external=True, build_integration_path=build_integration_path), self.PROJECT_LANGUAGE) self._verify_templated_files(templates.EXTERNAL_TEMPLATES, build_integration_path, self.PROJECT_LANGUAGE) @mock.patch('helper._get_current_datetime', return_value=datetime.datetime(year=2021, month=1, day=1)) def test_generate_swift_project(self, _): """Tests that the swift project uses the correct base image.""" helper._generate_impl(helper.Project(self.PROJECT_NAME), 'swift') self._verify_templated_files( templates.TEMPLATES, os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.PROJECT_NAME), 'swift') class ProjectTest(fake_filesystem_unittest.TestCase): """Tests for Project class.""" def setUp(self): self.project_name = 'project' self.internal_project = helper.Project(self.project_name) self.external_project_path = os.path.join('/path', 'to', self.project_name) self.external_project = helper.Project(self.external_project_path, is_external=True) self.setUpPyfakefs() def test_init_external_project(self): """Tests __init__ method for external projects.""" self.assertEqual(self.external_project.name, self.project_name) self.assertEqual(self.external_project.path, self.external_project_path) self.assertEqual( self.external_project.build_integration_path, os.path.join(self.external_project_path, constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH)) def test_init_internal_project(self): """Tests __init__ method for internal projects.""" self.assertEqual(self.internal_project.name, self.project_name) path = os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.project_name) self.assertEqual(self.internal_project.path, path) self.assertEqual(self.internal_project.build_integration_path, path) def test_dockerfile_path_internal_project(self): """Tests that dockerfile_path works as intended.""" self.assertEqual( self.internal_project.dockerfile_path, os.path.join(helper.OSS_FUZZ_DIR, 'projects', self.project_name, 'Dockerfile')) def test_dockerfile_path_external_project(self): """Tests that dockerfile_path works as intended.""" self.assertEqual( self.external_project.dockerfile_path, os.path.join(self.external_project_path, constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH, 'Dockerfile')) def test_out(self): """Tests that out works as intended.""" out_dir = self.internal_project.out self.assertEqual( out_dir, os.path.join(helper.OSS_FUZZ_DIR, 'build', 'out', self.project_name)) self.assertTrue(os.path.exists(out_dir)) def test_work(self): """Tests that work works as intended.""" work_dir = self.internal_project.work self.assertEqual( work_dir, os.path.join(helper.OSS_FUZZ_DIR, 'build', 'work', self.project_name)) self.assertTrue(os.path.exists(work_dir)) def test_corpus(self): """Tests that corpus works as intended.""" corpus_dir = self.internal_project.corpus self.assertEqual( corpus_dir, os.path.join(helper.OSS_FUZZ_DIR, 'build', 'corpus', self.project_name)) self.assertTrue(os.path.exists(corpus_dir)) def test_language_internal_project(self): """Tests that language works as intended for an internal project.""" project_yaml_path = os.path.join(self.internal_project.path, 'project.yaml') self.fs.create_file(project_yaml_path, contents='language: python') self.assertEqual(self.internal_project.language, 'python') def test_language_external_project(self): """Tests that language works as intended for an external project.""" self.assertEqual(self.external_project.language, 'c++') ================================================ FILE: infra/indexer/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.19) project(Indexer LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -stdlib=libc++ -fexperimental-library -fno-rtti") set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld -lc++") include(FetchContent) FetchContent_Declare( absl URL https://github.com/abseil/abseil-cpp/archive/987c57f325f7fa8472fa84e1f885f7534d391b0d.zip # https://github.com/abseil/abseil-cpp/releases/tag/20250814.0 ) FetchContent_MakeAvailable(absl) # Force static linking of libraries. set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") # LLVM / Clang find_package(LLVM REQUIRED CONFIG COMPONENTS LLVMSupport ) find_package(Clang REQUIRED CONFIG COMPONENTS clang-cpp clangTooling clangFrontend clangAST clangBasic clangLex clangSema ) message(STATUS "Found LLVM: ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVM include directories: ${LLVM_INCLUDE_DIRS}") message(STATUS "Using LLVM library directories: ${LLVM_LIBRARY_DIRS}") include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) # SQLite find_package(SQLite3 REQUIRED) # GoogleTest (for unittests) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/6910c9d9165801d8827d628cb72eb7ea9dd538c5.zip ) # For Windows: Prevent overriding the parent project's compiler/linker settings set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) add_library(index index/file_copier.cc index/in_memory_index.cc index/sqlite.cc index/types.cc index/in_memory_index.h index/sqlite.h index/types.h ) target_include_directories(index PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ) target_link_libraries(index PUBLIC absl::flat_hash_map absl::log absl::check absl::strings absl::span SQLite::SQLite3 ) add_library(merge_queue merge_queue.cc queue_state.cc merge_queue.h queue_state.h ) target_link_libraries(merge_queue PUBLIC absl::base absl::log absl::strings absl::synchronization index ) target_include_directories(merge_queue PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ) add_library(frontend frontend/ast_visitor.cc frontend/common.cc frontend/frontend.cc frontend/index_action.cc frontend/pp_callbacks.cc frontend/ast_visitor.h frontend/common.h frontend/frontend.h frontend/index_action.h frontend/pp_callbacks.h ) target_include_directories(frontend PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ) target_link_libraries(frontend PUBLIC absl::flags absl::log absl::check absl::strings LLVMSupport clangAST clangBasic clangFrontend clangLex clangSema clangTooling index merge_queue ) target_include_directories(frontend INTERFACE SYSTEM ${LLVM_INCLUDE_DIRS}) add_executable(indexer main.cc) target_link_libraries(indexer PRIVATE absl::flags absl::flags_parse absl::log absl::log_initialize absl::check absl::string_view LLVMSupport clangTooling frontend index merge_queue -static ) enable_testing() include(GoogleTest) add_executable(index_unittest index/file_copier_unittest.cc index/in_memory_index_unittest.cc index/types_unittest.cc ) target_link_libraries(index_unittest PRIVATE GTest::gmock_main absl::hash absl::strings index ) gtest_discover_tests(index_unittest) add_executable(frontend_test frontend/frontend_test.cc ) target_link_libraries(frontend_test PRIVATE frontend index GTest::gmock_main ) gtest_discover_tests(frontend_test) ================================================ FILE: infra/indexer/Dockerfile ================================================ FROM gcr.io/oss-fuzz-base/base-clang-full RUN mkdir /indexer WORKDIR /indexer COPY . /indexer RUN apt-get update && apt-get install -y libsqlite3-dev make zlib1g-dev RUN mkdir build && cd build && cmake .. && cmake --build . -j -v ================================================ FILE: infra/indexer/frontend/ast_visitor.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/ast_visitor.h" #include #include #include #include #include #include "indexer/frontend/common.h" #include "indexer/index/types.h" #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/FileEntry.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/TypeTraits.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" namespace oss_fuzz { namespace indexer { namespace { const clang::PrintingPolicy& GetPrintingPolicy() { static clang::PrintingPolicy static_policy = ([] { clang::PrintingPolicy policy({}); policy.adjustForCPlusPlus(); policy.SplitTemplateClosers = false; policy.SuppressTemplateArgsInCXXConstructors = true; return policy; })(); return static_policy; } // Helper functions used to distinguish between declarations and definitions, so // that we can mark declarations as incomplete and resolve them at a later // stage. bool IsADefinition(const clang::Decl* decl) { if (llvm::isa(decl)) { const auto* record_decl = llvm::cast(decl); if (!record_decl->isThisDeclarationADefinition() && !llvm::isa(decl)) { return false; } } else if (llvm::isa(decl)) { const auto* function_decl = llvm::cast(decl); if (llvm::isa(function_decl)) { const auto* cxx_method_decl = llvm::cast(function_decl); if (cxx_method_decl->getParent()->isLambda()) { return true; } } if (!function_decl->isThisDeclarationADefinition()) { return false; } } return true; } bool IsParentADefinition(const clang::Decl* decl) { const auto* parent_context = decl->getNonTransparentDeclContext(); if (llvm::isa(parent_context)) { const auto* parent = llvm::cast(parent_context); return IsADefinition(parent); } else { return true; } } const clang::ClassTemplateDecl* GetClassTemplateDefinition( const clang::ClassTemplateDecl* class_template_decl) { if (class_template_decl->getTemplatedDecl()->getDefinition()) { class_template_decl = class_template_decl->getTemplatedDecl() ->getDefinition() ->getDescribedClassTemplate(); } return class_template_decl; } const clang::ClassTemplateSpecializationDecl* FindSpecialization( const clang::ClassTemplateDecl* class_template_decl, const llvm::ArrayRef args, const clang::ASTContext& context) { // Without this, sugared types can lead to lookup misses. llvm::SmallVector canonical_args; for (const clang::TemplateArgument& arg : args) { canonical_args.push_back(context.getCanonicalTemplateArgument(arg)); } // XXX(kartynnik): `findSpecialization` is a non-`const` method because it can // lead to loading external specializations. Arguably this could have been // handled through `mutable` fields because logically this doesn't affect the // forthcoming behavior of the object. void* insert_pos = nullptr; return const_cast(class_template_decl) ->findSpecialization(canonical_args, insert_pos); } // Helper functions to find the closest explicit template specialization that // matches the provided template arguments. const clang::Decl* GetSpecializationDecl( const clang::ClassTemplateDecl* class_template_decl, const llvm::ArrayRef template_arguments, const clang::ASTContext& context) { class_template_decl = GetClassTemplateDefinition(class_template_decl); const clang::Decl* decl = class_template_decl; const auto* specialization_decl = FindSpecialization(class_template_decl, template_arguments, context); while (specialization_decl) { // This happens when we have a forward declaration of a template class, // followed by an explicit instantiation, followed by the definition. In // that case, when we look for the correct specialization of the template // class definition, we get a ClassTemplateSpecializationDecl which is of // type TSK_Undeclared and which references the forward declaration of the // template class instead of the correct definition. Calling // getInstantiatedFrom on such a ClassTemplateSpecializationDecl will return // null. // // FrontendTest.UsingSpecialization tests the handling of this case. if (specialization_decl->getSpecializationKind() == clang::TemplateSpecializationKind::TSK_Undeclared) { return class_template_decl; } // Otherwise we should be able to continue walking the chain of // specialisations until we find the best match. const auto instantiated_from = specialization_decl->getInstantiatedFrom(); if (instantiated_from.isNull()) { // Includes the case of `specialization_decl->isExplicitSpecialization()`. decl = specialization_decl; break; } else if (llvm::isa(instantiated_from)) { decl = llvm::cast(instantiated_from); break; } else { specialization_decl = llvm::cast( instantiated_from); } } if (llvm::isa(decl)) { decl = GetClassTemplateDefinition(llvm::cast(decl)); } return decl; } const clang::Decl* GetSpecializationDecl( const clang::TemplateSpecializationType* type, const clang::ASTContext& context) { // There's no direct link to the clang::Type for the template type being // specialized, so this gets us a reference to the underlying template. // // Note that template_decl can be nullptr in the case of template template // parameters that are still instantiation dependent in this specialization. // Those are not "real" types, so we don't want to add references to them. const auto* template_decl = type->getTemplateName().getAsTemplateDecl(); const clang::Decl* decl = template_decl; if (template_decl) { if (llvm::isa(template_decl)) { auto* class_template_decl = llvm::cast(template_decl); decl = GetSpecializationDecl(class_template_decl, type->template_arguments(), context); } else if (llvm::isa(template_decl)) { return llvm::cast(template_decl) ->getTemplatedDecl(); } } return decl; } const clang::Decl* GetSpecializationDecl( const clang::ClassTemplateSpecializationDecl* decl, const clang::ASTContext& context) { // If this is an explicit specialization, then there's no need to look for // the best matching specialization. if (decl->isExplicitSpecialization()) { return decl; } return GetSpecializationDecl(decl->getSpecializedTemplate(), decl->getTemplateArgs().asArray(), context); } const clang::CXXRecordDecl* GetTemplatePrototypeRecordDecl( const clang::ClassTemplateSpecializationDecl* decl, const clang::ASTContext& context) { const clang::Decl* specialization_decl = GetSpecializationDecl(decl, context); if (const auto* class_template_decl = llvm::dyn_cast(specialization_decl)) { return class_template_decl->getTemplatedDecl(); } const clang::CXXRecordDecl* record_decl = llvm::dyn_cast( specialization_decl); CHECK_NE(record_decl, nullptr); return record_decl; } bool IsIncompleteFunction(const clang::FunctionDecl* function_decl) { return !function_decl->hasBody() && !function_decl->isDefaulted() && !function_decl->isPureVirtual() && !function_decl->getBuiltinID(true) && !function_decl->hasDefiningAttr(); } // `decl` is required to be a `clang::NamedDecl`. // If it is inside a template instantiation, finds the context where it is // instantiated from and finds the corresponding entity by name. const clang::NamedDecl* GetTemplatePrototypeNamedDecl( const clang::Decl* decl, const clang::ASTContext& context) { const clang::NamedDecl* named_decl = llvm::dyn_cast(decl); CHECK_NE(named_decl, nullptr); clang::DeclarationName field_name = named_decl->getDeclName(); if (field_name.getAsString().empty()) { // E.g. for a `DecompositionDecl`. return nullptr; } const clang::DeclContext* template_context = nullptr; const clang::TemplateDecl* template_decl = nullptr; if (const auto* class_specialization_decl = llvm::dyn_cast( named_decl->getDeclContext())) { if (class_specialization_decl->isExplicitSpecialization()) { return nullptr; } if (const clang::CXXRecordDecl* template_definition = GetTemplatePrototypeRecordDecl(class_specialization_decl, context)) { template_context = template_definition; template_decl = template_definition->getDescribedClassTemplate(); } else { return nullptr; } } else if (const auto* function_decl = llvm::dyn_cast( named_decl->getDeclContext())) { if (const clang::FunctionDecl* instantiation_pattern = function_decl->getTemplateInstantiationPattern()) { template_context = instantiation_pattern; template_decl = instantiation_pattern->getDescribedFunctionTemplate(); } else if (function_decl->getDescribedFunctionTemplate() && function_decl->getDescribedFunctionTemplate() ->getInstantiatedFromMemberTemplate()) { template_decl = function_decl->getDescribedFunctionTemplate() ->getInstantiatedFromMemberTemplate(); template_context = llvm::dyn_cast( template_decl->getTemplatedDecl()); } else { return nullptr; } } else { return nullptr; } if (template_context) { // We are using `decls` instead of `fields` to also account for statics. for (const clang::Decl* inner_decl : template_context->decls()) { if (const auto* inner_named_decl = llvm::dyn_cast(inner_decl)) { if (inner_named_decl->getDeclName() == field_name) { if (llvm::isa(inner_named_decl)) { // TODO: Figure out if we can support these. return nullptr; } return inner_named_decl; } } } } if (template_decl) { // Look up template parameters as well. for (const clang::NamedDecl* template_parameter : *template_decl->getTemplateParameters()) { if (template_parameter->getDeclName() == field_name) { return template_parameter; } } } return nullptr; } // Helper functions used to print template parameters for template declarations // and specializations, since this code can be shared between class and function // templates. std::string FormatTemplateParameters( const clang::TemplateParameterList* params) { llvm::SmallString<128> string; llvm::raw_svector_ostream stream(string); stream << "<"; for (int i = 0; i < params->size(); ++i) { if (i != 0) { stream << ", "; } const auto* param = params->getParam(i); if (llvm::isa(param)) { const auto* value_param = llvm::cast(param); auto value_type = value_param->getType(); stream << value_type.getAsString(GetPrintingPolicy()); } else { param->getNameForDiagnostic(stream, GetPrintingPolicy(), false); if (param->isParameterPack()) { stream << "..."; } } } stream << ">"; return stream.str().str(); } template std::string FormatTemplateArguments(const clang::TemplateParameterList* params, llvm::ArrayRef args) { llvm::SmallString<128> string; llvm::raw_svector_ostream stream(string); clang::printTemplateArgumentList(stream, args, GetPrintingPolicy(), params); return stream.str().str(); } // Helper functions to generate the `` suffixes when handling // templates. std::string GetTemplateParameterSuffix(const clang::TemplateDecl* decl) { return FormatTemplateParameters(decl->getTemplateParameters()); } std::string GetTemplateParameterSuffix( const clang::ClassTemplateSpecializationDecl* decl) { const clang::TemplateParameterList* params = decl->getSpecializedTemplate()->getTemplateParameters(); if (const auto* partial_spec_decl = llvm::dyn_cast(decl)) { if (const clang::ASTTemplateArgumentListInfo* args_as_written = partial_spec_decl->getTemplateArgsAsWritten()) { return FormatTemplateArguments(params, args_as_written->arguments()); } } return FormatTemplateArguments(params, decl->getTemplateArgs().asArray()); } std::string GetTemplateParameterSuffix( const clang::TemplateSpecializationType* type, const clang::ASTContext& context) { const auto* template_decl = type->getTemplateName().getAsTemplateDecl(); if (llvm::isa(template_decl)) { const auto* class_template_decl = llvm::cast(template_decl); return GetTemplateParameterSuffix(FindSpecialization( class_template_decl, type->template_arguments(), context)); } else { CHECK(llvm::isa(template_decl)); const auto* type_alias_template_decl = llvm::cast(template_decl); return FormatTemplateArguments( type_alias_template_decl->getTemplateParameters(), type->template_arguments()); } } std::string GetTemplateParameterSuffix( const clang::FunctionTemplateSpecializationInfo* info) { return FormatTemplateArguments(info->getTemplate()->getTemplateParameters(), info->TemplateArguments->asArray()); } std::string GetTemplateParameterSuffix( const clang::VarTemplateSpecializationDecl* decl, const clang::ASTContext& context) { const clang::TemplateParameterList* params = decl->getSpecializedTemplate()->getTemplateParameters(); if (const auto* partial_spec_decl = llvm::dyn_cast(decl)) { if (const clang::ASTTemplateArgumentListInfo* args_as_written = partial_spec_decl->getTemplateArgsAsWritten()) { return FormatTemplateArguments(params, args_as_written->arguments()); } } return FormatTemplateArguments(params, decl->getTemplateArgs().asArray()); } std::string GetName(const clang::Decl* decl) { std::string name = ""; if (auto field_decl = llvm::dyn_cast(decl); field_decl && field_decl->isAnonymousStructOrUnion()) { // Implicit unnamed fields for anonymous structs/unions are named after the // latter. We ignore them elsewhere; this is only for tests to assert // they're absent (the name contains the source file path otherwise). decl = field_decl->getType()->getAsRecordDecl(); CHECK_NE(decl, nullptr); } if (llvm::isa(decl)) { const auto* record_decl = llvm::cast(decl); name = record_decl->getName().str(); if (name.empty() && record_decl->isStruct()) { return "(anonymous struct)"; } else if (name.empty() && record_decl->isUnion()) { return "(anonymous union)"; } } else if (llvm::isa(decl)) { // Lambda function handling is a little bit tricky, since we want to use // the implicit operator() definition, but that doesn't track whether we are // in a lambda function, so we need to check whether the parent decl is an // implicit lambda class. if (llvm::isa(decl)) { auto* cxx_method_decl = llvm::cast(decl); if (cxx_method_decl->getParent()->isLambda()) { return "lambda"; } } const auto* named_decl = llvm::cast(decl); llvm::SmallString<32> string; llvm::raw_svector_ostream stream(string); named_decl->printName(stream, GetPrintingPolicy()); name = string.str().str(); } return name; } std::string GetNameSuffix(const clang::Decl* decl, const clang::ASTContext& context) { std::string name_suffix = ""; if (llvm::isa(decl)) { const auto* cxx_record_decl = llvm::cast(decl); if (llvm::isa(decl)) { const auto* class_template_specialization_decl = llvm::cast(decl); name_suffix = GetTemplateParameterSuffix(class_template_specialization_decl); } else if (cxx_record_decl->getDescribedClassTemplate()) { name_suffix = GetTemplateParameterSuffix( cxx_record_decl->getDescribedClassTemplate()); } } else if (llvm::isa(decl)) { const auto* function_decl = llvm::cast(decl); std::string template_param_suffix = ""; if (function_decl->getTemplateSpecializationInfo()) { template_param_suffix = GetTemplateParameterSuffix( function_decl->getTemplateSpecializationInfo()); } else if (function_decl->getDescribedFunctionTemplate()) { template_param_suffix = GetTemplateParameterSuffix( function_decl->getDescribedFunctionTemplate()); } std::vector param_types; param_types.reserve(function_decl->getNumParams()); for (int i = 0; i < function_decl->getNumParams(); ++i) { const clang::ParmVarDecl* parm_decl = function_decl->getParamDecl(i); param_types.emplace_back( parm_decl->getType().getAsString(GetPrintingPolicy())); } if (function_decl->isVariadic()) { param_types.emplace_back("..."); } name_suffix = absl::StrCat(template_param_suffix, "(", absl::StrJoin(param_types, ", "), ")"); if (llvm::isa(decl)) { const auto* cxx_method_decl = llvm::cast(decl); if (!cxx_method_decl->getParent()->isLambda()) { if (cxx_method_decl->isConst()) { absl::StrAppend(&name_suffix, " const"); } if (cxx_method_decl->isVolatile()) { absl::StrAppend(&name_suffix, " volatile"); } switch (cxx_method_decl->getRefQualifier()) { case clang::RQ_None: break; case clang::RQ_LValue: absl::StrAppend(&name_suffix, " &"); break; case clang::RQ_RValue: absl::StrAppend(&name_suffix, " &&"); break; } } } } else if (llvm::isa(decl)) { const auto* var_decl = llvm::cast(decl); if (const auto* var_template_decl = var_decl->getDescribedVarTemplate()) { name_suffix = GetTemplateParameterSuffix(var_template_decl); } else if (const auto* var_template_specialization_decl = llvm::dyn_cast(decl)) { name_suffix = GetTemplateParameterSuffix(var_template_specialization_decl, context); } } else if (llvm::isa(decl)) { const auto* type_alias_decl = llvm::cast(decl); const auto* type_alias_template_decl = type_alias_decl->getDescribedAliasTemplate(); if (type_alias_template_decl) { name_suffix = GetTemplateParameterSuffix(type_alias_template_decl); } } return name_suffix; } std::string GetNamePrefixForDeclContext(const clang::DeclContext* decl_context, const clang::ASTContext& ast_context, bool include_function_scope = true) { std::list parts = {""}; while (decl_context) { if (llvm::isa(decl_context)) { if (!include_function_scope) { // If we're not including function scopes, then we can stop when we // reach the first containing function. break; } const auto* parent_decl = llvm::cast(decl_context); parts.push_front(absl::StrCat(GetName(parent_decl), GetNameSuffix(parent_decl, ast_context))); } else if (llvm::isa(decl_context)) { // namespace name should always appear in our name prefix. const auto* namespace_decl = llvm::cast(decl_context); if (namespace_decl->isAnonymousNamespace()) { parts.push_front("(anonymous namespace)"); } else { parts.push_front(namespace_decl->getName().str()); } } else if (llvm::isa(decl_context)) { bool is_lambda = false; if (llvm::isa(decl_context)) { const auto* cxx_record_decl = llvm::cast(decl_context); is_lambda = cxx_record_decl->isLambda(); } // class / union / struct name should always appear in our name prefix, // unless it's the implicit class for a lambda function. if (!is_lambda) { const auto* parent_decl = llvm::cast(decl_context); parts.push_front(absl::StrCat(GetName(parent_decl), GetNameSuffix(parent_decl, ast_context))); } } else if (llvm::isa(decl_context)) { const auto* enum_decl = llvm::cast(decl_context); // The only time that an enum should appear in our name prefix is when it // is a c++11 scoped enum / enum class. if (enum_decl->isScoped() || enum_decl->isScopedUsingClassTag()) { const auto* parent_decl = llvm::cast(decl_context); parts.push_front(absl::StrCat(GetName(parent_decl), GetNameSuffix(parent_decl, ast_context))); } } decl_context = decl_context->getParent(); } return absl::StrJoin(parts, "::"); } std::string GetNamePrefix(const clang::Decl* decl, const clang::ASTContext& ast_context) { if (llvm::isa(decl)) { return {}; } // Function names should only appear in the name prefix in specific cases. // // 1. Declaration of a template parameter for a function or member function // template: // ``` // template // void foo(T bar); // ``` // In this case, the Type entity for `T` should be qualified as // `foo()::T` // // 2. Declaration of a nested type/class/enum or a nested function: // ``` // int foo() { // class Bar { // }; // } // ``` // In this case, the Class entity for `Bar` should be qualified as // `foo()::Bar` // // Technically, I think the return type should be included when functions are // used as qualifiers, but since return type overloading is not allowed I // don't think that this is necessary, so it is omitted at present. // // In practice this means that we want to include functions in fully qualified // names for anything other than variable declarations. bool include_function_scope = !llvm::isa(decl); const auto* decl_context = decl->getNonTransparentDeclContext(); return GetNamePrefixForDeclContext(decl_context, ast_context, include_function_scope); } bool IsIgnoredImplicitDecl(const clang::Decl* decl) { // Don't index unreferenced implicit entities except implicit methods. // (We opt to declare all the implicit methods with a preference to report // e.g. an "implicitly defined" destructor over reporting it missing.) return decl->isImplicit() && !llvm::isa(decl); } bool IsNotInherited(const clang::Decl* decl) { if (decl->isImplicit() || llvm::isa(decl) || llvm::isa(decl)) { return true; } // Assignment operators are not inherited. if (const auto* function_decl = llvm::dyn_cast(decl)) { if (function_decl->isOverloadedOperator() && function_decl->getOverloadedOperator() == clang::OO_Equal) { return true; } } return false; } using SeenNames = llvm::SmallSet; void CollectPotentialMemberNamesFromAncestors( const clang::CXXRecordDecl* class_decl, SeenNames& seen_names) { class_decl = class_decl->getDefinition(); if (!class_decl) { return; } for (const auto& base_spec : class_decl->bases()) { if (const clang::CXXRecordDecl* base_decl = base_spec.getType()->getAsCXXRecordDecl(); base_decl && (base_decl = base_decl->getDefinition())) { // We are using `decls` instead of `fields` to also account for statics. for (const auto* decl : base_decl->decls()) { if (const auto* named_decl = llvm::dyn_cast(decl)) { const clang::DeclarationName& decl_name = named_decl->getDeclName(); if (decl_name.getAsString().empty()) { continue; } if (!seen_names.contains(decl_name)) { // Process all the members with this name (e.g. method overloads). auto result = base_decl->lookup(named_decl->getDeclName()); for (const auto* found_decl : result) { if (!IsNotInherited(found_decl)) { seen_names.insert(decl_name); break; } } } } } CollectPotentialMemberNamesFromAncestors(base_decl, seen_names); } } } bool IsCompleteClass(const clang::CXXRecordDecl* class_decl) { // According to `Sema::LookupQualifiedName` constraints for a `TagDecl`. return class_decl->isDependentContext() || class_decl->isCompleteDefinition() || class_decl->isBeingDefined(); } template void ForAllInheritedMembers(clang::Sema& sema, const clang::CXXRecordDecl* class_decl, Action&& action) { CHECK_NE(class_decl, nullptr); if (!IsCompleteClass(class_decl)) { return; } SeenNames seen_names; CollectPotentialMemberNamesFromAncestors(class_decl, seen_names); for (const clang::DeclarationName& decl_name : seen_names) { clang::LookupResult lookup_result( sema, decl_name, {}, clang::Sema::LookupNameKind::LookupMemberName); lookup_result.suppressDiagnostics(); // `LookupQualifiedName` requires a mutable context - in particular, // implicit methods can be lazily defined in the process. // However, the pattern of `const` usage there is awkward - at the time of // writing, `LookupDirect` takes it as a `const` pointer, then passed to // `DeclareImplicitMemberFunctionsWithName` which casts the `const` away... auto* mutable_class_decl = const_cast(class_decl); sema.LookupQualifiedName(lookup_result, mutable_class_decl, /*InUnqualifiedLookup=*/false); if (!lookup_result.isSingleResult() && !lookup_result.isOverloadedResult()) { // Ambiguous lookups that require qualification are not instantiated. // However, qualified accesses (`A().B::x`) do count as references. continue; } for (const auto decl : lookup_result) { // Check that it is an inherited member and not one from the class itself. if (decl->getNonTransparentDeclContext()->getPrimaryContext() == class_decl->getPrimaryContext()) { continue; } action(decl); } } } void ReportTranslationUnit(llvm::raw_string_ostream& stream, const clang::ASTContext& context) { const clang::SourceManager& source_manager = context.getSourceManager(); clang::FileID main_file_id = source_manager.getMainFileID(); const clang::FileEntry* main_file_entry = source_manager.getFileEntryForID(main_file_id); if (main_file_entry) { llvm::StringRef main_file_path = main_file_entry->tryGetRealPathName(); stream << "Translation unit: '" << main_file_path << "'\n"; } } std::string GetEnumValue(const clang::EnumConstantDecl* decl) { const llvm::APSInt& value = decl->getInitVal(); std::string string_value; llvm::raw_string_ostream stream(string_value); stream << value; return string_value; } // The mapping from (not necessarily immediate) base classes defining a method // to their definitions thereof. using DefiningSuperBasesToMethods = llvm::SmallMapVector; template void AddVirtualMethodLinksImpl( const clang::CXXMethodDecl* prototype_method_decl, const clang::CXXRecordDecl* child_class_decl, const DefiningSuperBasesToMethods& defining_super_bases_to_methods, EntityId child_id, InMemoryIndex& index, EntityIdByDecl&& get_entity_id_for_decl, const clang::ASTContext& context) { llvm::SmallPtrSet seen; llvm::SmallVector to_visit; auto add_bases_to_visit = [&to_visit, &seen](const clang::CXXRecordDecl* class_decl) { for (const auto& base : class_decl->bases()) { auto* base_cxx_record = base.getType()->getAsCXXRecordDecl(); if (!base_cxx_record) { continue; } base_cxx_record = base_cxx_record->getDefinition(); if (!base_cxx_record) { continue; } if (!seen.contains(base_cxx_record)) { to_visit.push_back(base_cxx_record); seen.insert(base_cxx_record); } } }; add_bases_to_visit(child_class_decl); while (!to_visit.empty()) { const clang::CXXRecordDecl* base_cxx_record = to_visit.pop_back_val(); const auto it = defining_super_bases_to_methods.find(base_cxx_record); if (it != defining_super_bases_to_methods.end()) { // There is a definition in `base_cxx_record` we can link to. const clang::CXXMethodDecl* overridden_method_decl = it->second; EntityId parent_id = get_entity_id_for_decl(overridden_method_decl); if (parent_id != kInvalidEntityId) { (void)index.GetVirtualMethodLinkId({parent_id, child_id}); } else { LOG(DFATAL) << "Parent of virtual method " << index.GetEntityById(child_id).full_name() << " in class " << base_cxx_record->getQualifiedNameAsString() << " is an invalid entity"; } continue; } // `base_cxx_record` doesn't define this method directly. for (const auto [defining_super_base, overridden_method_decl] : defining_super_bases_to_methods) { if (!base_cxx_record->isDerivedFrom(defining_super_base)) { continue; } // Because it can be present in `base_cxx_record` only through inheritance // (see above), check if it was synthesized there from // `overridden_method_decl` in `defining_super_base`. const EntityId inherited_id = get_entity_id_for_decl(overridden_method_decl); if (inherited_id == kInvalidEntityId) { LOG(DFATAL) << "Parent of virtual method " << index.GetEntityById(child_id).full_name() << " in class " << defining_super_base->getQualifiedNameAsString() << " is an invalid entity"; continue; } const Entity& inherited_entity = index.GetEntityById(inherited_id); const std::string new_name_prefix = GetNamePrefixForDeclContext(base_cxx_record, context); // Re-synthesize it to get the ID of the synthetic entity. const EntityId parent_id = index.GetExistingEntityId( Entity(inherited_entity, /*new_name_prefix=*/new_name_prefix, /*inherited_entity_id=*/inherited_id)); if (parent_id == kInvalidEntityId) { // No such synthetic entity, likely due to name resolution ambiguity in // the base. Skip it and consider its immediate super-bases. add_bases_to_visit(base_cxx_record); } else { (void)index.GetVirtualMethodLinkId({parent_id, child_id}); } // We can't break here - can have multiple bases with this virtual method. } } } const clang::CXXRecordDecl* GetCXXRecordForType(const clang::QualType& type) { clang::QualType derived_type = type; if (const auto* pointer_type = type->getAs()) { derived_type = pointer_type->getPointeeType(); } if (derived_type->isDependentType()) { return nullptr; } const auto* record_type = derived_type->castAs(); CHECK(record_type); #if LLVM_VERSION_MAJOR > 22 const clang::RecordDecl* decl = record_type->getDecl(); #else const clang::RecordDecl* decl = record_type->getOriginalDecl(); #endif CHECK(decl); return llvm::dyn_cast(decl); } } // namespace bool AstVisitor::VisitCallExpr(const clang::CallExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitCXXConstructExpr(const clang::CXXConstructExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitCXXDeleteExpr(const clang::CXXDeleteExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitCXXNewExpr(const clang::CXXNewExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitDeclRefExpr(const clang::DeclRefExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitEnumDecl(const clang::EnumDecl* decl) { GetEntityIdForDecl(decl); return true; } bool AstVisitor::VisitEnumConstantDecl(const clang::EnumConstantDecl* decl) { GetEntityIdForDecl(decl); return true; } bool AstVisitor::VisitFieldDecl(const clang::FieldDecl* decl) { GetEntityIdForDecl(decl); AddReferencesForDecl(decl); return true; } bool AstVisitor::VisitFunctionDecl(const clang::FunctionDecl* decl) { // We only need to add an entity for a FunctionDecl that is the definition, // or if there is no definition in this translation unit, and we never add an // entity for a deleted function. if (decl->isDeleted()) { return true; } if (IsADefinition(decl) || !decl->getDefinition()) { GetEntityIdForDecl(decl); AddReferencesForDecl(decl); } return true; } bool AstVisitor::VisitLambdaExpr(const clang::LambdaExpr* expr) { GetEntityIdForDecl(expr->getCallOperator()); return true; } bool AstVisitor::VisitMemberExpr(const clang::MemberExpr* expr) { AddReferencesForExpr(expr); return true; } bool AstVisitor::VisitNonTypeTemplateParmDecl( const clang::NonTypeTemplateParmDecl* decl) { if (IsParentADefinition(decl)) { GetEntityIdForDecl(decl); } return true; } bool AstVisitor::VisitRecordDecl(clang::RecordDecl* decl) { if (auto* record_decl = llvm::dyn_cast(decl)) { if (record_decl->isInjectedClassName()) { // struct C { // // C is implicitly declared here as a synonym for the class name. // }; // C::C c; // same as "C c;" // Only index `C` in this case, and don't index `C::C`. return true; } if (IsADefinition(record_decl)) { SynthesizeInheritedMemberEntities(record_decl); } // We opt to declare all the implicit members with a preference to report // e.g. an "implicitly defined" destructor over reporting it missing. sema_.ForceDeclarationOfImplicitMembers(record_decl); } // As for FunctionDecl, we only need to add an entity for a RecordDecl if this // is the definition, or if there is no definition in this translation unit. if (IsADefinition(decl) || !decl->getDefinition()) { GetEntityIdForDecl(decl); AddReferencesForDecl(decl); } return true; } void AstVisitor::SynthesizeInheritedMemberEntities( const clang::CXXRecordDecl* class_decl) { CHECK(IsADefinition(class_decl)); const std::string new_name_prefix = GetNamePrefixForDeclContext( /*decl_context=*/class_decl, /*ast_context=*/context_); ForAllInheritedMembers(sema_, class_decl, [&](const clang::Decl* decl) { const EntityId inherited_id = GetEntityIdForDecl(decl); if (inherited_id == kInvalidEntityId) { return; } const Entity& inherited_entity = index_.GetEntityById(inherited_id); const Entity synth_entity(inherited_entity, /*new_name_prefix=*/new_name_prefix, /*inherited_entity_id=*/inherited_id); const EntityId synth_id = index_.GetEntityId(synth_entity); if (inherited_entity.is_virtual_method()) { AddSynthesizedVirtualMethodLinks(llvm::cast(decl), class_decl, synth_id); } }); } bool AstVisitor::VisitTemplateTypeParmDecl( const clang::TemplateTypeParmDecl* decl) { if (IsParentADefinition(decl)) { GetEntityIdForDecl(decl); } return true; } bool AstVisitor::VisitTypedefNameDecl(const clang::TypedefNameDecl* decl) { GetEntityIdForDecl(decl); AddReferencesForDecl(decl); return true; } bool AstVisitor::VisitUnaryExprOrTypeTraitExpr( const clang::UnaryExprOrTypeTraitExpr* expr) { // This is handling for the special kind of expression // size_t foo_size = sizeof(struct Foo); if ((expr->getKind() == clang::UETT_SizeOf || expr->getKind() == clang::UETT_AlignOf) && expr->isArgumentType()) { const auto* arg_type = expr->getArgumentType().getTypePtrOrNull(); if (arg_type) { AddTypeReferencesForSourceRange(expr->getSourceRange(), arg_type); } } return true; } bool AstVisitor::VisitVarDecl(const clang::VarDecl* decl) { if (IsParentADefinition(decl)) { GetEntityIdForDecl(decl); } AddReferencesForDecl(decl); return true; } LocationId AstVisitor::GetLocationId(clang::SourceLocation start, clang::SourceLocation end) { return oss_fuzz::indexer::GetLocationId(index_, context_.getSourceManager(), start, end); } LocationId AstVisitor::GetLocationId(const clang::Decl* decl) { // If we have a template specialization or instantiation, we should make // sure we use the source location that matches the closest explicit // specialization instead of the base template. if (llvm::isa(decl)) { const auto* specialization_decl = llvm::cast(decl); decl = GetSpecializationDecl(specialization_decl, context_); } // For class template definitions, the AST has two nodes: // - ClassTemplateDecl `template ` // - CXXRecordDecl `class Foo { ... };` // So, if we have a `CXXRecordDecl`, then we should check if we have an // associated class template, and use the outer location to give the full // definition. if (llvm::isa(decl)) { const auto* cxx_record_decl = llvm::cast(decl); if (cxx_record_decl->getDefinition()) { cxx_record_decl = cxx_record_decl->getDefinition(); } const auto* class_template_decl = cxx_record_decl->getDescribedClassTemplate(); if (class_template_decl) { decl = GetClassTemplateDefinition(class_template_decl); } } // For function template definitions, the AST also has two nodes: // - FunctionTemplateDecl `template ` // - FunctionDecl `void Foo(T bar) { ... }` // So we similarly need to check whether we have an associated function // template. However, for instantiation of function templates, we have an // extra level of indirection via `FunctionTemplateSpecializationInfo`. if (llvm::isa(decl)) { const auto* function_decl = llvm::cast(decl); if (function_decl->isTemplateInstantiation()) { function_decl = function_decl->getTemplateInstantiationPattern(); } else if (function_decl->getTemplateSpecializationInfo()) { const auto* tmp_info = function_decl->getTemplateSpecializationInfo(); function_decl = tmp_info->getFunction(); } decl = function_decl; const auto* func_template = function_decl->getDescribedFunctionTemplate(); if (func_template) { decl = func_template; } } // Same for variable template declarations. if (llvm::isa(decl)) { const auto* var_decl = llvm::cast(decl); const auto* var_template_decl = var_decl->getDescribedVarTemplate(); if (var_template_decl) { decl = var_template_decl; } } // Same for type alias template declarations. if (llvm::isa(decl)) { const auto* type_alias_decl = llvm::cast(decl); const auto* type_alias_template_decl = type_alias_decl->getDescribedTemplate(); if (type_alias_template_decl) { decl = type_alias_template_decl; } } // b/438675191: Workaround for a `libclang` bug (incorrect start location of // abbreviated function templates stemming from a missing `template` keyword). if (const auto* function_template_decl = llvm::dyn_cast(decl); function_template_decl && function_template_decl->getBeginLoc().isInvalid()) { return GetLocationId( function_template_decl->getTemplatedDecl()->getBeginLoc(), function_template_decl->getEndLoc()); } // If we reach here then we have updated decl to point to the correct location // already. return GetLocationId(decl->getBeginLoc(), decl->getEndLoc()); } std::optional AstVisitor::GetTemplateSubstituteRelationship( const clang::Decl* template_decl, const clang::Decl* original_decl) { if (template_decl == nullptr) { return std::nullopt; } EntityId template_entity_id = GetEntityIdForDecl(template_decl); if (template_entity_id == kInvalidEntityId) { // `original_decl` might have been materialized with `for_reference`. if (!IsIgnoredImplicitDecl(original_decl)) { std::string str; llvm::raw_string_ostream stream(str); stream << "Please report an indexer issue marked 'TEMPLATE':\n"; ReportTranslationUnit(stream, context_); stream << "Original Decl:\n"; original_decl->dump(stream); stream << "Template prototype Decl:\n"; template_decl->dump(stream); llvm::errs() << str; } return std::nullopt; } const Entity& template_entity = index_.GetEntityById(template_entity_id); const auto relationship_kind = SubstituteRelationship::Kind::kIsTemplateInstantiationOf; if (const auto& next_relationship = template_entity.substitute_relationship(); next_relationship && next_relationship->kind() == relationship_kind) { // Contract consecutive references to point to the ultimate prototype. template_entity_id = next_relationship->substitute_entity_id(); } return SubstituteRelationship(relationship_kind, template_entity_id); } // See the description of the `VirtualMethodLink` type for a discussion. void AstVisitor::AddVirtualMethodLinks(const clang::CXXMethodDecl* method_decl, EntityId child_id) { // For an actual virtual method, trace the chains to its prototypes, if any. if (method_decl->overridden_methods().empty()) { return; } DefiningSuperBasesToMethods defining_super_bases_to_methods; for (const clang::CXXMethodDecl* overridden_method_decl : method_decl->overridden_methods()) { const clang::CXXRecordDecl* overridden_method_record = overridden_method_decl->getParent(); defining_super_bases_to_methods.insert( {overridden_method_record, overridden_method_decl}); } AddVirtualMethodLinksImpl( method_decl, method_decl->getParent(), defining_super_bases_to_methods, child_id, index_, [&](const clang::Decl* decl) -> EntityId { return GetEntityIdForDecl(decl); }, context_); } void AstVisitor::AddSynthesizedVirtualMethodLinks( const clang::CXXMethodDecl* prototype_method_decl, const clang::CXXRecordDecl* child_class_decl, EntityId child_id) { DefiningSuperBasesToMethods defining_super_bases_to_methods; // For a synthesized entity, trace the chain(s) back to the origin class. defining_super_bases_to_methods.insert( {prototype_method_decl->getParent(), prototype_method_decl}); AddVirtualMethodLinksImpl( prototype_method_decl, child_class_decl, defining_super_bases_to_methods, child_id, index_, [&](const clang::Decl* decl) -> EntityId { return GetEntityIdForDecl(decl); }, context_); } EntityId AstVisitor::GetEntityIdForDecl(const clang::Decl* decl, bool for_reference) { auto it = decl_to_entity_id_.find(decl); if (it != decl_to_entity_id_.end()) { const CachedEntityId& cached = it->second; if (for_reference || !cached.for_reference_only) { return cached.entity_id; } } std::optional entity = GetEntityForDecl(decl, for_reference); if (entity) { const EntityId id = index_.GetEntityId(*entity); decl_to_entity_id_.insert_or_assign(it, decl, {id, for_reference}); if (entity->is_virtual_method()) { const auto method_decl = llvm::cast(decl); AddVirtualMethodLinks(method_decl, id); } return id; } if (for_reference) { // If even `for_reference` yields an invalid entity, we can cache that. decl_to_entity_id_.insert( it, {decl, {kInvalidEntityId, /*for_reference_only=*/false}}); } return kInvalidEntityId; } std::optional AstVisitor::GetEntityForDecl(const clang::Decl* decl, bool for_reference, LocationId location_id) { CHECK_NE(decl, nullptr); // Unless they are referenced, do not index `IsIgnoredImplicitDecl` subjects. if (!for_reference && IsIgnoredImplicitDecl(decl)) { return std::nullopt; } // Handle assignments of lambda types, as we need to get the entity for the // lambda::operator() rather than the implicit invisible lambda class. if (llvm::isa(decl)) { auto* function_decl = llvm::cast(decl); if (function_decl->isLambda()) { return GetEntityForDecl(function_decl->getLambdaCallOperator(), location_id); } } // Similarly, for ClassTemplateDecl we want the underlying CXXRecordDecl and // not the template wrapper decl. if (llvm::isa(decl)) { const auto* class_template_decl = llvm::cast(decl); decl = class_template_decl->getTemplatedDecl(); } // Resolve FunctionTemplateDecl to the underlying FunctionDecl. if (llvm::isa(decl)) { const auto* function_template_decl = llvm::cast(decl); decl = function_template_decl->getTemplatedDecl(); } // Resolve VarTemplateDecl to the underlying VarDecl. if (llvm::isa(decl)) { const auto* var_template_decl = llvm::cast(decl); decl = var_template_decl->getTemplatedDecl(); } // Resolve TypeAliasTemplateDecl to the underlying TypeAliasDecl. if (llvm::isa(decl)) { const auto* type_template_decl = llvm::cast(decl); decl = type_template_decl->getTemplatedDecl(); } // Then handle structured binding. if (llvm::isa(decl)) { auto* binding_decl = llvm::cast(decl); decl = binding_decl->getHoldingVar(); // It's possible that we don't have a holding var here. if (!decl) { return std::nullopt; } } // Then resolve from the declaration to the definition of the entity. if (llvm::isa(decl)) { auto* var_decl = llvm::cast(decl); if (!var_decl->isThisDeclarationADefinition() && var_decl->getDefinition()) { decl = var_decl->getDefinition(); } } else if (llvm::isa(decl)) { auto* tag_decl = llvm::cast(decl); if (!tag_decl->isThisDeclarationADefinition() && tag_decl->getDefinition()) { decl = tag_decl->getDefinition(); } } else if (llvm::isa(decl)) { auto* function_decl = llvm::cast(decl); if (!function_decl->isThisDeclarationADefinition() && function_decl->getDefinition()) { decl = function_decl->getDefinition(); } } // Defer getting the location in case the entity is invalid. auto get_location_id = [&]() { return location_id == kInvalidLocationId ? GetLocationId(decl) : location_id; }; const std::string name = GetName(decl); if (name.empty()) { return std::nullopt; } const std::string name_prefix = GetNamePrefix(decl, context_); const std::string name_suffix = GetNameSuffix(decl, context_); std::optional substitute_relationship; if (llvm::isa(decl) || llvm::isa(decl) || llvm::isa(decl)) { if (decl->isImplicit() || llvm::isa(decl)) { // Implicit `VarDecl`s encountered were range `for` loop variables; // implicit `FieldDecl`s were unnamed anonymous struct/union fields // (see `FieldDecl::isAnonymousStructOrUnion`). // `DecompositionDecl` is unnamed but inherits from `VarDecl`. return std::nullopt; } if (llvm::isa(decl) || llvm::isa(decl)) { // Check for template instantiation. substitute_relationship = GetTemplateSubstituteRelationship( GetTemplatePrototypeNamedDecl(decl, context_), decl); } return Entity(Entity::Kind::kVariable, name_prefix, name, name_suffix, get_location_id(), /*is_incomplete=*/false, /*is_weak=*/false, substitute_relationship); } else if (llvm::isa(decl)) { const auto* record_decl = llvm::cast(decl); bool is_incomplete = !record_decl->getDefinition(); if (llvm::isa(decl)) { auto* class_template_specialization_decl = llvm::cast(decl); // All explicit specializations should be considered complete, as they // will be the definition that is used (when the specialization matches). if (class_template_specialization_decl->isExplicitSpecialization()) { is_incomplete = false; } else { // Otherwise, a template instantiation is complete iff the base class // being templated from is complete. const auto* class_template_decl = class_template_specialization_decl->getSpecializedTemplate(); is_incomplete = !class_template_decl->getTemplatedDecl()->getDefinition(); substitute_relationship = GetTemplateSubstituteRelationship( GetTemplatePrototypeRecordDecl(class_template_specialization_decl, context_), class_template_specialization_decl); } } return Entity(Entity::Kind::kClass, name_prefix, name, name_suffix, get_location_id(), is_incomplete, /*is_weak=*/false, substitute_relationship); } else if (llvm::isa(decl)) { substitute_relationship = GetTemplateSubstituteRelationship( GetTemplatePrototypeNamedDecl(decl, context_), decl); return Entity(Entity::Kind::kEnum, name_prefix, name, name_suffix, get_location_id(), /*is_incomplete=*/false, /*is_weak=*/false, substitute_relationship); } else if (llvm::isa(decl)) { const auto* enum_constant_decl = llvm::cast(decl); substitute_relationship = GetTemplateSubstituteRelationship( GetTemplatePrototypeNamedDecl(decl, context_), decl); return Entity(Entity::Kind::kEnumConstant, name_prefix, name, name_suffix, get_location_id(), /*is_incomplete=*/false, /*is_weak=*/false, substitute_relationship, /*enum_value=*/GetEnumValue(enum_constant_decl)); } else if (llvm::isa(decl) || llvm::isa(decl)) { substitute_relationship = GetTemplateSubstituteRelationship( GetTemplatePrototypeNamedDecl(decl, context_), decl); return Entity(Entity::Kind::kType, name_prefix, name, name_suffix, get_location_id(), /*is_incomplete=*/false, /*is_weak=*/false, substitute_relationship); } else if (llvm::isa(decl)) { const auto* function_decl = llvm::cast(decl); bool is_incomplete = IsIncompleteFunction(function_decl); bool is_weak = !is_incomplete && function_decl->hasAttr(); Entity::VirtualMethodKind virtual_method_kind = Entity::VirtualMethodKind::kNotAVirtualMethod; if (const auto* method_decl = llvm::dyn_cast(function_decl)) { if (method_decl->isVirtual()) { virtual_method_kind = method_decl->isPureVirtual() ? Entity::VirtualMethodKind::kPureVirtual : Entity::VirtualMethodKind::kNonPureVirtual; } } // Note: Implicit methods are generally defined after template // instantiation, but an implicit comparison operator coming from (C++20) // constexpr operator<=>(const TemplatedClass& other); // can be instantiated by class template instantiations. // In this case we report the instantiation via `kIsTemplateInstantiationOf` // which refers to an implicit method in the template // (`kIsImplicitlyDefinedFor`). // // In contrast, an implicit destructor of an (implicit) template // instantiation will have `kIsImplicitlyDefinedFor` which in turn // has a 'kIsTemplateInstantiationOf`. // Check for template instantiation. const clang::Decl* function_template = nullptr; if (function_decl->getTemplateInstantiationPattern()) { function_template = function_decl->getTemplateInstantiationPattern(); } else if (function_decl->getDescribedFunctionTemplate() && function_decl->getDescribedFunctionTemplate() ->getInstantiatedFromMemberTemplate()) { function_template = function_decl->getDescribedFunctionTemplate() ->getInstantiatedFromMemberTemplate(); } if (function_template) { substitute_relationship = GetTemplateSubstituteRelationship(function_template, decl); } if (!substitute_relationship) { if (const auto method_decl = llvm::dyn_cast(function_decl)) { // Check for an implicitly defined method. if (!substitute_relationship && method_decl->isImplicit()) { auto parent_class = method_decl->getParent(); if (parent_class->getName().empty()) { // An anonymous struct's/union's implicit method; ignore. return std::nullopt; } auto implicitly_defined_for_entity_id = GetEntityIdForDecl(parent_class); if (implicitly_defined_for_entity_id == kInvalidEntityId) { // Case in point: Implicitly defined `struct __va_list_tag`. return std::nullopt; } else { substitute_relationship = { SubstituteRelationship::Kind::kIsImplicitlyDefinedFor, implicitly_defined_for_entity_id}; } } } } return Entity(Entity::Kind::kFunction, name_prefix, name, name_suffix, get_location_id(), is_incomplete, is_weak, substitute_relationship, /*enum_value=*/std::nullopt, /*virtual_method_kind=*/virtual_method_kind); } return std::nullopt; } void AstVisitor::AddTypeReferencesFromLocation(LocationId location_id, const clang::Type* type, bool outermost_type) { const clang::Decl* type_decl = nullptr; // We can't add references if the location is invalid. if (location_id == kInvalidLocationId) return; // First strip indirections while (type->isPointerType() || type->isReferenceType()) { const auto* pointee_type = type->getPointeeOrArrayElementType(); if (pointee_type == type) { break; } type = pointee_type; } if (llvm::isa(type)) { auto* specialization_type = llvm::cast(type); // We need to add references to the parameter types in the case of a // template specialization. We only do this in the first level of recursion, // so that we don't get too noisy with the cross-references. if (outermost_type) { for (const auto& template_argument : specialization_type->template_arguments()) { if (template_argument.getKind() == clang::TemplateArgument::ArgKind::Type) { const auto* argument_type = template_argument.getAsType().getTypePtrOrNull(); if (argument_type) { AddTypeReferencesFromLocation(location_id, argument_type, /*outermost_type=*/false); } } } } // We want to add a reference to the "best matching" underlying template. // This should be the source code entity that closest matches the template // parameters; so the source code version of the template that will be // instantiated for this type. const auto* specialization_decl = GetSpecializationDecl(specialization_type, context_); if (specialization_decl) { auto entity_id = GetEntityIdForDecl(specialization_decl, /*for_reference=*/true); if (entity_id != kInvalidEntityId) { (void)index_.GetReferenceId({entity_id, location_id}); } } const auto* template_decl = specialization_type->getTemplateName().getAsTemplateDecl(); LocationId decl_location_id = kInvalidLocationId; if (specialization_decl) { decl_location_id = GetLocationId(specialization_decl); } else if (template_decl) { decl_location_id = GetLocationId(template_decl); } // We need to manually create the entities for template specializations, // because when we have partial specializations or forward declarations, // we need a different source location than the one associated to the // template ClassTemplateDecl, and for partial specializations we also // need to override the name_suffix generation with information that is only // stored in the TemplateSpecializationType. if (decl_location_id != kInvalidLocationId) { if (template_decl && llvm::isa(template_decl)) { std::string name_prefix = GetNamePrefix(template_decl, context_); std::string name = GetName(template_decl); std::string name_suffix = GetTemplateParameterSuffix(specialization_type, context_); auto* alias_template_decl = llvm::cast(template_decl); auto entity_id = index_.GetEntityId( {Entity::Kind::kType, name_prefix, name, name_suffix, decl_location_id, /*is_incomplete=*/false, /*is_weak=*/false, SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, GetEntityIdForDecl(alias_template_decl->getTemplatedDecl(), /*for_reference=*/true))}); if (entity_id != kInvalidEntityId) { (void)index_.GetReferenceId({entity_id, location_id}); } } } // Type declaration becomes the instantiation of the underlying template. type_decl = type->getAsTagDecl(); if (type_decl) { auto entity_id = GetEntityIdForDecl(type_decl, /*for_reference=*/true); if (entity_id != kInvalidEntityId) { (void)index_.GetReferenceId({entity_id, location_id}); } } } else { if (llvm::isa(type)) { type_decl = llvm::cast(type)->getDecl(); } else if (type->isTypedefNameType()) { // We need to add references to the inner-types in the case of typedefs. const clang::TypedefType* typedef_type_ptr = type->getAs(); if (typedef_type_ptr) { const auto* typedef_decl = typedef_type_ptr->getDecl(); const auto* underlying_type_ptr = typedef_decl->getUnderlyingType().getTypePtrOrNull(); if (underlying_type_ptr) { AddTypeReferencesFromLocation(location_id, underlying_type_ptr, /*outermost_type=*/false); } type_decl = typedef_decl; } } else { type_decl = type->getAsTagDecl(); } if (type_decl) { auto entity_id = GetEntityIdForDecl(type_decl, /*for_reference=*/true); if (entity_id != kInvalidEntityId) { (void)index_.GetReferenceId({entity_id, location_id}); } } } } void AstVisitor::AddReferencesForDecl(const clang::Decl* decl) { clang::SourceRange range = decl->getSourceRange(); const clang::Type* type_ptr = nullptr; if (llvm::isa(decl)) { const auto* typedef_decl = llvm::cast(decl); type_ptr = typedef_decl->getUnderlyingType().getTypePtrOrNull(); } else if (llvm::isa(decl)) { if (const auto* method_decl = llvm::dyn_cast(decl)) { for (const clang::CXXMethodDecl* overridden_method : method_decl->overridden_methods()) { AddDeclReferenceForSourceRange(range, overridden_method); } } const auto* function_decl = llvm::cast(decl); type_ptr = function_decl->getReturnType().getTypePtrOrNull(); // We truncate function return type type references to reference only the // function declaration/definition and not to include the lines for the // function body. if (function_decl->hasBody()) { range.setEnd(function_decl->getBody()->getSourceRange().getBegin()); } } else if (llvm::isa(decl)) { const auto* cxx_record_decl = llvm::cast(decl); if (cxx_record_decl->isThisDeclarationADefinition()) { // C++ class definitions may have multiple inheritance, so we need to add // references to all base classes here. for (const auto& base : cxx_record_decl->bases()) { const auto* base_type_ptr = base.getType().getTypePtrOrNull(); if (base_type_ptr) { AddTypeReferencesForSourceRange(range, base_type_ptr); } } } } else if (llvm::isa(decl)) { const auto* value_decl = llvm::cast(decl); type_ptr = value_decl->getType().getTypePtrOrNull(); } if (type_ptr) { AddTypeReferencesForSourceRange(range, type_ptr); } } void AstVisitor::AddReferencesForExpr(const clang::Expr* expr) { const clang::Decl* decl = nullptr; if (llvm::isa(expr)) { decl = llvm::cast(expr)->getOperatorDelete(); } else if (llvm::isa(expr)) { decl = llvm::cast(expr)->getOperatorNew(); } else if (llvm::isa(expr)) { decl = llvm::cast(expr)->getCalleeDecl(); if (decl && llvm::isa(decl)) { const auto* method_decl = llvm::cast(decl); if (method_decl->getParent()) { const auto* type = method_decl->getParent() ->getASTContext() .getCanonicalTagType(method_decl->getParent()) .getTypePtr(); if (type) { AddTypeReferencesForSourceRange(expr->getSourceRange(), type); } } } } else if (llvm::isa(expr)) { // Perhaps surprisingly, `CXXConstructExpr` is not a `CallExpr`. decl = llvm::cast(expr)->getConstructor(); if (decl && llvm::isa(decl)) { const auto* constructor_decl = llvm::cast(decl); if (constructor_decl->getParent()) { const auto* type = constructor_decl->getParent() ->getASTContext() .getCanonicalTagType(constructor_decl->getParent()) .getTypePtr(); if (type) { AddTypeReferencesForSourceRange(expr->getSourceRange(), type); } } } } else if (llvm::isa(expr)) { decl = llvm::cast(expr)->getDecl(); } else if (llvm::isa(expr)) { const auto* member_expr = llvm::cast(expr); const clang::ValueDecl* value_decl = member_expr->getMemberDecl(); decl = value_decl; if (clang::Expr* base = member_expr->getBase()) { AddReferencesForExpr(base); // Check if the call can be devirtualized (the type is known precisely, // or either the member function or its defining class are marked `final` // etc.) Add a reference to the devirtualized method as well in that case. if (const auto* method_decl = llvm::dyn_cast(value_decl); method_decl && method_decl->isVirtual()) { if (const clang::CXXMethodDecl* devirtualized_method_decl = method_decl->getDevirtualizedMethod(base, /*IsAppleKext=*/false); devirtualized_method_decl && devirtualized_method_decl != method_decl) { AddDeclReferenceForSourceRange(expr->getSourceRange(), devirtualized_method_decl); } } // Check if the access is through an inheriting descendant, in which case // we add a cross-reference to the corresponding synthetic entity. // // Skip the case of an explicit qualification (`instance.Base::method`) // because it is commonly used for members not accessible through the // instance directly (for disambiguation). if (!member_expr->getQualifierLoc()) { if (const clang::CXXRecordDecl* expr_record_decl = GetCXXRecordForType(base->IgnoreParenBaseCasts()->getType())) { const clang::DeclContext* decl_context = value_decl->getNonTransparentDeclContext(); // If the base expression is not of the same record type as the parent // of the retrieved member... if (const auto* record_decl = llvm::dyn_cast(decl_context); record_decl && record_decl->getCanonicalDecl() != expr_record_decl->getCanonicalDecl()) { // ...add synthetic entity cross-references. AddSyntheticMemberReference(expr_record_decl, value_decl, expr->getSourceRange()); } } } } } else if (llvm::isa(expr)) { decl = llvm::cast(expr) ->getLambdaClass() ->getLambdaCallOperator(); } if (decl) { AddDeclReferenceForSourceRange(expr->getSourceRange(), decl); } } void AstVisitor::AddSyntheticMemberReference( const clang::CXXRecordDecl* child_class, const clang::ValueDecl* inherited_member, const clang::SourceRange& range) { const EntityId base_member_entity_id = GetEntityIdForDecl(inherited_member); if (base_member_entity_id == kInvalidEntityId) { return; } const Entity& base_member_entity = index_.GetEntityById(base_member_entity_id); const Entity synthetic_inherited_member = Entity( base_member_entity, GetNamePrefixForDeclContext(child_class, context_), /*inherited_entity_id=*/base_member_entity_id); const EntityId synthetic_inherited_member_id = index_.GetEntityId(synthetic_inherited_member); auto location_id = GetLocationId(range.getBegin(), range.getEnd()); (void)index_.GetReferenceId({synthetic_inherited_member_id, location_id}); } void AstVisitor::AddDeclReferenceForSourceRange(const clang::SourceRange& range, const clang::Decl* decl) { auto entity_id = GetEntityIdForDecl(decl, /*for_reference=*/true); auto location_id = GetLocationId(range.getBegin(), range.getEnd()); if (entity_id != kInvalidEntityId && location_id != kInvalidLocationId) { (void)index_.GetReferenceId({entity_id, location_id}); } } void AstVisitor::AddTypeReferencesForSourceRange( const clang::SourceRange& range, const clang::Type* type) { if (range.isInvalid()) { return; } auto location_id = GetLocationId(range.getBegin(), range.getEnd()); AddTypeReferencesFromLocation(location_id, type); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/ast_visitor.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_FRONTEND_AST_VISITOR_H_ #define OSS_FUZZ_INFRA_INDEXER_FRONTEND_AST_VISITOR_H_ #include #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "absl/container/flat_hash_map.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Sema/Sema.h" namespace oss_fuzz { namespace indexer { // AstVisitor handles the indexing operations for the AST. This should not be // used directly, and the exposed api in indexer/frontend.h should be used // instead. class AstVisitor : public clang::RecursiveASTVisitor { public: AstVisitor(InMemoryIndex& index, clang::ASTContext& context, clang::CompilerInstance& compiler) : index_(index), context_(context), sema_(compiler.getSema()) {} bool shouldVisitImplicitCode() const { return true; } bool shouldVisitTemplateInstantiations() const { return true; } // clang::RecursiveASTVisitor functions: // These are not overrides, since clang uses template magic to implement the // AST visitor instead of virtual function calls. bool VisitCallExpr(const clang::CallExpr *expr); bool VisitCXXConstructExpr(const clang::CXXConstructExpr *expr); bool VisitCXXNewExpr(const clang::CXXNewExpr *expr); bool VisitCXXDeleteExpr(const clang::CXXDeleteExpr *expr); bool VisitDeclRefExpr(const clang::DeclRefExpr *expr); bool VisitEnumDecl(const clang::EnumDecl *decl); bool VisitEnumConstantDecl(const clang::EnumConstantDecl *decl); bool VisitFieldDecl(const clang::FieldDecl *decl); bool VisitFunctionDecl(const clang::FunctionDecl *decl); bool VisitLambdaExpr(const clang::LambdaExpr *expr); bool VisitMemberExpr(const clang::MemberExpr *expr); bool VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl *decl); bool VisitRecordDecl(clang::RecordDecl *decl); bool VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl *decl); bool VisitTypedefNameDecl(const clang::TypedefNameDecl *decl); bool VisitUnaryExprOrTypeTraitExpr( const clang::UnaryExprOrTypeTraitExpr *expr); bool VisitVarDecl(const clang::VarDecl *decl); private: LocationId GetLocationId(clang::SourceLocation start, clang::SourceLocation end); LocationId GetLocationId(const clang::Decl *decl); std::optional GetEntityForDecl( const clang::Decl* decl, bool for_reference = false, LocationId location_id = kInvalidLocationId); EntityId GetEntityIdForDecl(const clang::Decl *decl, bool for_reference = false); std::optional GetTemplateSubstituteRelationship( const clang::Decl* template_decl, const clang::Decl* original_decl); void SynthesizeInheritedMemberEntities( const clang::CXXRecordDecl* class_decl); void AddSyntheticMemberReference(const clang::CXXRecordDecl* child_class, const clang::ValueDecl* inherited_member, const clang::SourceRange& range); void AddTypeReferencesFromLocation(LocationId location_id, const clang::Type *type, bool outermost_type = true); void AddReferencesForDecl(const clang::Decl *decl); void AddReferencesForExpr(const clang::Expr *expr); void AddDeclReferenceForSourceRange(const clang::SourceRange &range, const clang::Decl *decl); void AddTypeReferencesForSourceRange(const clang::SourceRange &range, const clang::Type *type); void AddVirtualMethodLinks(const clang::CXXMethodDecl* method_decl, EntityId child_id); void AddSynthesizedVirtualMethodLinks( const clang::CXXMethodDecl* prototype_method_decl, const clang::CXXRecordDecl* child_class_decl, EntityId child_id); InMemoryIndex &index_; clang::ASTContext &context_; clang::Sema& sema_; struct CachedEntityId { EntityId entity_id; bool for_reference_only; }; absl::flat_hash_map decl_to_entity_id_; }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_FRONTEND_AST_VISITOR_H_ ================================================ FILE: infra/indexer/frontend/common.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/common.h" #include #include // NOLINT #include #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/ErrorOr.h" namespace oss_fuzz { namespace indexer { std::string ToNormalizedAbsolutePath( absl::string_view path, const clang::SourceManager& source_manager) { std::filesystem::path native_path = std::filesystem::path(path); if (!native_path.is_absolute()) { llvm::ErrorOr cwd = source_manager.getFileManager() .getVirtualFileSystem() .getCurrentWorkingDirectory(); QCHECK(cwd) << "unable to get cwd"; native_path = std::filesystem::path(*cwd); native_path.append(path); } return native_path.lexically_normal(); } // Converting from `SourceLocation` to a usable file location is non-trivial, // see comments in-line for explanation. LocationId GetLocationId(InMemoryIndex& index, const clang::SourceManager& source_manager, clang::SourceLocation start, clang::SourceLocation end) { std::string path = ""; uint32_t start_line = 0, end_line = 0; // If the location is inside a macro expansion, we want to first resolve it to // the source location (of the expansion). For example: // // 1: #define INNER_MACRO 1 // 2: #define OUTER_MACRO INNER_MACRO // 3: OUTER_MACRO // // If we look at the reference to INNER_MACRO here, we'd want to see that it // is referenced from line 3, not from line 2. // // `getExpansionLoc` is the identity function if the location is not in an // expansion. start = source_manager.getExpansionLoc(start); end = source_manager.getExpansionLoc(end); // At this point, both of the `SourceLocations` that are valid should be file // locations. `getPresumedLoc` will then resolve these to meaningful file // locations. clang::PresumedLoc presumed_start = source_manager.getPresumedLoc(start, false); if (!presumed_start.isInvalid()) { path = presumed_start.getFilename(); start_line = presumed_start.getLine(); end_line = presumed_start.getLine(); } clang::PresumedLoc presumed_end = source_manager.getPresumedLoc(end, false); if (!presumed_end.isInvalid()) { end_line = presumed_end.getLine(); } if (end_line < start_line) { end_line = start_line; } if (IsRealPath(path)) { // This is a real file path, so normalize it. path = ToNormalizedAbsolutePath(path, source_manager); } return index.GetLocationId({path, start_line, end_line}); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/common.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_FRONTEND_COMMON_H_ #define OSS_FUZZ_INFRA_INDEXER_FRONTEND_COMMON_H_ #include #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "absl/strings/string_view.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" namespace oss_fuzz { namespace indexer { // Converts a source-level `path` into a normalized absolute form suitable for // passing to the indexer as a location path. std::string ToNormalizedAbsolutePath( absl::string_view path, const clang::SourceManager& source_manager); // Converts a pair of `SourceLocation` to a `LocationId` for a location in the // index. LocationId GetLocationId(InMemoryIndex& index, const clang::SourceManager& source_manager, clang::SourceLocation start, clang::SourceLocation end); } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_FRONTEND_COMMON_H_ ================================================ FILE: infra/indexer/frontend/frontend.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/frontend.h" #include #include #include #include #include #include #include #include "indexer/frontend/index_action.h" #include "indexer/index/file_copier.h" #include "indexer/merge_queue.h" #include "absl/flags/flag.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/StringRef.h" ABSL_FLAG(std::string, extra_compiler_args, "", "Extra compiler flags"); namespace oss_fuzz { namespace indexer { namespace frontend_internal { std::vector ParseCommandLine(absl::string_view commandLine) { std::vector args; std::string currentArg; bool inSingleQuotes = false; bool inDoubleQuotes = false; bool escaped = false; for (char c : commandLine) { if (c == '\\' && inDoubleQuotes) { escaped = true; continue; } if (c == '\'' && !inDoubleQuotes && !escaped) { if (inSingleQuotes) { inSingleQuotes = false; args.push_back(currentArg); currentArg.clear(); } else { inSingleQuotes = true; } } else if (c == '"' && !inSingleQuotes && !escaped) { if (inDoubleQuotes) { inDoubleQuotes = false; args.push_back(currentArg); currentArg.clear(); } else { inDoubleQuotes = true; } } else if (std::isspace(c) && !inSingleQuotes && !inDoubleQuotes) { if (!currentArg.empty()) { args.push_back(currentArg); currentArg.clear(); } } else { currentArg += c; } escaped = false; } if (!currentArg.empty()) { args.push_back(currentArg); } return args; } } // namespace frontend_internal namespace { // We need to strip clang-specific arguments from the command line, as these are // usually invocations of clang plugins, which will not be present in our build // of clang/llvm. clang::tooling::CommandLineArguments RemoveClangArgumentsAdjuster( const clang::tooling::CommandLineArguments& arguments, llvm::StringRef) { clang::tooling::CommandLineArguments result; for (size_t i = 0; i < arguments.size(); ++i) { if (arguments[i] == "-Xclang") { ++i; } else if (absl::StartsWith(arguments[i], "-cfg=") || absl::StartsWith(arguments[i], "-exec_root=")) { // Also skip these arguments, it's reclient... } else if (absl::EndsWith(arguments[i], ".o.d")) { // Also skip these arguments, these are there to create dependencies // between build actions. } else { result.push_back(arguments[i]); } } return result; } clang::tooling::CommandLineArguments ExtraArgumentsAdjuster( const clang::tooling::CommandLineArguments& arguments, llvm::StringRef) { clang::tooling::CommandLineArguments result = arguments; std::vector extra_args = frontend_internal::ParseCommandLine( absl::GetFlag(FLAGS_extra_compiler_args)); result.insert(result.end(), extra_args.begin(), extra_args.end()); return result; } } // namespace // Gets the index tool and arguments adjuster to be used with clang tooling to // perform indexing on a compilation database. std::vector, clang::tooling::ArgumentsAdjuster>> GetIndexActions(FileCopier& file_copier, MergeQueue& merge_queue) { std::vector, clang::tooling::ArgumentsAdjuster>> actions; auto index_action = std::make_unique(file_copier, merge_queue); auto adjuster = clang::tooling::combineAdjusters(RemoveClangArgumentsAdjuster, ExtraArgumentsAdjuster); actions.push_back( std::make_pair(std::move(index_action), std::move(adjuster))); return actions; } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/frontend.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_FRONTEND_FRONTEND_H_ #define OSS_FUZZ_INFRA_INDEXER_FRONTEND_FRONTEND_H_ #include #include #include #include #include "indexer/index/file_copier.h" #include "indexer/merge_queue.h" #include "absl/strings/string_view.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/Tooling.h" namespace oss_fuzz { namespace indexer { namespace frontend_internal { // Parses a command line string into a vector of arguments. // This is used internally in GetIndexActions() to parse the // --extra_compiler_args flag, exposed here for testing only. std::vector ParseCommandLine(absl::string_view commandLine); } // namespace frontend_internal // Gets the index tool and arguments adjuster to be used with clang tooling to // perform indexing on a compilation database. std::vector, clang::tooling::ArgumentsAdjuster>> GetIndexActions(FileCopier& file_copier, MergeQueue& merge_queue); } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_FRONTEND_FRONTEND_H_ ================================================ FILE: infra/indexer/frontend/frontend_test.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/frontend.h" #include // NOLINT #include #include #include #include #include #include #include #include #include #include "indexer/frontend/index_action.h" #include "indexer/index/file_copier.h" #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "indexer/merge_queue.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/flags/declare.h" #include "absl/flags/flag.h" #include "absl/log/check.h" #include "clang/Tooling/Tooling.h" ABSL_DECLARE_FLAG(std::vector, ignore_pragmas); namespace oss_fuzz { namespace indexer { namespace frontend_internal { using ::testing::ElementsAre; TEST(ParseCommandLineTest, BasicWhitespaceSeparation) { std::vector args = ParseCommandLine("one two three\tfour"); EXPECT_THAT(args, ElementsAre("one", "two", "three", "four")); } TEST(ParseCommandLineTest, SingleQuotedWords) { std::vector args = ParseCommandLine("hello 'world' 'again '"); EXPECT_THAT(args, ElementsAre("hello", "world", "again ")); } TEST(ParseCommandLineTest, DoubleQuotedWords) { std::vector args = ParseCommandLine("test \"more words\" \"inside \" "); EXPECT_THAT(args, ElementsAre("test", "more words", "inside ")); } TEST(ParseCommandLineTest, BackslashInsideSingleQuotes) { std::vector args = ParseCommandLine("prefix 'a\\b' 'c\\d'"); EXPECT_THAT(args, ElementsAre("prefix", "a\\b", "c\\d")); } TEST(ParseCommandLineTest, BackslashInsideDoubleQuotes) { std::vector args = ParseCommandLine("item1 \"item2 \\' \\\"item3 \""); EXPECT_THAT(args, ElementsAre("item1", "item2 ' \"item3 ")); } TEST(ParseCommandLineTest, EscapedDoubleQuoteInsideDoubleQuotes) { std::vector args = ParseCommandLine("value1 \"value2\\\" \\\"value3 \""); EXPECT_THAT(args, ElementsAre("value1", "value2\" \"value3 ")); } TEST(ParseCommandLineTest, UnterminatedDoubleQuote) { std::vector args = ParseCommandLine("start \"middle end '"); EXPECT_THAT(args, ElementsAre("start", "middle end '")); } TEST(ParseCommandLineTest, EmptyQuotedStrings) { std::vector args = ParseCommandLine("before '' \"\" after"); EXPECT_THAT(args, ElementsAre("before", "", "", "after")); } TEST(ParseCommandLineTest, HashInsideSingleQuotes) { std::vector args = ParseCommandLine("'#'"); EXPECT_THAT(args, ElementsAre("#")); } TEST(ParseCommandLineTest, HashInsideDoubleQuotes) { std::vector args = ParseCommandLine("another \"#\" here"); EXPECT_THAT(args, ElementsAre("another", "#", "here")); } } // namespace frontend_internal namespace { typedef void (*TExtraSourceTreeAction)(const std::filesystem::path&); std::unique_ptr GetSnippetIndex( std::string code, const std::vector& extra_args = {}, bool fail_on_error = false, TExtraSourceTreeAction extra_action = nullptr) { auto source_dir = std::filesystem::path(::testing::TempDir()) / "src"; std::filesystem::remove_all(source_dir); CHECK(std::filesystem::create_directory(source_dir)); { std::ofstream source_file(source_dir / "snippet.cc"); source_file << code; CHECK(source_file.good()); } std::string source_file_path = (source_dir / "snippet.cc").string(); std::string source_dir_path = source_dir.string(); if (extra_action != nullptr) { extra_action(source_dir); } auto index_dir = std::filesystem::path(::testing::TempDir()) / "idx"; std::filesystem::remove_all(index_dir); CHECK(std::filesystem::create_directory(index_dir)); std::string index_dir_path = index_dir.string(); std::string sysroot_path = "/"; FileCopier file_copier(source_dir_path, index_dir_path, {sysroot_path}); std::unique_ptr merge_queue = MergeQueue::Create(1); auto index_action = std::make_unique(file_copier, *merge_queue); const bool result = clang::tooling::runToolOnCodeWithArgs( std::move(index_action), code, extra_args, source_file_path); merge_queue->WaitUntilComplete(); auto index = merge_queue->TakeIndex(); if (fail_on_error && !result) { return nullptr; } return index; } FlatIndex IndexSnippet(std::string code, const std::vector& extra_args = {}) { return std::move(*GetSnippetIndex(code, extra_args)).Export(); } std::string KindToString(Entity::Kind kind) { if (kind == Entity::Kind::kMacro) { return "Macro"; } else if (kind == Entity::Kind::kEnum) { return "Enum"; } else if (kind == Entity::Kind::kEnumConstant) { return "EnumConstant"; } else if (kind == Entity::Kind::kVariable) { return "Variable"; } else if (kind == Entity::Kind::kFunction) { return "Function"; } else if (kind == Entity::Kind::kClass) { return "Class"; } else if (kind == Entity::Kind::kType) { return "Type"; } else { return "Invalid"; } } void PrintRequiredEntityParameters(const FlatIndex& index, const Entity& entity) { const auto& location = index.locations[entity.location_id()]; std::cerr << "Entity::Kind::k" << KindToString(entity.kind()) << ", " << "\"" << entity.name_prefix() << "\", " << "\"" << entity.name() << "\", " << "\"" << entity.name_suffix() << "\", " << "\"" << location.path() << "\", " << location.start_line() << ", " << location.end_line(); } void PrintAllEntityParameters(const FlatIndex& index, const Entity& entity); void PrintOptionalEntityParameters(const FlatIndex& index, const Entity& entity) { std::vector preceding_defaults; auto flush_preceding_defaults = [&preceding_defaults]() { for (const auto& preceding_default : preceding_defaults) { std::cerr << preceding_default; } preceding_defaults.clear(); }; if (entity.is_incomplete()) { std::cerr << ", /*is_incomplete=*/true"; } else { preceding_defaults.push_back(", /*is_incomplete=*/false"); } std::optional substitute_relationship_kind = (entity.substitute_relationship() ? std::make_optional(entity.substitute_relationship()->kind()) : std::nullopt); auto handle_substitute_relationship = [&](SubstituteRelationship::Kind kind, const char* parameter_name) { if (substitute_relationship_kind != kind) { preceding_defaults.push_back(", /*"); preceding_defaults.push_back(parameter_name); preceding_defaults.push_back("=*/std::nullopt"); return; } flush_preceding_defaults(); std::cerr << ", /*" << parameter_name << "=*/RequiredEntityId(index, "; const Entity& template_prototype_entity = index .entities[entity.substitute_relationship()->substitute_entity_id()]; PrintAllEntityParameters(index, template_prototype_entity); std::cerr << ")"; }; handle_substitute_relationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, "template_prototype_entity_id"); handle_substitute_relationship( SubstituteRelationship::Kind::kIsImplicitlyDefinedFor, "implicitly_defined_for_entity_id"); if (entity.enum_value().has_value()) { flush_preceding_defaults(); std::cerr << ", /*enum_value=*/\"" << *entity.enum_value() << "\""; } else { preceding_defaults.push_back(", /*enum_value=*/std::nullopt"); } handle_substitute_relationship(SubstituteRelationship::Kind::kIsInheritedFrom, "inherited_from_entity_id"); switch (entity.virtual_method_kind()) { // No default. Exhaustiveness checks will force us to handle new cases. case Entity::VirtualMethodKind::kNotAVirtualMethod: { preceding_defaults.push_back( ", /*virtual_method_kind=*/" "Entity::VirtualMethodKind::kNotAVirtualMethod"); }; break; case Entity::VirtualMethodKind::kPureVirtual: { flush_preceding_defaults(); std::cerr << ", " "/*virtual_method_kind=*/Entity::VirtualMethodKind::kPureVirtual"; }; break; case Entity::VirtualMethodKind::kNonPureVirtual: { flush_preceding_defaults(); std::cerr << ", /*virtual_method_kind=*/" "Entity::VirtualMethodKind::kNonPureVirtual"; }; break; } } void PrintAllEntityParameters(const FlatIndex& index, const Entity& entity) { PrintRequiredEntityParameters(index, entity); PrintOptionalEntityParameters(index, entity); } // Helper function for adding new tests, this will print all the potentially // valid `EXPECT...`s for a given index. These should be vetted and cleaned up // before adding to the test body. This should not be referenced in committed // tests. void PrintValidExpectations( const FlatIndex& index, std::optional only_of_kind = std::nullopt, bool omit_implicit = false) { for (EntityId entity_id = 0; entity_id < index.entities.size(); ++entity_id) { const auto& entity = index.entities[entity_id]; if (omit_implicit && entity.substitute_relationship() && entity.substitute_relationship()->kind() == SubstituteRelationship::Kind::kIsImplicitlyDefinedFor) { continue; } if (only_of_kind && entity.kind() != *only_of_kind) { continue; } const auto& location = index.locations[entity.location_id()]; if (location.path() == "" || location.path() == "") { continue; } std::cerr << "EXPECT_HAS_ENTITY(index, "; PrintAllEntityParameters(index, entity); std::cerr << ");\n"; for (const auto& reference : index.references) { if (reference.entity_id() == entity_id) { const auto& ref_location = index.locations[reference.location_id()]; std::cerr << "EXPECT_HAS_REFERENCE(index, "; PrintRequiredEntityParameters(index, entity); std::cerr << ", \"" << ref_location.path() << "\", " << ref_location.start_line() << ", " << ref_location.end_line(); PrintOptionalEntityParameters(index, entity); std::cerr << ");\n"; } } } for (const auto& link : index.virtual_method_links) { const Entity& parent = index.entities[link.parent()]; const Entity& child = index.entities[link.child()]; std::cerr << "EXPECT_HAS_VIRTUAL_LINK(index, \"" << parent.full_name() << "\", \"" << child.full_name() << "\");\n"; } } void PrintEntity(std::ostream& stream, const FlatIndex& index, const Entity& entity, int padding = 0) { const std::string indent(padding, ' '); const auto& location = index.locations[entity.location_id()]; stream << indent << KindToString(entity.kind()) << " `" << entity.name_prefix() << entity.name() << entity.name_suffix() << "`\n" << indent << (entity.is_incomplete() ? " Declared at \"" : " Defined at \"") << location.path() << "\" lines " << location.start_line() << "-" << location.end_line() << "\n"; if (entity.substitute_relationship().has_value()) { const SubstituteRelationship& relationship = *entity.substitute_relationship(); switch (relationship.kind()) { // No default. Exhaustiveness checks will force us to handle new cases. case SubstituteRelationship::Kind::kIsTemplateInstantiationOf: { stream << indent << " Template instantiation of:\n"; }; break; case SubstituteRelationship::Kind::kIsImplicitlyDefinedFor: { stream << indent << " Implicitly defined for:\n"; }; break; case SubstituteRelationship::Kind::kIsInheritedFrom: { stream << indent << " Inherited from:\n"; }; break; } const auto& substitute_entity = index.entities[relationship.substitute_entity_id()]; PrintEntity(stream, index, substitute_entity, /*padding=*/padding + 4); } if (entity.enum_value().has_value()) { stream << " Enum value: " << *entity.enum_value() << "\n"; } switch (entity.virtual_method_kind()) { case Entity::VirtualMethodKind::kNotAVirtualMethod: break; case Entity::VirtualMethodKind::kPureVirtual: stream << indent << " Pure virtual\n"; break; case Entity::VirtualMethodKind::kNonPureVirtual: stream << indent << " Non-pure virtual\n"; break; } } std::string DebugPrintIndex(const FlatIndex& index) { std::stringstream stream; for (EntityId entity_id = 0; entity_id < index.entities.size(); ++entity_id) { const auto& entity = index.entities[entity_id]; const auto& location = index.locations[entity.location_id()]; if (location.path().empty() || location.path() == "" || location.path() == "") { continue; } PrintEntity(stream, index, entity); for (const auto& reference : index.references) { if (reference.entity_id() == entity_id) { const auto& ref_location = index.locations[reference.location_id()]; stream << " Referenced at \"" << ref_location.path() << "\" lines " << ref_location.start_line() << "-" << ref_location.end_line() << "\n"; } } } if (!index.virtual_method_links.empty()) { stream << "Virtual method links:\n"; for (const auto& link : index.virtual_method_links) { const Entity& parent = index.entities[link.parent()]; const Entity& child = index.entities[link.child()]; stream << " " << parent.full_name() << " -> " << child.full_name() << "\n"; } } return stream.str(); } void DumpIndex(const FlatIndex& index) { std::cerr << DebugPrintIndex(index); } [[maybe_unused]] void DumpAll(const FlatIndex& index) { DumpIndex(index); PrintValidExpectations(index); } std::optional GetSubstituteRelationship( std::optional template_prototype_entity_id, std::optional implicitly_defined_for_entity_id, std::optional inherited_from_entity_id) { auto count = [](const auto& optional) { return optional ? 1 : 0; }; auto substitutions = count(template_prototype_entity_id) + count(implicitly_defined_for_entity_id) + count(inherited_from_entity_id); CHECK_LE(substitutions, 1) << "Multiple simultaneous substitutions are not allowed"; if (template_prototype_entity_id) { return SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, *template_prototype_entity_id); } if (implicitly_defined_for_entity_id) { return SubstituteRelationship( SubstituteRelationship::Kind::kIsImplicitlyDefinedFor, *implicitly_defined_for_entity_id); } if (inherited_from_entity_id) { return SubstituteRelationship( SubstituteRelationship::Kind::kIsInheritedFrom, *inherited_from_entity_id); } return std::nullopt; } std::optional FindEntity( const FlatIndex& index, Entity::Kind kind, std::string name_prefix, std::string name, std::string name_suffix, std::string path, int start_line, int end_line, bool is_incomplete = false, const std::optional& template_prototype_entity_id = std::nullopt, const std::optional& implicitly_defined_for_entity_id = std::nullopt, const std::optional enum_value = std::nullopt, const std::optional& inherited_from_entity_id = std::nullopt, Entity::VirtualMethodKind virtual_method_kind = Entity::VirtualMethodKind::kNotAVirtualMethod) { std::optional entity; for (LocationId location_id = 0; location_id < index.locations.size(); ++location_id) { const auto& index_location = index.locations[location_id]; if (index_location.path() == path && index_location.start_line() == start_line && index_location.end_line() == end_line) { entity = {kind, name_prefix, name, name_suffix, location_id, is_incomplete, /*is_weak=*/false, GetSubstituteRelationship(template_prototype_entity_id, implicitly_defined_for_entity_id, inherited_from_entity_id), enum_value, virtual_method_kind}; break; } } if (!entity.has_value()) { return std::nullopt; } for (const auto& index_entity : index.entities) { if (*entity == index_entity) { return entity; } } return std::nullopt; } bool IndexHasEntity( const FlatIndex& index, Entity::Kind kind, std::string name_prefix, std::string name, std::string name_suffix, std::string path, int start_line, int end_line, bool is_incomplete = false, const std::optional& template_prototype_entity_id = std::nullopt, const std::optional& implicitly_defined_for_entity_id = std::nullopt, const std::optional enum_value = std::nullopt, const std::optional& inherited_from_entity_id = std::nullopt, Entity::VirtualMethodKind virtual_method_kind = Entity::VirtualMethodKind::kNotAVirtualMethod) { return FindEntity(index, kind, name_prefix, name, name_suffix, path, start_line, end_line, is_incomplete, template_prototype_entity_id, implicitly_defined_for_entity_id, enum_value, inherited_from_entity_id, virtual_method_kind) .has_value(); } bool IndexHasReference( const FlatIndex& index, Entity::Kind kind, std::string name_prefix, std::string name, std::string name_suffix, std::string path, int start_line, int end_line, std::string ref_path, int ref_start_line, int ref_end_line, bool is_incomplete = false, const std::optional template_prototype_entity_id = std::nullopt, const std::optional implicitly_defined_for_entity_id = std::nullopt, const std::optional enum_value = std::nullopt, const std::optional& inherited_from_entity_id = std::nullopt, Entity::VirtualMethodKind virtual_method_kind = Entity::VirtualMethodKind::kNotAVirtualMethod) { LocationId ref_location_id = kInvalidLocationId; EntityId ref_entity_id = kInvalidEntityId; std::optional entity; for (LocationId location_id = 0; location_id < index.locations.size(); ++location_id) { const auto& index_location = index.locations[location_id]; if (index_location.path() == path && index_location.start_line() == start_line && index_location.end_line() == end_line) { entity = {kind, name_prefix, name, name_suffix, location_id, is_incomplete, /*is_weak=*/false, GetSubstituteRelationship(template_prototype_entity_id, implicitly_defined_for_entity_id, inherited_from_entity_id), enum_value, virtual_method_kind}; } if (index_location.path() == ref_path && index_location.start_line() == ref_start_line && index_location.end_line() == ref_end_line) { ref_location_id = location_id; } } if (!entity.has_value()) { return false; } for (EntityId entity_id = 0; entity_id < index.entities.size(); ++entity_id) { const auto& index_entity = index.entities[entity_id]; if (*entity == index_entity) { ref_entity_id = entity_id; } } if (ref_entity_id == kInvalidEntityId || ref_location_id == kInvalidLocationId) { return false; } for (const auto& reference : index.references) { if (reference.entity_id() == ref_entity_id && reference.location_id() == ref_location_id) { return true; } } return false; } bool IndexHasVirtualMethodLink(const FlatIndex& index, std::string_view parent_full_name, std::string_view child_full_name) { for (const auto& link : index.virtual_method_links) { const Entity& parent = index.entities[link.parent()]; const Entity& child = index.entities[link.child()]; if (parent.full_name() == parent_full_name && child.full_name() == child_full_name) { return true; } } return false; } template std::optional RequiredEntityId(const FlatIndex& index, Args&&... args) { auto entity = FindEntity(index, std::forward(args)...); EXPECT_TRUE(entity.has_value()); if (!entity.has_value()) { return std::nullopt; } for (EntityId entity_id = 0; entity_id < index.entities.size(); ++entity_id) { const Entity& other_entity = index.entities[entity_id]; if (entity == other_entity) { return entity_id; } } return std::nullopt; } } // anonymous namespace #define EXPECT_HAS_ENTITY(index, ...) \ EXPECT_TRUE(IndexHasEntity(index, __VA_ARGS__)) << DebugPrintIndex(index) #define EXPECT_HAS_REFERENCE(index, ...) \ EXPECT_TRUE(IndexHasReference(index, __VA_ARGS__)) << DebugPrintIndex(index) #define EXPECT_HAS_VIRTUAL_LINK(index, ...) \ EXPECT_TRUE(IndexHasVirtualMethodLink(index, __VA_ARGS__)) \ << DebugPrintIndex(index) TEST(FrontendTest, MacroDefinition) { auto index = IndexSnippet("#define MACRO 1\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1); } TEST(FrontendTest, MultilineMacroDefinition) { auto index = IndexSnippet( "#define MACRO 1\\\n" " + 2 + 3\\\n" " + 4 + 5\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 3); } TEST(FrontendTest, MacroArgsDefinition) { auto index = IndexSnippet("#define MACRO(x) (void)(x)\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1); } TEST(FrontendTest, MacroVarargsDefinition) { auto index = IndexSnippet("#define MACRO(...) (void)(__VA_ARGS__)\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1); } TEST(FrontendTest, MacroExpansion) { auto index = IndexSnippet( "#define MACRO 1\n" "constexpr int a = MACRO;\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); } TEST(FrontendTest, MacroArgsExpansion) { auto index = IndexSnippet( "#define MACRO(x) (x)\n" "constexpr int a = MACRO(1);\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); } TEST(FrontendTest, MacroVarargsExpansion) { auto index = IndexSnippet( "#define MACRO(...) __VA_ARGS__\n" "int MACRO(a, b, c);\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); } TEST(FrontendTest, NestedMacroExpansion) { auto index = IndexSnippet( "#define INNER_MACRO a\n" "#define OUTER_MACRO INNER_MACRO = 1\n" "constexpr int OUTER_MACRO;\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "OUTER_MACRO", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "INNER_MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); } TEST(FrontendTest, MultipleMacroExpansion) { auto index = IndexSnippet( "#define INNER_MACRO(x) x\n" "#define OUTER_MACRO(x, y) INNER_MACRO(x) = y\n" "constexpr int OUTER_MACRO(a, 1);\n" "constexpr int OUTER_MACRO(b, 2);\n" "constexpr int OUTER_MACRO(c, 3);\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "OUTER_MACRO", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "OUTER_MACRO", "", "snippet.cc", 2, 2, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "OUTER_MACRO", "", "snippet.cc", 2, 2, "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "INNER_MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "INNER_MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kMacro, "", "INNER_MACRO", "", "snippet.cc", 1, 1, "snippet.cc", 5, 5); } TEST(FrontendTest, EnumDeclaration) { auto index = IndexSnippet( "enum Enum {\n" " kEnumConstant0 = 0,\n" " kEnumConstant1 = 1,\n" " kElaborateEnumConstant = " "kEnumConstant0 * kEnumConstant1 - 7,\n" "};\n" "Enum enum_instance = kEnumConstant0;\n" "enum class LargeUnsigned : decltype(0ULL) {\n" " kNonNegative = 0xffffffffffffffff,\n" "};\n" "enum class Huge : unsigned __int128 {\n" " kValue = ~(unsigned __int128)(0),\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnum, "", "Enum", "", "snippet.cc", 1, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "", "kEnumConstant0", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "", "kEnumConstant1", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "", "kElaborateEnumConstant", "", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"-7"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "enum_instance", "", "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "", "Enum", "", "snippet.cc", 1, 5, "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "", "kEnumConstant0", "", "snippet.cc", 2, 2, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "Huge::", "kValue", "", "snippet.cc", 11, 11, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"340282366920938463463374607431768211455"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "LargeUnsigned::", "kNonNegative", "", "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"18446744073709551615"); } TEST(FrontendTest, EnumClassDeclaration) { auto index = IndexSnippet( "enum class Enum : char {\n" " kEnumConstant0 = 0,\n" " kEnumConstant1 = 1,\n" "};\n" "Enum enum_instance = Enum::kEnumConstant0;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnum, "", "Enum", "", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "Enum::", "kEnumConstant0", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "Enum::", "kEnumConstant1", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "enum_instance", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "", "Enum", "", "snippet.cc", 1, 4, "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "Enum::", "kEnumConstant0", "", "snippet.cc", 2, 2, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); } TEST(FrontendTest, NamespacedEnumDeclaration) { auto index = IndexSnippet( "namespace n {\n" "enum Enum {\n" " kEnumConstant0 = 0,\n" " kEnumConstant1 = 1,\n" "};\n" "Enum enum_instance0 = kEnumConstant0;\n" "} // namespace n\n" "n::Enum enum_instance1 = n::kEnumConstant1;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "n::", "kEnumConstant0", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "n::", "kEnumConstant1", "", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "n::", "enum_instance0", "", "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "enum_instance1", "", "snippet.cc", 8, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5, "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "n::", "kEnumConstant0", "", "snippet.cc", 3, 3, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5, "snippet.cc", 8, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "n::", "kEnumConstant1", "", "snippet.cc", 4, 4, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); } TEST(FrontendTest, NamespacedEnumClassDeclaration) { auto index = IndexSnippet( "namespace n {\n" "enum class Enum : char {\n" " kEnumConstant0 = 0,\n" " kEnumConstant1 = 1,\n" "};\n" "Enum enum_instance0 = Enum::kEnumConstant0;\n" "} // namespace n\n" "n::Enum enum_instance1 = n::Enum::kEnumConstant1;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "n::Enum::", "kEnumConstant0", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnumConstant, "n::Enum::", "kEnumConstant1", "", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "n::", "enum_instance0", "", "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "enum_instance1", "", "snippet.cc", 8, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5, "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "n::Enum::", "kEnumConstant0", "", "snippet.cc", 3, 3, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"0"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnum, "n::", "Enum", "", "snippet.cc", 2, 5, "snippet.cc", 8, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kEnumConstant, "n::Enum::", "kEnumConstant1", "", "snippet.cc", 4, 4, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/"1"); } TEST(FrontendTest, VariableDeclaration) { auto index = IndexSnippet( "int foo = 0;\n" "extern \"C\" int bar = 1;\n" "volatile int* const baz = nullptr;\n" "const int* (*qux)() = nullptr;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "qux", "", "snippet.cc", 4, 4); } TEST(FrontendTest, ArrayDeclaration) { auto index = IndexSnippet( "const char foo[] = {\n" " 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',\n" " 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',\n" "};\n" "const char* bar = \"AAAAAAAAA\"\n" " \"BBBBBBBBB\"\n" " \"CCCCCCCCC\";\n" "const char* baz = \"AAAAAAAAA\"\\\n" " \"BBBBBBBBB\"\\\n" " \"CCCCCCCCC\";\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 5, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 8, 10); } TEST(FrontendTest, AnonymousStructDeclaration) { auto index = IndexSnippet( "struct {\n" " int foo;\n" "} bar;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "(anonymous struct)", "", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "(anonymous struct)::", "foo", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 3); } TEST(FrontendTest, ConstructorReference) { auto index = IndexSnippet( "class TestClass {\n" " public:\n" " TestClass() {}\n" "};\n" "template\n" "class Template {\n" " public:\n" " Template() {}\n" "};\n" "class Derived : public Template {};\n" "int main() {\n" " TestClass instance;\n" " struct Test {} test;\n" " Derived();\n" "}\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "TestClass::", "TestClass", "()", "snippet.cc", 3, 3, "snippet.cc", 12, 12, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Derived", "", "snippet.cc", 10, 10, "snippet.cc", 14, 14, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Derived::", "Derived", "()", "snippet.cc", 10, 10, "snippet.cc", 14, 14, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Derived", "", "snippet.cc", 10, 10)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "main()::Test::", "Test", "()", "snippet.cc", 13, 13, "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "main()::", "Test", "", "snippet.cc", 13, 13)); } TEST(FrontendTest, NamespacedVariableDeclaration) { auto index = IndexSnippet( "namespace n {\n" "int foo = 0;\n" "namespace {\n" "int bar = 1;\n" "} // anonymous namespace\n" "} // namespace n\n" "int baz = 2;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "n::", "foo", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "n::(anonymous namespace)::", "bar", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 7, 7); } TEST(FrontendTest, FunctionDeclaration) { auto index = IndexSnippet( "int foo();\n" "extern \"C\" int bar(int baz);\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "()", "snippet.cc", 1, 1, /*is_incomplete=*/true); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "bar", "(int)", "snippet.cc", 2, 2, /*is_incomplete=*/true); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 2, 2)); } TEST(FrontendTest, FunctionDefinition) { auto index = IndexSnippet( "extern int foo(int bar);\n" "int foo(int bar) {\n" " int baz = bar;\n" " return foo(baz) + bar;\n" "}"); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 1)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 2, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 3, 3, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 2, 5, "snippet.cc", 4, 4); } TEST(FrontendTest, MacroWrappedFunctionDefinition1) { auto index = IndexSnippet( "#define MACRO(x, y, z) x y z\n" "MACRO(int, foo, (int bar)) {\n" " return bar;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 2, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); } TEST(FrontendTest, MacroWrappedFunctionDefinition2) { auto index = IndexSnippet( "#define MACRO(x, y, z) x y ## z\n" "MACRO(void, foo, bar)() {\n" " return;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kMacro, "", "MACRO", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foobar", "()", "snippet.cc", 2, 4); } TEST(FrontendTest, VariadicFunctionDefinition) { auto index = IndexSnippet( "void foo(int bar, ...) {\n" "}"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int, ...)", "snippet.cc", 1, 2); } TEST(FrontendTest, CapturingLambdaDefinition) { auto index = IndexSnippet( "void foo(int bar) {\n" " auto baz = [bar](int xof) {\n" " return bar + xof;\n" " };\n" "}"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 2, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "xof", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "xof", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "foo(int)::", "lambda", "(int)", "snippet.cc", 2, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "foo(int)::", "lambda", "(int)", "snippet.cc", 2, 4, "snippet.cc", 2, 4); } TEST(FrontendTest, NonCapturingLambdaDefinition) { auto index = IndexSnippet( "void foo(int bar) {\n" " auto baz = [](int xof) {\n" " return xof;\n" " };\n" "}"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 2, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "xof", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "xof", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "foo(int)::", "lambda", "(int)", "snippet.cc", 2, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "foo(int)::", "lambda", "(int)", "snippet.cc", 2, 4, "snippet.cc", 2, 4); } TEST(FrontendTest, ClassDefinition) { auto index = IndexSnippet( "class Foo;\n" "class Foo {\n" " void bar();\n" " void baz() const;\n" "};\n" "void Foo::bar() {\n" "}\n" "void Foo::baz() const {\n" "}\n" "class Bar;\n"); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "bar", "()", "snippet.cc", 6, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "baz", "() const", "snippet.cc", 8, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 10, 10, /*is_incomplete=*/true); } TEST(FrontendTest, LocalClassDefinition) { auto index = IndexSnippet( "void foo() {\n" " class Bar {\n" " public:\n" " void baz() {\n" " }\n" " } bar;\n" " bar.baz();\n" "}"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "()", "snippet.cc", 1, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "foo()::", "Bar", "", "snippet.cc", 2, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "foo()::", "Bar", "", "snippet.cc", 2, 6, "snippet.cc", 2, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "foo()::Bar::", "baz", "()", "snippet.cc", 4, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "foo()::Bar::", "baz", "()", "snippet.cc", 4, 5, "snippet.cc", 7, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 6, "snippet.cc", 7, 7); } TEST(FrontendTest, Typedef) { auto index = IndexSnippet( "typedef int foo;\n" "typedef struct Bar{\n" "} Baz;\n" "Baz baz;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 2, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 2, 3, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "foo", "", "snippet.cc", 1, 1); } TEST(FrontendTest, Using) { auto index = IndexSnippet( "using foo = int;\n" "using Bar = struct Baz{};\n" "Bar bar;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "foo", "", "snippet.cc", 1, 1); } TEST(FrontendTest, TypeTemplateClass) { auto index = IndexSnippet( "template \n" "class Foo;\n" "template \n" "class Foo {\n" " void bar();\n" "};\n" "template \n" "void Foo::bar() {\n" "}\n" "Foo baz;\n"); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kType, "Foo::", "S", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "S", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "bar", "()", "snippet.cc", 7, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 6)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 6, "snippet.cc", 10, 10, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 6)); } TEST(FrontendTest, UsingTypeTemplateClass) { auto index = IndexSnippet( "class Foo;\n" "template \n" "class Bar {};\n" "using Baz = Bar;\n" "Baz* baz;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/true); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4, /*is_incomplete=*/true); // TODO: Potential implicit reference. EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 5, 5, /*is_incomplete=*/true)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Bar::", "T", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 4, 4, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 5, 5); } TEST(FrontendTest, ValueTemplateClass) { auto index = IndexSnippet( "template \n" "class Foo {\n" " void bar();\n" "};\n" "template \n" "void Foo::bar() {\n" "}\n" "Foo<'A', 99> baz;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "S", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "bar", "()", "snippet.cc", 5, 7); // TODO: For consistency, we'd probably want the following // instead. However, due to the way that the AST handles template method // definitions, this isn't possible without manually walking the AST; and if // we add custom walking for template method definitions, we'd have to // remove the standard handling for other template types, and manually walk // those as well... // EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, // "Foo::", "T", "", "snippet.cc", // 5, 5)); // EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6)); // EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, // "Foo::", "S", "", "snippet.cc", // 5, 5)); // EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "Foo::", "S", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6)); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "S", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "S", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "T", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "T", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "<'A', 99>", "snippet.cc", 1, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "<'A', 99>", "snippet.cc", 1, 4, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); } TEST(FrontendTest, TypeTemplateClassFullSpecialisation) { auto index = IndexSnippet( "template \n" "class Foo {\n" "};\n" "template <>\n" "class Foo {\n" " int foo;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "foo", "", "snippet.cc", 6, 6); } TEST(FrontendTest, ValueTemplateClassFullSpecialisation) { auto index = IndexSnippet( "template \n" "class Foo {\n" "};\n" "template <>\n" "class Foo<99> {\n" " int foo;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "<99>", "snippet.cc", 4, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo<99>::", "foo", "", "snippet.cc", 6, 6); } TEST(FrontendTest, TypeTemplateClassPartialSpecialisation) { auto index = IndexSnippet( "template \n" "class Foo {\n" " S bar;\n" "};\n" "template \n" "class Foo {\n" " T bar;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "S", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "bar", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "Foo::", "S", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 5, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "bar", "", "snippet.cc", 7, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 5, 5, "snippet.cc", 7, 7); } TEST(FrontendTest, ValueTemplateClassPartialSpecialisation) { auto index = IndexSnippet( "template \n" "class Foo {\n" " int bar = S;\n" "};\n" "template \n" "class Foo {\n" " int bar = T;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "S", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "Foo::", "S", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 5, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "bar", "", "snippet.cc", 7, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 5, 5, "snippet.cc", 7, 7); } TEST(FrontendTest, TypeTemplateFunction) { auto index = IndexSnippet( "template \n" "void foo(T bar) {\n" "};\n" "void baz() {\n" " foo(0);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(T)", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T)", "snippet.cc", 1, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "foo(T)::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "foo(T)::", "T", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "baz", "()", "snippet.cc", 4, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 3, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T)", "snippet.cc", 1, 3)); } TEST(FrontendTest, ValueTemplateFunction) { auto index = IndexSnippet( "template \n" "int foo(int bar) {\n" " return bar + T;\n" "};\n" "void baz() {\n" " foo<88>(0);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "foo(int)::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "foo(int)::", "T", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "baz", "()", "snippet.cc", 5, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "<88>(int)", "snippet.cc", 1, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 4)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "", "foo", "<88>(int)", "snippet.cc", 1, 4, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 4)); } TEST(FrontendTest, TemplateTemplateFunction) { auto index = IndexSnippet( "template \n" "class Foo {\n" "};\n" "template class S, class T>\n" "void bar(const S& baz) {\n" "};\n" "void qux() {\n" " Foo foo;\n" " bar(foo);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "bar", "(const S &)", "snippet.cc", 4, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "bar(const S &)::", "T", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "", "bar", "(const Foo &)", "snippet.cc", 4, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "bar", "(const S &)", "snippet.cc", 4, 6)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "", "bar", "(const Foo &)", "snippet.cc", 4, 6, "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "bar", "(const S &)", "snippet.cc", 4, 6)); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 8, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 8, 8, "snippet.cc", 9, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "qux", "()", "snippet.cc", 7, 10); } TEST(FrontendTest, TemplateParameterPackFunction) { auto index = IndexSnippet( "template \n" "void foo(T... args) {\n" "}\n" "void bar() {\n" " foo(1, 2);\n" " foo(\"aaaaa\", 2, \"bbbb\");\n" "}\n"); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "", "foo", "(const char *, int, const char *)", "snippet.cc", 1, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T...)", "snippet.cc", 1, 3)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "", "foo", "(const char *, int, const char *)", "snippet.cc", 1, 3, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T...)", "snippet.cc", 1, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int, int)", "snippet.cc", 1, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T...)", "snippet.cc", 1, 3)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "", "foo", "(int, int)", "snippet.cc", 1, 3, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "", "foo", "(T...)", "snippet.cc", 1, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(T...)", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "foo(T...)::", "T", "", "snippet.cc", 1, 1); } TEST(FrontendTest, FunctionScopedClassDefinition) { auto index = IndexSnippet( "namespace foo {\n" "void bar() {\n" " class Baz {};\n" "};\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "foo::", "bar", "()", "snippet.cc", 2, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "foo::bar()::", "Baz", "", "snippet.cc", 3, 3); } TEST(FrontendTest, OperatorOverloads) { auto index = IndexSnippet( "struct Foo {\n" " operator int() {\n" " return 0;\n" " }\n" " Foo& operator+=(const Foo& other) {\n" " return *this;\n" " }\n" "};\n" "int main() {\n" " Foo foo;\n" " Foo bar;\n" " foo += bar;\n" " return foo;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 8, "snippet.cc", 10, 10); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 8, "snippet.cc", 11, 11); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 11, 11); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 11, 11, "snippet.cc", 12, 12); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 10, 10); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 10, 10, "snippet.cc", 12, 12); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 10, 10, "snippet.cc", 13, 13); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 9, 14); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "other", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "operator int", "()", "snippet.cc", 2, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Foo::", "operator int", "()", "snippet.cc", 2, 4, "snippet.cc", 13, 13); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "operator+=", "(const Foo &)", "snippet.cc", 5, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Foo::", "operator+=", "(const Foo &)", "snippet.cc", 5, 7, "snippet.cc", 12, 12); } TEST(FrontendTest, NoIdentifierOperator) { // This causes some interesting stuff to happen with identifiers, as the // operator== doesn't have an identifier for the name. Not clear on why this // is different to the operator overloading testcase. auto index = IndexSnippet( "template\n" "class Foo {};\n" "template\n" "inline bool\n" "operator==(const Foo& lhs, const Foo& rhs)\n" "{ return &lhs == &rhs; }\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "lhs", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "lhs", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "operator==", "(const Foo &, const Foo &)", "snippet.cc", 3, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "rhs", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "rhs", "", "snippet.cc", 5, 5, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "operator==(const Foo &, const Foo &)::", "T", "", "snippet.cc", 3, 3); } TEST(FrontendTest, PointerToStruct) { auto index = IndexSnippet( "struct Foo {\n" " int field;\n" "};\n" "extern void f(const Foo*);\n" "int main() {\n" " const Foo* const* foo_ptr = nullptr;\n" " f(*foo_ptr);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "f", "(const Foo *)", "snippet.cc", 4, 4, /*is_incomplete=*/true); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "f", "(const Foo *)", "snippet.cc", 4, 4, "snippet.cc", 7, 7, /*is_incomplete=*/true); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo_ptr", "", "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo_ptr", "", "snippet.cc", 6, 6, "snippet.cc", 7, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 5, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "field", "", "snippet.cc", 2, 2); } TEST(FrontendTest, PointerToType) { auto index = IndexSnippet( "typedef struct FooStruct {} Foo;\n" "using Bar = int;\n" "int main() {\n" " Foo* foo_ptr = nullptr;\n" " Bar* bar_ptr = nullptr;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "FooStruct", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "FooStruct", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar_ptr", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo_ptr", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 3, 6); } TEST(FrontendTest, ReferenceToStruct) { auto index = IndexSnippet( "struct Foo {\n" " int field;\n" "};\n" "extern void f(Foo&);\n" "int main() {\n" " Foo foo;\n" " Foo& foo_ref = foo;\n" " f(foo_ref);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "f", "(Foo &)", "snippet.cc", 4, 4, /*is_incomplete=*/true); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "f", "(Foo &)", "snippet.cc", 4, 4, "snippet.cc", 8, 8, /*is_incomplete=*/true); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 6, 6, "snippet.cc", 7, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo_ref", "", "snippet.cc", 7, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo_ref", "", "snippet.cc", 7, 7, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 5, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "field", "", "snippet.cc", 2, 2); } TEST(FrontendTest, ReferenceToReturnType) { auto index = IndexSnippet( "struct Foo {\n" " int bar;\n" "};\n" "Foo* baz() {\n" " return nullptr;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "baz", "()", "snippet.cc", 4, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "bar", "", "snippet.cc", 2, 2); } TEST(FrontendTest, ReferenceToSizeof) { auto index = IndexSnippet( "struct Foo {\n" " int bar;\n" "} foo;\n" "int size_1 = (int)sizeof(struct Foo);\n" "int size_2 = (int)sizeof(foo);\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 3, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "size_1", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "size_2", "", "snippet.cc", 5, 5); } TEST(FrontendTest, DeletedConstructor) { auto index = IndexSnippet( "class Foo {\n" " Foo(const Foo&) = delete;\n" " Foo(Foo&&) = delete;\n" " Foo& operator=(const Foo&) = delete;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 5); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "Foo::", "Foo", "(Foo &&)", "snippet.cc", 3, 3, /*is_incomplete=*/true)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "Foo::", "Foo", "(const Foo &)", "snippet.cc", 2, 2, /*is_incomplete=*/true)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "Foo::", "operator=", "(const Foo &)", "snippet.cc", 4, 4, /*is_incomplete=*/true)); } TEST(FrontendTest, PureVirtualMethod) { auto index = IndexSnippet( "class Foo {\n" " virtual void Bar() = 0;\n" "};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 3); // Pure virtual methods are complete, even though they have no body. EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "Bar", "()", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kPureVirtual); } TEST(FrontendTest, OverriddenMethod) { auto index = IndexSnippet( "class Foo {\n" // 1 " public:\n" // 2 " virtual void Bar() {\n" // 3 " }\n" // 4 "};\n" // 5 "class Baz : public Foo {\n" // 6 " public:\n" // 7 " // No override\n" // 8 " // of `Bar()`\n" // 9 "};\n" // 10 "class Foobar : public Baz {\n" // 11 " public:\n" // 12 " void Bar() override {\n" // 13 " }\n" // 14 "};\n" // 15 "int main() {\n" // 16 " Foo* foo = new Foobar;\n" // 17 " foo->Bar();\n" // 18 "};\n"); // 19 EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 5, "snippet.cc", 6, 10); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 5, "snippet.cc", 17, 17); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 5, "snippet.cc", 18, 18); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 6, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "Bar", "()", "snippet.cc", 3, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Foo::", "Bar", "()", "snippet.cc", 3, 4, "snippet.cc", 18, 18, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foobar", "", "snippet.cc", 11, 15); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foobar", "", "snippet.cc", 11, 15, "snippet.cc", 17, 17); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foobar::", "Bar", "()", "snippet.cc", 13, 14, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); // We should have a cross-reference from the overridden method definition to // the base method definition. EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Foo::", "Bar", "()", "snippet.cc", 3, 4, "snippet.cc", 13, 14, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "Baz::", "Bar", "()", "snippet.cc", 3, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "Bar", "()", "snippet.cc", 3, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_EQ(index.virtual_method_links.size(), 2); EXPECT_HAS_VIRTUAL_LINK(index, "Foo::Bar()", "Baz::Bar()"); EXPECT_HAS_VIRTUAL_LINK(index, "Baz::Bar()", "Foobar::Bar()"); } TEST(FrontendTest, CursedInheritance) { auto index = IndexSnippet( "namespace ns {\n" // 1 " struct Base {\n" // 2 " void foo() {}\n" // 3 " int foo(int) { return 7; }\n" // 4 " int a;\n" // 5 " char Deriv() { return ' '; }\n" // 6 " }; \n" // 7 "}\n" // 8 "struct Deriv : ns::Base {\n" // 9 " void foo() {}\n" // 10 " void foo(char*) {}\n" // 11 " void foo(int[]) {}\n" // 12 " int a;\n" // 13 "};\n" // 14 "struct DerivDeriv : public Deriv {\n" // 15 "};\n" // 16 "\n" // 17 "int main() {\n" // 18 " DerivDeriv().ns::Base::foo(3);\n" // 19 " (void)DerivDeriv().ns::Base::a;\n" // 20 " Deriv d = DerivDeriv::Deriv();\n" // 21 "}"); // 22 // Ensure we have a full set of overloads from `Deriv::foo`. EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "DerivDeriv::", "foo", "()", "snippet.cc", 10, 10, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Deriv::", "foo", "()", "snippet.cc", 10, 10)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "DerivDeriv::", "foo", "(char *)", "snippet.cc", 11, 11, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Deriv::", "foo", "(char *)", "snippet.cc", 11, 11)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "DerivDeriv::", "foo", "(int *)", "snippet.cc", 12, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Deriv::", "foo", "(int *)", "snippet.cc", 12, 12)); // The overload in `Base` is shadowed. We do not support `.ns::Base::foo`. EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "DerivDeriv::", "foo", "(int)", "snippet.cc", 12, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "ns::Base::", "foo", "(int)", "snippet.cc", 4, 4))); // Unqualified `a` is inherited from `Deriv`. We don't support `.ns::Base::a`. EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "DerivDeriv::", "a", "", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kVariable, "Deriv::", "a", "", "snippet.cc", 13, 13)); // However, the references via such qualifications are still tracked. EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "ns::Base::", "a", "", "snippet.cc", 5, 5, "snippet.cc", 20, 20); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "ns::Base::", "foo", "(int)", "snippet.cc", 4, 4, "snippet.cc", 19, 19); // There are no virtual methods involved. EXPECT_TRUE(index.virtual_method_links.empty()); } TEST(FrontendTest, MoreCursedInheritance) { auto index = IndexSnippet( "struct A {\n" // 1 " virtual char* foo() { return nullptr; }\n" // 2 " virtual void moo() {}\n" // 3 " virtual void bar() = 0;\n" // 4 "};\n" // 5 "struct B {\n" // 6 " virtual int* foo() { return nullptr; }\n" // 7 " virtual int moo(int) { return 13; }\n" // 8 " virtual void bar() = 0;\n" // 9 "};\n" // 10 "struct C: A, B {\n" // 11 " void moo() override {}\n" // 12 " void bar() override {}\n" // 13 "};\n" // 14 "struct D: C {\n" // 15 " int moo(int) override { return 666; }\n" // 16 "};\n" // 17 "int main() {\n" // 18 " D().A::foo(); D().B::foo();\n" // 19 " D().moo(3);\n" // 20 " D().bar();\n" // 21 " struct E: D { void moo() override {} };\n" // 22 "}\n"); // 23 EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "A::", "bar", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "A::", "foo", "()", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "A::", "moo", "()", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "B::", "bar", "()", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "B::", "foo", "()", "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "B::", "moo", "(int)", "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "C::", "moo", "()", "snippet.cc", 12, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "D::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual), /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "D::", "moo", "(int)", "snippet.cc", 16, 16, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "main()::E::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual), /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "main()::E::", "moo", "()", "snippet.cc", 22, 22, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "A::", "bar", "()", "snippet.cc", 4, 4, "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "A::", "foo", "()", "snippet.cc", 2, 2, "snippet.cc", 19, 19, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "A::", "moo", "()", "snippet.cc", 3, 3, "snippet.cc", 12, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "B::", "bar", "()", "snippet.cc", 9, 9, "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "B::", "foo", "()", "snippet.cc", 7, 7, "snippet.cc", 19, 19, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "B::", "moo", "(int)", "snippet.cc", 8, 8, "snippet.cc", 16, 16, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, "snippet.cc", 21, 21, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "C::", "moo", "()", "snippet.cc", 12, 12, "snippet.cc", 22, 22, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "D::", "moo", "(int)", "snippet.cc", 16, 16, "snippet.cc", 20, 20, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); // `C::foo` is ambiguous, so we omit it. EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "C::", "foo", "()", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "A::", "foo", "()", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual)); EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "C::", "foo", "()", "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "B::", "foo", "()", "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual)); // `C::moo(int)` is not available as an overload in `C` because of `C::moo()`. EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "C::", "moo", "(int)", "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "B::", "moo", "(int)", "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual)); // ...And `D::moo()` is not available as an overload in `D` due to `moo(int)`. EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "D::", "moo", "()", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "A::", "moo", "()", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual)); EXPECT_EQ(index.virtual_method_links.size(), 7); EXPECT_HAS_VIRTUAL_LINK(index, "A::bar()", "C::bar()"); EXPECT_HAS_VIRTUAL_LINK(index, "B::bar()", "C::bar()"); EXPECT_HAS_VIRTUAL_LINK(index, "C::bar()", "D::bar()"); EXPECT_HAS_VIRTUAL_LINK(index, "D::bar()", "main()::E::bar()"); EXPECT_HAS_VIRTUAL_LINK(index, "A::moo()", "C::moo()"); // There's no `C::moo()` -> `D::moo()` link because `D::moo(int)` shadows it. EXPECT_HAS_VIRTUAL_LINK(index, "C::moo()", "main()::E::moo()"); // Note that this link skips `C` because it is devoid of `moo(int)`. EXPECT_HAS_VIRTUAL_LINK(index, "B::moo(int)", "D::moo(int)"); // Qualified-name member accesses only create references to the base class // entities... EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "A::", "foo", "()", "snippet.cc", 2, 2, "snippet.cc", 19, 19, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "B::", "foo", "()", "snippet.cc", 7, 7, "snippet.cc", 19, 19, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); // ...whereas an unqualified-name one also creates a reference to the // synthesized inherited entity in the child. EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, "snippet.cc", 21, 21, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "D::", "bar", "()", "snippet.cc", 13, 13, "snippet.cc", 21, 21, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId( index, Entity::Kind::kFunction, "C::", "bar", "()", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual), /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); } TEST(FrontendTest, Devirtualization) { auto index = IndexSnippet( "struct Foo {\n" // 1 " virtual void bar() const {}\n" // 2 "};\n" // 3 "struct Bar final : public Foo {\n" // 4 " void bar() const override {}\n" // 5 "};\n" // 6 "int main(void) {\n" // 7 " const auto* bar = new Bar();\n" // 8 " ((Foo*)bar)->bar();\n" // 9 "}"); // 10 EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Bar::", "bar", "() const", "snippet.cc", 5, 5, "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, /*virtual_method_kind=*/Entity::VirtualMethodKind::kNonPureVirtual); } TEST(FrontendTest, InheritanceThroughTemplateInstantiation) { auto index = IndexSnippet( "class Foo {\n" // 1 " public:\n" // 2 " virtual void Bar() {}\n" // 3 " virtual int foo() { return 1; }\n" // 4 "};\n" // 5 "template \n" // 6 "class Template : public Foo {\n" // 7 " public:\n" // 8 " int field = 0;\n" // 9 "};\n" // 10 "class Bar : public Template {\n" // 11 "};\n"); // 12 EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "Template::", "foo", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "foo", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "Template::", "foo", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "foo", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual), Entity::VirtualMethodKind::kNonPureVirtual); // `Bar::Bar` is a constructor set shadowing the virtual function. EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Bar::", "Bar", "()", "snippet.cc", 11, 11, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 11, 12), /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNotAVirtualMethod); } TEST(FrontendTest, Builtin) { auto index = IndexSnippet( "int foo(int value) {\n" " __builtin_trap();\n" " __builtin_trap();\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "__builtin_trap", "()", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "__builtin_trap", "()", "snippet.cc", 2, 2, "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "__builtin_trap", "()", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(int)", "snippet.cc", 1, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "value", "", "snippet.cc", 1, 1); } TEST(FrontendTest, RecursiveTemplateInstantiation) { auto index = IndexSnippet( "volatile int bar = 0;\n" "template struct Foo;\n" "template <>\n" "struct Foo<> {\n" " static void foo() {};\n" "};\n" "template \n" "struct Foo {\n" " static void foo(int arg, Args... args) {\n" " bar += arg;\n" " Foo::foo(args...);\n" " }\n" "};\n" "template \n" "struct Foo {\n" " static void foo(char arg, Args... args) {\n" " bar += arg;\n" " Foo::foo(args...);\n" " }\n" "};\n" "template \n" "struct Foo {\n" " static void foo(Arg arg, Args... args) {\n" " Foo::foo(args...);\n" " }\n" "};\n" "int main() {\n" " Foo::foo(1, 'b', 3, 'd');\n" "}\n"); // First the expected classes EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, /*is_incomplete=*/true); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "<>", "snippet.cc", 3, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 7, 13); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 14, 20); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 21, 26); // And the expected functions. EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo<>::", "foo", "()", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "foo", "(char, Args...)", "snippet.cc", 16, 19); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "foo", "(int, Args...)", "snippet.cc", 9, 12); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "foo", "(Arg, Args...)", "snippet.cc", 23, 25); // Then make sure we get the final instantiation function with the correct // parameter types. EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "foo", "(int, char, int, char)", "snippet.cc", 9, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "foo", "(int, Args...)", "snippet.cc", 9, 12)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Foo::", "foo", "(int, char, int, char)", "snippet.cc", 9, 12, "snippet.cc", 28, 28, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "foo", "(int, Args...)", "snippet.cc", 9, 12)); } TEST(FrontendTest, IncompleteTemplate) { auto index = IndexSnippet( "template \n" "class Foo;\n" "using Bar = Foo;\n" "template \n" "class Foo {\n" " public:\n" " int baz_;\n" "};\n" "Bar bar;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8, "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8, "snippet.cc", 9, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8, "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8, "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 8)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 3, "snippet.cc", 9, 9); } TEST(FrontendTest, ConstrainedSpecialization) { auto index = IndexSnippet( "template \n" "class Foo {};\n" "template \n" "class Bar {};\n" "template \n" "class Bar> {};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", ">", "snippet.cc", 5, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 3, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Bar>::", "T", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Bar::", "T", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "T", "", "snippet.cc", 1, 1); } TEST(FrontendTest, MoreTemplateSpecialization) { auto index = IndexSnippet( "template \n" "class Foo {};\n" "template \n" "using Bar = Foo;\n" "template \n" "using Baz = Foo, T>;\n" "Bar bar;\n" "Baz baz;\n"); // Check that the baseline template entities exist EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, "snippet.cc", 6, 6); // TODO: Maybe add these if we have implicit reference support. EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, "snippet.cc", 7, 7)); EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, "snippet.cc", 8, 8)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 4, "snippet.cc", 6, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 4, "snippet.cc", 7, 7); // TODO: Maybe add these if we have implicit reference support. EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 3, 4, "snippet.cc", 8, 8)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 5, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 5, 6, "snippet.cc", 8, 8); // Check that the correct specializations of Foo exist EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2, "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", ", char>", "snippet.cc", 1, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "Foo", ", char>", "snippet.cc", 1, 2, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 2)); // Note: These entities no longer exist, because they're also implicit. Maybe // we want them, but it's unclear how we'd be able to use them without the // implicit references. // EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", // "snippet.cc", 1, 2); // EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", // "snippet.cc", 1, 2, "snippet.cc", 8, 8); } TEST(FrontendTest, FormatTemplateArgumentsOne) { auto index = IndexSnippet( "template class Foo {};\n" "Foo foo;\n"); // Base templates. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); // Specializations. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); } TEST(FrontendTest, FormatTemplateArgumentsTwo) { auto index = IndexSnippet( "template class Foo {};\n" "template class Bar {};\n" "template using Baz = Foo>;\n" "Baz baz;\n"); // Base templates. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 3, 3); // Specializations. // TODO: If we add implicit references at some point, we should // reintroduce these two as implicit references. EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 2)); EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 4, 4)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", ">", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", ">", "snippet.cc", 1, 1, "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 3, 3)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 3, 3, "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Baz", "", "snippet.cc", 3, 3)); } TEST(FrontendTest, FormatTemplateArgumentsThree) { auto index = IndexSnippet( "template class Foo {};\n" "template using Bar = Foo;\n" "Bar bar;\n"); // Base templates. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3); // Specializations. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2)); } TEST(FrontendTest, EvenMoreTemplates) { auto index = IndexSnippet( "template class Foo { };\n" "template using Bar = Foo;\n" "\n" "template class Baz {};\n" "template using Brrrr = Foo, B>;\n" "\n" "int main() {\n" " Bar bar;\n" " Brrrr brrrr;\n" "}\n"); // Base templates. EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 4, 4, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5, "snippet.cc", 9, 9); // Specializations/instantiations. EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5, "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Brrrr", "", "snippet.cc", 5, 5)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", ", char>", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", ", char>", "snippet.cc", 1, 1, "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); } TEST(FrontendTest, QualifiedTypeSpecialization) { auto index = IndexSnippet( "template class Foo { };\n" "template class Foo { };\n" "template class Foo { };\n" "Foo foo;\n" "Foo const_foo;\n" "Foo volatile_foo;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); } TEST(FrontendTest, QualifiedTypeSpecializationTwo) { auto index = IndexSnippet( "template class Foo { };\n" "template class Foo { };\n" "template class Foo { };\n" "template class Foo { };\n" "Foo foo;\n" "Foo const_foo;\n" "Foo const_const_foo;\n" "Foo volatile_foo;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, "snippet.cc", 6, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, "snippet.cc", 7, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4, "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4)); } TEST(FrontendTest, QualifiedTypeSpecializationThree) { auto index = IndexSnippet( "template class Foo { };\n" "template class Foo { };\n" "Foo foo_1;\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2); // TODO: Figure out why clang finds the correct specialization // for the cases in FrontendTest.QualifiedTypeSpecialization and // FrontendTest.QualifiedTypeSpecializationTwo but not here. This reference // incorrectly goes to the base template instead. // // EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", // "", "snippet.cc", 2, 2, "snippet.cc", // 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2, "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 2, 2)); } TEST(FrontendTest, UsingSpecialization) { auto index = IndexSnippet( "template class Foo;\n" "using Bar = Foo;\n" "template class Foo {};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "A", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3, "snippet.cc", 2, 2, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3)); } TEST(FrontendTest, UsingSpecializationTwo) { auto index = IndexSnippet( "template class Foo;\n" "using Bar = Foo;\n" "template class Foo {};\n" "template <> class Foo {};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Bar", "", "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::", "A", "", "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 4, 4, "snippet.cc", 2, 2); } TEST(FrontendTest, BooleanParameter) { auto index = IndexSnippet("void foo(bool bar) {}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "(bool)", "snippet.cc", 1, 1); } TEST(FrontendTest, BooleanTemplate) { auto index = IndexSnippet("template class Foo {};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "T", "", "snippet.cc", 1, 1); } TEST(FrontendTest, InheritanceReference) { auto index = IndexSnippet( "class Base {};\n" "class Child : public Base {};\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Base", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Base", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Child", "", "snippet.cc", 2, 2); } TEST(FrontendTest, MemberTemplateInstantiation) { auto index = IndexSnippet( "class Foo {\n" " public:\n" " template \n" " static T GetA();\n" " int GetB() {\n" " return Foo::GetA();\n" " }\n" "};\n" "template \n" "T Foo::GetA() {\n" " return 99;\n" "}\n" "int main() {\n" " Foo foo;\n" " return foo.GetB() + Foo::GetA();\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 8); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 8, "snippet.cc", 14, 14); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12, "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12)); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12, "snippet.cc", 15, 15, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 9, 12)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "GetB", "()", "snippet.cc", 5, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Foo::", "GetB", "()", "snippet.cc", 5, 7, "snippet.cc", 15, 15); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Foo::GetA()::", "T", "", "snippet.cc", 9, 9); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "Foo::GetA()::", "T", "", "snippet.cc", 9, 9, "snippet.cc", 10, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 13, 16); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 14, 14); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 14, 14, "snippet.cc", 15, 15); } TEST(FrontendTest, ClassTemplateMemberReference) { auto index = IndexSnippet( "template \n" "class Foo {\n" " public:\n" " static T GetA();\n" " static const T kConstant = 99;\n" "};\n" "template \n" "T Foo::GetA() {\n" " return 99;\n" "}\n" "int main() {\n" " int result = Foo::kConstant;\n" " return result + Foo::GetA();\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 6)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 6, "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 6)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 7, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "kConstant", "", "snippet.cc", 5, 5); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 7, 10, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 7, 10)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 7, 10, "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Foo::", "GetA", "()", "snippet.cc", 7, 10)); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "Foo::", "kConstant", "", "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kVariable, "Foo::", "kConstant", "", "snippet.cc", 5, 5)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kVariable, "Foo::", "kConstant", "", "snippet.cc", 5, 5, "snippet.cc", 12, 12, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kVariable, "Foo::", "kConstant", "", "snippet.cc", 5, 5)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 11, 14); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "result", "", "snippet.cc", 12, 12); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "result", "", "snippet.cc", 12, 12, "snippet.cc", 13, 13); } TEST(FrontendTest, AnonymousStructMemberCollision) { auto index = IndexSnippet( "struct {\n" " int bar;\n" "} foo;\n" "struct {\n" " int bar;\n" "} baz;\n" "int main() {\n" " return foo.bar + baz.bar;\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "(anonymous struct)", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "(anonymous struct)", "", "snippet.cc", 1, 3, "snippet.cc", 1, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "(anonymous struct)", "", "snippet.cc", 4, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "(anonymous struct)", "", "snippet.cc", 4, 6, "snippet.cc", 4, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 4, 6); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "baz", "", "snippet.cc", 4, 6, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 1, 3, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 7, 9); // BUG: b/416218844 - These two entities have identical names. EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "(anonymous struct)::", "bar", "", "snippet.cc", 2, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "(anonymous struct)::", "bar", "", "snippet.cc", 2, 2, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "(anonymous struct)::", "bar", "", "snippet.cc", 5, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "(anonymous struct)::", "bar", "", "snippet.cc", 5, 5, "snippet.cc", 8, 8); } TEST(FrontendTest, ImplicitThisOverload) { auto index = IndexSnippet( "class Test {\n" " public:\n" " int foo(int a) && { return a; }\n" " const char* foo(int a) volatile & { \n" " return \"A\";\n" " }\n" " int* foo(int a) const & { return nullptr; }\n" "};\n" "int main() {\n" " return Test().foo(1);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "a", "", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "a", "", "snippet.cc", 3, 3, "snippet.cc", 3, 3); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "a", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Test::", "foo", "(int) &&", "snippet.cc", 3, 3); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Test::", "foo", "(int) &&", "snippet.cc", 3, 3, "snippet.cc", 10, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Test::", "foo", "(int) volatile &", "snippet.cc", 4, 6); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Test::", "foo", "(int) const &", "snippet.cc", 7, 7); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 9, 11); } TEST(FrontendTest, TemplatedConstructor) { auto index = IndexSnippet( "template\n" "class Test {\n" " public:\n" " template Test(U&&) {}\n" "};\n" "int main() {\n" " Test(17);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Test::", "Test", "(U &&)", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "Test::Test(U &&)::", "U", "", "snippet.cc", 4, 4); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "Test::", "Test", "(int &&)", "snippet.cc", 4, 4, "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "Test::", "Test", "(U &&)", "snippet.cc", 4, 4)); } TEST(FrontendTest, UnknownPragmas) { // This test doesn't actually fail to index, it just tests that unrecognised // pragmas are treated as errors by the indexer, and that `IndexSnippet` // can detect that there was an error and return nullptr. The indexer itself // doesn't care about these errors, so we check that as well. // https://chromium.googlesource.com/chromium/src/+/main/tools/clang/plugins/UnsafeBuffersPlugin.cpp constexpr auto kSnippet = "#pragma allow_unsafe_buffers\n" "int foo = 1;\n" "#pragma allow_unsafe_libc_calls\n" "char bar = 2;\n"; // First we check that the indexer does indeed treat unrecognised pragmas as // errors. auto index_one = GetSnippetIndex(kSnippet, /*extra_args=*/{"-Werror", "-Wunknown-pragmas"}, /*fail_on_error=*/true); EXPECT_EQ(index_one, nullptr); // Then we tell it to ignore those errors, and produce the index regardless. auto index_two = GetSnippetIndex(kSnippet, /*extra_args=*/{"-Werror", "-Wunknown-pragmas"}, /*fail_on_error=*/false); ASSERT_NE(index_two, nullptr); auto flat_index_two = std::move(*index_two).Export(); EXPECT_HAS_ENTITY(flat_index_two, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(flat_index_two, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 2, 2); // Now we specifically suppress the unrecognised pragmas, so that we should be // able to index without any errors. absl::SetFlag(&FLAGS_ignore_pragmas, {"allow_unsafe_buffers", "allow_unsafe_libc_calls"}); auto index_three = GetSnippetIndex(kSnippet, /*extra_args=*/{"-Werror", "-Wunknown-pragmas"}, /*fail_on_error=*/true); ASSERT_NE(index_three, nullptr); auto flat_index_three = std::move(*index_three).Export(); EXPECT_HAS_ENTITY(flat_index_three, Entity::Kind::kVariable, "", "bar", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(flat_index_three, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 2, 2); } TEST(FrontendTest, TemplatedXRef) { auto index = IndexSnippet( "class RefCounted {\n" "public:\n" " void AddRef() { return; }\n" "};\n" "template \n" "class Foo {\n" "public:\n" " explicit Foo(T* p) : ptr_(p) {\n" " if (ptr_) {\n" " ptr_->AddRef();\n" " }\n" " }\n" "private:\n" " T* ptr_;\n" "};\n" "Foo foo(new RefCounted());\n"); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "RefCounted::", "AddRef", "()", "snippet.cc", 3, 3, "snippet.cc", 10, 10); } TEST(FrontendTest, TemplateMemberFn) { auto index = IndexSnippet( "template \n" "class TestTemplateClass {\n" " public:\n" " TestTemplateClass() {}\n" "\n" " template \n" " static S TestTemplateMemberFn(T t) {\n" " return static_cast(t);\n" " }\n" "};\n" "\n" "template \n" "class TestTemplateClass2 {\n" " public:\n" " template TestTemplateClass2(U&&) { enum E{}; }\n" "};\n" "\n" "void template_xrefs() {\n" " int template_xref =\n" " TestTemplateClass::" "TestTemplateMemberFn(99);\n" " TestTemplateClass2 test2(3);\n" "}\n" "\n" "template \n" "class TestTemplateClass3 : public TestTemplateClass {\n" "};\n" "void more_template_xrefs() {\n" " int template_xref =\n" " TestTemplateClass3::" "TestTemplateMemberFn(99);\n" "}\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 1, 10, /*is_incomplete=*/false); EXPECT_HAS_ENTITY( index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 1, 10, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 1, 10)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 1, 10, "snippet.cc", 20, 20, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 1, 10)); EXPECT_HAS_ENTITY(index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE(index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16, "snippet.cc", 21, 21, /*is_incomplete=*/false); EXPECT_HAS_ENTITY( index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16, "snippet.cc", 21, 21, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass2", "", "snippet.cc", 12, 16)); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "t", "", "snippet.cc", 7, 7, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "t", "", "snippet.cc", 7, 7, "snippet.cc", 8, 8, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "t", "", "snippet.cc", 7, 7); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "t", "", "snippet.cc", 7, 7, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "template_xref", "", "snippet.cc", 19, 20, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "template_xrefs", "()", "snippet.cc", 18, 22, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "test2", "", "snippet.cc", 21, 21, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "TestTemplateClass2::", "T", "", "snippet.cc", 12, 12, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "TestTemplateClass2::", "TestTemplateClass2", "(U &&)", "snippet.cc", 15, 15, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kEnum, "TestTemplateClass2::TestTemplateClass2(U &&)::", "E", "", "snippet.cc", 15, 15, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "TestTemplateClass2::TestTemplateClass2(U &&)::", "U", "", "snippet.cc", 15, 15, /*is_incomplete=*/false); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass2::", "TestTemplateClass2", "(int &&)", "snippet.cc", 15, 15, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "TestTemplateClass2::", "TestTemplateClass2", "(U &&)", "snippet.cc", 15, 15)); EXPECT_HAS_ENTITY( index, Entity::Kind::kEnum, "TestTemplateClass2::TestTemplateClass2(int &&)::", "E", "", "snippet.cc", 15, 15, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kEnum, "TestTemplateClass2::TestTemplateClass2(U &&)::", "E", "", "snippet.cc", 15, 15)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "TestTemplateClass::", "T", "", "snippet.cc", 1, 1, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "TestTemplateClass::", "T", "", "snippet.cc", 1, 1, "snippet.cc", 7, 7, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateClass", "()", "snippet.cc", 4, 4, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(T)", "snippet.cc", 6, 9, /*is_incomplete=*/false); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "TestTemplateClass::TestTemplateMemberFn(T)::", "S", "", "snippet.cc", 6, 6, /*is_incomplete=*/false); EXPECT_HAS_REFERENCE( index, Entity::Kind::kType, "TestTemplateClass::TestTemplateMemberFn(T)::", "S", "", "snippet.cc", 6, 6, "snippet.cc", 7, 7, /*is_incomplete=*/false); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(int)", "snippet.cc", 6, 9, /*is_incomplete=*/true, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(T)", "snippet.cc", 6, 9)); // Template function parameter in a class template specialization. EXPECT_HAS_ENTITY( index, Entity::Kind::kType, "TestTemplateClass::TestTemplateMemberFn(int)::", "S", "", "snippet.cc", 6, 6, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "TestTemplateClass::TestTemplateMemberFn(T)::", "S", "", "snippet.cc", 6, 6)); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(int)", "snippet.cc", 6, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(T)", "snippet.cc", 6, 9)); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(int)", "snippet.cc", 6, 9, "snippet.cc", 20, 20, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kFunction, "TestTemplateClass::", "TestTemplateMemberFn", "(T)", "snippet.cc", 6, 9)); // Implicit entities for entities which have template prototypes. EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "TestTemplateClass3", "()", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "TestTemplateClass3", "(TestTemplateClass3 &&)", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "TestTemplateClass3", "(const TestTemplateClass3 &)", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "operator=", "(TestTemplateClass3 &&)", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "operator=", "(const TestTemplateClass3 &)", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); // Implicitly defined destructor in a class instantiated from a template. EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass3::", "~TestTemplateClass3", "()", "snippet.cc", 25, 25, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId( index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass3", "", "snippet.cc", 24, 26))); } TEST(FrontendTest, ImplicitCode) { auto index = IndexSnippet( "class Foo {\n" " public:\n" " virtual ~Foo() {}\n" "};\n" "Foo instance;" "class Bar : public Foo {};\n" "Bar instance2;\n" "Bar func() { return {}; }\n" "typedef union { int x; short y; } u;\n" "struct Baz {\n" " Baz() {\n" " int arr[] = {1, 2, 3};\n" " for (auto x : arr) {};\n" " };\n" " union { int a; char b; }; // anonymous union field\n" "};"); EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "Foo::", "~Foo", "()", "snippet.cc", 3, 3, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/std::nullopt, /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "Foo", "()", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "Foo", "(const Foo &)", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Foo::", "operator=", "(const Foo &)", "snippet.cc", 1, 1, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Bar::", "Bar", "()", "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 5, 5)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Bar::", "~Bar", "()", "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 5, 5), /*enum_value=*/std::nullopt, /*inherited_from_entity_id=*/std::nullopt, Entity::VirtualMethodKind::kNonPureVirtual); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Foo::", "Foo", "()", "snippet.cc", 1, 1, "snippet.cc", 5, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Foo", "", "snippet.cc", 1, 4)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "Bar::", "Bar", "()", "snippet.cc", 5, 5, "snippet.cc", 7, 7, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Bar", "", "snippet.cc", 5, 5)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "Baz", "()", "snippet.cc", 10, 13); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "Baz", "(Baz &&)", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 9, 15)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "Baz", "(const Baz &)", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 9, 15)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "operator=", "(Baz &&)", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 9, 15)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "operator=", "(const Baz &)", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 9, 15)); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "Baz::", "~Baz", "()", "snippet.cc", 9, 9, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "Baz", "", "snippet.cc", 9, 15)); // Anonymous union destructor should be absent, with or without implicit-for. EXPECT_FALSE(IndexHasEntity( index, Entity::Kind::kFunction, "(anonymous union)::", "~u", "()", "snippet.cc", 8, 8, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "(anonymous union)", "", "snippet.cc", 8, 8))); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "(anonymous union)::", "~u", "()", "snippet.cc", 8, 8)); // Implicit variables from range for loops should be absent. EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "", "__begin1", "", "snippet.cc", 12, 12)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "", "__end1", "", "snippet.cc", 12, 12)); EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "", "__range1", "", "snippet.cc", 12, 12)); EXPECT_FALSE(IndexHasReference(index, Entity::Kind::kVariable, "", "__range1", "", "snippet.cc", 12, 12, "snippet.cc", 12, 12)); // Implicit unnamed field produced by an anonymous union should be absent. EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kVariable, "Baz::", "(anonymous union)", "", "snippet.cc", 14, 14)); // Unreferenced `operator delete` should be absent. EXPECT_FALSE(IndexHasEntity(index, Entity::Kind::kFunction, "", "operator delete", "(void *)", "", 0, 0, /*is_incomplete=*/true)); } TEST(FrontendTest, ReferencedImplicitCode) { auto index = IndexSnippet("void func() { delete new int; }\n"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "func", "()", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "operator delete", "(void *, __size_t)", "", 0, 0, /*is_incomplete=*/true); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "operator delete", "(void *, __size_t)", "", 0, 0, "snippet.cc", 1, 1, /*is_incomplete=*/true); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "operator new", "(__size_t)", "", 0, 0, /*is_incomplete=*/true); EXPECT_HAS_REFERENCE(index, Entity::Kind::kFunction, "", "operator new", "(__size_t)", "", 0, 0, "snippet.cc", 1, 1, /*is_incomplete=*/true); } TEST(FrontendTest, ImplicitComparisonInstantiation) { auto index = IndexSnippet( "namespace std {\n" "struct strong_ordering {\n" " int n;\n" " static const strong_ordering less, equal, greater;\n" "};\n" "constexpr strong_ordering strong_ordering::less = {-1};\n" "constexpr strong_ordering strong_ordering::equal = {0};\n" "constexpr strong_ordering strong_ordering::greater = {1};\n" "constexpr bool operator!=(strong_ordering, int);\n" "} // namespace std\n" "template \n" "struct TestTemplateClass {\n" " constexpr auto operator<=>(const TestTemplateClass&) " "const = default;\n" "};\n" "const bool X = (TestTemplateClass() ==\n" " TestTemplateClass());\n", {"-std=c++20"}); // Implicit `operator==` instantiated from a template implicit `operator==` // coming from `auto operator<=>`. EXPECT_HAS_ENTITY( index, Entity::Kind::kFunction, "TestTemplateClass::", "operator==", "(const TestTemplateClass &) const", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId( index, Entity::Kind::kFunction, "TestTemplateClass::", "operator==", "(const TestTemplateClass &) const", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 11, 14))); EXPECT_HAS_REFERENCE( index, Entity::Kind::kFunction, "TestTemplateClass::", "operator==", "(const TestTemplateClass &) const", "snippet.cc", 13, 13, "snippet.cc", 15, 16, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId( index, Entity::Kind::kFunction, "TestTemplateClass::", "operator==", "(const TestTemplateClass &) const", "snippet.cc", 13, 13, /*is_incomplete=*/false, /*template_prototype_entity_id=*/std::nullopt, /*implicitly_defined_for_entity_id=*/ RequiredEntityId(index, Entity::Kind::kClass, "", "TestTemplateClass", "", "snippet.cc", 11, 14))); } TEST(FrontendTest, VarAndTypeAliasTemplates) { auto index = IndexSnippet( "template \n" // 1 "constexpr T kPi = T(3.1415926535897932385);\n" // 2 "\n" // 3 "template \n" // 4 "using Blah = Y[15];\n" // 5 "\n" // 6 "int main() {\n" // 7 " (void)kPi;\n" // 8 " (void)kPi;\n" // 9 " Blah foo = {kPi, };\n" // 10 "}\n"); // 11 EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5, "snippet.cc", 10, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5)); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5, "snippet.cc", 10, 10, /*is_incomplete=*/false, /*template_prototype_entity_id=*/ RequiredEntityId(index, Entity::Kind::kType, "", "Blah", "", "snippet.cc", 4, 5)); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "T", "", "snippet.cc", 1, 1); EXPECT_HAS_REFERENCE(index, Entity::Kind::kType, "", "T", "", "snippet.cc", 1, 1, "snippet.cc", 2, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kType, "", "Y", "", "snippet.cc", 4, 4); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "foo", "", "snippet.cc", 10, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2, "snippet.cc", 8, 8); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2, "snippet.cc", 9, 9); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2); EXPECT_HAS_REFERENCE(index, Entity::Kind::kVariable, "", "kPi", "", "snippet.cc", 1, 2, "snippet.cc", 10, 10); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "main", "()", "snippet.cc", 7, 11); } TEST(FrontendTest, AbbreviatedFunctionTemplate) { auto index = IndexSnippet("void template_function(auto arg) {}", {"-std=c++20"}); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "template_function", "(auto)", "snippet.cc", 1, 1); } TEST(FrontendTest, CommandLineMacro) { auto index = IndexSnippet("int MACRO;", {"-DMACRO=expansion"}); EXPECT_HAS_ENTITY(index, Entity::Kind::kVariable, "", "expansion", "", "snippet.cc", 1, 1); int found = 0; for (const auto& index_entity : index.entities) { if (index_entity.full_name() == "MACRO") { EXPECT_EQ(index_entity.kind(), Entity::Kind::kMacro); // NOTE(kartynnik): Why isn't this ``? EXPECT_EQ(index.locations[index_entity.location_id()].path(), ""); ++found; } } EXPECT_EQ(found, 1); } TEST(FrontendTest, AliasedSymbol) { auto index = IndexSnippet( "extern \"C\" int foo(void) { return 0; }\n" "int bar(void) __attribute__((alias(\"foo\")));\n" "int main(void) { bar(); return 0; }"); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "foo", "()", "snippet.cc", 1, 1); EXPECT_HAS_ENTITY(index, Entity::Kind::kFunction, "", "bar", "()", "snippet.cc", 2, 2); } TEST(FrontendTest, GhostFileLocations) { FlatIndex index = std::move( *GetSnippetIndex( /*code=*/"#include \"ghostfile.h\"\n", /*extra_args=*/{}, /*fail_on_error=*/true, /*extra_action=*/ [](const std::filesystem::path& source_dir) { std::ofstream ghost_file(source_dir / "ghostfile.h"); ghost_file << "// Copyright 2025 Google Inc. All rights reserved."; CHECK(ghost_file.good()); })) .Export(); bool found_self = false; bool found_include = false; bool found_other = false; for (const Location& location : index.locations) { if (location.is_whole_file()) { if (location.path().ends_with("snippet.cc")) { found_self = true; } else if (location.path().ends_with("ghostfile.h")) { found_include = true; } } else if (location.is_real()) { found_other = true; } } EXPECT_TRUE(found_self); EXPECT_TRUE(found_include); EXPECT_FALSE(found_other); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/index_action.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/index_action.h" #include #include #include #include #include "indexer/frontend/ast_visitor.h" #include "indexer/frontend/common.h" #include "indexer/frontend/pp_callbacks.h" #include "indexer/index/file_copier.h" #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "indexer/merge_queue.h" #include "absl/flags/flag.h" #include "absl/log/check.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "clang/AST/ASTConsumer.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/Pragma.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringRef.h" ABSL_FLAG(std::vector, ignore_pragmas, {}, "#pragma(s) to ignore, comma-separated"); namespace oss_fuzz { namespace indexer { class AstConsumer : public clang::ASTConsumer { public: explicit AstConsumer(InMemoryIndex& index, clang::CompilerInstance& compiler) : index_(index), compiler_(compiler) {} ~AstConsumer() override = default; void HandleTranslationUnit(clang::ASTContext& context) override { AstVisitor visitor(index_, context, compiler_); visitor.TraverseDecl(context.getTranslationUnitDecl()); } private: InMemoryIndex& index_; clang::CompilerInstance& compiler_; }; IndexAction::IndexAction(FileCopier& file_copier, MergeQueue& merge_queue) : index_(std::make_unique(file_copier)), merge_queue_(merge_queue) {} bool IndexAction::BeginSourceFileAction(clang::CompilerInstance& compiler) { CHECK(index_); dependencies_collector_ = std::make_unique(); clang::Preprocessor& preprocessor = compiler.getPreprocessor(); dependencies_collector_->attachToPreprocessor(preprocessor); preprocessor.addPPCallbacks( std::make_unique(*index_, compiler.getSourceManager())); for (const std::string& ignored_pragma : absl::GetFlag(FLAGS_ignore_pragmas)) { preprocessor.AddPragmaHandler( new clang::EmptyPragmaHandler(ignored_pragma)); } // TODO: b/409708640 - Support indexing assembly files. return !absl::EndsWith(compiler.getFrontendOpts().Inputs[0].getFile(), ".S"); } void IndexAction::EndSourceFileAction() { const clang::SourceManager& source_manager = getCompilerInstance().getSourceManager(); for (const std::string& filename : dependencies_collector_->getDependencies()) { if (!IsRealPath(filename)) { continue; } const auto absolute_path = ToNormalizedAbsolutePath(filename, source_manager); // Create a "whole file" location per filename to make sure files without // indexed symbols are still copied and e.g. accounted for in deltas. index_->GetLocationId(Location::WholeFile(absolute_path)); } dependencies_collector_.reset(); merge_queue_.Add(std::move(index_)); } std::unique_ptr IndexAction::CreateASTConsumer( clang::CompilerInstance& compiler, llvm::StringRef path) { return std::make_unique(*index_, compiler); } IndexActionFactory::IndexActionFactory(FileCopier& file_copier, MergeQueue& merge_queue) : file_copier_(file_copier), merge_queue_(merge_queue) {} std::unique_ptr IndexActionFactory::create() { return std::make_unique(file_copier_, merge_queue_); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/index_action.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_FRONTEND_INDEX_ACTION_H_ #define OSS_FUZZ_INFRA_INDEXER_FRONTEND_INDEX_ACTION_H_ #include #include "indexer/index/file_copier.h" #include "indexer/index/in_memory_index.h" #include "indexer/merge_queue.h" #include "clang/AST/ASTConsumer.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/Utils.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/StringRef.h" namespace oss_fuzz { namespace indexer { class AllDependenciesCollector : public clang::DependencyCollector { public: // Also include files from the "system" locations. bool needSystemDependencies() override { return true; } }; // IndexAction provides the entry-point for the indexing tooling. This should // typically not be used directly, and the functions exposed in // indexer/frontend.h should be used instead. class IndexAction : public clang::ASTFrontendAction { public: explicit IndexAction(FileCopier& file_copier, MergeQueue& merge_queue); bool BeginSourceFileAction(clang::CompilerInstance& compiler) override; void EndSourceFileAction() override; std::unique_ptr CreateASTConsumer( clang::CompilerInstance& compiler, llvm::StringRef) override; private: std::unique_ptr index_; MergeQueue& merge_queue_; std::unique_ptr dependencies_collector_; }; class IndexActionFactory : public clang::tooling::FrontendActionFactory { public: explicit IndexActionFactory(FileCopier& file_copier, MergeQueue& merge_queue); std::unique_ptr create() override; private: FileCopier& file_copier_; MergeQueue& merge_queue_; }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_FRONTEND_INDEX_ACTION_H_ ================================================ FILE: infra/indexer/frontend/pp_callbacks.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/frontend/pp_callbacks.h" #include "indexer/frontend/common.h" #include "indexer/index/types.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/StringRef.h" namespace oss_fuzz { namespace indexer { LocationId PpCallbacks::GetLocationId(clang::SourceLocation start, clang::SourceLocation end) { return oss_fuzz::indexer::GetLocationId(index_, source_manager_, start, end); } EntityId PpCallbacks::GetEntityIdForMacro(llvm::StringRef name, const clang::MacroInfo* macro_info) { LocationId location_id = GetLocationId(macro_info->getDefinitionLoc(), macro_info->getDefinitionEndLoc()); if (location_id == kInvalidLocationId) { return kInvalidEntityId; } return index_.GetEntityId({Entity::Kind::kMacro, "", name, "", location_id}); } void PpCallbacks::MacroExpands(const clang::Token& name_token, const clang::MacroDefinition& definition, clang::SourceRange range, const clang::MacroArgs* args) { llvm::StringRef name = name_token.getIdentifierInfo()->getName(); const clang::MacroInfo* info = definition.getMacroInfo(); LocationId location_id = GetLocationId(range.getBegin(), range.getEnd()); EntityId entity_id = GetEntityIdForMacro(name, info); if (location_id != kInvalidLocationId && entity_id != kInvalidEntityId) { index_.GetReferenceId({entity_id, location_id}); } } void PpCallbacks::MacroDefined(const clang::Token& name_token, const clang::MacroDirective* directive) { llvm::StringRef name = name_token.getIdentifierInfo()->getName(); const clang::MacroInfo* info = directive->getMacroInfo(); GetEntityIdForMacro(name, info); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/frontend/pp_callbacks.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_FRONTEND_PP_CALLBACKS_H_ #define OSS_FUZZ_INFRA_INDEXER_FRONTEND_PP_CALLBACKS_H_ #include "indexer/index/in_memory_index.h" #include "indexer/index/types.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/StringRef.h" namespace oss_fuzz { namespace indexer { // PpCallbacks indexes macro definitions and expansions. class PpCallbacks : public clang::PPCallbacks { public: PpCallbacks(InMemoryIndex& index, clang::SourceManager& source_manager) : index_(index), source_manager_(source_manager) {} ~PpCallbacks() override = default; // clang::PPCallbacks functions: void MacroExpands(const clang::Token& name, const clang::MacroDefinition& definition, clang::SourceRange range, const clang::MacroArgs* args) override; void MacroDefined(const clang::Token& name, const clang::MacroDirective* directive) override; private: LocationId GetLocationId(clang::SourceLocation start, clang::SourceLocation end); EntityId GetEntityIdForMacro(llvm::StringRef name, const clang::MacroInfo* macro_info); InMemoryIndex& index_; clang::SourceManager& source_manager_; }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_FRONTEND_PP_CALLBACKS_H_ ================================================ FILE: infra/indexer/index/file_copier.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/file_copier.h" #include // NOLINT #include #include // NOLINT #include #include "absl/container/flat_hash_set.h" #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" namespace oss_fuzz { namespace indexer { namespace { void PreparePath(std::string& path) { if (!path.empty() && !path.ends_with('/')) { path.append("/"); } CHECK(path.empty() || std::filesystem::path(path).is_absolute()) << path; } } // namespace FileCopier::FileCopier(absl::string_view base_path, absl::string_view index_path, const std::vector& extra_paths, Behavior behavior, bool skip_missing_files) : base_path_(base_path), extra_paths_(extra_paths), index_path_(index_path), behavior_(behavior), skip_missing_files_(skip_missing_files) { if (behavior_ == Behavior::kNoOp) { return; } PreparePath(base_path_); for (std::string& extra_path : extra_paths_) { PreparePath(extra_path); } } std::string FileCopier::AbsoluteToIndexPath(absl::string_view path) const { CHECK(path.starts_with('/')) << "Absolute path expected: " << path; std::string result = std::string(path); if (!base_path_.empty() && absl::StartsWith(path, base_path_)) { result = path.substr(base_path_.size()); } else { bool found = false; for (const auto& extra_path : extra_paths_) { if (!extra_path.empty() && absl::StartsWith(path, extra_path)) { found = true; } } CHECK(found) << "File outside of --source_dir and --extra_dirs: " << path; } return result; } void FileCopier::RegisterIndexedFile(absl::string_view index_path) { if (behavior_ == Behavior::kNoOp) { return; } absl::MutexLock lock(mutex_); indexed_files_.emplace(index_path); } void FileCopier::CopyIndexedFiles() { if (behavior_ == Behavior::kNoOp) { return; } absl::MutexLock lock(mutex_); for (const std::string& indexed_path : indexed_files_) { std::filesystem::path src_path = indexed_path; std::filesystem::path dst_path; if (src_path.is_absolute()) { dst_path = std::filesystem::path(index_path_) / "absolute" / indexed_path.substr(1); } else { src_path = std::filesystem::path(base_path_) / indexed_path; dst_path = std::filesystem::path(index_path_) / "relative" / indexed_path; } if (!std::filesystem::exists(src_path)) { if (!skip_missing_files_) { LOG(QFATAL) << "Source file " << src_path << " does not exist and skip_missing_files is false."; } else { LOG(WARNING) << "Skipping non-existent source file: " << src_path; continue; } } DLOG(INFO) << "\nFrom: " << src_path << "\n To: " << dst_path << "\n"; std::error_code error_code; // The destination directory may already exist, but report other errors. (void)std::filesystem::create_directories(dst_path.parent_path(), error_code); QCHECK(!error_code) << "Failed to create directory: " << dst_path.parent_path() << " (error: " << error_code.message() << ")"; using std::filesystem::copy_options; const copy_options options = behavior_ == Behavior::kOverwriteExistingFiles ? copy_options::overwrite_existing : copy_options::none; std::filesystem::copy_file(src_path, dst_path, options, error_code); QCHECK(!error_code) << "Failed to copy file " << src_path << " to " << dst_path << " (error: " << error_code.message() << ")"; } } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/file_copier.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_INDEX_FILE_COPIER_H_ #define OSS_FUZZ_INFRA_INDEXER_INDEX_FILE_COPIER_H_ #include // NOLINT #include #include #include "absl/base/thread_annotations.h" #include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" namespace oss_fuzz { namespace indexer { // FileCopier tracks the source code files that have been copied across all // InMemoryIndexes for the current project. The same FileCopier is shared by // all InMemoryIndexes for the current project. class FileCopier { public: enum class Behavior { kNoOp, kFailOnExistingFiles, kOverwriteExistingFiles, }; FileCopier(absl::string_view base_path, absl::string_view index_path, const std::vector& extra_paths, Behavior behavior = Behavior::kFailOnExistingFiles, bool skip_missing_files = false); FileCopier(const FileCopier&) = delete; // Takes an absolute path. Rewrites this path into the representation it will // have in the index (relative if within the source tree and absolute // otherwise). std::string AbsoluteToIndexPath(absl::string_view path) const; // `index_path` is expected to be produced by `ToIndexPath`. void RegisterIndexedFile(absl::string_view index_path); // Single-threaded. void CopyIndexedFiles(); private: std::string base_path_; std::vector extra_paths_; const std::filesystem::path index_path_; const Behavior behavior_; const bool skip_missing_files_; absl::Mutex mutex_; absl::flat_hash_set indexed_files_ ABSL_GUARDED_BY(mutex_); }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_INDEX_FILE_COPIER_H_ ================================================ FILE: infra/indexer/index/file_copier_unittest.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/file_copier.h" #include // NOLINT #include #include #include #include #include "gtest/gtest.h" namespace oss_fuzz { namespace indexer { namespace { void CreateFile(const std::filesystem::path& path) { std::filesystem::create_directories(path.parent_path()); std::ofstream tmp_file(path); tmp_file << path.filename().string(); ASSERT_TRUE(tmp_file.good()); } std::optional GetFileContents(const std::filesystem::path& path) { std::ifstream file(path); if (!file.good()) { return std::nullopt; } std::stringstream buffer; buffer << file.rdbuf(); return buffer.str(); } } // namespace TEST(FileCopierTest, AbsoluteToIndexPath) { auto tmp_dir_path = std::filesystem::path(::testing::TempDir()); auto base_path = tmp_dir_path / "src"; auto index_path = tmp_dir_path / "idx"; FileCopier file_copier(base_path.string(), index_path.string(), {"/"}); EXPECT_EQ(file_copier.AbsoluteToIndexPath("/a/b/c/d.cc"), "/a/b/c/d.cc"); EXPECT_EQ( file_copier.AbsoluteToIndexPath((base_path / "a/b/c/d.cc").string()), "a/b/c/d.cc"); EXPECT_DEATH(file_copier.AbsoluteToIndexPath("a/b/c/d.cc"), "Absolute path expected"); } TEST(FileCopierTest, AbsoluteToIndexPathOutside) { auto tmp_dir_path = std::filesystem::path(::testing::TempDir()); auto base_path = tmp_dir_path / "src"; auto index_path = tmp_dir_path / "idx"; FileCopier file_copier(base_path.string(), index_path.string(), {"/sysroot"}); EXPECT_DEATH(file_copier.AbsoluteToIndexPath("/a/b/c/d.cc"), "/a/b/c/d.cc"); } TEST(FileCopierTest, FileCopying) { auto tmp_dir_path = std::filesystem::path(::testing::TempDir()); auto base_path = tmp_dir_path / "src"; auto index_path = tmp_dir_path / "idx"; auto sysroot_path = tmp_dir_path / "sysroot"; FileCopier file_copier(base_path.string(), index_path.string(), {sysroot_path.string()}); auto file_a = base_path / "a.cc"; CreateFile(file_a); auto file_a_copy = index_path / "relative/a.cc"; auto file_b = base_path / "x" / "b.cc"; CreateFile(file_b); auto file_b_copy = index_path / "relative/x/b.cc"; auto file_c = sysroot_path / "y/z/c.cc"; CreateFile(file_c); auto file_c_copy = index_path / "absolute" / sysroot_path.lexically_relative("/") / "y/z/c.cc"; file_copier.RegisterIndexedFile( file_copier.AbsoluteToIndexPath(file_a.string())); file_copier.RegisterIndexedFile( file_copier.AbsoluteToIndexPath(file_b.string())); file_copier.RegisterIndexedFile( file_copier.AbsoluteToIndexPath(file_c.string())); file_copier.CopyIndexedFiles(); EXPECT_EQ(GetFileContents(file_a_copy).value_or(""), "a.cc"); EXPECT_EQ(GetFileContents(file_b_copy).value_or(""), "b.cc"); EXPECT_EQ(GetFileContents(file_c_copy).value_or(""), "c.cc"); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/in_memory_index.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/in_memory_index.h" #include #include #include #include #include #include #include #include #include "indexer/index/file_copier.h" #include "indexer/index/types.h" #include "absl/algorithm/container.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/container/node_hash_map.h" #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/types/span.h" namespace oss_fuzz { namespace indexer { namespace { // TODO: record the high-percentile entity counts in typical // translation units and adjust this accordingly. This should be large enough // to avoid rehashing during indexing. const size_t kInitialReservationCount = 0x1000; bool HasTheSameIdentity(const Entity& lhs, const Entity& rhs) { return lhs.kind() == rhs.kind() && lhs.name_prefix() == rhs.name_prefix() && lhs.name() == rhs.name() && lhs.name_suffix() == rhs.name_suffix(); } void MaybePrintLinkerMessage(absl::Span entities, absl::Span locations) { std::stringstream stream; // First we check the mix of complete and incomplete entities that match this // identity. size_t complete_count = 0; size_t strong_count = 0; for (const auto& entity : entities) { if (!entity.is_incomplete()) { complete_count++; if (!entity.is_weak()) strong_count++; } else { // All complete entities come first. break; } } size_t incomplete_count = entities.size() - complete_count; // If strong definitions exist, ignore weak ones. if (strong_count) complete_count = strong_count; // There are two cases where we might want to print a warning message. // First, if we have an incomplete entity that shares an identity with // multiple complete entities, then we cannot link this correctly. // Secondly, if we have an incomplete entity that does not have a // corresponding complete entity, then linking will be incomplete. if (complete_count > 1 && incomplete_count) { stream << "error: multiple definitions for " << entities[0].full_name() << "\n"; } else if (!complete_count && incomplete_count) { #ifndef NDEBUG // TODO: Enable this in opt builds once the number of warnings is // more reasonable. stream << "warning: no definition found for " << entities[0].full_name() << "\n"; #else return; #endif // NDEBUG } else { return; } for (const auto& entity : entities) { const auto& location = locations[entity.location_id()]; stream << " " << location.path() << ":" << location.start_line() << "-" << location.end_line() << (entity.is_incomplete() ? "" : " [definition]") << (entity.is_weak() ? " [weak]" : "") << "\n"; } std::cerr << stream.str(); } struct ComparePairFirst { template bool operator()(const std::pair& lhs, const std::pair& rhs) const { return lhs.first < rhs.first; } }; } // namespace InMemoryIndex::InMemoryIndex(FileCopier& file_copier) : file_copier_(file_copier) { Expand(kInitialReservationCount, kInitialReservationCount, kInitialReservationCount, kInitialReservationCount); } InMemoryIndex::~InMemoryIndex() = default; void InMemoryIndex::Merge(const InMemoryIndex& other) { // This is guaranteed to be large enough to avoid another rehash for the rest // of this merge operation. This may be a larger reservation than we need; but // this is not an issue, since we almost always use the same indexes to merge // into, so the overly-large reservation will be used later. Expand(other.locations_.size(), other.entities_.size(), other.references_.size(), other.virtual_method_links_.size()); std::vector new_location_ids(other.locations_.size(), kInvalidLocationId); for (const auto& [location, id] : other.locations_) { new_location_ids[id] = GetIdForLocationWithIndexPath(location); } // We need to update the location_id for entities, the entity_id and // location_id for references, and parent/child entity ids for virtual method // links during insertion. // Entity references point to entities with lower ids. Process them // in the increasing order of old ids to ensure reference resolution. using EntitiesIterator = decltype(other.entities_)::const_iterator; std::vector> other_entities( other.entities_.size()); for (auto it = other.entities_.cbegin(); it != other.entities_.cend(); ++it) { const EntityId old_id = it->second; CHECK(old_id < other_entities.size() && !other_entities[old_id]); other_entities[old_id] = it; } std::vector new_entity_ids(other.entities_.size(), kInvalidEntityId); std::vector> substitute_relationships(other.entities_.size()); for (const auto& optional_iter : other_entities) { // The fact that the CHECK above was satisfied `other_entities.size()` times // means that all the `other_entities` items have values. CHECK(optional_iter); const auto& iter = *optional_iter; const Entity& entity = iter->first; const EntityId id = iter->second; std::optional new_substitute_entity_id; if (entity.substitute_relationship()) { const EntityId old_substitute_entity_id = entity.substitute_relationship()->substitute_entity_id(); CHECK_LT(old_substitute_entity_id, id); new_substitute_entity_id = new_entity_ids[old_substitute_entity_id]; CHECK_NE(*new_substitute_entity_id, kInvalidEntityId); } const EntityId new_id = GetEntityId(Entity( entity, /*new_location_id=*/new_location_ids[entity.location_id()], new_substitute_entity_id)); new_entity_ids[id] = new_id; } for (const auto& [reference, id] : other.references_) { GetReferenceId({new_entity_ids[reference.entity_id()], new_location_ids[reference.location_id()]}); } for (const auto& [link, id] : other.virtual_method_links_) { GetVirtualMethodLinkId( {new_entity_ids[link.parent()], new_entity_ids[link.child()]}); } } void InMemoryIndex::Expand(size_t locations_count, size_t entities_count, size_t references_count, size_t virtual_method_links_count) { locations_.reserve(locations_.size() + locations_count); entities_.reserve(entities_.size() + entities_count); references_.reserve(references_.size() + references_count); virtual_method_links_.reserve(virtual_method_links_.size() + virtual_method_links_count); } LocationId InMemoryIndex::GetLocationId(Location location) { if (location.is_real()) { // Adjust paths within the base_path to be relative paths. location.path_ = file_copier_.AbsoluteToIndexPath(location.path()); } return GetIdForLocationWithIndexPath(location); } LocationId InMemoryIndex::GetIdForLocationWithIndexPath( const Location& location) { auto [iter, inserted] = locations_.insert({location, next_location_id_}); if (inserted) { next_location_id_++; if (location.is_real()) { file_copier_.RegisterIndexedFile(location.path()); } } return iter->second; } EntityId InMemoryIndex::GetEntityId(const Entity& entity) { // If an entity and its substitute have identical renderings and are thus // indistinguishable during index merging, prevent creating self-references // due to this collapse by pre-merging them here already. if (entity.substitute_relationship()) { const EntityId substitute_entity_id = entity.substitute_relationship()->substitute_entity_id(); const Entity& substitute_entity = GetEntityById(substitute_entity_id); if (HasTheSameIdentity(substitute_entity, entity)) { return substitute_entity_id; } } auto [iter, inserted] = entities_.insert({entity, next_entity_id_}); const EntityId entity_id = iter->second; if (inserted) { next_entity_id_++; id_to_entity_.push_back(&iter->first); if (auto relationship = entity.substitute_relationship_) { CHECK_LT(relationship->substitute_entity_id(), entity_id); } } return entity_id; } EntityId InMemoryIndex::GetExistingEntityId(const Entity& entity) const { auto it = entities_.find(entity); if (it == entities_.end()) { return kInvalidEntityId; } return it->second; } const Entity& InMemoryIndex::GetEntityById(EntityId entity_id) const { CHECK_NE(entity_id, kInvalidEntityId); CHECK_LT(entity_id, id_to_entity_.size()); return *id_to_entity_[entity_id]; } ReferenceId InMemoryIndex::GetReferenceId(const Reference& reference) { auto [iter, inserted] = references_.insert({reference, next_reference_id_}); if (inserted) { next_reference_id_++; } return iter->second; } VirtualMethodLinkId InMemoryIndex::GetVirtualMethodLinkId( const VirtualMethodLink& link) { auto [iter, inserted] = virtual_method_links_.insert({link, next_virtual_method_link_id_}); if (inserted) { next_virtual_method_link_id_++; } return iter->second; } FlatIndex InMemoryIndex::Export() && { FlatIndex result; // Order is important here, since until we've sorted Locations we don't have // a fixed order for Entities, and similarly until both the Entities and // Locations are sorted the order of the References is still being updated. std::vector new_location_ids(locations_.size(), kInvalidLocationId); { // First sort the locations in pairs with their original id. std::vector> sorted_locations; for (const auto& [location, id] : locations_) { sorted_locations.emplace_back(location, id); } absl::c_sort(sorted_locations, ComparePairFirst()); CHECK_EQ(sorted_locations.size(), locations_.size()); locations_.clear(); // Now iterate through the sorted locations, building a lookup from the old // to the new sorted ids, and building the results vector. result.locations.reserve(sorted_locations.size()); LocationId new_id = 0; for (auto& [location, old_id] : sorted_locations) { result.locations.emplace_back(/*path=*/std::move(location.path_), /*start_line=*/location.start_line(), /*end_line=*/location.end_line()); new_location_ids[old_id] = new_id++; } } std::vector new_entity_ids(entities_.size(), kInvalidEntityId); { // Repeat for entities, but updating stale location ids. std::vector> sorted_entities; for (const auto& [entity, id] : entities_) { const LocationId old_location_id = entity.location_id(); LocationId new_location_id = new_location_ids[old_location_id]; CHECK_NE(new_location_id, kInvalidLocationId); if (entity.substitute_relationship()) { CHECK_LT(entity.substitute_relationship()->substitute_entity_id(), id); } auto& iter = sorted_entities.emplace_back(entity, id); Entity& new_entity = iter.first; new_entity.location_id_ = new_location_id; } absl::c_sort(sorted_entities, ComparePairFirst()); CHECK_EQ(sorted_entities.size(), entities_.size()); entities_.clear(); id_to_entity_.clear(); // Now iterate through the sorted entities, building a lookup from the old // to the new sorted ids, and building the results vector. Since entities // are sorted by name, then by type, then by completeness and weakness (and // finally by location), we can perform linking at this stage to remove // incomplete entities where possible and get rid of overridden weak // symbols. result.entities.reserve(sorted_entities.size()); EntityId new_id = kInvalidEntityId; std::vector same_entities; for (auto& [entity, old_id] : sorted_entities) { if (!same_entities.empty() && HasTheSameIdentity(entity, same_entities[0])) { same_entities.emplace_back(entity); if (!entity.is_incomplete() && !entity.is_weak()) { result.entities.emplace_back(std::move(entity)); ++new_id; } } else { MaybePrintLinkerMessage(same_entities, result.locations); same_entities = {entity}; result.entities.emplace_back(std::move(entity)); ++new_id; } new_entity_ids[old_id] = new_id; } MaybePrintLinkerMessage(same_entities, result.locations); CHECK_EQ(new_entity_ids.size(), sorted_entities.size()); CHECK_LE(result.entities.size(), sorted_entities.size()); // Update the substitute entity ids. for (Entity& entity : result.entities) { if (entity.substitute_relationship()) { entity.substitute_relationship_->entity_id_ = new_entity_ids[entity.substitute_relationship_->entity_id_]; } } } // Here we don't need to maintain a mapping from the old to the new reference // ids. result.references.reserve(references_.size()); for (const auto& [reference, id] : references_) { EntityId new_entity_id = new_entity_ids[reference.entity_id()]; CHECK_NE(new_entity_id, kInvalidEntityId); LocationId new_location_id = new_location_ids[reference.location_id()]; CHECK_NE(new_location_id, kInvalidLocationId); result.references.emplace_back(new_entity_id, new_location_id); } absl::c_sort(result.references); // Remove duplicates that could have arisen due to location column erasure. auto last = std::unique(result.references.begin(), result.references.end()); result.references.erase(last, result.references.end()); // Likewise, no need to maintain the old-to-new link id mapping. result.virtual_method_links.reserve(virtual_method_links_.size()); for (const auto& [link, id] : virtual_method_links_) { EntityId new_parent = new_entity_ids[link.parent()]; CHECK_NE(new_parent, kInvalidEntityId); EntityId new_child = new_entity_ids[link.child()]; CHECK_NE(new_child, kInvalidEntityId); result.virtual_method_links.emplace_back(new_parent, new_child); } absl::c_sort(result.virtual_method_links); return result; } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/in_memory_index.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_INDEX_IN_MEMORY_INDEX_H_ #define OSS_FUZZ_INFRA_INDEXER_INDEX_IN_MEMORY_INDEX_H_ #include #include #include "indexer/index/file_copier.h" #include "indexer/index/types.h" #include "absl/container/flat_hash_map.h" #include "absl/container/node_hash_map.h" namespace oss_fuzz { namespace indexer { // InMemoryIndex is a space-inefficient index structure that allows for fast // insertion and lookup. This is the main data-structure used for index storage // while building the index, and it supports both adding single entries to the // index and efficiently merging multiple indexes together. class InMemoryIndex { public: // `base_path` is the filesystem path of the main source root for the project // being indexed. Paths within `base_path` will be expressed as relative paths // in the index. explicit InMemoryIndex(FileCopier& file_copier); ~InMemoryIndex(); void Merge(const InMemoryIndex& other); // Ensures that there is sufficient additional storage to add at least // `locations_count` new unique locations, `entities_count` new unique // entities, ... void Expand(size_t locations_count, size_t entities_count, size_t references_count, size_t virtual_method_links_count); // The `GetXxxId` functions return the id of an existing, matching object if // there is already one in the index, or allocate a new id if there is not an // identical object in the index. // `GetLocationId` expects a location with an absolute path if not built-in; // use `ToNormalizedAbsolutePath` to obtain one. LocationId GetLocationId(Location location); EntityId GetEntityId(const Entity& entity); const Entity& GetEntityById(EntityId entity_id) const; ReferenceId GetReferenceId(const Reference& reference); VirtualMethodLinkId GetVirtualMethodLinkId(const VirtualMethodLink& link); // In contrast, `GetExistingEntityId` returns `kInvalidEntityId` if such an // entity has not been passed to `GetEntityId` before. EntityId GetExistingEntityId(const Entity& entity) const; // Build a sorted FlatIndex from the contents of this index. This invalidates // the contents of this InMemoryIndex, which should no longer be used. // Usage: // FlatIndex& flat_index = std::move(index).Export(); FlatIndex Export() &&; private: FileCopier& file_copier_; // Like `GetLocationId`, but requires the path to be already index-adjusted. LocationId GetIdForLocationWithIndexPath(const Location& location); // Although we could sort location_lookup_ in advance, the performance impact // on indexing if we use a btree_map is significant, and it's much faster // to sort the index at the end. LocationId next_location_id_ = 0; absl::flat_hash_map locations_; EntityId next_entity_id_ = 0; // Pointer stability is needed for `id_to_entity_`. absl::node_hash_map entities_; // Maps back from the entity ID to an entity in `entities_`. std::vector id_to_entity_; ReferenceId next_reference_id_ = 0; absl::flat_hash_map references_; VirtualMethodLinkId next_virtual_method_link_id_ = 0; absl::flat_hash_map virtual_method_links_; }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_INDEX_IN_MEMORY_INDEX_H_ ================================================ FILE: infra/indexer/index/in_memory_index_unittest.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/in_memory_index.h" #include #include #include // NOLINT #include #include #include #include #include "indexer/index/file_copier.h" #include "indexer/index/types.h" #include "gtest/gtest.h" #include "absl/log/check.h" #include "absl/strings/match.h" #include "absl/types/span.h" namespace oss_fuzz { namespace indexer { namespace { void PopulateLocationFiles(absl::Span locations, const std::filesystem::path& base_path) { for (const auto& location : locations) { auto path = std::filesystem::path(location.path()); if (!path.is_absolute()) { path = base_path / path; } std::filesystem::create_directories(path.parent_path()); std::ofstream tmp_file(path); tmp_file << "A"; CHECK(tmp_file.good()); } } template std::vector EnsureSorted(std::vector items) { for (size_t index = 1; index < items.size(); ++index) { CHECK(items[index - 1] < items[index]); } return items; } std::vector GetTestLocations() { auto tmp_dir_path = std::filesystem::path(::testing::TempDir()); // This should return a sorted vector of Locations. std::vector locations = EnsureSorted({ // This path is outside base path, and should remain unmodified in the // output. Location((tmp_dir_path / "last/path.cc").string(), 0, 1), Location((tmp_dir_path / "some/file/path.cc").string(), 0, 1), Location((tmp_dir_path / "some/file/path.cc").string(), 0, 99), Location((tmp_dir_path / "some/other/file/path.cc").string(), 0, 1), Location((tmp_dir_path / "some/other/file/path.cc").string(), 0, 99), }); PopulateLocationFiles(locations, tmp_dir_path); return locations; } std::vector GetTestEntities() { // This should return a sorted vector of Entities. return EnsureSorted({ Entity(Entity::Kind::kVariable, "bar::", "foo", "", 0), Entity(Entity::Kind::kEnum, "foo::", "bar", "", 0), Entity(Entity::Kind::kVariable, "foo::", "bar", "", 0), Entity(Entity::Kind::kVariable, "foo::", "bar", "", 1, /*is_incomplete=*/true), Entity(Entity::Kind::kFunction, "foo::", "bar", "()", 0), Entity(Entity::Kind::kFunction, "foo::", "bar", "(int baz)", 0), Entity(Entity::Kind::kEnum, "foo::", "foo", "", 0), }); } std::vector GetTestReferences() { // This should return a sorted vector of References. return EnsureSorted({ Reference(0, 0), Reference(0, 1), Reference(1, 1), }); } std::vector GetSecondTestLocations() { auto tmp_dir_path = std::filesystem::path(::testing::TempDir()); // This should return a sorted vector of Locations. std::vector locations = EnsureSorted({ // This path is outside base path, and should remain unmodified in the // output. Location((tmp_dir_path / "aaaa/last/path.cc").string(), 0, 0), Location((tmp_dir_path / "aaaa/last/path.cc").string(), 1, 1), Location((tmp_dir_path / "bbbb/last/path.cc").string(), 1, 1), }); PopulateLocationFiles(locations, tmp_dir_path); return locations; } std::vector EnsureSubstituteReferenceOrdering( std::vector entities) { for (size_t index = 0; index < entities.size(); ++index) { const Entity& entity = entities[index]; if (entity.substitute_relationship()) { CHECK_LT(entity.substitute_relationship()->substitute_entity_id(), index); } } return entities; } std::vector GetSecondTestEntities() { // This should return a sorted vector of Entities whose substitute entity // reference IDs are lower than their indices in the vector. return EnsureSubstituteReferenceOrdering(EnsureSorted({ Entity(Entity::Kind::kClass, "bar::", "Foo", "", 0), Entity(Entity::Kind::kClass, "bar::", "Foo", "", 0, /*is_incomplete=*/false, /*is_weak=*/false, /*substitute_relationship=*/ SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, 0)), Entity(Entity::Kind::kClass, "jar::", "Bar", "", 0), Entity(Entity::Kind::kClass, "jar::", "Bar", "", 0, /*is_incomplete=*/false, /*is_weak=*/false, /*substitute_relationship=*/ SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, 2)), })); } std::vector GetThirdTestEntities() { // This should return a sorted vector of Entities whose substitute entity // reference IDs are lower than their indices in the vector. return EnsureSubstituteReferenceOrdering(EnsureSorted({ Entity(Entity::Kind::kEnum, "bar::", "Baz", "", 1), Entity(Entity::Kind::kClass, "bar::", "Foo", "", 0), Entity(Entity::Kind::kClass, "bar::", "Foo", "", 0, /*is_incomplete=*/false, /*is_weak=*/false, /*substitute_relationship=*/ SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, 1)), Entity(Entity::Kind::kClass, "jar::", "Bad", "", 0), Entity(Entity::Kind::kClass, "jar::", "Bad", "", 0, /*is_incomplete=*/false, /*is_weak=*/false, /*substitute_relationship=*/ SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, 3)), })); } } // namespace TEST(InMemoryIndexTest, Locations) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index(file_copier); auto locations = GetTestLocations(); for (const auto& location : locations) { index.GetLocationId(location); } FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); for (size_t i = 0; i < flat_index.locations.size(); ++i) { ASSERT_EQ(flat_index.locations[i], locations[i]); } } TEST(InMemoryIndexTest, LocationsBasePath) { auto base_path = (std::filesystem::path(::testing::TempDir()) / "some").string(); FileCopier file_copier(base_path, ::testing::TempDir(), {"/"}); InMemoryIndex index(file_copier); auto locations = GetTestLocations(); for (const auto& location : locations) { index.GetLocationId(location); } FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); // The first location is outside the base path, and should be unmodified. ASSERT_EQ(flat_index.locations[0], locations[0]); for (size_t i = 1; i < flat_index.locations.size(); ++i) { // All of the other locations are inside the base path, and should be made // into relative paths. ASSERT_NE(flat_index.locations[i].path(), locations[i].path()); ASSERT_EQ(flat_index.locations[i].start_line(), locations[i].start_line()); ASSERT_EQ(flat_index.locations[i].end_line(), locations[i].end_line()); ASSERT_TRUE( absl::EndsWith(locations[i].path(), flat_index.locations[i].path())); } } TEST(InMemoryIndexTest, Entities) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index(file_copier); auto locations = GetTestLocations(); auto entities = GetTestEntities(); for (const auto& location : locations) { index.GetLocationId(location); } for (const auto& entity : entities) { index.GetEntityId(entity); } FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.entities.size(), entities.size() - 1); for (size_t i = 0; i < flat_index.entities.size(); ++i) { // There is an incomplete entity in the input, which should be linked out // during the index export, so we need to skip over this entry. size_t j = i < 3 ? i : i + 1; ASSERT_EQ(flat_index.entities[i], entities[j]); } } TEST(InMemoryIndexTest, SubstituteEntities) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index(file_copier); auto locations = GetSecondTestLocations(); auto entities = GetSecondTestEntities(); for (const auto& location : locations) { index.GetLocationId(location); } for (const auto& entity : entities) { index.GetEntityId(entity); } FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.entities.size(), entities.size()); ASSERT_TRUE(flat_index.entities[1].substitute_relationship().has_value()); EXPECT_EQ(flat_index.entities[1].substitute_relationship()->kind(), SubstituteRelationship::Kind::kIsTemplateInstantiationOf); EXPECT_EQ( flat_index.entities[1].substitute_relationship()->substitute_entity_id(), 0); ASSERT_TRUE(flat_index.entities[3].substitute_relationship().has_value()); EXPECT_EQ(flat_index.entities[3].substitute_relationship()->kind(), SubstituteRelationship::Kind::kIsTemplateInstantiationOf); EXPECT_EQ( flat_index.entities[3].substitute_relationship()->substitute_entity_id(), 2); } TEST(InMemoryIndexTest, References) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index(file_copier); auto locations = GetTestLocations(); auto entities = GetTestEntities(); auto references = GetTestReferences(); for (const auto& location : locations) { index.GetLocationId(location); } for (const auto& entity : entities) { index.GetEntityId(entity); } for (const auto& reference : references) { index.GetReferenceId(reference); } FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.references.size(), references.size()); for (size_t i = 0; i < flat_index.references.size(); ++i) { ASSERT_EQ(flat_index.references[i], references[i]); } } TEST(InMemoryIndexTest, Merge) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index_one(file_copier); InMemoryIndex index_two(file_copier); auto locations = GetTestLocations(); auto entities = GetTestEntities(); auto references = GetTestReferences(); for (const auto& location : locations) { index_one.GetLocationId(location); index_two.GetLocationId(location); } for (size_t i = 0; i < entities.size(); ++i) { if (i < 3) { index_one.GetEntityId(entities[i]); } index_two.GetEntityId(entities[i]); } for (const auto& reference : references) { index_one.GetReferenceId(reference); } { // First make sure that merging a single index to an empty index works. InMemoryIndex index(file_copier); index.Merge(index_one); FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); ASSERT_EQ(flat_index.entities.size(), 3); ASSERT_EQ(flat_index.references.size(), references.size()); } { // Now check that merging two different indexes doesn't add duplicate // entries. InMemoryIndex index(file_copier); index.Merge(index_one); index.Merge(index_two); FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); ASSERT_EQ(flat_index.entities.size(), entities.size() - 1); ASSERT_EQ(flat_index.references.size(), references.size()); for (size_t i = 0; i < flat_index.locations.size(); ++i) { ASSERT_EQ(flat_index.locations[i], locations[i]); } for (size_t i = 0; i < flat_index.entities.size(); ++i) { size_t j = i < 3 ? i : i + 1; ASSERT_EQ(flat_index.entities[i], entities[j]); } for (size_t i = 0; i < flat_index.references.size(); ++i) { ASSERT_EQ(flat_index.references[i], references[i]); } } } TEST(InMemoryIndexTest, MergeWithSubstituteEntities) { FileCopier file_copier("", ::testing::TempDir(), {"/"}); InMemoryIndex index_one(file_copier); InMemoryIndex index_two(file_copier); auto locations = GetSecondTestLocations(); auto entities_one = GetSecondTestEntities(); auto entities_two = GetThirdTestEntities(); for (const auto& location : locations) { index_one.GetLocationId(location); index_two.GetLocationId(location); } for (const auto& entity : entities_one) { index_one.GetEntityId(entity); } for (const auto& entity : entities_two) { index_two.GetEntityId(entity); } { // First make sure that merging a single index to an empty index works. InMemoryIndex index(file_copier); index.Merge(index_one); FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); ASSERT_EQ(flat_index.entities.size(), entities_one.size()); EXPECT_EQ(flat_index.entities[0].substitute_relationship(), std::nullopt); ASSERT_TRUE(flat_index.entities[1].substitute_relationship().has_value()); EXPECT_EQ(flat_index.entities[1].substitute_relationship()->kind(), SubstituteRelationship::Kind::kIsTemplateInstantiationOf); EXPECT_EQ(flat_index.entities[1] .substitute_relationship() ->substitute_entity_id(), 0); EXPECT_EQ(flat_index.entities[2].substitute_relationship(), std::nullopt); ASSERT_TRUE(flat_index.entities[3].substitute_relationship().has_value()); EXPECT_EQ(flat_index.entities[3].substitute_relationship()->kind(), SubstituteRelationship::Kind::kIsTemplateInstantiationOf); EXPECT_EQ(flat_index.entities[3] .substitute_relationship() ->substitute_entity_id(), 2); } { // Now check that merging two different indexes doesn't add duplicate // entries. InMemoryIndex index(file_copier); index.Merge(index_one); index.Merge(index_two); FlatIndex flat_index = std::move(index).Export(); ASSERT_EQ(flat_index.locations.size(), locations.size()); ASSERT_EQ(flat_index.entities.size(), 7); for (size_t i = 0; i < flat_index.locations.size(); ++i) { ASSERT_EQ(flat_index.locations[i], locations[i]); } ASSERT_EQ(flat_index.entities[0], entities_two[0]); // bar::Baz ASSERT_EQ(flat_index.entities[1], entities_two[1]); // bar::Foo ASSERT_EQ(flat_index.entities[2], entities_two[2]); // bar::Foo ASSERT_EQ(flat_index.entities[3], entities_two[3]); // jar::Bad ASSERT_EQ(flat_index.entities[4], entities_two[4]); // jar::Bad ASSERT_EQ(flat_index.entities[5], entities_one[2]); // jar::Bar const auto& original = entities_one[3]; // jar::Bar ASSERT_EQ( flat_index.entities[6], Entity( original.kind(), original.name_prefix(), original.name(), original.name_suffix(), original.location_id(), original.is_incomplete(), original.is_weak(), SubstituteRelationship( SubstituteRelationship::Kind::kIsTemplateInstantiationOf, 5))); } } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/sqlite.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/sqlite.h" #include #include // NOLINT #include #include "indexer/index/types.h" #include "absl/cleanup/cleanup.h" #include "absl/log/log.h" #include "absl/types/span.h" #include "sqlite3.h" #define SCHEMA_VERSION "4" namespace oss_fuzz { namespace indexer { namespace { // We disable foreign keys and don't enforce unique constraints by default // to speed up index writing (and to account for forward references without // transactions). However, with `enable_expensive_checks`, we add these // afterwards. const char kCreateDb[] = "PRAGMA foreign_keys = OFF;\n" "PRAGMA user_version = " SCHEMA_VERSION ";\n" "\n" "CREATE TABLE location(\n" " id INTEGER PRIMARY KEY,\n" " dirname TEXT NOT NULL,\n" " basename TEXT NOT NULL,\n" " start_line INT NOT NULL,\n" " end_line INT NOT NULL);\n" "\n" "CREATE TABLE entity(\n" " id INTEGER PRIMARY KEY,\n" " kind INT NOT NULL,\n" " is_incomplete BOOLEAN,\n" " name_prefix TEXT,\n" " name TEXT NOT NULL,\n" " name_suffix TEXT,\n" " location_id INTEGER NOT NULL,\n" " substitute_entity_id INTEGER,\n" " substitute_relationship_kind INTEGER,\n" " enum_value TEXT,\n" " virtual_method_kind INT NOT NULL,\n" " FOREIGN KEY (location_id) REFERENCES location(id),\n" " FOREIGN KEY (substitute_entity_id) REFERENCES entity(id),\n" " CHECK(" " (substitute_entity_id IS NULL) == (substitute_relationship_kind IS NULL)" " ));\n" "\n" "CREATE TABLE reference(\n" " id INTEGER PRIMARY KEY,\n" " entity_id INTEGER NOT NULL,\n" " location_id INTEGER NOT NULL,\n" " FOREIGN KEY (entity_id) REFERENCES entity(id),\n" " FOREIGN KEY (location_id) REFERENCES location(id));\n" "\n" "CREATE TABLE virtual_method_link(\n" " id INTEGER PRIMARY KEY,\n" " parent_entity_id INTEGER NOT NULL,\n" " child_entity_id INTEGER NOT NULL,\n" " FOREIGN KEY (parent_entity_id) REFERENCES entity(id),\n" " FOREIGN KEY (child_entity_id) REFERENCES entity(id));\n" "\n" "CREATE INDEX entity_name ON entity(name);\n" "\n" "CREATE INDEX location_basename_start_line ON location(" " basename,\n" " start_line);\n" "\n" "CREATE INDEX reference_entity_location ON reference(" " entity_id,\n" " location_id);\n" "\n" "CREATE INDEX virtual_method_link_parent ON virtual_method_link(" " parent_entity_id);"; // UNIQUE indices are almost equivalent to UNIQUE column constraints (only used // with `enable_expensive_checks`). const char kCreateUniqueIndices[] = "CREATE UNIQUE INDEX unique_location\n" " ON location(dirname, basename, start_line, end_line);\n" "\n" "CREATE UNIQUE INDEX unique_entity\n" " ON entity(kind, name_prefix, name, name_suffix, location_id);\n" "\n" "CREATE UNIQUE INDEX unique_reference\n" " ON reference(entity_id, location_id);\n" "\n" "CREATE UNIQUE INDEX unique_link\n" " ON virtual_method_link(parent_entity_id, child_entity_id);"; const char kInsertLocation[] = "INSERT INTO location\n" " (id, dirname, basename, start_line, end_line)\n" " VALUES (?1, ?2, ?3, ?4, ?5);"; const char kInsertEntity[] = "INSERT INTO entity\n" " (id, kind, is_incomplete, name_prefix, name, name_suffix, location_id,\n" " substitute_entity_id, substitute_relationship_kind, enum_value,\n" " virtual_method_kind)\n" " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11);"; const char kInsertReference[] = "INSERT INTO reference\n" " (id, entity_id, location_id)\n" " VALUES (?1, ?2, ?3);"; const char kInsertLink[] = "INSERT INTO virtual_method_link\n" " (id, parent_entity_id, child_entity_id)\n" " VALUES (?1, ?2, ?3);"; const char kFinalizeDb[] = "VACUUM;\n" "REINDEX;\n" "ANALYZE;\n"; bool InsertLocations(sqlite3* db, absl::Span locations) { sqlite3_stmt* insert_location = nullptr; if (sqlite3_prepare_v2(db, kInsertLocation, sizeof(kInsertLocation), &insert_location, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite compiling prepared statement failed: `" << sqlite3_errmsg(db) << "`"; return false; } absl::Cleanup cleanup = [insert_location] { sqlite3_finalize(insert_location); }; for (LocationId i = 0; i < locations.size(); ++i) { const Location& location = locations[i]; std::filesystem::path location_path(location.path()); const std::string dirname = location_path.parent_path(); const std::string basename = location_path.filename(); if (sqlite3_bind_int64(insert_location, 1, i) != SQLITE_OK || sqlite3_bind_text(insert_location, 2, dirname.data(), dirname.size(), SQLITE_STATIC) != SQLITE_OK || sqlite3_bind_text(insert_location, 3, basename.data(), basename.size(), SQLITE_STATIC) != SQLITE_OK || sqlite3_bind_int(insert_location, 4, location.start_line()) != SQLITE_OK || sqlite3_bind_int(insert_location, 5, location.end_line()) != SQLITE_OK) { LOG(ERROR) << "sqlite binding insert_location failed: `" << sqlite3_errmsg(db) << "`"; return false; } if (sqlite3_step(insert_location) != SQLITE_DONE) { LOG(ERROR) << "sqlite executing insert_entity failed: `" << sqlite3_errmsg(db) << "`"; return false; } sqlite3_reset(insert_location); sqlite3_clear_bindings(insert_location); } return true; } bool InsertEntities(sqlite3* db, absl::Span entities) { sqlite3_stmt* insert_entity = nullptr; if (sqlite3_prepare_v2(db, kInsertEntity, sizeof(kInsertEntity), &insert_entity, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite compiling prepared statement failed: `" << sqlite3_errmsg(db) << "`"; return false; } absl::Cleanup cleanup = [insert_entity] { sqlite3_finalize(insert_entity); }; for (EntityId i = 0; i < entities.size(); ++i) { const Entity& entity = entities[i]; if (sqlite3_bind_int64(insert_entity, 1, i) != SQLITE_OK || sqlite3_bind_int(insert_entity, 2, static_cast(entity.kind())) != SQLITE_OK || sqlite3_bind_int(insert_entity, 3, static_cast(entity.is_incomplete())) != SQLITE_OK || sqlite3_bind_text(insert_entity, 5, entity.name().data(), entity.name().size(), SQLITE_STATIC) != SQLITE_OK || sqlite3_bind_int64(insert_entity, 7, entity.location_id()) != SQLITE_OK) { LOG(ERROR) << "sqlite binding insert_entity failed: `" << sqlite3_errmsg(db) << "`"; return false; } // Note that unbound parameters default to NULL, which is allowed in our // schema for name_{prefix,suffix}, substitute_entity_{id,relationship}, and // enum_value. if (!entity.name_prefix().empty() && sqlite3_bind_text(insert_entity, 4, entity.name_prefix().data(), entity.name_prefix().size(), SQLITE_STATIC) != SQLITE_OK) { return false; } if (!entity.name_suffix().empty() && sqlite3_bind_text(insert_entity, 6, entity.name_suffix().data(), entity.name_suffix().size(), SQLITE_STATIC) != SQLITE_OK) { return false; } if (entity.substitute_relationship().has_value()) { if (sqlite3_bind_int64( insert_entity, 8, entity.substitute_relationship()->substitute_entity_id()) != SQLITE_OK) { return false; } if (sqlite3_bind_int64( insert_entity, 9, static_cast(entity.substitute_relationship()->kind())) != SQLITE_OK) { return false; } } if (entity.enum_value().has_value() && sqlite3_bind_text(insert_entity, 10, entity.enum_value()->data(), entity.enum_value()->size(), SQLITE_STATIC) != SQLITE_OK) { return false; } if (sqlite3_bind_int(insert_entity, 11, static_cast(entity.virtual_method_kind())) != SQLITE_OK) { return false; } if (sqlite3_step(insert_entity) != SQLITE_DONE) { LOG(ERROR) << "sqlite executing insert_entity failed: " << sqlite3_errmsg(db); return false; } sqlite3_reset(insert_entity); sqlite3_clear_bindings(insert_entity); } return true; } bool InsertReferences(sqlite3* db, absl::Span references) { sqlite3_stmt* insert_reference = nullptr; if (sqlite3_prepare_v2(db, kInsertReference, sizeof(kInsertReference), &insert_reference, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite compiling prepared statement failed: `" << sqlite3_errmsg(db) << "`"; return false; } absl::Cleanup cleanup = [insert_reference] { sqlite3_finalize(insert_reference); }; for (ReferenceId i = 0; i < references.size(); ++i) { const Reference& reference = references[i]; if (sqlite3_bind_int64(insert_reference, 1, i) != SQLITE_OK || sqlite3_bind_int64(insert_reference, 2, reference.entity_id()) != SQLITE_OK || sqlite3_bind_int64(insert_reference, 3, reference.location_id()) != SQLITE_OK) { LOG(ERROR) << "sqlite binding insert_reference failed: `" << sqlite3_errmsg(db) << "`"; return false; } if (sqlite3_step(insert_reference) != SQLITE_DONE) { LOG(ERROR) << "sqlite executing insert_reference failed: `" << sqlite3_errmsg(db) << "`"; return false; } sqlite3_reset(insert_reference); sqlite3_clear_bindings(insert_reference); } return true; } bool InsertVirtualMethodLinks(sqlite3* db, absl::Span links) { sqlite3_stmt* insert_link = nullptr; if (sqlite3_prepare_v2(db, kInsertLink, sizeof(kInsertLink), &insert_link, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite compiling prepared statement failed: `" << sqlite3_errmsg(db) << "`"; return false; } absl::Cleanup cleanup = [insert_link] { sqlite3_finalize(insert_link); }; for (VirtualMethodLinkId i = 0; i < links.size(); ++i) { const VirtualMethodLink& link = links[i]; if (sqlite3_bind_int64(insert_link, 1, i) != SQLITE_OK || sqlite3_bind_int64(insert_link, 2, link.parent()) != SQLITE_OK || sqlite3_bind_int64(insert_link, 3, link.child()) != SQLITE_OK) { LOG(ERROR) << "sqlite binding insert_link failed: `" << sqlite3_errmsg(db) << "`"; return false; } if (sqlite3_step(insert_link) != SQLITE_DONE) { LOG(ERROR) << "sqlite executing insert_link failed: `" << sqlite3_errmsg(db) << "`"; return false; } sqlite3_reset(insert_link); sqlite3_clear_bindings(insert_link); } return true; return true; } } // anonymous namespace bool SaveAsSqlite(const FlatIndex& index, const std::string& path, bool enable_expensive_checks) { LOG(INFO) << "creating in-memory database"; const size_t kSqliteMmapSize = 0x1000000000ull; if (sqlite3_config(SQLITE_CONFIG_SINGLETHREAD) != SQLITE_OK || sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, kSqliteMmapSize, kSqliteMmapSize) != SQLITE_OK || sqlite3_initialize() != SQLITE_OK) { LOG(ERROR) << "sqlite setup failed"; return false; } sqlite3* db = nullptr; char* error = nullptr; if (sqlite3_open(":memory:", &db) != SQLITE_OK) { LOG(ERROR) << "sqlite open in-memory database failed: `" << sqlite3_errmsg(db) << "`"; sqlite3_close(db); return false; } absl::Cleanup cleanup = [db] { sqlite3_close(db); }; if (sqlite3_exec(db, kCreateDb, nullptr, nullptr, &error) != SQLITE_OK) { LOG(ERROR) << "sqlite create database failed: `" << error << "`"; sqlite3_free(error); return false; } if (enable_expensive_checks) { if (sqlite3_exec(db, kCreateUniqueIndices, nullptr, nullptr, &error) != SQLITE_OK) { LOG(ERROR) << "sqlite creating unique indices failed: `" << error << "`"; sqlite3_free(error); return false; } } LOG(INFO) << "inserting locations"; if (!InsertLocations(db, index.locations)) { return false; } LOG(INFO) << "inserting entities"; if (!InsertEntities(db, index.entities)) { return false; } LOG(INFO) << "inserting references"; if (!InsertReferences(db, index.references)) { return false; } LOG(INFO) << "inserting virtual method links"; if (!InsertVirtualMethodLinks(db, index.virtual_method_links)) { return false; } if (enable_expensive_checks) { // Enable foreign keys and check for foreign key violations. if (sqlite3_exec(db, "PRAGMA foreign_keys = ON;", nullptr, nullptr, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite re-enabling foreign keys failed: `" << sqlite3_errmsg(db) << "`"; return false; } sqlite3_stmt* foreign_key_check = nullptr; if (sqlite3_prepare_v2(db, "PRAGMA foreign_key_check;", -1, &foreign_key_check, nullptr) != SQLITE_OK) { LOG(ERROR) << "sqlite compiling foreign_key_check failed: `" << sqlite3_errmsg(db) << "`"; return false; } absl::Cleanup fk_cleanup = [foreign_key_check] { sqlite3_finalize(foreign_key_check); }; int rc = sqlite3_step(foreign_key_check); if (rc == SQLITE_ROW) { LOG(ERROR) << "sqlite foreign key check failed: violations found"; return false; } else if (rc != SQLITE_DONE) { LOG(ERROR) << "sqlite foreign key check execution failed: `" << sqlite3_errmsg(db) << "`"; return false; } } LOG(INFO) << "finalizing database"; if (sqlite3_exec(db, kFinalizeDb, nullptr, nullptr, &error) != SQLITE_OK) { LOG(ERROR) << "database finalization failed: `" << error << "`"; sqlite3_free(error); return false; } LOG(INFO) << "writing out database"; sqlite3* file_db = nullptr; if (sqlite3_open(path.c_str(), &file_db) != SQLITE_OK) { LOG(ERROR) << "sqlite opening file_db failed"; sqlite3_close(file_db); return false; } bool backup_success = true; sqlite3_backup* backup = sqlite3_backup_init(file_db, "main", db, "main"); if (!backup) { backup_success = false; } if (backup_success) { bool step_success = sqlite3_backup_step(backup, -1) == SQLITE_DONE; bool finish_success = sqlite3_backup_finish(backup) == SQLITE_OK; backup_success = step_success && finish_success; } if (!backup_success) { LOG(ERROR) << "sqlite backup to file_db failed"; } sqlite3_close(file_db); return backup_success; } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/sqlite.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_INDEX_SQLITE_H_ #define OSS_FUZZ_INFRA_INDEXER_INDEX_SQLITE_H_ #include #include "indexer/index/types.h" namespace oss_fuzz { namespace indexer { bool SaveAsSqlite(const FlatIndex& index, const std::string& path, bool enable_expensive_checks = false); } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_INDEX_SQLITE_H_ ================================================ FILE: infra/indexer/index/types.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/types.h" #include #include #include #include #include #include #include "absl/log/check.h" #include "absl/strings/string_view.h" namespace oss_fuzz { namespace indexer { namespace { bool IsPositiveDecimalInteger(const char* str) noexcept { CHECK_NE(str, nullptr); if (*str == '\0') { return false; } for (; *str != '\0'; ++str) { if (!isdigit(*str)) { return false; } } return true; } bool IsDecimalInteger(const char* str) { CHECK_NE(str, nullptr); if (*str == '-') { return IsPositiveDecimalInteger(str + 1); } return IsPositiveDecimalInteger(str); } } // namespace Location::Location(absl::string_view path, uint32_t start_line, uint32_t end_line) : path_(path), start_line_(start_line), end_line_(end_line) { CHECK_LE(start_line, end_line); } // This is implicitly used for != in C++20. bool operator==(const Location& lhs, const Location& rhs) { return lhs.path() == rhs.path() && lhs.start_line() == rhs.start_line() && lhs.end_line() == rhs.end_line(); } // Locations are ordered by file, then start line, then end line. // This is implicitly used for relational comparisons in C++20 (<, <=, >, >=). std::strong_ordering operator<=>(const Location& lhs, const Location& rhs) { return std::forward_as_tuple(lhs.path(), lhs.start_line(), lhs.end_line()) <=> std::forward_as_tuple(rhs.path(), rhs.start_line(), rhs.end_line()); } Entity::Entity(Kind kind, absl::string_view name_prefix, absl::string_view name, absl::string_view name_suffix, LocationId location_id, bool is_incomplete, bool is_weak, std::optional substitute_relationship, std::optional enum_value, VirtualMethodKind virtual_method_kind) : kind_(kind), is_incomplete_(is_incomplete), is_weak_(is_weak), name_prefix_(name_prefix), name_(name), name_suffix_(name_suffix), location_id_(location_id), substitute_relationship_(substitute_relationship), enum_value_(enum_value), virtual_method_kind_(virtual_method_kind) { CHECK_GT(name.size(), 0); CHECK_NE(location_id, kInvalidLocationId); if (kind == Kind::kEnumConstant) { CHECK(enum_value && IsDecimalInteger(enum_value->c_str())); } else { CHECK(!enum_value.has_value()); } if (virtual_method_kind != VirtualMethodKind::kNotAVirtualMethod) { CHECK(kind == Kind::kFunction); } } bool operator==(const Entity& lhs, const Entity& rhs) { return lhs.kind() == rhs.kind() && lhs.is_incomplete() == rhs.is_incomplete() && lhs.is_weak() == rhs.is_weak() && lhs.name() == rhs.name() && lhs.name_prefix() == rhs.name_prefix() && lhs.name_suffix() == rhs.name_suffix() && lhs.location_id() == rhs.location_id() && lhs.substitute_relationship() == rhs.substitute_relationship() && lhs.enum_value() == rhs.enum_value() && lhs.virtual_method_kind() == rhs.virtual_method_kind(); } // Entities are sorted by fully-qualified name, then by kind, then by // completeness, by weakness, and finally by location, substitution // relationship fields, enum value, and virtual method kind. std::strong_ordering operator<=>(const Entity& lhs, const Entity& rhs) { return std::forward_as_tuple(lhs.name_prefix(), lhs.name(), lhs.name_suffix(), lhs.kind(), lhs.is_incomplete(), lhs.is_weak(), lhs.location_id(), lhs.substitute_relationship(), lhs.enum_value(), lhs.virtual_method_kind()) <=> std::forward_as_tuple(rhs.name_prefix(), rhs.name(), rhs.name_suffix(), rhs.kind(), rhs.is_incomplete(), rhs.is_weak(), rhs.location_id(), rhs.substitute_relationship(), rhs.enum_value(), rhs.virtual_method_kind()); } Reference::Reference(EntityId entity_id, LocationId location_id) : entity_id_(entity_id), location_id_(location_id) { CHECK_NE(entity_id, kInvalidEntityId); CHECK_NE(location_id, kInvalidLocationId); } bool operator==(const Reference& lhs, const Reference& rhs) { return lhs.entity_id() == rhs.entity_id() && lhs.location_id() == rhs.location_id(); } // References are sorted by entity then location. std::strong_ordering operator<=>(const Reference& lhs, const Reference& rhs) { return std::forward_as_tuple(lhs.entity_id(), lhs.location_id()) <=> std::forward_as_tuple(rhs.entity_id(), rhs.location_id()); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/index/types.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Defines the main types used for indexing, at the lowest level. These types // explicitly don't use pointers to express relationships to allow simple // serialization. #ifndef OSS_FUZZ_INFRA_INDEXER_INDEX_TYPES_H_ #define OSS_FUZZ_INFRA_INDEXER_INDEX_TYPES_H_ #include #include #include #include #include #include #include "absl/log/check.h" #include "absl/strings/string_view.h" namespace oss_fuzz { namespace indexer { namespace testing_internal { class TestPeer; } // namespace testing_internal class InMemoryIndex; using LocationId = uint64_t; using EntityId = uint64_t; using ReferenceId = uint64_t; using VirtualMethodLinkId = uint64_t; constexpr LocationId kInvalidLocationId = 0xffffffffffffffffull; constexpr EntityId kInvalidEntityId = 0xffffffffffffffffull; inline bool IsRealPath(absl::string_view path) { // Examples of built-in paths: `` and ``. return !path.empty() && !path.starts_with('<'); } // Represents a source-file location. class Location { public: Location(absl::string_view path, uint32_t start_line, uint32_t end_line); static Location WholeFile(absl::string_view path) { return Location(path, /*start_line=*/0, /*end_line=*/0); } inline const std::string& path() const { return path_; } inline uint32_t start_line() const { return start_line_; } inline uint32_t end_line() const { return end_line_; } inline bool is_real() const { return IsRealPath(path()); } inline bool is_whole_file() const { return start_line_ == 0 && end_line_ == 0; } private: friend class InMemoryIndex; std::string path_; uint32_t start_line_; uint32_t end_line_; }; bool operator==(const Location& lhs, const Location& rhs); std::strong_ordering operator<=>(const Location& lhs, const Location& rhs); template H AbslHashValue(H h, const Location& location) { return H::combine(std::move(h), location.path(), location.start_line(), location.end_line()); } // Represents a relationship whereby an entity's source code is shown in lieu of // that of another entity, typically because the latter is not explicitly // defined in code. class SubstituteRelationship { public: enum class Kind : uint8_t { // This entity is instantiated from the substitute entity (a template). // Example: Looking up Foo when only Foo implementation is provided. kIsTemplateInstantiationOf = 1, // This entity is implicitly defined for the substitute entity (but not in // the sense of being instantiated from a template or inherited). // // Example: An implicit constructor / destructor is defined for a class. // Even if the class is a template instantiation, these implicit methods // are defined post-instantiation (as in `FrontendTest.TemplateMemberFn`). // // Non-example: Implicit `operator==` instantiation from its counterpart // `operator==` implicitly defined in a class template by // const auto operator<=>(...) const = default; // In this case that template `operator==` will be a // `kIsTemplateInstantiationOf` substitute which, in turn, will have a // `kIsImplicitlyDefinedFor` one, specifically the class template. // (See `FrontendTest.ImplicitComparisonInstantiation` for this // situation.) kIsImplicitlyDefinedFor = 2, // This entity's implementation is inherited from the base class and not // overridden. // (We report it as "this implementation is inherited from another" with a // slight abuse of wording.) kIsInheritedFrom = 3, }; SubstituteRelationship(Kind kind, EntityId entity_id) : kind_(kind), entity_id_(entity_id) { CHECK_NE(entity_id, kInvalidEntityId); } Kind kind() const { return kind_; } EntityId substitute_entity_id() const { return entity_id_; } bool operator==(const SubstituteRelationship&) const = default; std::strong_ordering operator<=>(const SubstituteRelationship&) const = default; private: friend class Entity; friend class InMemoryIndex; Kind kind_; EntityId entity_id_; }; template H AbslHashValue(H h, const SubstituteRelationship& relationship) { return H::combine(std::move(h), relationship.kind(), relationship.substitute_entity_id()); } // Represents a source-level entity definition. class Entity { public: enum class Kind : uint8_t { // #define Macro ... kMacro = 1, // enum Enum { ... } kEnum = 2, // enum ... { EnumConstant = ... } kEnumConstant = 3, // int Variable = ... kVariable = 4, // int Function() { ... } kFunction = 5, // class Class { ... }; struct Class { ... }; kClass = 6, // typedef Type int; using Type = int; union Type { ... }; kType = 7, }; enum class VirtualMethodKind : uint8_t { kNotAVirtualMethod = 0, kPureVirtual = 1, kNonPureVirtual = 2, }; Entity(Kind kind, absl::string_view name_prefix, absl::string_view name, absl::string_view name_suffix, LocationId location_id, bool is_incomplete = false, bool is_weak = false, std::optional substitute_relationship = std::nullopt, std::optional enum_value = std::nullopt, VirtualMethodKind virtual_method_kind = VirtualMethodKind::kNotAVirtualMethod); // Allows to create a copy of `entity` with the ID field values replaced. template Entity(TEntity&& entity, LocationId new_location_id, std::optional new_substitute_entity_id) : Entity(std::forward(entity)) { location_id_ = new_location_id; CHECK_EQ(substitute_relationship_.has_value(), new_substitute_entity_id.has_value()); if (substitute_relationship_.has_value()) { substitute_relationship_->entity_id_ = *new_substitute_entity_id; } } // Allows to create a copy of `entity` inheriting its implementation. template Entity(TEntity&& entity, absl::string_view new_name_prefix, EntityId inherited_entity_id) : Entity(std::forward(entity)) { name_prefix_ = new_name_prefix; substitute_relationship_ = SubstituteRelationship( SubstituteRelationship::Kind::kIsInheritedFrom, inherited_entity_id); } inline Kind kind() const { return kind_; } inline bool is_incomplete() const { return is_incomplete_; } inline bool is_weak() const { return is_weak_; } inline const std::string& name_prefix() const { return name_prefix_; } inline const std::string& name() const { return name_; } inline const std::string& name_suffix() const { return name_suffix_; } inline std::string full_name() const { return name_prefix() + name() + name_suffix(); } inline LocationId location_id() const { return location_id_; } inline const std::optional& substitute_relationship() const { return substitute_relationship_; } inline const std::optional& enum_value() const { return enum_value_; } inline bool is_virtual_method() const { return virtual_method_kind_ != VirtualMethodKind::kNotAVirtualMethod; } inline VirtualMethodKind virtual_method_kind() const { return virtual_method_kind_; } private: friend class InMemoryIndex; friend class testing_internal::TestPeer; Kind kind_; // If an Entity is not complete, then it is a forward declaration. Incomplete // entries could be removed/merged with the corresponding complete Entities // during merge. bool is_incomplete_; // If the entity is weak, it should be overridden by strong entities at link // time. // Always false for incomplete entities. bool is_weak_; // Name is split into three components for storage and lookup. // "foo::bar::Baz(int qux)" // name_prefix = "foo::bar::" // name = "Baz" // name_suffix = "(int qux)" // // The only mandatory component is `name`, the other two are optional and may // not be present depending on the entity kind. std::string name_prefix_; std::string name_; std::string name_suffix_; LocationId location_id_; std::optional substitute_relationship_; // Tracks the decimal value of an enum constant (only for `kEnumConstant`). // (A string to support both signed and unsigned 64-bit values - and beyond, // like the `__int128` extension.) std::optional enum_value_; VirtualMethodKind virtual_method_kind_; }; bool operator==(const Entity& lhs, const Entity& rhs); std::strong_ordering operator<=>(const Entity& lhs, const Entity& rhs); template H AbslHashValue(H h, const Entity& entity) { return H::combine(std::move(h), entity.kind(), entity.is_incomplete(), entity.is_weak(), entity.name(), entity.name_prefix(), entity.name_suffix(), entity.location_id(), entity.substitute_relationship(), entity.enum_value(), entity.virtual_method_kind()); } // Represents a source-level reference to an entity. This may be an implicit or // "hidden" reference that doesn't involve explicitly mentioning the entity by // name. class Reference { public: Reference(EntityId entity_id, LocationId location_id); EntityId entity_id() const { return entity_id_; } LocationId location_id() const { return location_id_; } private: friend class InMemoryIndex; EntityId entity_id_; LocationId location_id_; }; bool operator==(const Reference& lhs, const Reference& rhs); std::strong_ordering operator<=>(const Reference& lhs, const Reference& rhs); template H AbslHashValue(H h, const Reference& reference) { return H::combine(std::move(h), reference.entity_id(), reference.location_id()); } // Represents a link between two virtual member functions. // (Note that the C++ standard doesn't use the term "method" but we follow // Clang's liberal approach of `CXXMethodDecl` for brevity.) // // We mostly track immediate parent-child relationships to be able to // answer the question "What virtual method implementations can be invoked as // `ptr->method()`?" even for `*ptr` being of a class that doesn't override, but // only inherits a virtual method `child`. // The only exception to this is when the immediate parent doesn't have the // method due to name resolution ambiguity / an own set of overloads for this // method hiding the overload in question, in which case we skip to the lowest // ancestor(s) that do(es) have it: // struct A { virtual void X() {} }; // struct B { virtual int X(int) { return 0; } }; // // Has no `X(int)` due to its own overload set for X. // struct C: A, B { void X() override {} }; // // `X(int)` can still be overridden through it though! // // We link `D::X(int)` directly to `B::X(int)`, bypassing `C`. // struct D: C { int X(int) override { return 13; } }; // The same behavior is observed when we remove the `X()` override from `C` // since `C::X()` is an ambiguity. class VirtualMethodLink { public: // `parent` and `child` should point to `Entity::Kind::kFunction` entities // with `is_virtual_method() == true`. VirtualMethodLink(EntityId parent, EntityId child) : parent_(parent), child_(child) { CHECK_NE(parent, kInvalidEntityId); CHECK_NE(child, kInvalidEntityId); } EntityId parent() const { return parent_; } EntityId child() const { return child_; } bool operator==(const VirtualMethodLink&) const = default; std::strong_ordering operator<=>(const VirtualMethodLink&) const = default; private: EntityId parent_; EntityId child_; }; template H AbslHashValue(H h, const VirtualMethodLink& link) { return H::combine(std::move(h), link.parent(), link.child()); } // A simple holder for a sorted index, used as an interchange format/interface // definition between uses of the index. struct FlatIndex { std::vector locations; std::vector entities; std::vector references; std::vector virtual_method_links; }; namespace testing_internal { // For test use only: Provides access to some private members of the above. class TestPeer { public: static void SetSubstituteRelationship( Entity& entity, const SubstituteRelationship& relationship) { entity.substitute_relationship_ = relationship; } }; } // namespace testing_internal } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_INDEX_TYPES_H_ ================================================ FILE: infra/indexer/index/types_unittest.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/index/types.h" #include #include #include "gtest/gtest.h" #include "absl/hash/hash_testing.h" namespace oss_fuzz { namespace indexer { namespace { std::vector GetTestLocations() { // This should return a sorted vector of Locations. return { Location("/some/file/path.cc", 0, 1), Location("/some/file/path.cc", 0, 99), Location("/some/other/file/path.cc", 0, 1), Location("/some/other/file/path.cc", 0, 99), }; } std::vector GetTestEntities() { // This should return a sorted vector of Entities. return { Entity(Entity::Kind::kVariable, "bar::", "foo", "", 0), Entity(Entity::Kind::kEnum, "foo::", "bar", "", 0), Entity(Entity::Kind::kVariable, "foo::", "bar", "", 0), Entity(Entity::Kind::kVariable, "foo::", "bar", "", 1), Entity(Entity::Kind::kVariable, "foo::", "bar", "", 1, /*is_incomplete=*/true), Entity(Entity::Kind::kFunction, "foo::", "bar", "()", 0), Entity(Entity::Kind::kFunction, "foo::", "bar", "(int baz)", 0), Entity(Entity::Kind::kEnum, "foo::", "foo", "", 0), }; } std::vector GetTestReferences() { // This should return a sorted vector of References. return { Reference(0, 0), Reference(0, 1), Reference(1, 1), }; } } // namespace TEST(LocationTest, TestEquality) { auto locations = GetTestLocations(); for (size_t i = 0; i < locations.size(); ++i) { for (size_t j = 0; j < locations.size(); ++j) { if (i == j) { ASSERT_EQ(locations[i], locations[j]) << i << " == " << j; } else { ASSERT_NE(locations[i], locations[j]) << i << " == " << j; } } } } TEST(LocationTest, TestStrictComparison) { auto locations = GetTestLocations(); for (size_t i = 0; i < locations.size(); ++i) { for (size_t j = 0; j < locations.size(); ++j) { if (i < j) { ASSERT_TRUE(locations[i] < locations[j]) << i << " < " << j; ASSERT_FALSE(locations[i] > locations[j]) << i << " > " << j; } else if (i > j) { ASSERT_FALSE(locations[i] < locations[j]) << i << " < " << j; ASSERT_TRUE(locations[i] > locations[j]) << i << " > " << j; } else { ASSERT_FALSE(locations[i] < locations[j]) << i << " < " << j; ASSERT_FALSE(locations[i] > locations[j]) << i << " > " << j; } } } } TEST(LocationTest, TestComparison) { auto locations = GetTestLocations(); for (size_t i = 0; i < locations.size(); ++i) { for (size_t j = 0; j < locations.size(); ++j) { if (i < j) { ASSERT_TRUE(locations[i] <= locations[j]) << i << " <= " << j; ASSERT_FALSE(locations[i] >= locations[j]) << i << " >= " << j; } else if (i > j) { ASSERT_FALSE(locations[i] <= locations[j]) << i << " <= " << j; ASSERT_TRUE(locations[i] >= locations[j]) << i << " >= " << j; } else { ASSERT_TRUE(locations[i] <= locations[j]) << i << " <= " << j; ASSERT_TRUE(locations[i] >= locations[j]) << i << " >= " << j; } } } } TEST(LocationTest, TestHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(GetTestLocations())); } TEST(EntityTest, TestEquality) { auto entities = GetTestEntities(); for (size_t i = 0; i < entities.size(); ++i) { for (size_t j = 0; j < entities.size(); ++j) { if (i == j) { ASSERT_EQ(entities[i], entities[j]) << i << " == " << j; } else { ASSERT_NE(entities[i], entities[j]) << i << " == " << j; } } } } TEST(EntityTest, TestStrictComparison) { auto entities = GetTestEntities(); for (size_t i = 0; i < entities.size(); ++i) { for (size_t j = 0; j < entities.size(); ++j) { if (i < j) { ASSERT_TRUE(entities[i] < entities[j]) << i << " < " << j; ASSERT_FALSE(entities[i] > entities[j]) << i << " > " << j; } else if (i > j) { ASSERT_FALSE(entities[i] < entities[j]) << i << " < " << j; ASSERT_TRUE(entities[i] > entities[j]) << i << " > " << j; } else { ASSERT_FALSE(entities[i] < entities[j]) << i << " < " << j; ASSERT_FALSE(entities[i] > entities[j]) << i << " > " << j; } } } } TEST(EntityTest, TestComparison) { auto entities = GetTestEntities(); for (size_t i = 0; i < entities.size(); ++i) { for (size_t j = 0; j < entities.size(); ++j) { if (i < j) { ASSERT_TRUE(entities[i] <= entities[j]) << i << " <= " << j; ASSERT_FALSE(entities[i] >= entities[j]) << i << " >= " << j; } else if (i > j) { ASSERT_FALSE(entities[i] <= entities[j]) << i << " <= " << j; ASSERT_TRUE(entities[i] >= entities[j]) << i << " >= " << j; } else { ASSERT_TRUE(entities[i] <= entities[j]) << i << " <= " << j; ASSERT_TRUE(entities[i] >= entities[j]) << i << " >= " << j; } } } } TEST(EntityTest, TestHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(GetTestEntities())); } TEST(ReferenceTest, TestEquality) { auto references = GetTestReferences(); for (size_t i = 0; i < references.size(); ++i) { for (size_t j = 0; j < references.size(); ++j) { if (i == j) { ASSERT_EQ(references[i], references[j]) << i << " == " << j; } else { ASSERT_NE(references[i], references[j]) << i << " == " << j; } } } } TEST(ReferenceTest, TestStrictComparison) { auto references = GetTestReferences(); for (size_t i = 0; i < references.size(); ++i) { for (size_t j = 0; j < references.size(); ++j) { if (i < j) { ASSERT_TRUE(references[i] < references[j]) << i << " < " << j; ASSERT_FALSE(references[i] > references[j]) << i << " > " << j; } else if (i > j) { ASSERT_FALSE(references[i] < references[j]) << i << " < " << j; ASSERT_TRUE(references[i] > references[j]) << i << " > " << j; } else { ASSERT_FALSE(references[i] < references[j]) << i << " < " << j; ASSERT_FALSE(references[i] > references[j]) << i << " > " << j; } } } } TEST(ReferenceTest, TestComparison) { auto references = GetTestReferences(); for (size_t i = 0; i < references.size(); ++i) { for (size_t j = 0; j < references.size(); ++j) { if (i < j) { ASSERT_TRUE(references[i] <= references[j]) << i << " <= " << j; ASSERT_FALSE(references[i] >= references[j]) << i << " >= " << j; } else if (i > j) { ASSERT_FALSE(references[i] <= references[j]) << i << " <= " << j; ASSERT_TRUE(references[i] >= references[j]) << i << " >= " << j; } else { ASSERT_TRUE(references[i] <= references[j]) << i << " <= " << j; ASSERT_TRUE(references[i] >= references[j]) << i << " >= " << j; } } } } TEST(ReferenceTest, TestHash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(GetTestReferences())); } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/init.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This is only built/included in the open source indexer. #ifndef OSS_FUZZ_INFRA_INDEXER_INIT_H_ #define OSS_FUZZ_INFRA_INDEXER_INIT_H_ #include "absl/flags/parse.h" #include "absl/flags/usage.h" #include "absl/log/initialize.h" #include "absl/strings/string_view.h" void InitGoogle(absl::string_view usage, int* argc, char*** argv, bool remove_flags) { absl::InitializeLog(); absl::SetProgramUsageMessage(*argv[0]); absl::ParseCommandLine(*argc, *argv); } void InitGoogleExceptChangeRootAndUser(absl::string_view usage, int* argc, char*** argv, bool remove_flags) { InitGoogle(usage, argc, argv, remove_flags); } #endif // OSS_FUZZ_INFRA_INDEXER_INIT_H_ ================================================ FILE: infra/indexer/main.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include // NOLINT #include #include #include // NOLINT #include #include #include "init.h" #include "indexer/frontend/frontend.h" #include "indexer/index/file_copier.h" #include "indexer/index/sqlite.h" #include "indexer/merge_queue.h" #include "absl/flags/flag.h" #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/strings/string_view.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Tooling.h" #include "llvm/Support/Error.h" ABSL_FLAG(std::string, source_dir, "", "Source directory"); ABSL_FLAG(std::string, build_dir, "", "Build directory"); ABSL_FLAG(std::string, index_dir, "", "Output index file directory (should be empty if it exists for a new " "index or contain the old index for a --delta); required unless" "--database_only is specified"); ABSL_FLAG(std::vector, extra_dirs, {"/"}, "Additional source directory/-ies (comma-separated)"); ABSL_FLAG(std::string, dry_run_regex, "", "If specified, dry-run only on files matching this (POSIX-like) " "`llvm::Regex` and don't store the index"); ABSL_FLAG(int, index_threads, 4, "Number of parallel indexing threads"); ABSL_FLAG(int, merge_queues, 1, "Number of parallel merge queues"); ABSL_FLAG(int, merge_queue_size, 16, "Length of merge queues"); ABSL_FLAG(bool, enable_expensive_checks, false, "Enable expensive database integrity checks"); ABSL_FLAG(bool, ignore_indexing_errors, false, "Ignore indexing errors"); ABSL_FLAG(bool, delta, false, "Has no effect with --database_only (which can however be directly " "pointed to the delta database filename for the same effect). Expects" " --index_dir to point to an existing database. Stores a delta" " database alongside it only for the translation units in" "`compile_commands.json` (for incremental indexing). IMPORTANT: The " "latter should contain all the translation units dependent on any " "files changed since the original index was built. Source files that " "get indexed are copied to --index_dir (again)"); ABSL_FLAG(std::string, database_only, "", "Do not copy source files, only build the index database at the given" " location (--index_dir is not effective in that case)"); ABSL_FLAG(bool, skip_missing_files, false, "If set to true, missing source files will be skipped with a warning." " If false, the indexer will error out on missing files."); static constexpr char kIndexDbName[] = "db.sqlite"; static constexpr char kDeltaDbName[] = "delta.sqlite"; int main(int argc, char** argv) { using oss_fuzz::indexer::FileCopier; using oss_fuzz::indexer::MergeQueue; using oss_fuzz::indexer::SaveAsSqlite; using clang::tooling::AllTUsToolExecutor; using clang::tooling::CompilationDatabase; #ifdef NO_CHANGE_ROOT_AND_USER // When running inside a container, we cannot drop privileges. InitGoogleExceptChangeRootAndUser(argv[0], &argc, &argv, true); #else InitGoogle(argv[0], &argc, &argv, true); #endif const std::string& source_dir = absl::GetFlag(FLAGS_source_dir); const std::string& build_dir = absl::GetFlag(FLAGS_build_dir); const std::string& index_dir = absl::GetFlag(FLAGS_index_dir); const std::string& database_only = absl::GetFlag(FLAGS_database_only); const std::vector& extra_dirs = absl::GetFlag(FLAGS_extra_dirs); const bool delta = absl::GetFlag(FLAGS_delta); #ifndef NDEBUG LOG(ERROR) << "indexer is built without optimisations. Use 'blaze run -c opt'" << " for indexing larger codebases, or this will be extra slow."; #endif std::string error; auto db = CompilationDatabase::autoDetectFromDirectory(build_dir, error); if (!db) { LOG(ERROR) << "Failed to load compilation database: " << error; return 1; } const std::string& dry_run_regex = absl::GetFlag(FLAGS_dry_run_regex); if (!dry_run_regex.empty()) { clang::tooling::Filter.setValue(dry_run_regex); } std::string index_path = database_only; FileCopier::Behavior behavior = FileCopier::Behavior::kNoOp; if (database_only.empty()) { if (delta) { index_path = std::filesystem::path(index_dir) / kDeltaDbName; behavior = FileCopier::Behavior::kOverwriteExistingFiles; } else { index_path = std::filesystem::path(index_dir) / kIndexDbName; if (std::filesystem::exists(index_path)) { LOG(ERROR) << "Index database '" << index_path << "' already exists. Either specify an empty --index_dir or" "use --delta or --database_only"; return 1; } behavior = FileCopier::Behavior::kFailOnExistingFiles; } } FileCopier file_copier(source_dir, index_dir, extra_dirs, behavior, absl::GetFlag(FLAGS_skip_missing_files)); std::unique_ptr merge_queue = MergeQueue::Create( absl::GetFlag(FLAGS_merge_queues), absl::GetFlag(FLAGS_merge_queue_size)); auto executor = AllTUsToolExecutor(*db, absl::GetFlag(FLAGS_index_threads)); auto index_actions = oss_fuzz::indexer::GetIndexActions(file_copier, *merge_queue); auto index_error = executor.execute(index_actions); if (index_error) { LOG(ERROR) << "Indexing errors:\n" << llvm::toString(std::move(index_error)); if (!absl::GetFlag(FLAGS_ignore_indexing_errors)) { merge_queue->Cancel(); std::error_code ignored_error_code; std::filesystem::remove_all(std::filesystem::path(index_dir), ignored_error_code); return 1; } } merge_queue->WaitUntilComplete(); auto index = merge_queue->TakeIndex(); if (!index) { LOG(ERROR) << "Failed to create index"; std::error_code ignored_error_code; std::filesystem::remove_all(std::filesystem::path(index_dir), ignored_error_code); return 1; } if (!dry_run_regex.empty()) { return 0; } LOG(INFO) << "copying files"; file_copier.CopyIndexedFiles(); LOG(INFO) << "exporting index"; auto flat_index = std::move(*index).Export(); bool saved = SaveAsSqlite(flat_index, index_path, absl::GetFlag(FLAGS_enable_expensive_checks)); return saved ? 0 : 1; } ================================================ FILE: infra/indexer/merge_queue.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/merge_queue.h" #include #include #include #include #include // NOLINT #include #include #include "indexer/index/in_memory_index.h" #include "indexer/queue_state.h" #include "absl/base/thread_annotations.h" #include "absl/log/check.h" #include "absl/synchronization/mutex.h" namespace oss_fuzz { namespace indexer { MergeQueue::~MergeQueue() = default; // Single threaded implementation of the MergeQueue interface, backed by a // ManagedQueue merging into a single owned InMemoryIndex. class SingleThreadMergeQueue : public MergeQueue { public: explicit SingleThreadMergeQueue(int queue_limit = 16); ~SingleThreadMergeQueue() override ABSL_LOCKS_EXCLUDED(queue_mutex_, index_mutex_); void Add(std::unique_ptr index) override ABSL_LOCKS_EXCLUDED(queue_mutex_); void WaitUntilComplete() override; void Cancel() override; std::unique_ptr TakeIndex() override ABSL_LOCKS_EXCLUDED(index_mutex_); private: bool WaitForWriting() ABSL_EXCLUSIVE_LOCKS_REQUIRED(queue_mutex_); bool WaitForReading() ABSL_EXCLUSIVE_LOCKS_REQUIRED(queue_mutex_); void ThreadFunction() ABSL_LOCKS_EXCLUDED(queue_mutex_, index_mutex_); absl::Mutex index_mutex_; std::unique_ptr index_ ABSL_GUARDED_BY(index_mutex_); const int queue_limit_; absl::Mutex queue_mutex_; QueueState state_ ABSL_GUARDED_BY(queue_mutex_); std::queue> queue_ ABSL_GUARDED_BY(queue_mutex_); std::jthread thread_; }; SingleThreadMergeQueue::SingleThreadMergeQueue(int queue_limit) : index_(nullptr), queue_limit_(queue_limit), state_(QueueState::QueueType::kMerge) { thread_ = std::jthread(&SingleThreadMergeQueue::ThreadFunction, this); } SingleThreadMergeQueue::~SingleThreadMergeQueue() { state_.SetDestroyed(); } bool SingleThreadMergeQueue::WaitForWriting() { return state_.IsWaiting() || state_.IsFinished() || queue_.size() < queue_limit_; } bool SingleThreadMergeQueue::WaitForReading() { return state_.IsWaiting() || state_.IsFinished() || !queue_.empty(); } void SingleThreadMergeQueue::ThreadFunction() { while (true) { std::unique_ptr index_to_merge = nullptr; { absl::MutexLock queue_lock(queue_mutex_); queue_mutex_.Await( absl::Condition(this, &SingleThreadMergeQueue::WaitForReading) ); // Either the queue has finished, or the queue is empty and the caller is // waiting for us to finish. if (state_.IsFinished() || queue_.empty()) { return; } index_to_merge = std::move(queue_.front()); queue_.pop(); } // Drop queue_mutex_ if (index_to_merge) { absl::MutexLock index_lock(index_mutex_); if (!index_) { index_ = std::move(index_to_merge); } else { index_->Merge(*index_to_merge); index_to_merge.reset(); } } } } void SingleThreadMergeQueue::Add(std::unique_ptr new_index) { absl::MutexLock queue_lock(queue_mutex_); state_.SetAdded(); queue_mutex_.Await( absl::Condition(this, &SingleThreadMergeQueue::WaitForWriting)); if (!state_.IsFinished()) { queue_.push(std::move(new_index)); } } void SingleThreadMergeQueue::WaitUntilComplete() { { absl::MutexLock queue_lock(queue_mutex_); state_.SetWaiting(); } thread_.join(); { absl::MutexLock queue_lock(queue_mutex_); state_.SetFinished(); } } void SingleThreadMergeQueue::Cancel() { { absl::MutexLock queue_lock(queue_mutex_); state_.SetFinished(/*cancelled=*/true); } thread_.join(); (void)TakeIndex(); } std::unique_ptr SingleThreadMergeQueue::TakeIndex() { { absl::MutexLock queue_lock(queue_mutex_); state_.SetTaken(); } absl::MutexLock index_lock(index_mutex_); return std::move(index_); } // Parallel merge queue implementation which round-robin schedules incoming // merge tasks onto one-of-N internal SingleThreadMergeQueues, and then once // indexing is complete does a parallel merge of those queues to produce a // single result index. class ParallelMergeQueue : public MergeQueue { public: explicit ParallelMergeQueue(int queue_count, int queue_limit = 16); ~ParallelMergeQueue() override; void Add(std::unique_ptr index) override; void WaitUntilComplete() override; void Cancel() override; std::unique_ptr TakeIndex() override; private: QueueState state_; std::atomic next_queue_; std::vector> queues_; }; ParallelMergeQueue::ParallelMergeQueue(int queue_count, int queue_limit) : state_(QueueState::QueueType::kMerge), next_queue_(0) { for (int i = 0; i < queue_count; ++i) { queues_.emplace_back(std::make_unique(queue_limit)); } } ParallelMergeQueue::~ParallelMergeQueue() { state_.SetDestroyed(); } void ParallelMergeQueue::Add(std::unique_ptr index) { state_.SetAdded(); size_t queue_index = next_queue_.fetch_add(1, std::memory_order_relaxed); queues_[queue_index % queues_.size()]->Add(std::move(index)); } void ParallelMergeQueue::WaitUntilComplete() { state_.SetWaiting(); while (queues_.size() > 1) { auto merge_into = std::move(queues_.back()); queues_.pop_back(); auto merge_from = std::move(queues_.back()); queues_.pop_back(); merge_from->WaitUntilComplete(); merge_into->Add(merge_from->TakeIndex()); queues_.push_back(std::move(merge_into)); } CHECK_EQ(queues_.size(), 1); queues_[0]->WaitUntilComplete(); state_.SetFinished(); } void ParallelMergeQueue::Cancel() { state_.SetFinished(/*cancelled=*/true); for (auto& queue : queues_) { queue->Cancel(); } state_.SetTaken(); } std::unique_ptr ParallelMergeQueue::TakeIndex() { state_.SetTaken(); return queues_[0]->TakeIndex(); } // static std::unique_ptr MergeQueue::Create(int queue_count, int queue_length) { if (queue_count == 1) { return std::make_unique(queue_length); } else { return std::make_unique(queue_count, queue_length); } } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/merge_queue.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_MERGE_QUEUE_H_ #define OSS_FUZZ_INFRA_INDEXER_MERGE_QUEUE_H_ #include #include "indexer/index/in_memory_index.h" namespace oss_fuzz { namespace indexer { // Interface for the merging queue. // // The `MergeQueue::Create` class function should be used to create an // appropriate queue instance for the provided parameters. class MergeQueue { public: virtual ~MergeQueue(); // Add implementations are required to be thread-safe, and support being // called from multiple threads in parallel. virtual void Add(std::unique_ptr index) = 0; // WaitUntilComplete should ensure that all currently-queued merge tasks are // complete before returning. It does not provide any guarantee that all // future merge tasks are complete, so it should be ensured that all merge // tasks have been queued (by a call to Add) before this is used. virtual void WaitUntilComplete() = 0; // Cancel should ensure that all currently queued merge tasks are cancelled // or completed before returning. After cancellation, further attempts to add // new merge tasks is considered a bug (and will result in a crash). virtual void Cancel() = 0; // TakeIndex should only be called after WaitUntilComplete has been called. // It takes ownership of the completed merged index. virtual std::unique_ptr TakeIndex() = 0; static std::unique_ptr Create(int queue_count = 1, int queue_length = 16); }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_MERGE_QUEUE_H_ ================================================ FILE: infra/indexer/queue_state.cc ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "indexer/queue_state.h" #include #include #include #include "absl/log/check.h" #include "absl/strings/str_join.h" namespace oss_fuzz { namespace indexer { QueueState::QueueState(QueueType type) : type_(type) {} void QueueState::SetAdded() { Advance(static_cast(kNotAdded | kAdded), kAdded); } void QueueState::SetWaiting() { Advance(static_cast(kNotAdded | kAdded), kWaiting); } void QueueState::SetFinished(bool cancelled) { if (cancelled) { Advance(static_cast(kNotAdded | kAdded | kWaiting), kFinished); } else { Advance(kWaiting, kFinished); } } void QueueState::SetTaken() { CHECK(type_ == QueueType::kMerge); Advance(kFinished, kTaken); } void QueueState::SetDestroyed() { if (type_ == QueueType::kIndex) { Advance(static_cast(kNotAdded | kFinished), kDestroyed); } else { Advance(static_cast(kNotAdded | kTaken), kDestroyed); } } bool QueueState::IsWaiting() const { return state_.load(std::memory_order_acquire) == kWaiting; } bool QueueState::IsFinished() const { return state_.load(std::memory_order_acquire) >= kFinished; } std::string QueueState::StateToString(State state) { std::vector parts; if (state & State::kNotAdded) { parts.push_back("kNotAdded"); } if (state & State::kAdded) { parts.push_back("kAdded"); } if (state & State::kWaiting) { parts.push_back("kWaiting"); } if (state & State::kFinished) { parts.push_back("kFinished"); } if (state & State::kTaken) { parts.push_back("kTaken"); } if (state & State::kDestroyed) { parts.push_back("kDestroyed"); } return absl::StrJoin(parts, "|"); } void QueueState::Advance(State from, State to) { State current = state_.load(std::memory_order_acquire); CHECK_NE((current & from), 0) << "Found " << StateToString(current) << " while advancing " << StateToString(from) << " -> " << StateToString(to); if (current != to) { while (!state_.compare_exchange_weak(current, to, std::memory_order_release, std::memory_order_relaxed)) { CHECK_NE((current & from), 0) << "Found " << StateToString(current) << " while advancing " << StateToString(from) << " -> " << StateToString(to); } } } } // namespace indexer } // namespace oss_fuzz ================================================ FILE: infra/indexer/queue_state.h ================================================ // Copyright 2026 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef OSS_FUZZ_INFRA_INDEXER_QUEUE_STATE_H_ #define OSS_FUZZ_INFRA_INDEXER_QUEUE_STATE_H_ #include #include namespace oss_fuzz { namespace indexer { // Since the IndexQueues and MergeQueues have a non-trivial state space, and run // across multiple threads, we have a small thread-safe state-machine used to // ensure that only valid state transitions are permitted. // // The logic is similar for both queue types, for illustration the allowed // transitions for an IndexQueue are: // // kNotAdded -> kAdded on queue->Add() // -> kWaiting on queue->WaitUntilComplete() entry // -> kDestroyed on ~queue // // kAdded -> kWaiting on queue->WaitUntilComplete() entry // // kWaiting -> kFinished on queue->WaitUntilComplete() exit // // kFinished -> kDestroyed on ~queue // // And for a MergeQueue: // // kNotAdded -> kAdded on queue->Add() // -> kWaiting on queue->WaitUntilComplete() entry // -> kDestroyed on ~queue // // kAdded -> kWaiting on queue->WaitUntilComplete() entry // // kWaiting -> kFinished on queue->WaitUntilComplete() exit // // kFinished -> kTaken on queue->TakeIndex() // // kTaken -> kDestroyed on ~queue // // Attempting any other transitions will result in a CHECK failure. class QueueState { public: enum class QueueType { kIndex, kMerge }; explicit QueueState(QueueType type); void SetAdded(); void SetWaiting(); void SetFinished(bool cancelled = false); void SetTaken(); void SetDestroyed(); bool IsWaiting() const; bool IsFinished() const; private: enum State { kNotAdded = 1, kAdded = 1 << 1, kWaiting = 1 << 2, // Note that ordering is important here, and all states following kFinished // are considered "finished". kFinished = 1 << 3, kTaken = 1 << 4, kDestroyed = 1 << 5, }; std::string StateToString(State state); void Advance(State from, State to); const QueueType type_; std::atomic state_ = kNotAdded; }; } // namespace indexer } // namespace oss_fuzz #endif // OSS_FUZZ_INFRA_INDEXER_QUEUE_STATE_H_ ================================================ FILE: infra/indexer/ubuntu-20-04.Dockerfile ================================================ FROM gcr.io/oss-fuzz-base/base-clang-full:ubuntu-20-04 RUN mkdir /indexer WORKDIR /indexer COPY . /indexer RUN apt-get update && apt-get install -y libsqlite3-dev make zlib1g-dev RUN mkdir build && cd build && cmake .. && cmake --build . -j -v ================================================ FILE: infra/indexer/ubuntu-24-04.Dockerfile ================================================ FROM gcr.io/oss-fuzz-base/base-clang-full:ubuntu-24-04 RUN mkdir /indexer WORKDIR /indexer COPY . /indexer RUN apt-get update && apt-get install -y libsqlite3-dev make zlib1g-dev RUN mkdir build && cd build && cmake .. && cmake --build . -j -v ================================================ FILE: infra/manifest.py ================================================ #! /usr/bin/env python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for pushing manifest files to docker that point to AMD64 and ARM images.""" import logging import subprocess import sys def push_manifest(image): """Pushes a manifest file in place of |image| for ARM and AMD64 versions of that image.""" subprocess.run(['docker', 'pull', image], check=True) amd64_image = f'{image}:manifest-amd64' subprocess.run(['docker', 'tag', image, amd64_image], check=True) subprocess.run(['docker', 'push', amd64_image], check=True) arm_version = f'{image}-testing-arm' subprocess.run(['docker', 'pull', arm_version], check=True) arm64_image = f'{image}:manifest-arm64v8' subprocess.run(['docker', 'tag', arm_version, arm64_image], check=True) subprocess.run([ 'docker', 'manifest', 'create', image, '--amend', arm64_image, '--amend', amd64_image ], check=True) subprocess.run(['docker', 'manifest', 'push', image], check=True) return True def main(): """Sets up manifests for base-builder and base-runner so they can be used for ARM builds.""" logging.info('Doing simple gcloud command to ensure 2FA passes. ' 'Otherwise docker push fails.') subprocess.run(['gcloud', 'projects', 'list', '--limit=1'], check=True) images = [ 'gcr.io/oss-fuzz-base/base-builder', 'gcr.io/oss-fuzz-base/base-runner' ] results = [push_manifest(image) for image in images] return 0 if all(results) else 1 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/pr_helper.py ================================================ #!/usr/bin/env python # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Adds comments for PR to provide more information for approvers.""" import base64 import json import os import subprocess import requests import yaml OWNER = 'google' REPO = 'oss-fuzz' GITHUB_URL = 'https://github.com/' GITHUB_NONREF_URL = f'https://www.github.com/{OWNER}/{REPO}' # Github URL that doesn't send emails on linked issues. API_URL = 'https://api.github.com' BASE_URL = f'{API_URL}/repos/{OWNER}/{REPO}' BRANCH = 'master' CRITICALITY_SCORE_PATH = '/home/runner/go/bin/criticality_score' COMMITS_LIMIT = 50 # Only process the most recent 50 commits. def get_criticality_score(repo_url): """Gets the criticality score of the project.""" # Criticality score does not support repo url ends with '.git' if repo_url.endswith('.git'): repo_url = repo_url[:-4] report = subprocess.run([ CRITICALITY_SCORE_PATH, '--format', 'json', '-gcp-project-id=clusterfuzz-external', '-depsdev-disable', repo_url ], capture_output=True, text=True) try: report_dict = json.loads(report.stdout) except: print(f'Criticality score failed with stdout: {report.stdout}') print(f'Criticality score failed with stderr: {report.stderr}') return 'N/A' return report_dict.get('default_score', 'N/A') def is_known_contributor(content, email): """Checks if the author is in the contact list.""" return (email == content.get('primary_contact') or email in content.get('vendor_ccs', []) or email in content.get('auto_ccs', [])) def save_env(message, is_ready_for_merge, is_internal=False): """Saves the outputs as environment variables.""" with open(os.environ['GITHUB_ENV'], 'a') as github_env: github_env.write(f'MESSAGE={message}\n') github_env.write(f'IS_READY_FOR_MERGE={is_ready_for_merge}\n') github_env.write(f'IS_INTERNAL={is_internal}') def main(): """Verifies if a PR is ready to merge.""" github = GithubHandler() # Bypasses PRs of the internal members. if github.is_author_internal_member(): save_env(None, None, True) return message = '' is_ready_for_merge = True pr_author = github.get_pr_author() # Gets all modified projects path. projects_path = github.get_projects_path() verified, email = github.get_author_email() for project_path in projects_path: project_url = f'{GITHUB_URL}/{OWNER}/{REPO}/tree/{BRANCH}/{project_path}' content_dict = github.get_project_yaml(project_path) # Gets information for the new integrating project. if not content_dict: is_ready_for_merge = False new_project = github.get_integrated_project_info() repo_url = new_project.get('main_repo') if repo_url is None: message += (f'{pr_author} is integrating a new project, ' 'but the `main_repo` is missing. ' 'The criticality score cannot be computed.
') else: message += (f'{pr_author} is integrating a new project:
' f'- Main repo: {repo_url}
- Criticality score: ' f'{get_criticality_score(repo_url)}
') continue # Checks if the author is in the contact list. if email: if is_known_contributor(content_dict, email): # Checks if the email is verified. verified_marker = ' (verified)' if verified else '' message += ( f'{pr_author}{verified_marker} is either the primary contact or ' f'is in the CCs list of [{project_path}]({project_url}).
') if verified: continue # Checks the previous commits. commit_sha = github.has_author_modified_project(project_path) if commit_sha is None: history_message = '' contributors = github.get_past_contributors(project_path) if contributors: history_message = 'The past contributors are: ' history_message += ', '.join(contributors) message += ( f'{pr_author} is a new contributor to ' f'[{project_path}]({project_url}). The PR must be approved by known ' f'contributors before it can be merged. {history_message}
') is_ready_for_merge = False continue # If the previous commit is not associated with a pull request. pr_message = (f'{pr_author} has previously contributed to ' f'[{project_path}]({project_url}). The previous commit was ' f'{GITHUB_NONREF_URL}/commit/{commit_sha}
') previous_pr_number = github.get_pull_request_number(commit_sha) if previous_pr_number is not None: pr_message = (f'{pr_author} has previously contributed to ' f'[{project_path}]({project_url}). ' f'The previous PR was [#{previous_pr_number}]' f'({GITHUB_NONREF_URL}/pull/{previous_pr_number})
') message += pr_message save_env(message, is_ready_for_merge, False) class GithubHandler: """Github requests handler.""" def __init__(self): self._pr_author = os.environ['PRAUTHOR'] self._token = os.environ['GITHUBTOKEN'] self._pr_number = os.environ['PRNUMBER'] self._headers = { 'Authorization': f'Bearer {self._token}', 'X-GitHub-Api-Version': '2022-11-28' } self._maintainers = set() os.environ['GITHUB_AUTH_TOKEN'] = self._token def get_pr_author(self): """Gets the pr author user name.""" return self._pr_author def get_projects_path(self): """Gets the current project path.""" response = requests.get(f'{BASE_URL}/pulls/{self._pr_number}/files', headers=self._headers) if not response.ok: return [] projects_path = set() for file in response.json(): file_path = file['filename'] dir_path = file_path.split(os.sep) if len(dir_path) > 1 and dir_path[0] == 'projects': projects_path.add(os.sep.join(dir_path[0:2])) return list(projects_path) def get_author_email(self): """Retrieves the author's email address for a pull request, including non-public emails.""" user_response = requests.get(f'{API_URL}/users/{self._pr_author}') if user_response.ok: email = user_response.json()['email'] if email: return True, email commits_response = requests.get( f'{BASE_URL}/pulls/{self._pr_number}/commits', headers=self._headers) if not commits_response.ok: return False, None email = commits_response.json()[0]['commit']['author']['email'] verified = commits_response.json()[0]['commit']['verification']['verified'] return verified, email def get_project_yaml(self, project_path): """Gets the project yaml file.""" contents_url = f'{BASE_URL}/contents/{project_path}/project.yaml' return self.get_yaml_file_content(contents_url) def get_yaml_file_content(self, contents_url): """Gets yaml file content.""" response = requests.get(contents_url, headers=self._headers) if not response.ok: return {} content = base64.b64decode(response.json()['content']).decode('UTF-8') return yaml.safe_load(content) def get_integrated_project_info(self): """Gets the new integrated project.""" response = requests.get(f'{BASE_URL}/pulls/{self._pr_number}/files', headers=self._headers) for file in response.json(): file_path = file['filename'] if 'project.yaml' in file_path: return self.get_yaml_file_content(file['contents_url']) return {} def get_pull_request_number(self, commit): """Gets the pull request number.""" pr_response = requests.get(f'{BASE_URL}/commits/{commit}/pulls', headers=self._headers) if not pr_response.ok: return None return pr_response.json()[0]['number'] def get_past_contributors(self, project_path): """Returns a list of past contributors of a certain project.""" commits_response = requests.get(f'{BASE_URL}/commits?path={project_path}', headers=self._headers) if not commits_response.ok: return [] commits = commits_response.json() contributors: dict[str, bool] = {} for i, commit in enumerate(commits): if i >= COMMITS_LIMIT: break if not commit['author'] or not commit['commit']: continue login = commit['author']['login'] verified = commit['commit']['verification']['verified'] if login in self._maintainers: continue if login not in contributors: contributors[login] = verified if verified: # Override previous verification bit. contributors[login] = True all_contributors = [] for login, verified in contributors.items(): login_verify = login if verified else f'{login} (unverified)' all_contributors.append(login_verify) return all_contributors def get_maintainers(self): """Get a list of internal members.""" if self._maintainers: return self._maintainers response = requests.get(f'{BASE_URL}/contents/infra/MAINTAINERS.csv', headers=self._headers) if not response.ok: return self._maintainers maintainers_file = base64.b64decode( response.json()['content']).decode('UTF-8') for line in maintainers_file.split(os.linesep): self._maintainers.add(line.split(',')[2]) return self._maintainers def is_author_internal_member(self): """Returns if the author is an internal member.""" return self._pr_author in self.get_maintainers() def has_author_modified_project(self, project_path): """Checks if the author has modified this project before.""" commits_response = requests.get( f'{BASE_URL}/commits?path={project_path}&author={self._pr_author}', headers=self._headers) if not commits_response.ok or not commits_response.json(): return None commit = commits_response.json()[0] return commit['sha'] if __name__ == '__main__': main() ================================================ FILE: infra/presubmit.py ================================================ #!/usr/bin/env python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Checks code for common issues before submitting.""" import argparse import os import re import subprocess import sys import unittest import yaml import constants _SRC_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) VALID_PROJECT_REGEX_STR = '^[a-z0-9_-]+$' VALID_PROJECT_REGEX = re.compile(VALID_PROJECT_REGEX_STR) def _is_project_file(actual_path, expected_filename): """Returns True if actual_path's name is |expected_filename| and is a file that exists and is in in projects/.""" if os.path.basename(actual_path) != expected_filename: return False if os.path.basename(os.path.dirname( os.path.dirname(actual_path))) != 'projects': return False return os.path.exists(actual_path) # TODO: Check for -fsanitize=fuzzer in files as well. def _check_one_lib_fuzzing_engine(build_sh_file): """Returns False if |build_sh_file| contains -lFuzzingEngine. This is deprecated behavior. $LIB_FUZZING_ENGINE should be used instead so that -fsanitize=fuzzer is used.""" if not _is_project_file(build_sh_file, 'build.sh'): return True with open(build_sh_file) as build_sh: build_sh_lines = build_sh.readlines() for line_num, line in enumerate(build_sh_lines): uncommented_code = line.split('#')[0] if '-lFuzzingEngine' in uncommented_code: print('Error: build.sh contains deprecated "-lFuzzingEngine" on line: ' f'{line_num}. Please use "$LIB_FUZZING_ENGINE" instead.') return False return True def check_lib_fuzzing_engine(paths): """Calls _check_one_lib_fuzzing_engine on each path in |paths|. Returns True if the result of every call is True.""" return all(_check_one_lib_fuzzing_engine(path) for path in paths) class ProjectYamlChecker: """Checks for a project.yaml file.""" # Sections in a project.yaml and the constant values that they are allowed # to have. SECTIONS_AND_CONSTANTS = { 'sanitizers': constants.SANITIZERS, 'architectures': constants.ARCHITECTURES, 'fuzzing_engines': constants.ENGINES, } # Note: this list must be updated when we allow new sections. VALID_SECTION_NAMES = [ 'architectures', 'auto_ccs', 'blackbox', 'builds_per_day', 'coverage_extra_args', 'disabled', 'disable_remediation', 'fuzzing_engines', 'help_url', 'homepage', 'language', 'labels', # For internal use only, hard to lint as it uses fuzzer names. 'main_repo', 'primary_contact', 'run_tests', 'sanitizers', 'selective_unpack', 'vendor_ccs', 'view_restrictions', 'file_github_issue', 'indexer', # Flags specific to infra/indexer. 'base_os_version', ] REQUIRED_SECTIONS = ['main_repo'] def __init__(self, filename): self.filename = filename with open(filename) as file_handle: self.data = yaml.safe_load(file_handle) self.success = True def do_checks(self): """Does all project.yaml checks. Returns True if they pass.""" if self.is_disabled(): return True checks = [ self.check_project_yaml_constants, self.check_required_sections, self.check_valid_section_names, self.check_valid_emails, self.check_valid_language, self.check_valid_project_name, ] for check_function in checks: check_function() return self.success def is_disabled(self): """Returns True if this project is disabled.""" return self.data.get('disabled', False) def error(self, message): """Prints an error message and sets self.success to False.""" self.success = False print(f'Error in {self.filename}: {message}') def check_valid_project_name(self): """Checks that the project has a valid name.""" banned_names = ['google', 'g00gle'] project_name = os.path.basename(os.path.dirname(self.filename)) for banned_name in banned_names: if banned_name in project_name: self.error('Projects can\'t have \'google\' in the name.') if not VALID_PROJECT_REGEX.match(project_name): self.error(f'Projects must conform to regex {VALID_PROJECT_REGEX_STR}') def check_project_yaml_constants(self): """Returns True if certain sections only have certain constant values.""" for section, allowed_constants in self.SECTIONS_AND_CONSTANTS.items(): if section not in self.data: continue actual_constants = self.data[section] allowed_constants_str = ', '.join(allowed_constants) for constant in actual_constants: if isinstance(constant, str): if constant not in allowed_constants: self.error(f'{constant} (in {section} section) is not a valid ' f'constant ({allowed_constants_str}).') elif isinstance(constant, dict): # The only alternative value allowed is the experimental flag, i.e. # `constant == {'memory': {'experimental': True}}`. Do not check the # experimental flag, but assert that the sanitizer is a valid one. if (len(constant.keys()) > 1 or list(constant.keys())[0] not in allowed_constants): self.error(f'Not allowed value in the project.yaml: {constant}') else: self.error(f'Not allowed value in the project.yaml: {constant}') def check_valid_section_names(self): """Returns True if all section names are valid.""" for name in self.data: if name not in self.VALID_SECTION_NAMES: self.error( f'{name} is not a valid section name ({self.VALID_SECTION_NAMES})') def check_required_sections(self): """Returns True if all required sections are in |self.data|.""" for section in self.REQUIRED_SECTIONS: if section not in self.data: self.error(f'{section} section is missing.') def check_valid_emails(self): """Returns True if emails are valid looking..""" # Get email addresses. email_addresses = [] primary_contact = self.data.get('primary_contact') if primary_contact: email_addresses.append(primary_contact) auto_ccs = self.data.get('auto_ccs') if auto_ccs: email_addresses.extend(auto_ccs) # Check that email addresses seem normal. for email_address in email_addresses: if '@' not in email_address or '.' not in email_address: self.error(f'{email_address} is an invalid email address.') def check_valid_language(self): """Returns True if the language is specified and valid.""" language = self.data.get('language') if not language: self.error('Missing "language" attribute in project.yaml.') elif language not in constants.LANGUAGES: self.error( f'"language: {language}" is not supported ({constants.LANGUAGES}).') def _check_one_project_yaml(project_yaml_filename): """Does checks on the project.yaml file. Returns True on success.""" if _is_project_file(project_yaml_filename, 'project.yml'): print(project_yaml_filename, 'must be named project.yaml.') return False if not _is_project_file(project_yaml_filename, 'project.yaml'): return True checker = ProjectYamlChecker(project_yaml_filename) return checker.do_checks() def check_project_yaml(paths): """Calls _check_one_project_yaml on each path in |paths|. Returns True if the result of every call is True.""" return all([_check_one_project_yaml(path) for path in paths]) def _check_one_seed_corpus(path): """Returns False and prints error if |path| is a seed corpus.""" if os.path.basename(os.path.dirname(os.path.dirname(path))) != 'projects': return True if os.path.splitext(path)[1] == '.zip': print('Don\'t commit seed corpora into the ClusterFuzz repo,' 'they bloat it forever.') return False return True def check_seed_corpus(paths): """Calls _check_one_seed_corpus on each path in |paths|. Returns True if the result of every call is True.""" return all([_check_one_seed_corpus(path) for path in paths]) def _check_one_apt_update(path): """Checks that a Dockerfile uses apt-update before apt-install""" if os.path.basename(os.path.dirname(os.path.dirname(path))) != 'projects': return True if os.path.basename(path) != 'Dockerfile': return True with open(path, 'r') as file: dockerfile = file.read() if 'RUN apt install' in dockerfile or 'RUN apt-get install' in dockerfile: print('Please add an "apt-get update" before "apt-get install". ' 'Otherwise, a cached and outdated RUN layer may lead to install ' 'failures in file %s.' % str(path)) return False return True def check_apt_update(paths): """Checks that all Dockerfile use apt-update before apt-install""" return all([_check_one_apt_update(path) for path in paths]) def do_checks(changed_files): """Runs all presubmit checks. Returns False if any fails.""" checks = [ check_license, yapf, check_project_yaml, check_lib_fuzzing_engine, check_seed_corpus, check_apt_update, ] # Use a list comprehension here and in other cases where we use all() so that # we don't quit early on failure. This is more user-friendly since the more # errors we spit out at once, the less frequently the less check-fix-check # cycles they need to do. return all([check(changed_files) for check in checks]) _CHECK_LICENSE_FILENAMES = ['Dockerfile'] _CHECK_LICENSE_EXTENSIONS = [ '.bash', '.c', '.cc', '.cpp', '.css', '.Dockerfile', '.go', '.h', '.htm', '.html', '.java', '.js', '.proto', '.py', '.rs', '.sh', '.ts', ] THIRD_PARTY_DIR_NAME = 'third_party' _LICENSE_STRING = 'http://www.apache.org/licenses/LICENSE-2.0' def check_license(paths): """Validates license header.""" if not paths: return True success = True for path in paths: path_parts = str(path).split(os.sep) if any(path_part == THIRD_PARTY_DIR_NAME for path_part in path_parts): continue filename = os.path.basename(path) extension = os.path.splitext(path)[1] if (filename not in _CHECK_LICENSE_FILENAMES and extension not in _CHECK_LICENSE_EXTENSIONS): continue with open(path) as file_handle: if _LICENSE_STRING not in file_handle.read(): print('Missing license header in file %s.' % str(path)) success = False return success def bool_to_returncode(success): """Returns 0 if |success|. Otherwise returns 1.""" if success: print('Success.') return 0 print('Failed.') return 1 def is_nonfuzzer_python(path): """Returns True if |path| ends in .py.""" return os.path.splitext(path)[1] == '.py' and '/projects/' not in path def lint(_=None): """Runs python's linter on infra. Returns False if it fails linting.""" # Use --score no to make linting quieter. command = ['python3', '-m', 'pylint', '--score', 'no', '-j', '0', 'infra'] returncode = subprocess.run(command, check=False).returncode return returncode == 0 def yapf(paths, validate=True): """Does yapf on |path| if it is Python file. Only validates format if |validate|. Otherwise, formats the file. Returns False if validation or formatting fails.""" paths = [path for path in paths if is_nonfuzzer_python(path)] if not paths: return True validate_argument = '-d' if validate else '-i' command = ['yapf', validate_argument, '-p'] command.extend(paths) returncode = subprocess.run(command, check=False).returncode return returncode == 0 def get_changed_files(): """Returns a list of absolute paths of files changed in this git branch.""" branch_commit_hash = subprocess.check_output( ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode() diff_commands = [ # Return list of modified files in the commits on this branch. ['git', 'diff', '--name-only', branch_commit_hash + '..'], # Return list of modified files from uncommitted changes. ['git', 'diff', '--name-only'] ] changed_files = set() for command in diff_commands: file_paths = subprocess.check_output(command).decode().splitlines() for file_path in file_paths: if not os.path.isfile(file_path): continue changed_files.add(file_path) print(f'Changed files: {" ".join(changed_files)}') return [os.path.abspath(f) for f in changed_files] def run_build_tests(): """Runs build tests because they can't be run in parallel.""" suite_list = [ unittest.TestLoader().discover(os.path.join(_SRC_ROOT, 'infra', 'build'), pattern='*_test.py'), ] suite = unittest.TestSuite(suite_list) print('Running build tests.') result = unittest.TextTestRunner().run(suite) return not result.failures and not result.errors def run_nonbuild_tests(parallel): """Runs all tests but build tests. Does them in parallel if |parallel|. The reason why we exclude build tests is because they use an emulator that prevents them from being used in parallel.""" # We look for all project directories because otherwise pytest won't run tests # that are not in valid modules (e.g. "base-images"). relevant_dirs = set() all_files = get_all_files() for file_path in all_files: directory = os.path.dirname(file_path) relevant_dirs.add(directory) # Use ignore-glob because ignore doesn't seem to work properly with the way we # pass directories to pytest. command = [ 'pytest', '--ignore-glob=infra/base-images/base-builder/indexer/*', '--ignore-glob=infra/build/*', '--ignore-glob=projects/*', '--ignore-glob=infra/experimental/contrib/*', '--ignore-glob=infra/experimental/chronos/*', '--ignore-glob=infra/experimental/mcp/*', ] if parallel: command.extend(['-n', 'auto']) command += list(relevant_dirs) print('Running non-build tests.') # TODO(metzman): Get rid of this once config_utils stops using it. env = os.environ.copy() env['CIFUZZ_TEST'] = '1' return subprocess.run(command, check=False, env=env).returncode == 0 def run_tests(_=None, parallel=False, build_tests=True, nonbuild_tests=True): """Runs all unit tests.""" build_success = True nonbuild_success = True if nonbuild_tests: nonbuild_success = run_nonbuild_tests(parallel) else: print('Skipping nonbuild tests as specified.') if build_tests: build_success = run_build_tests() else: print('Skipping build tests as specified.') return nonbuild_success and build_success def run_systemsan_tests(_=None): """Runs SystemSan unit tests.""" command = ['make', 'test'] return subprocess.run(command, cwd='infra/experimental/SystemSan', check=False).returncode == 0 def get_all_files(): """Returns a list of absolute paths of files in this repo.""" get_all_files_command = ['git', 'ls-files'] output = subprocess.check_output(get_all_files_command).decode().splitlines() return [os.path.abspath(path) for path in output if os.path.isfile(path)] def main(): """Check changes on a branch for common issues before submitting.""" # Get program arguments. parser = argparse.ArgumentParser(description='Presubmit script for oss-fuzz.') parser.add_argument( 'command', choices=['format', 'lint', 'license', 'infra-tests', 'systemsan-tests'], nargs='?') parser.add_argument('-a', '--all-files', action='store_true', help='Run presubmit check(s) on all files', default=False) parser.add_argument('-p', '--parallel', action='store_true', help='Run tests in parallel.', default=False) parser.add_argument('-s', '--skip-build-tests', action='store_true', help='Skip build tests which are slow and must run ' 'sequentially.', default=False) parser.add_argument('-n', '--skip-nonbuild-tests', action='store_true', help='Only do build tests.', default=False) args = parser.parse_args() if args.all_files: relevant_files = get_all_files() else: relevant_files = get_changed_files() os.chdir(_SRC_ROOT) # Do one specific check if the user asked for it. if args.command == 'format': success = yapf(relevant_files, False) return bool_to_returncode(success) if args.command == 'lint': success = lint() return bool_to_returncode(success) if args.command == 'license': success = check_license(relevant_files) return bool_to_returncode(success) if args.command == 'infra-tests': success = run_tests(relevant_files, parallel=args.parallel, build_tests=(not args.skip_build_tests), nonbuild_tests=(not args.skip_nonbuild_tests)) return bool_to_returncode(success) if args.command == 'systemsan-tests': success = run_systemsan_tests(relevant_files) return bool_to_returncode(success) # Do all the checks (but no tests). success = do_checks(relevant_files) return bool_to_returncode(success) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/pytest.ini ================================================ [pytest] python_files = *_test.py log_cli = true ================================================ FILE: infra/repo_manager.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Class to manage a git repository via python. This class is to be used to implement git commands over a python API and manage the current state of the git repo. Typical usage example: r_man = RepoManager('https://github.com/google/oss-fuzz.git') r_man.checkout('5668cc422c2c92d38a370545d3591039fb5bb8d4') """ import datetime import logging import os import shutil import urllib.parse import utils class RepoManager: """Repo manager.""" def __init__(self, repo_dir): self.repo_dir = repo_dir def _is_git_repo(self): """Test if the current repo dir is a git repo or not. Returns: True if the current repo_dir is a valid git repo. """ git_path = os.path.join(self.repo_dir, '.git') return os.path.isdir(git_path) def git(self, cmd, check_result=False): """Run a git command. Args: command: The git command as a list to be run. check_result: Should an exception be thrown on failed command. Returns: stdout, stderr, error code. """ return utils.execute(['git'] + cmd, location=self.repo_dir, check_result=check_result) def commit_exists(self, commit): """Checks to see if a commit exists in the project repo. Args: commit: The commit SHA you are checking. Returns: True if the commit exits in the project. """ if not commit.rstrip(): return False _, _, err_code = self.git(['cat-file', '-e', commit]) return not err_code def commit_date(self, commit): """Get the date of a commit. Args: commit: The commit hash. Returns: A datetime representing the date of the commit. """ out, _, _ = self.git(['show', '-s', '--format=%ct', commit], check_result=True) return datetime.datetime.fromtimestamp(int(out), tz=datetime.timezone.utc) def get_git_diff(self, base='origin...'): """Gets a list of files that have changed from the repo head. Returns: A list of changed file paths or None on Error. """ self.fetch_unshallow() # Add '--' so that git knows we aren't talking about files. command = ['diff', '--name-only', base, '--'] out, err_msg, err_code = self.git(command) if err_code: logging.error('Git diff failed with error message %s.', err_msg) return None if not out: logging.error('No diff was found.') return None return [line for line in out.splitlines() if line] def get_current_commit(self): """Gets the current commit SHA of the repo. Returns: The current active commit SHA. """ out, _, _ = self.git(['rev-parse', 'HEAD'], check_result=True) return out.strip() def get_parent(self, commit, count): """Gets the count'th parent of the given commit. Returns: The parent commit SHA. """ self.fetch_unshallow() out, _, err_code = self.git(['rev-parse', commit + '~' + str(count)], check_result=False) if err_code: return None return out.strip() def fetch_all_remotes(self): """Fetch all remotes for checkouts that track a single branch.""" self.git([ 'config', 'remote.origin.fetch', '+refs/heads/*:refs/remotes/origin/*' ], check_result=True) self.git(['remote', 'update'], check_result=True) def get_commit_list(self, newest_commit, oldest_commit=None, limit=None): """Gets the list of commits(inclusive) between the old and new commits. Args: newest_commit: The newest commit to be in the list. oldest_commit: The (optional) oldest commit to be in the list. Returns: The list of commit SHAs from newest to oldest. Raises: ValueError: When either the oldest or newest commit does not exist. RuntimeError: When there is an error getting the commit list. """ self.fetch_unshallow() if oldest_commit and not self.commit_exists(oldest_commit): raise ValueError('The oldest commit %s does not exist' % oldest_commit) if not self.commit_exists(newest_commit): raise ValueError('The newest commit %s does not exist' % newest_commit) if oldest_commit == newest_commit: return [oldest_commit] if oldest_commit: commit_range = oldest_commit + '..' + newest_commit else: commit_range = newest_commit limit_args = [] if limit: limit_args.append(f'--max-count={limit}') out, _, err_code = self.git(['rev-list', commit_range] + limit_args) commits = out.split('\n') commits = [commit for commit in commits if commit] if err_code or not commits: raise RuntimeError('Error getting commit list between %s and %s ' % (oldest_commit, newest_commit)) # Make sure result is inclusive if oldest_commit: commits.append(oldest_commit) return commits def fetch_branch(self, branch): """Fetches a remote branch from origin.""" return self.git( ['fetch', 'origin', '{branch}:{branch}'.format(branch=branch)]) def fetch_unshallow(self): """Gets the current git repository history.""" shallow_file = os.path.join(self.repo_dir, '.git', 'shallow') if os.path.exists(shallow_file): _, err, err_code = self.git(['fetch', '--unshallow'], check_result=False) if err_code: logging.error('Unshallow returned non-zero code: %s', err) def checkout_pr(self, pr_ref): """Checks out a remote pull request. Args: pr_ref: The pull request reference to be checked out. """ self.fetch_unshallow() self.git(['fetch', 'origin', pr_ref], check_result=True) self.git(['checkout', '-f', 'FETCH_HEAD'], check_result=True) self.git(['submodule', 'update', '-f', '--init', '--recursive'], check_result=True) def checkout_commit(self, commit, clean=True): """Checks out a specific commit from the repo. Args: commit: The commit SHA to be checked out. Raises: RuntimeError: when checkout is not successful. ValueError: when commit does not exist. """ self.fetch_unshallow() if not self.commit_exists(commit): raise ValueError('Commit %s does not exist in current branch' % commit) self.git(['checkout', '-f', commit], check_result=True) self.git(['submodule', 'update', '-f', '--init', '--recursive'], check_result=True) if clean: self.git(['clean', '-fxd'], check_result=True) if self.get_current_commit() != commit: raise RuntimeError('Error checking out commit %s' % commit) def remove_repo(self): """Removes the git repo from disk.""" if os.path.isdir(self.repo_dir): shutil.rmtree(self.repo_dir) def clone_repo_and_get_manager(repo_url, base_dir, repo_name=None, username=None, password=None): """Clones a repo and constructs a repo manager class. Args: repo_url: The github url needed to clone. base_dir: The full file-path where the git repo is located. repo_name: The name of the directory the repo is cloned to. """ if repo_name is None: repo_name = os.path.basename(repo_url).replace('.git', '') repo_dir = os.path.join(base_dir, repo_name) manager = RepoManager(repo_dir) if not os.path.exists(repo_dir): _clone(repo_url, base_dir, repo_name, username=username, password=password) return manager def _clone(repo_url, base_dir, repo_name, username=None, password=None): """Creates a clone of the repo in the specified directory. Raises: ValueError: when the repo is not able to be cloned. """ if username and password: parsed_url = urllib.parse.urlparse(repo_url) new_netloc = f'{username}:{password}@{parsed_url.netloc}' repo_url = urllib.parse.urlunparse(parsed_url._replace(netloc=new_netloc)) utils.execute(['git', 'clone', repo_url, repo_name], location=base_dir, check_result=True, log_command=not password) ================================================ FILE: infra/repo_manager_test.py ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Test the functionality of the RepoManager class.""" import contextlib import os import tempfile import unittest from unittest import mock import repo_manager import utils # pylint: disable=protected-access OSS_FUZZ_REPO_URL = 'https://github.com/google/oss-fuzz' @contextlib.contextmanager def get_oss_fuzz_repo(): """Clones a temporary copy of the OSS-Fuzz repo. Returns the path to the repo.""" repo_name = 'oss-fuzz' with tempfile.TemporaryDirectory() as tmp_dir: repo_manager._clone(OSS_FUZZ_REPO_URL, tmp_dir, repo_name) yield os.path.join(tmp_dir, repo_name) class CloneTest(unittest.TestCase): """Tests the _clone function.""" @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') def test_clone_valid_repo_integration(self): """Integration test that tests the correct location of the git repo.""" with get_oss_fuzz_repo() as oss_fuzz_repo: git_path = os.path.join(oss_fuzz_repo, '.git') self.assertTrue(os.path.isdir(git_path)) def test_clone_invalid_repo(self): """Tests that cloning an invalid repo will fail.""" with tempfile.TemporaryDirectory() as tmp_dir: with self.assertRaises(RuntimeError): repo_manager._clone('https://github.com/oss-fuzz-not-real.git', tmp_dir, 'oss-fuzz') @mock.patch('utils.execute') def test_clone_with_username(self, mock_execute): # pylint: disable=no-self-use """Test clone with username.""" repo_manager._clone('https://github.com/fake/repo.git', '/', 'name', username='user', password='password') mock_execute.assert_called_once_with([ 'git', 'clone', 'https://user:password@github.com/fake/repo.git', 'name' ], location='/', check_result=True, log_command=False) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class RepoManagerCheckoutTest(unittest.TestCase): """Tests the checkout functionality of RepoManager.""" def test_checkout_valid_commit(self): """Tests that the git checkout command works.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) commit_to_test = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b' repo_man.checkout_commit(commit_to_test) self.assertEqual(commit_to_test, repo_man.get_current_commit()) def test_checkout_invalid_commit(self): """Tests that the git checkout invalid commit fails.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) with self.assertRaises(ValueError): repo_man.checkout_commit(' ') with self.assertRaises(ValueError): repo_man.checkout_commit('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') with self.assertRaises(ValueError): repo_man.checkout_commit('not-a-valid-commit') @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class RepoManagerGetCommitListTest(unittest.TestCase): """Tests the get_commit_list method of RepoManager.""" def test_get_valid_commit_list(self): """Tests an accurate commit list can be retrieved from the repo manager.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) old_commit = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b' new_commit = 'fa662173bfeb3ba08d2e84cefc363be11e6c8463' commit_list = [ 'fa662173bfeb3ba08d2e84cefc363be11e6c8463', '17035317a44fa89d22fe6846d868d4bf57def78b', '97dee00a3c4ce95071c3e061592f5fd577dea886', '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b' ] result_list = repo_man.get_commit_list(new_commit, old_commit) self.assertListEqual(commit_list, result_list) def test_get_invalid_commit_list(self): """Tests that the proper errors are thrown when invalid commits are passed to get_commit_list.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) old_commit = '04ea24ee15bbe46a19e5da6c5f022a2ffdfbdb3b' new_commit = 'fa662173bfeb3ba08d2e84cefc363be11e6c8463' with self.assertRaises(ValueError): repo_man.get_commit_list('fakecommit', new_commit) with self.assertRaises(ValueError): repo_man.get_commit_list(new_commit, 'fakecommit') with self.assertRaises(RuntimeError): repo_man.get_commit_list(old_commit, new_commit) # pylint: disable=arguments-out-of-order @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class GitDiffTest(unittest.TestCase): """Tests get_git_diff.""" def test_diff_exists(self): """Tests that a real diff is returned when a valid repo manager exists.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) with mock.patch.object(utils, 'execute', return_value=('test.py\ndiff.py', None, 0)): diff = repo_man.get_git_diff() self.assertCountEqual(diff, ['test.py', 'diff.py']) def test_diff_empty(self): """Tests that None is returned when there is no difference between repos.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) with mock.patch.object(utils, 'execute', return_value=('', None, 0)): diff = repo_man.get_git_diff() self.assertIsNone(diff) def test_error_on_command(self): """Tests that None is returned when the command errors out.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) with mock.patch.object(utils, 'execute', return_value=('', 'Test error.', 1)): diff = repo_man.get_git_diff() self.assertIsNone(diff) def test_diff_no_change(self): """Tests that None is returned when there is no difference between repos.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) diff = repo_man.get_git_diff() self.assertIsNone(diff) @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'), 'INTEGRATION_TESTS=1 not set') class CheckoutPrIntegrationTest(unittest.TestCase): """Does Integration tests on the checkout_pr method of RepoManager.""" def test_pull_request_exists(self): """Tests that a diff is returned when a valid PR is checked out.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) repo_man.checkout_pr('refs/pull/3415/merge') diff = repo_man.get_git_diff() self.assertCountEqual(diff, ['README.md']) def test_checkout_invalid_pull_request(self): """Tests that the git checkout invalid pull request fails.""" with get_oss_fuzz_repo() as oss_fuzz_repo: repo_man = repo_manager.RepoManager(oss_fuzz_repo) with self.assertRaises(RuntimeError): repo_man.checkout_pr(' ') with self.assertRaises(RuntimeError): repo_man.checkout_pr('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') with self.assertRaises(RuntimeError): repo_man.checkout_pr('not/a/valid/pr') if __name__ == '__main__': unittest.main() ================================================ FILE: infra/retry.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Retry decorator. Copied from ClusterFuzz source.""" import functools import inspect import logging import sys import time # pylint: disable=too-many-arguments,broad-except def sleep(seconds): """Invoke time.sleep. This is to avoid the flakiness of time.sleep. See: crbug.com/770375""" time.sleep(seconds) def get_delay(num_try, delay, backoff): """Compute backoff delay.""" return delay * (backoff**(num_try - 1)) def wrap(retries, delay, backoff=2, exception_type=Exception, retry_on_false=False): """Retry decorator for a function.""" assert delay > 0 assert backoff >= 1 assert retries >= 0 def decorator(func): """Decorator for the given function.""" tries = retries + 1 is_generator = inspect.isgeneratorfunction(func) function_with_type = func.__qualname__ if is_generator: function_with_type += ' (generator)' def handle_retry(num_try, exception=None): """Handle retry.""" if (exception is None or isinstance(exception, exception_type)) and num_try < tries: logging.info('Retrying on %s failed with %s. Retrying again.', function_with_type, sys.exc_info()[1]) sleep(get_delay(num_try, delay, backoff)) return True logging.error('Retrying on %s failed with %s. Raise.', function_with_type, sys.exc_info()[1]) return False @functools.wraps(func) def _wrapper(*args, **kwargs): """Regular function wrapper.""" for num_try in range(1, tries + 1): try: result = func(*args, **kwargs) if retry_on_false and not result: if not handle_retry(num_try): return result continue return result except Exception as error: if not handle_retry(num_try, exception=error): raise @functools.wraps(func) def _generator_wrapper(*args, **kwargs): """Generator function wrapper.""" # This argument is not applicable for generator functions. assert not retry_on_false already_yielded_element_count = 0 for num_try in range(1, tries + 1): try: for index, result in enumerate(func(*args, **kwargs)): if index >= already_yielded_element_count: yield result already_yielded_element_count += 1 break except Exception as error: if not handle_retry(num_try, exception=error): raise if is_generator: return _generator_wrapper return _wrapper return decorator ================================================ FILE: infra/run_fuzzers.Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image for running fuzzers on CIFuzz (the run_fuzzers action on GitHub # actions). FROM gcr.io/oss-fuzz-base/cifuzz-base # Python file to execute when the docker container starts up. # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/run_fuzzers_entrypoint.py"] WORKDIR ${OSS_FUZZ_ROOT}/infra # Copy infra source code. ADD . ${OSS_FUZZ_ROOT}/infra RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt ================================================ FILE: infra/run_fuzzers.ubuntu-24-04.Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Docker image for running fuzzers on CIFuzz (the run_fuzzers action on GitHub # actions). FROM gcr.io/oss-fuzz-base/cifuzz-base:ubuntu-24-04 # Python file to execute when the docker container starts up. # We can't use the env var $OSS_FUZZ_ROOT here. Since it's a constant env var, # just expand to '/opt/oss-fuzz'. ENTRYPOINT ["python3", "/opt/oss-fuzz/infra/cifuzz/run_fuzzers_entrypoint.py"] WORKDIR ${OSS_FUZZ_ROOT}/infra # Copy infra source code. ADD . ${OSS_FUZZ_ROOT}/infra RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt ================================================ FILE: infra/templates.py ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Templates for OSS-Fuzz project files.""" PROJECT_YAML_TEMPLATE = """\ homepage: "" language: %(language)s primary_contact: "" main_repo: "https://path/to/main/repo.git" file_github_issue: true """ DOCKER_TEMPLATE = """\ # Copyright %(year)d Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/%(base_builder)s RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 %(project_name)s # or use other version control WORKDIR %(project_name)s COPY build.sh $SRC/ """ EXTERNAL_DOCKER_TEMPLATE = """\ FROM gcr.io/oss-fuzz-base/%(base_builder)s:v1 RUN apt-get update && apt-get install -y make autoconf automake libtool COPY . $SRC/%(project_name)s WORKDIR %(project_name)s COPY .clusterfuzzlite/build.sh $SRC/ """ BUILD_TEMPLATE = """\ #!/bin/bash -eu # Copyright %(year)d Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project # e.g. # ./autogen.sh # ./configure # make -j$(nproc) all # build fuzzers # e.g. # $CXX $CXXFLAGS -std=c++11 -Iinclude \\ # /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \\ # $LIB_FUZZING_ENGINE /path/to/library.a """ EXTERNAL_BUILD_TEMPLATE = """\ #!/bin/bash -eu # build project # e.g. # ./autogen.sh # ./configure # make -j$(nproc) all # build fuzzers # e.g. # $CXX $CXXFLAGS -std=c++11 -Iinclude \\ # /path/to/name_of_fuzzer.cc -o $OUT/name_of_fuzzer \\ # $LIB_FUZZING_ENGINE /path/to/library.a """ EXTERNAL_PROJECT_YAML_TEMPLATE = """\ language: %(language)s """ TEMPLATES = { 'build.sh': BUILD_TEMPLATE, 'Dockerfile': DOCKER_TEMPLATE, 'project.yaml': PROJECT_YAML_TEMPLATE } EXTERNAL_TEMPLATES = { 'build.sh': EXTERNAL_BUILD_TEMPLATE, 'Dockerfile': EXTERNAL_DOCKER_TEMPLATE, 'project.yaml': EXTERNAL_PROJECT_YAML_TEMPLATE } ================================================ FILE: infra/test ================================================ ================================================ FILE: infra/test_repos.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """This module contains a list of test repository's used in unit/integration tests. Note: If you notice tests failing for unexpected reasons, make sure the data in the test repos are correct. This is because the test repos are dynamic and may change. Note: This should be removed when a better method of testing is established. """ import collections import os ExampleRepo = collections.namedtuple('ExampleRepo', [ 'project_name', 'oss_repo_name', 'git_repo_name', 'image_location', 'git_url', 'new_commit', 'old_commit', 'intro_commit', 'fuzz_target', 'testcase_path' ]) TEST_DIR_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'testcases') # WARNING: Tests are dependent upon the following repos existing and the # specified commits existing. # TODO(metzman): Fix this problem. # TODO(metzman): The testcases got deleted here because the test that used them # was skipped. Probably worth deleting the test. TEST_REPOS = [ ExampleRepo(project_name='curl', oss_repo_name='curl', git_repo_name='curl', image_location='/src', git_url='https://github.com/curl/curl.git', old_commit='df26f5f9c36e19cd503c0e462e9f72ad37b84c82', new_commit='dda418266c99ceab368d723facb52069cbb9c8d5', intro_commit='df26f5f9c36e19cd503c0e462e9f72ad37b84c82', fuzz_target='curl_fuzzer_ftp', testcase_path=os.path.join(TEST_DIR_PATH, 'curl_test_data')), ExampleRepo(project_name='libarchive', oss_repo_name='libarchive', git_repo_name='libarchive', image_location='/src', git_url='https://github.com/libarchive/libarchive.git', old_commit='5bd2a9b6658a3a6efa20bb9ad75bd39a44d71da6', new_commit='458e49358f17ec58d65ab1c45cf299baaf3c98d1', intro_commit='840266712006de5e737f8052db920dfea2be4260', fuzz_target='libarchive_fuzzer', testcase_path=os.path.join(TEST_DIR_PATH, 'libarchive_test_data')), ExampleRepo(project_name='gonids', oss_repo_name='gonids', git_repo_name='gonids', image_location='/root/go/src/github.com/google/', git_url='https://github.com/google/gonids', old_commit='', new_commit='', intro_commit='', fuzz_target='', testcase_path='') ] INVALID_REPO = ExampleRepo(project_name='notaproj', oss_repo_name='notarepo', git_repo_name='notarepo', git_url='invalid.git', image_location='/src', old_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', new_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', intro_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', fuzz_target='NONEFUZZER', testcase_path='not/a/path') ================================================ FILE: infra/tools/hold_back_images.py ================================================ #!/usr/bin/env python # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for pinning builder images for projects that break on upgrades. Works with projects that use language builders.""" import argparse import logging import os import re import sys import subprocess ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) PROJECTS_DIR = os.path.join(ROOT_DIR, 'projects') IMAGE_DIGEST_REGEX = re.compile(r'\[(.+)\]\n') FROM_LINE_REGEX = re.compile( r'FROM (gcr.io\/oss-fuzz-base\/base-builder[\-a-z0-9]*)(\@?.*)') def get_latest_docker_image_digest(image): """Returns a pinnable version of the latest |image|. This version will have a SHA.""" subprocess.run(['docker', 'pull', image], check=True) subprocess.run(['docker', 'pull', image], stdout=subprocess.PIPE, check=True) command = [ 'docker', 'image', 'inspect', '--format', '{{.RepoDigests}}', image ] output = subprocess.run(command, check=True, stdout=subprocess.PIPE).stdout.decode('utf-8') return IMAGE_DIGEST_REGEX.match(output).groups(1)[0] def get_args(): """Returns parsed arguments.""" parser = argparse.ArgumentParser(sys.argv[0], description='Hold back builder images.') parser.add_argument('projects', help='Projects.', nargs='+') parser.add_argument('--hold-image-digest', required=False, nargs='?', default=None, help='Image to hold on to.') parser.add_argument('--update-held', action='store_true', default=False, help='Update held images.') parser.add_argument('--issue-number', required=False, nargs='?', default=None, help='Issue to reference.') args = parser.parse_args() return args def get_hold_image_digest(line, hold_image_digest, update_held): """Returns the image digest for the |line| we want to pin. If the image is already pinned then it is only updated if |update_held. If |hold_image_digest is specified then it is returned, otherwise the latest pinnable version is returned.""" matches = FROM_LINE_REGEX.match(line).groups() if matches[1] and not update_held: return None, False initial_image = matches[0] if hold_image_digest: return hold_image_digest, True return get_latest_docker_image_digest(initial_image), True def hold_image(project, hold_image_digest, update_held, issue_number): """Rewrites the Dockerfile of |project| to pin the base-builder image on upgrade.""" dockerfile_path = os.path.join(PROJECTS_DIR, project, 'Dockerfile') with open(dockerfile_path, 'r') as dockerfile_handle: dockerfile = dockerfile_handle.readlines() for idx, line in enumerate(dockerfile[:]): if not line.startswith('FROM gcr.io/oss-fuzz-base/base-builder'): continue hold_image_digest, should_hold = get_hold_image_digest( line.strip(), hold_image_digest, update_held) if not should_hold: logging.error('Not holding back %s.', project) break dockerfile[idx] = f'FROM {hold_image_digest}\n' if issue_number: comment = ('# Held back because of github.com/google/oss-fuzz/pull/' f'{issue_number}\n# Please fix the build failure + upgrade.' '\n\n') dockerfile.insert(idx, comment) break else: # This path is taken when we don't break out of the loop. assert None, f'Could not find FROM line in {project}' dockerfile = ''.join(dockerfile) with open(dockerfile_path, 'w') as dockerfile_handle: dockerfile_handle.write(dockerfile) def main(): """Script for pinning builder images for projects that break on upgrades.""" args = get_args() for project in args.projects: hold_image(project, args.hold_image_digest, args.update_held, args.issue_number) return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/tools/wycheproof/.gitignore ================================================ wycheproof.zip ================================================ FILE: infra/tools/wycheproof/generate_job.py ================================================ #!/usr/bin/env python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for generating an OSS-Fuzz job for a wycheproof project.""" import sys def main(): """Usage generate_job.py .""" project = sys.argv[1] print(f'Name: wycheproof_nosanitizer_{project}') job_definition = f"""CUSTOM_BINARY = False BAD_BUILD_CHECK = False APP_NAME = WycheproofTarget.bash THREAD_ALIVE_CHECK_INTERVAL = 10 TEST_TIMEOUT = 3600 CRASH_RETRIES = 1 AGGREGATE_COVERAGE = False TESTCASE_COVERAGE = False FILE_GITHUB_ISSUE = False MANAGED = False MAX_FUZZ_THREADS = 1 RELEASE_BUILD_BUCKET_PATH = gs://clusterfuzz-builds-wycheproof/{project}/{project}-none-([0-9]+).zip PROJECT_NAME = {project} SUMMARY_PREFIX = {project} REVISION_VARS_URL = https://commondatastorage.googleapis.com/clusterfuzz-builds-wycheproof/{project}/{project}-none-%s.srcmap.json FUZZ_LOGS_BUCKET = {project}-logs.clusterfuzz-external.appspot.com CORPUS_BUCKET = {project}-corpus.clusterfuzz-external.appspot.com QUARANTINE_BUCKET = {project}-quarantine.clusterfuzz-external.appspot.com BACKUP_BUCKET = {project}-backup.clusterfuzz-external.appspot.com AUTOMATIC_LABELS = Proj-{project},Engine-wycheproof """ print(job_definition) if __name__ == '__main__': main() ================================================ FILE: infra/tools/wycheproof/launcher.py ================================================ #!/usr/bin/env python # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for running wycheproof.""" import logging import sys import subprocess def main(): """Runs wycheproof.""" if len(sys.argv) < 3: logging.error('Usage: %s .', sys.argv[0]) return 1 return subprocess.run(sys.argv[1:], check=False).returncode if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/tools/wycheproof/package.bash ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Script for zipping ClusterFuzz's blackbox fuzzer for wycheproof. zip wycheproof.zip run.py launcher.py ================================================ FILE: infra/tools/wycheproof/run.py ================================================ #!/usr/bin/env python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ """Script for creating "testcases" to run wycheproof on.""" import argparse import os import sys def get_args(): """Returns parsed program arguments.""" parser = argparse.ArgumentParser() parser.add_argument( '--input_dir', help='Ignored.', ) parser.add_argument('--output_dir', help='Directory for writing testcases.', required=True) parser.add_argument('--no_of_files', type=int, help='Ignored.') return parser.parse_args() def main(): """Generates a dummy testcase for use by a ClusterFuzz blackbox fuzzer.""" args = get_args() if not os.path.exists(args.output_dir): os.mkdir(args.output_dir) testcase = os.path.join(args.output_dir, 'fuzz-0') with open(testcase, 'w') as file_handle: file_handle.write(' ') return 0 if __name__ == '__main__': sys.exit(main()) ================================================ FILE: infra/uploader/Dockerfile ================================================ from ubuntu:16.04 RUN apt-get update && apt-get upgrade -y RUN apt-get install -y curl ENTRYPOINT ["curl", "--retry", "5", "-X", "PUT", "-T"] ================================================ FILE: infra/utils.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Utilities for OSS-Fuzz infrastructure.""" import logging import os import posixpath import re import shlex import stat import subprocess import sys import helper ALLOWED_FUZZ_TARGET_EXTENSIONS = ['', '.exe'] FUZZ_TARGET_SEARCH_STRING = 'LLVMFuzzerTestOneInput' VALID_TARGET_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+$') BLOCKLISTED_TARGET_NAME_REGEX = re.compile(r'^(jazzer_driver.*)$') # Location of google cloud storage for latest OSS-Fuzz builds. GCS_BASE_URL = 'https://storage.googleapis.com/' def chdir_to_root(): """Changes cwd to OSS-Fuzz root directory.""" # Change to oss-fuzz main directory so helper.py runs correctly. if os.getcwd() != helper.OSS_FUZZ_DIR: os.chdir(helper.OSS_FUZZ_DIR) def command_to_string(command): """Returns the stringfied version of |command| a list representing a binary to run and arguments to pass to it or a string representing a binary to run.""" if isinstance(command, str): return command return shlex.join(command) def execute(command, env=None, location=None, check_result=False, log_command=True): """Runs a shell command in the specified directory location. Args: command: The command as a list to be run. env: (optional) an environment to pass to Popen to run the command in. location (optional): The directory to run command in. check_result (optional): Should an exception be thrown on failure. Returns: stdout, stderr, returncode. Raises: RuntimeError: running a command resulted in an error. """ if not location: location = os.getcwd() process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=location, env=env) out, err = process.communicate() out = out.decode('utf-8', errors='ignore') err = err.decode('utf-8', errors='ignore') if log_command: command_str = command_to_string(command) display_err = err else: command_str = 'redacted' display_err = 'redacted' if err: logging.debug('Stderr of command "%s" is: %s.', command_str, display_err) if check_result and process.returncode: raise RuntimeError('Executing command "{0}" failed with error: {1}.'.format( command_str, display_err)) return out, err, process.returncode def get_fuzz_targets(path): """Gets fuzz targets in a directory. Args: path: A path to search for fuzz targets in. Returns: A list of paths to fuzzers or an empty list if None. """ if not os.path.exists(path): return [] fuzz_target_paths = [] for root, _, fuzzers in os.walk(path): for fuzzer in fuzzers: file_path = os.path.join(root, fuzzer) if is_fuzz_target_local(file_path): fuzz_target_paths.append(file_path) return fuzz_target_paths def get_container_name(): """Gets the name of the current docker container you are in. Returns: Container name or None if not in a container. """ result = subprocess.run( # pylint: disable=subprocess-run-check ['systemd-detect-virt', '-c'], stdout=subprocess.PIPE).stdout if b'docker' not in result: return None with open('/etc/hostname') as file_handle: return file_handle.read().strip() def is_executable(file_path): """Returns True if |file_path| is an exectuable.""" return os.path.exists(file_path) and os.access(file_path, os.X_OK) def is_fuzz_target_local(file_path): """Returns whether |file_path| is a fuzz target binary (local path). Copied from clusterfuzz src/python/bot/fuzzers/utils.py with slight modifications. """ # pylint: disable=too-many-return-statements filename, file_extension = os.path.splitext(os.path.basename(file_path)) if not VALID_TARGET_NAME_REGEX.match(filename): # Check fuzz target has a valid name (without any special chars). return False if BLOCKLISTED_TARGET_NAME_REGEX.match(filename): # Check fuzz target an explicitly disallowed name (e.g. binaries used for # jazzer-based targets). return False if file_extension not in ALLOWED_FUZZ_TARGET_EXTENSIONS: # Ignore files with disallowed extensions (to prevent opening e.g. .zips). return False if not is_executable(file_path): return False if filename.endswith('_fuzzer'): return True if os.path.exists(file_path) and not stat.S_ISREG(os.stat(file_path).st_mode): return False with open(file_path, 'rb') as file_handle: return file_handle.read().find(FUZZ_TARGET_SEARCH_STRING.encode()) != -1 def binary_print(string): """Prints string. Can print a binary string.""" if isinstance(string, bytes): string += b'\n' else: string += '\n' sys.stdout.buffer.write(string) sys.stdout.flush() def url_join(*url_parts): """Joins URLs together using the POSIX join method. Args: url_parts: Sections of a URL to be joined. Returns: Joined URL. """ return posixpath.join(*url_parts) def gs_url_to_https(url): """Converts |url| from a GCS URL (beginning with 'gs://') to an HTTPS one.""" return url_join(GCS_BASE_URL, remove_prefix(url, 'gs://')) def remove_prefix(string, prefix): """Returns |string| without the leading substring |prefix|.""" # Match behavior of removeprefix from python3.9: # https://www.python.org/dev/peps/pep-0616/ if string.startswith(prefix): return string[len(prefix):] return string ================================================ FILE: infra/utils_test.py ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests the functionality of the utils module's functions""" import os import tempfile import unittest from unittest import mock import utils import helper EXAMPLE_PROJECT = 'example' TEST_OUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cifuzz', 'test_data', 'build-out') class IsFuzzTargetLocalTest(unittest.TestCase): """Tests the is_fuzz_target_local function.""" def test_invalid_filepath(self): """Tests the function with an invalid file path.""" is_local = utils.is_fuzz_target_local('not/a/real/file') self.assertFalse(is_local) is_local = utils.is_fuzz_target_local('') self.assertFalse(is_local) is_local = utils.is_fuzz_target_local(' ') self.assertFalse(is_local) def test_valid_filepath(self): """Checks is_fuzz_target_local function with a valid filepath.""" is_local = utils.is_fuzz_target_local( os.path.join(TEST_OUT_DIR, 'example_crash_fuzzer')) self.assertTrue(is_local) is_local = utils.is_fuzz_target_local(TEST_OUT_DIR) self.assertFalse(is_local) class GetFuzzTargetsTest(unittest.TestCase): """Tests the get_fuzz_targets function.""" def test_valid_filepath(self): """Tests that fuzz targets can be retrieved once the fuzzers are built.""" fuzz_targets = utils.get_fuzz_targets(TEST_OUT_DIR) crash_fuzzer_path = os.path.join(TEST_OUT_DIR, 'example_crash_fuzzer') nocrash_fuzzer_path = os.path.join(TEST_OUT_DIR, 'example_nocrash_fuzzer') self.assertCountEqual(fuzz_targets, [crash_fuzzer_path, nocrash_fuzzer_path]) # Testing on a arbitrary directory with no fuzz targets in it. fuzz_targets = utils.get_fuzz_targets( os.path.join(helper.OSS_FUZZ_DIR, 'infra', 'travis')) self.assertFalse(fuzz_targets) def test_invalid_filepath(self): """Tests what get_fuzz_targets return when invalid filepath is used.""" fuzz_targets = utils.get_fuzz_targets('not/a/valid/file/path') self.assertFalse(fuzz_targets) class ExecuteTest(unittest.TestCase): """Tests the execute function.""" def test_valid_command(self): """Tests that execute can produce valid output.""" with tempfile.TemporaryDirectory() as tmp_dir: out, err, err_code = utils.execute(['ls', '.'], location=tmp_dir, check_result=False) self.assertEqual(err_code, 0) self.assertEqual(err, '') self.assertEqual(out, '') out, err, err_code = utils.execute(['mkdir', 'tmp'], location=tmp_dir, check_result=False) self.assertEqual(err_code, 0) self.assertEqual(err, '') self.assertEqual(out, '') out, err, err_code = utils.execute(['ls', '.'], location=tmp_dir, check_result=False) self.assertEqual(err_code, 0) self.assertEqual(err, '') self.assertEqual(out, 'tmp\n') def test_error_command(self): """Tests that execute can correctly surface errors.""" with tempfile.TemporaryDirectory() as tmp_dir: out, err, err_code = utils.execute(['ls', 'notarealdir'], location=tmp_dir, check_result=False) self.assertEqual(err_code, 2) self.assertIsNotNone(err) self.assertEqual(out, '') with self.assertRaises(RuntimeError): out, err, err_code = utils.execute(['ls', 'notarealdir'], location=tmp_dir, check_result=True) class BinaryPrintTest(unittest.TestCase): """Tests for utils.binary_print.""" @unittest.skip('Causes spurious failures because of side-effects.') def test_string(self): # pylint: disable=no-self-use """Tests that utils.binary_print can print a regular string.""" # Should execute without raising any exceptions. with mock.patch('sys.stdout.buffer.write') as mock_write: utils.binary_print('hello') mock_write.assert_called_with('hello\n') @unittest.skip('Causes spurious failures because of side-effects.') def test_binary_string(self): # pylint: disable=no-self-use """Tests that utils.binary_print can print a bianry string.""" # Should execute without raising any exceptions. with mock.patch('sys.stdout.buffer.write') as mock_write: utils.binary_print(b'hello') mock_write.assert_called_with(b'hello\n') class CommandToStringTest(unittest.TestCase): """Tests for command_to_string.""" def test_string(self): """Tests that command_to_string returns the argument passed to it when it is passed a string.""" command = 'command' self.assertEqual(utils.command_to_string(command), command) def test_list(self): """Tests that command_to_string returns the correct stringwhen it is passed a list.""" command = ['command', 'arg1', 'arg2'] self.assertEqual(utils.command_to_string(command), 'command arg1 arg2') if __name__ == '__main__': unittest.main() ================================================ FILE: projects/abseil-cpp/BUILD ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") cc_fuzz_test( name = "string_escape_fuzzer", srcs = ["string_escape_fuzzer.cc"], deps = ["@com_google_absl//absl/strings"], ) cc_fuzz_test( name = "string_utilities_fuzzer", srcs = ["string_utilities_fuzzer.cc"], deps = [ "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:str_format", # The below are added for OSS-Fuzz-gen purposes. The goal is to make # a general build rule from which we can build harnesses targeting # most of the abseil-cpp codebase. "@com_google_absl//absl/algorithm:algorithm", "@com_google_absl//absl/hash:hash", "@com_google_absl//absl/crc:crc32c", "@com_google_absl//absl/time:time", "@com_google_absl//absl/base:base", ], ) ================================================ FILE: projects/abseil-cpp/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN git clone --depth 1 https://github.com/abseil/abseil-cpp.git COPY BUILD WORKSPACE build.sh *_fuzzer.cc $SRC/ ================================================ FILE: projects/abseil-cpp/WORKSPACE ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") local_repository( name = "com_google_absl", path = "abseil-cpp/", ) # released on 2023-11-07 http_archive( name = "bazel_skylib", sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", ], ) # bazel_features is required by rules_cc compatibility_proxy_repo http_archive( name = "bazel_features", sha256 = "af3d4fb1cf4f25942cb4a933b1ad93a0ea9fe9ee70c2af7f369fb72a67c266e5", strip_prefix = "bazel_features-1.21.0", urls = ["https://github.com/bazel-contrib/bazel_features/releases/download/v1.21.0/bazel_features-v1.21.0.tar.gz"], ) load("@bazel_features//:deps.bzl", "bazel_features_deps") bazel_features_deps() # rules_cc required by abseil-cpp http_archive( name = "rules_cc", sha256 = "a2fdfde2ab9b2176bd6a33afca14458039023edb1dd2e73e6823810809df4027", strip_prefix = "rules_cc-0.2.14", urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.2.14/rules_cc-0.2.14.tar.gz"], ) load("@rules_cc//cc:extensions.bzl", "compatibility_proxy_repo") compatibility_proxy_repo() load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() # released on 2023-10-19 http_archive( name = "rules_fuzzing", sha256 = "ff52ef4845ab00e95d29c02a9e32e9eff4e0a4c9c8a6bcf8407a2f19eb3f9190", strip_prefix = "rules_fuzzing-0.4.1", urls = ["https://github.com/bazelbuild/rules_fuzzing/releases/download/v0.4.1/rules_fuzzing-0.4.1.zip"], ) load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies") rules_fuzzing_dependencies() load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init") rules_fuzzing_init() load("@fuzzing_py_deps//:requirements.bzl", "install_deps") install_deps() ================================================ FILE: projects/abseil-cpp/build.sh ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export USE_BAZEL_VERSION=7.4.0 # Disable `layering_check` feature. # As per https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63223, it breaks # the build. Someone could figure out exactly why it breaks the build, but just # disabling it suffices because it doesn't actually matter for our purposes. ;) # Also use C++17 as required by abseil-cpp. export BAZEL_EXTRA_BUILD_FLAGS='--features=-layering_check --cxxopt=-std=c++17' # The default query is complex and requires additional dependencies in order to # work (due to its use of `//...`) whereas this query is simple and sufficient. export BAZEL_FUZZ_TEST_QUERY='filter("_fuzzer$", //:all)' exec bazel_build_fuzz_tests ================================================ FILE: projects/abseil-cpp/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "abseil.io" language: c++ primary_contact: "dmauro@google.com" main_repo: 'https://github.com/abseil/abseil-cpp.git' ================================================ FILE: projects/abseil-cpp/string_escape_fuzzer.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include "absl/strings/escaping.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string str (reinterpret_cast(data), size); std::string escaped, unescaped; escaped = absl::CHexEscape(str); absl::CUnescape(escaped, &unescaped); if (str != unescaped) abort(); escaped = absl::CEscape(str); absl::CUnescape(escaped, &unescaped); if (str != unescaped) abort(); escaped = absl::Utf8SafeCEscape(str); absl::CUnescape(escaped, &unescaped); if (str != unescaped) abort(); escaped = absl::Utf8SafeCHexEscape(str); absl::CUnescape(escaped, &unescaped); if (str != unescaped) abort(); std::string encoded, decoded; absl::Base64Escape(str, &encoded); absl::Base64Unescape(encoded, &decoded); if (str != unescaped) abort(); absl::WebSafeBase64Escape(str, &encoded); absl::WebSafeBase64Unescape(encoded, &decoded); if (str != decoded) abort(); std::string hex_result, bytes_result; hex_result = absl::BytesToHexString(str); bytes_result = absl::HexStringToBytes(hex_result); if (str != decoded) abort(); return 0; } ================================================ FILE: projects/abseil-cpp/string_utilities_fuzzer.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fuzzed_data(data, size); float float_value = fuzzed_data.ConsumeFloatingPoint(); double double_value = fuzzed_data.ConsumeFloatingPoint(); int int_value = fuzzed_data.ConsumeIntegral(); bool bool_value = fuzzed_data.ConsumeBool(); std::string str1 = fuzzed_data.ConsumeRandomLengthString(); std::string str2 = fuzzed_data.ConsumeRemainingBytesAsString(); std::string float_str = absl::StrFormat("%g", float_value); std::string double_str = absl::StrFormat("%g", double_value); std::string int_str = absl::StrFormat("%d", int_value); std::string bool_str = absl::StrFormat("%d", bool_value); if (!absl::SimpleAtof(float_str, &float_value)) return 0; if (!absl::SimpleAtod(double_str, &double_value)) return 0; if (!absl::SimpleAtoi(int_str, &int_value)) return 0; if (!absl::SimpleAtob(bool_str, &bool_value)) return 0; absl::StrAppend(&str1, str2); std::string str_result = absl::StrCat(str1, float_value, double_value, int_value, bool_value); std::vector v = absl::StrSplit(str_result, "."); absl::StrJoin(v, "."); return 0; } ================================================ FILE: projects/abseil-py/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/abseil/abseil-py abseil-py COPY *.sh *py $SRC/ WORKDIR $SRC/abseil-py ================================================ FILE: projects/abseil-py/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install . cd ../ mkdir fuzzbuilds cd fuzzbuilds # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/abseil-py/fuzz_argparse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import enum import atheris from absl import flags from absl.flags import _exceptions from absl.flags import argparse_flags class FuzzEnum(enum.Enum): VAL1 = object() VAL2 = object() def TestOneInput(data): """Hits the logic in https://github.com/abseil/abseil-py/tree/main/absl/flags""" fdp = atheris.FuzzedDataProvider(data) def rs(size): return fdp.ConsumeUnicodeNoSurrogates(size) fuzz_flag_values = flags.FlagValues() try: flags.DEFINE_string(rs(256), None, rs(256), flag_values = fuzz_flag_values) except _exceptions.Error: pass try: flags.DEFINE_float(rs(256), 0.0, rs(256), flag_values = fuzz_flag_values) except _exceptions.Error: pass try: flags.DEFINE_enum_class(rs(256), None, FuzzEnum, rs(256), flag_values = fuzz_flag_values) except _exceptions.Error: pass try: flags.DEFINE_integer(rs(256), rs(256), rs(256), flag_values = fuzz_flag_values) except _exceptions.Error: pass command_line_args = [] for idx in range(fdp.ConsumeIntInRange(1, 20)): command_line_args.append(rs(256)) # Parse it all try: fuzz_flag_values(command_line_args) except _exceptions.Error: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/abseil-py/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/abseil/abseil-py language: python main_repo: https://github.com/abseil/abseil-py sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/ada-url/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone --depth 1 https://github.com/ada-url/ada ada-url RUN cp ada-url/fuzz/build.sh $SRC/ WORKDIR ada-url COPY run_tests.sh $SRC/ ================================================ FILE: projects/ada-url/project.yaml ================================================ homepage: "https://ada-url.github.io/ada" language: c++ primary_contact: "yagiz@nizipli.com" auto_ccs: - "daniel@lemire.me" main_repo: "https://github.com/ada-url/ada.git" sanitizers: - address - undefined - memory fuzzing_engines: - libfuzzer - afl - honggfuzz - centipede file_github_issue: true ================================================ FILE: projects/ada-url/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build-tests ================================================ FILE: projects/adal/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/AzureAD/azure-activedirectory-library-for-python adsl WORKDIR adsl COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/adal/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/adal/fuzz_util.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import binascii with atheris.instrument_imports(): from adal.util import * def TestInput(data): fdp = atheris.FuzzedDataProvider(data) is_http_success(fdp.ConsumeInt(10)) class DummyClass(object): _call_context = { 'log_context':{'correlation_id':fdp.ConsumeString(20)}, 'options':{'http':{ fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100) }} } def geturl(self): return fdp.ConsumeString(100) create_request_options(DummyClass(),{ fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100), 'headers':{ fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100), fdp.ConsumeString(10):fdp.ConsumeString(100) } }) try: copy_url(fdp.ConsumeString(100)) copy_url(DummyClass()) except ValueError as e: if (("contains invalid characters" not in str(e)) and ("Invalid IPv6 URL" not in str(e))): raise e try: base64_urlsafe_decode(fdp.ConsumeUnicodeNoSurrogates(100)) except binascii.Error as e: if "Invalid base64-encoded string" not in str(e): raise e def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/adal/fuzz_xmlutil.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys try: from xml.etree import cElementTree as ET except ImportError: from xml.etree import ElementTree as ET from xml.etree.ElementTree import ParseError with atheris.instrument_imports(): from adal.xmlutil import * XMLTEMPLATE=""" <%OUTTER%> <%INNER% name="%INNERNAME%"> <%LEAF1%>%LEAF1VALUE1% <%LEAF2%>%LEAF2VALUE1% <%LEAF3% name="%LEAF3NAME1%" value="%LEAF3VALUE1%"/> <%LEAF3% name="%LEAF3NAME4%" value="%LEAF3VALUE4%"/> <%INNER% name="%INNERNAME%"> <%LEAF1%>%LEAF1VALUE2% <%LEAF2%>%LEAF2VALUE2% <%LEAF3% name="%LEAF3NAME2%" value="%LEAF3VALUE2%"/> <%INNER% name="%INNERNAME%"> <%LEAF1%>%LEAF1VALUE3% <%LEAF2%>%LEAF2VALUE3% <%LEAF3% name="%LEAF3NAME3%" value="%LEAF3VALUE3%"/> """ def generate_sample_xml(fdp): global XMLTEMPLATE xml_string = XMLTEMPLATE replace_tag = ["%OUTTER%","%INNER%","%LEAF1%","%LEAF2%","%LEAF3%"] replace_value = ["%INNERNAME%", "%LEAF1VALUE1%","%LEAF2VALUE1%","%LEAF3NAME1%","%LEAF3VALUE1%", "%LEAF1VALUE2%","%LEAF2VALUE2%","%LEAF3NAME2%","%LEAF3VALUE3%", "%LEAF1VALUE3%","%LEAF2VALUE3%","%LEAF3NAME2%","%LEAF3VALUE4%", "%LEAF3NAME4","%LEAF3VALUE4%" ] for tag in replace_tag+replace_value: xml_string = xml_string.replace(tag,fdp.ConsumeUnicodeNoSurrogates(10)) return xml_string def TestInput(data): fdp = atheris.FuzzedDataProvider(data) try: expand_q_names(fdp.ConsumeString(100)) except IndexError as e: if "Unable to parse XPath string:" not in str(e): raise e except KeyError: return try: dom = ET.fromstring(generate_sample_xml(fdp)) except ParseError: return xpath_find(dom,fdp.ConsumeString(30)) serialize_node_children(dom) is_element_node(dom) find_element_text(dom) def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/adal/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/AzureAD/azure-activedirectory-library-for-python language: python main_repo: https://github.com/AzureAD/azure-activedirectory-library-for-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/aiohttp/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y \ pkg-config \ zlib1g \ zlib1g-dev \ libjpeg-dev \ libpng-dev \ libffi-dev \ make \ autoconf \ libtool RUN python3 -m pip install --upgrade pip RUN curl -sL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh RUN bash nodesource_setup.sh && apt-get install -y nodejs RUN git clone --recurse-submodules https://github.com/aio-libs/aiohttp COPY build.sh $SRC/ COPY fuzz_* $SRC/aiohttp/ WORKDIR $SRC/aiohttp ================================================ FILE: projects/aiohttp/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build the llhttp parser git submodule update --init --recursive pushd "$SRC/aiohttp/vendor/llhttp/" npm ci make popd # "$SRC/aiohttp/vendor/llhttp/" # Build & install aiohttp make cythonize make install-dev # Duplicate fuzzers to use Pure python code (in addition # to the existing C-compiled code). cp fuzz_http_parser.py fuzz_http_parser_pure_python.py sed -i 's/AIOHTTP_VAL=0/AIOHTTP_VAL=1/g' fuzz_http_parser_pure_python.py cp fuzz_http_payload_parser.py fuzz_http_payload_parser_pure_python.py sed -i 's/AIOHTTP_VAL=0/AIOHTTP_VAL=1/g' fuzz_http_payload_parser_pure_python.py # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/aiohttp/fuzz_http_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os AIOHTTP_VAL=0 if AIOHTTP_VAL == 0: os.environ["AIOHTTP_NO_EXTENSIONS"] = "" else: os.environ["AIOHTTP_NO_EXTENSIONS"] = "1" import sys import atheris # aiohttp imports import asyncio with atheris.instrument_imports(): import aiohttp from aiohttp.base_protocol import BaseProtocol from aiohttp import http_exceptions, streams @atheris.instrument_func def TestOneInput(data): loop = asyncio.get_event_loop() pr = BaseProtocol(loop) h_p = aiohttp.http_parser.HttpRequestParser(pr, loop, 32768) try: h_p.feed_data(data) h_p.feed_eof() except aiohttp.http_exceptions.HttpProcessingError: None def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) loop = asyncio.get_event_loop() asyncio.set_event_loop(loop) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aiohttp/fuzz_http_payload_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os AIOHTTP_VAL=0 if AIOHTTP_VAL == 0: os.environ["AIOHTTP_NO_EXTENSIONS"] = "" else: os.environ["AIOHTTP_NO_EXTENSIONS"] = "1" import sys import atheris # aiohttp imports import asyncio with atheris.instrument_imports(): import aiohttp from aiohttp.base_protocol import BaseProtocol from aiohttp import http_exceptions, streams @atheris.instrument_func def TestOneInput(data): loop = asyncio.get_event_loop() pr = BaseProtocol(loop) out = aiohttp.StreamReader(pr, 2**16, loop=None) h_p = aiohttp.http_parser.HttpPayloadParser(out, loop, 32768) try: h_p.feed_data(data) except aiohttp.http_exceptions.HttpProcessingError: None def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) loop = asyncio.get_event_loop() asyncio.set_event_loop(loop) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aiohttp/fuzz_multipart.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import sys import atheris # aiohttp imports import asyncio with atheris.instrument_imports(): import aiohttp from aiohttp.hdrs import ( CONTENT_TYPE, ) class FuzzStream: def __init__(self, content): self.content = io.BytesIO(content) async def read(self, size = None): return self.content.read(size) def at_eof(self): return self.content.tell() == len(self.content.getbuffer()) async def readline(self): return self.content.readline() def unread_data(self, data): self.content = io.BytesIO(data + self.content.read()) @atheris.instrument_func async def fuzz_bodypart_reader(data): fdp = atheris.FuzzedDataProvider(data) obj = aiohttp.BodyPartReader( b"--:", { CONTENT_TYPE: fdp.ConsumeUnicode(30), }, FuzzStream(fdp.ConsumeBytes(atheris.ALL_REMAINING)), ) if not obj.at_eof(): await obj.form() @atheris.instrument_func def TestOneInput(data): try: asyncio.run(fuzz_bodypart_reader(data)) except AssertionError: return def main(): atheris.Setup(sys.argv, TestOneInput) loop = asyncio.get_event_loop() asyncio.set_event_loop(loop) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aiohttp/fuzz_payload_url.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris # aiohttp specific with atheris.instrument_imports(): from aiohttp import http_exceptions, payload from yarl import URL @atheris.instrument_func def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) original = fdp.ConsumeString(sys.maxsize) try: p = payload.StringPayload(original) except UnicodeEncodeError: None try: u = URL(original) except ValueError: None def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aiohttp/fuzz_web_request.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris # aiohttp imports import asyncio with atheris.instrument_imports(): import aiohttp from aiohttp.test_utils import make_mocked_request from multidict import CIMultiDict from yarl import URL @atheris.instrument_func async def fuzz_run_one_async(data): fdp = atheris.FuzzedDataProvider(data) url_s = fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512)) try: URL(url_s) except Exception: return headers = CIMultiDict( { fdp.ConsumeString(20) : fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512)) } ) req = make_mocked_request("GET", url_s, headers=headers) l1 = len(req.forwarded) ret = await req.post() @atheris.instrument_func def TestOneInput(data): asyncio.run(fuzz_run_one_async(data)) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) loop = asyncio.get_event_loop() asyncio.set_event_loop(loop) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aiohttp/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/aio-libs/aiohttp language: python main_repo: https://github.com/aio-libs/aiohttp sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/airflow/Dockerfile ================================================ # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y sqlite3 RUN pip3 install --upgrade pip RUN git clone --depth 1 https://github.com/apache/airflow $SRC/airflow WORKDIR airflow COPY build.sh dag_fuzz.py $SRC/ ================================================ FILE: projects/airflow/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/airflow # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install colorlog pip3 install ./task-sdk ./airflow-core . # Build fuzzers in $OUT. cd $SRC CONFIG_TEMPLATES_PATH=$(python3 -c "import os, airflow; print(os.path.join(os.path.dirname(airflow.__file__), 'config_templates'))") compile_python_fuzzer dag_fuzz.py --add-data "$CONFIG_TEMPLATES_PATH:airflow/config_templates" --hidden-import="airflow.utils.log.timezone_aware" --hidden-import="aiosqlite" --hidden-import="airflow.sdk.serde.serializers" ================================================ FILE: projects/airflow/dag_fuzz.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import colorlog from datetime import datetime, timedelta with atheris.instrument_imports(include=['airflow'], enable_loader_override=False): import airflow from airflow import DAG from airflow.exceptions import AirflowException try: from airflow.providers.standard.operators.empty import EmptyOperator as DummyOperator from airflow.providers.standard.operators.python import PythonOperator except ImportError: try: from airflow.operators.empty import EmptyOperator as DummyOperator from airflow.operators.python import PythonOperator except ImportError: from airflow.operators.dummy_operator import DummyOperator from airflow.operators.python_operator import PythonOperator def py_func(): return def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) default_args = { 'owner': fdp.ConsumeString(8), 'depends_on_past': fdp.ConsumeBool(), 'start_date': datetime.now() - timedelta(days=fdp.ConsumeIntInRange(1,5)), 'email': [fdp.ConsumeString(8)], 'email_on_failure': fdp.ConsumeBool(), 'email_on_retry': fdp.ConsumeBool(), 'retries': fdp.ConsumeIntInRange(1,5), 'retry_delay': timedelta(minutes=fdp.ConsumeIntInRange(1,5)), } try: with DAG(fdp.ConsumeString(8), schedule_interval='@daily', default_args=default_args) as dag: dummy_task = DummyOperator(task_id=fdp.ConsumeString(8), retries=fdp.ConsumeIntInRange(1,5)) python_task = PythonOperator(task_id=fdp.ConsumeString(8), python_callable=py_func) dummy_task >> python_task except (AirflowException, ValueError, TypeError): pass def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/airflow/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/apache/airflow language: python main_repo: https://github.com/apache/airflow sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/alembic/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y build-essential zlib1g-dev zlib1g-dev:i386 python make automake RUN git clone -b v3.2.1 --depth 1 https://github.com/AcademySoftwareFoundation/imath $SRC/imath && \ cd $SRC/imath && \ mkdir build && \ cd build && \ cmake -D BUILD_SHARED_LIBS=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON ../ && \ make -j$(nproc) V=1 && make install RUN git clone --depth 1 https://github.com/alembic/alembic COPY run_tests.sh build.sh *.h *.cc $SRC/ WORKDIR $WORK/ ================================================ FILE: projects/alembic/alembic_dump_info_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include #include "alembic/lib/Alembic/AbcCoreFactory/All.h" #include "alembic/lib/Alembic/AbcCoreOgawa/All.h" #include "alembic/lib/Alembic/AbcGeom/All.h" #include "alembic/lib/Alembic/AbcMaterial/All.h" #include "fuzzer_temp_file.h" using Alembic::AbcCoreAbstract::PropertyHeader; using Alembic::AbcCoreAbstract::PropertyType; using Alembic::AbcCoreFactory::IFactory; using Alembic::AbcGeom::C4fArraySamplePtr; using Alembic::AbcGeom::IArchive; using Alembic::AbcGeom::IC4fGeomParam; using Alembic::AbcGeom::ICompoundProperty; using Alembic::AbcGeom::ICurves; using Alembic::AbcGeom::ICurvesSchema; using Alembic::AbcGeom::IFaceSet; using Alembic::AbcGeom::IFaceSetSchema; using Alembic::AbcGeom::IGeomBaseSchema; using Alembic::AbcGeom::IN3fGeomParam; using Alembic::AbcGeom::index_t; using Alembic::AbcGeom::Int32ArraySamplePtr; using Alembic::AbcGeom::IObject; using Alembic::AbcGeom::IPolyMesh; using Alembic::AbcGeom::IPolyMeshSchema; using Alembic::AbcGeom::ISubD; using Alembic::AbcGeom::ISubDSchema; using Alembic::AbcGeom::IV2fGeomParam; using Alembic::AbcGeom::IXform; using Alembic::AbcGeom::IXformSchema; using Alembic::AbcGeom::M44d; using Alembic::AbcGeom::M44f; using Alembic::AbcGeom::N3fArraySamplePtr; using Alembic::AbcGeom::ObjectHeader; using Alembic::AbcGeom::P3fArraySamplePtr; using Alembic::AbcGeom::UInt32ArraySamplePtr; using Alembic::AbcGeom::V2fArraySamplePtr; using Alembic::AbcMaterial::IMaterial; using Alembic::AbcMaterial::IMaterialSchema; template void dumpAttributes(T const &schema) { const size_t meshPropertyCount = schema.getNumProperties(); for (size_t p = 0; p < meshPropertyCount; p++) { const PropertyHeader &header = schema.getPropertyHeader(p); const PropertyType pType = header.getPropertyType(); const std::string &name = header.getName(); if (name == "P") { schema.getNumSamples(); } else if (name == "uv" || name == "st") { schema.getUVsParam().getNumSamples(); } else if (name == ".arbGeomParams") { // additional geometry elements (color sets, additional texture // coordinates) const ICompoundProperty geoParam = schema.getArbGeomParams(); const size_t geoPropCount = geoParam.getNumProperties(); for (size_t g = 0; g < geoPropCount; g++) { const PropertyHeader &headerGeo = geoParam.getPropertyHeader(g); const std::string &nameGeo = headerGeo.getName(); } } } } void dumpPolyMesh(const IObject &node) { const ObjectHeader &header = node.getHeader(); const IPolyMesh mesh(node.getParent(), header.getName()); const IPolyMeshSchema &schema = mesh.getSchema(); // Mesh properties dumpAttributes(schema); } void dumpSubD(const IObject &node) { const ObjectHeader &header = node.getHeader(); const ISubD mesh(node.getParent(), header.getName()); const ISubDSchema &schema = mesh.getSchema(); dumpAttributes(schema); schema.getSubdivisionSchemeProperty(); schema.getFaceVaryingInterpolateBoundaryProperty(); schema.getFaceVaryingPropagateCornersProperty(); schema.getInterpolateBoundaryProperty(); } void dumpFaceSet(const IObject &node) { const ObjectHeader &header = node.getHeader(); const IFaceSet faceSet(node.getParent(), header.getName()); const IFaceSetSchema &schema = faceSet.getSchema(); schema.getNumSamples(); } void dumpCurves(const IObject &node) { const ObjectHeader &header = node.getHeader(); const ICurves curves(node.getParent(), header.getName()); const ICurvesSchema &schema = curves.getSchema(); dumpAttributes(schema); } void dumpXform(const IObject &node) { const ObjectHeader &header = node.getHeader(); const IXform xform(node.getParent(), header.getName()); const IXformSchema &schema = xform.getSchema(); schema.getNumSamples(); schema.getNumOps(); } void dumpMaterial(const IObject &node) { const ObjectHeader &header = node.getHeader(); IMaterial material(node.getParent(), header.getName()); IMaterialSchema &schema = material.getSchema(); std::vector targetNames; schema.getTargetNames(targetNames); for (const std::string &target : targetNames) { std::vector shaderTypes; schema.getShaderTypesForTarget(target, shaderTypes); const size_t shaderTypeCount = shaderTypes.size(); for (size_t s = 0; s < shaderTypeCount; s++) { ICompoundProperty parameters = schema.getShaderParameters(target, shaderTypes[s]); const size_t parameterCount = parameters.getNumProperties(); } } } void dumpNodes(const IObject &node) { const ObjectHeader &header = node.getHeader(); // Dump the general node information. header.getName(); header.getFullName(); header.getMetaData().serialize(); // Dump the type specific information. if (Alembic::AbcGeom::IPolyMesh::matches(header)) { dumpPolyMesh(node); } else if (Alembic::AbcGeom::ISubD::matches(header)) { dumpSubD(node); } else if (Alembic::AbcGeom::IFaceSet::matches(header)) { dumpFaceSet(node); } else if (Alembic::AbcGeom::ICurves::matches(header)) { dumpCurves(node); } else if (Alembic::AbcGeom::IXform::matches(header)) { dumpXform(node); } else if (Alembic::AbcMaterial::IMaterial::matches(header)) { dumpMaterial(node); } else { // Miscellaneous nodes such as the root. ; } // Dump the child headers. const size_t childCount = node.getNumChildren(); for (size_t i = 0; i < childCount; i++) { dumpNodes(node.getChild(i)); } } void dumpInfo(const char *file) { // Load the Alembic archive and verify that it is valid. IFactory factory; IArchive archive = factory.getArchive(file); if (archive.valid()) { archive.getName(); dumpNodes(archive.getTop()); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzerTemporaryFile tempFile(data, size); dumpInfo(tempFile.filename()); return 0; } ================================================ FILE: projects/alembic/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build alembic mkdir -p $WORK/build_alembic cd $WORK/build_alembic cmake $SRC/alembic -DALEMBIC_SHARED_LIBS=OFF make -j$(nproc) INCLUDES=( "-I $SRC" "-I ${SRC}/alembic/lib" "-I ${WORK}/build_alembic/lib" "-I /usr/local/include/Imath" ) for fuzzer in $(find $SRC -name '*_fuzzer.cc'); do fuzzer_basename=$(basename -s .cc $fuzzer) $CXX $CXXFLAGS -std=c++11 ${INCLUDES[@]} \ $fuzzer $WORK/build_alembic/lib/Alembic/libAlembic.a $LIB_FUZZING_ENGINE \ -o $OUT/$fuzzer_basename $SRC/imath/build/src/Imath/libImath-3_2.a done ================================================ FILE: projects/alembic/fuzzer_temp_file.h ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that // require a file instead of an input buffer. #ifndef FUZZER_TEMP_FILE_H_ #define FUZZER_TEMP_FILE_H_ #include #include #include #include #include // Pure-C interface for creating and cleaning up temporary files. static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size) { char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename_buffer) { perror("Failed to allocate file name buffer."); abort(); } const int file_descriptor = mkstemp(filename_buffer); if (file_descriptor < 0) { perror("Failed to make temporary file."); abort(); } FILE *file = fdopen(file_descriptor, "wb"); if (!file) { perror("Failed to open file descriptor."); close(file_descriptor); abort(); } const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file); if (bytes_written != size) { fclose(file); fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size); abort(); } fclose(file); return filename_buffer; } static void fuzzer_release_tmpfile(char *filename) { if (unlink(filename) != 0) { perror("WARNING: Failed to delete temporary file."); } free(filename); } // C++ RAII object for creating temporary files. #ifdef __cplusplus class FuzzerTemporaryFile { public: FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) {} ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); } const char *filename() const { return filename_; } private: char *filename_; }; #endif #endif // FUZZER_TEMP_FILE_H_ ================================================ FILE: projects/alembic/project.yaml ================================================ homepage: "https://github.com/alembic/alembic" language: c++ primary_contact: "miller.lucas@gmail.com" sanitizers: - address main_repo: 'https://github.com/alembic/alembic' ================================================ FILE: projects/alembic/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build alembic ctest --test-dir $WORK/build_alembic ================================================ FILE: projects/ampproject/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e # ! This project was pinned after a clang bump. Please remove the pin, Try to fix any build warnings and errors, as well as runtime errors RUN apt-get update && apt-get install -y make autoconf automake libtool libomp-dev libgomp1 nodejs COPY build.sh *.diff $SRC/ RUN git clone --depth 1 https://github.com/ampproject/amphtml amphtml && \ cd amphtml && \ git apply --ignore-space-change --ignore-whitespace $SRC/fuzz_patch.diff WORKDIR amphtml ================================================ FILE: projects/ampproject/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export USE_BAZEL_VERSION=5.4.0 cd validator export FUZZTEST_TARGET_FOLDER="//cpp/htmlparser:parser_fuzz_test" compile_fuzztests.sh ================================================ FILE: projects/ampproject/fuzz_patch.diff ================================================ diff --git a/validator/WORKSPACE b/validator/WORKSPACE index 0510b05..26e878c 100644 --- a/validator/WORKSPACE +++ b/validator/WORKSPACE @@ -101,3 +101,10 @@ local_repository( name = "amphtml-extensions", path = "../extensions", ) + +http_archive( + name = "com_google_fuzztest", + sha256 = "c75f224b34c3c62ee901381fb743f6326f7b91caae0ceb8fe62f3fd36f187627", + strip_prefix = "fuzztest-58b4e7065924f1a284952b84ea827ce35a87e4dc", + urls = ["https://github.com/google/fuzztest/archive/58b4e7065924f1a284952b84ea827ce35a87e4dc.zip"], +) diff --git a/validator/cpp/htmlparser/BUILD b/validator/cpp/htmlparser/BUILD index 3d31520..41bfd93 100644 --- a/validator/cpp/htmlparser/BUILD +++ b/validator/cpp/htmlparser/BUILD @@ -555,3 +555,15 @@ cc_test( "@com_google_absl//absl/flags:flag", ], ) + +cc_test( + name = "parser_fuzz_test", + srcs = ["parser_fuzz_test.cc"], + deps = [ + ":parser", + "@com_google_fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", + "@com_google_googletest//:gtest_main", + ], +) + diff --git a/validator/cpp/htmlparser/parser_fuzz_test.cc b/validator/cpp/htmlparser/parser_fuzz_test.cc new file mode 100644 index 0000000..2ad7194 --- /dev/null +++ b/validator/cpp/htmlparser/parser_fuzz_test.cc @@ -0,0 +1,10 @@ +#include "cpp/htmlparser/parser.h" + +#include "fuzztest/fuzztest.h" + +void FuzzParser(std::string raw_html) { + htmlparser::Parser parser(raw_html); + parser.Parse(); +} + +FUZZ_TEST(CC_FUZZING, FuzzParser); ================================================ FILE: projects/ampproject/project.yaml ================================================ homepage: "https://github.com/ampproject/amphtml" language: c++ main_repo: "https://github.com/ampproject/amphtml" fuzzing_engines: - libfuzzer vendor_ccs: - "david@adalogics.com" ================================================ FILE: projects/angle/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install --no-install-recommends -y \ lsb-release sudo pkg-config file RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git ENV PATH=/src/depot_tools:$PATH WORKDIR angle RUN fetch angle RUN ./build/install-build-deps.sh --no-prompt COPY build.sh *.cc fuzzer_profile $SRC/ # Add fuzzer profile RUN cat $SRC/fuzzer_profile >> $SRC/angle/BUILD.gn ================================================ FILE: projects/angle/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Fix sanitizer ORIGINAL_SANITIZER="${SANITIZER:-}" if [ "$SANITIZER" = "coverage" ] || [ "$SANITIZER" = "introspector" ] || [ "$SANITIZER" = "none" ]; then export SANITIZER="address" fi # Configure arguments for gn build ARGS="treat_warnings_as_errors=false is_component_build=false libcxx_is_shared=false is_debug=false" ARGS+=" use_custom_libcxx=false use_sysroot=true ozone_platform_x11=false" ARGS+=" is_clang=true clang_use_chrome_plugins=false clang_base_path=\"/usr/local\"" # Configure arguments for gn build if [ "$SANITIZER" = "undefined" ]; then ARGS="$ARGS is_ubsan=true" fi # Prepare fuzzer in gn directory mkdir -p src/fuzz cp $SRC/*.cc src/fuzz/ # Generate ninja file for build gn gen out/fuzz --args="$ARGS" echo $SANITIZER # Build binary autoninja -C out/fuzz fuzz_sha1 autoninja -C out/fuzz fuzz_translator # Copy binary to $OUT cp ./out/fuzz/fuzz_sha1 $OUT cp ./out/fuzz/fuzz_translator $OUT # Reset sanitizer if [ -n "$ORIGINAL_SANITIZER" ]; then export SANITIZER="$ORIGINAL_SANITIZER" fi ================================================ FILE: projects/angle/fuzz_sha1.cc ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include "anglebase/sha1.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size <= 32 || size > 1024) return 0; angle::base::SecureHashAlgorithm sha; sha.Update(data, size); return 0; } ================================================ FILE: projects/angle/fuzzer_profile ================================================ declare_args() { complete_static_lib = true } if (angle_has_build) { executable("fuzz_sha1") { sources = [ "src/fuzz/fuzz_sha1.cc" ] deps = [ ":angle_static", ":angle_common", ] cflags = [ "-fsanitize=" + getenv("SANITIZER"), "-O1", "-fno-omit-frame-pointer", "-g", "-fprofile-instr-generate", "-fcoverage-mapping", "-resource-dir=/usr/local/lib/clang/22", "-fcoverage-prefix-map=../../src/=/src/angle/src/", "-fcoverage-prefix-map=../../include/=/src/angle/include/", "-fdebug-compilation-dir=/src/angle", ] ldflags = [ "-fsanitize=" + getenv("SANITIZER"), "-fprofile-instr-generate", ] if (getenv("FUZZING_ENGINE") == "centipede") { cflags += [ "-fsanitize-coverage=trace-pc-guard,pc-table,inline-8bit-counters,trace-cmp,indirect-calls" ] ldflags += [ getenv("LIB_FUZZING_ENGINE") ] } else if (getenv("FUZZING_ENGINE") == "afl") { cflags += [ "-fsanitize=fuzzer-no-link" ] ldflags += [ "/out/afl-compiler-rt-64.o", getenv("LIB_FUZZING_ENGINE"), ] } else if (getenv("FUZZING_ENGINE") == "libfuzzer") { cflags += [ "-fsanitize=fuzzer-no-link" ] ldflags += [ getenv("LIB_FUZZING_ENGINE_DEPRECATED") ] } else { cflags += [ "-fsanitize=fuzzer-no-link" ] ldflags += [ getenv("LIB_FUZZING_ENGINE") ] } configs -= ["//build/config/compiler:thin_archive"] libs = [ "/usr/local/lib/clang/22/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a", ] } executable("fuzz_translator") { sources = [ "src/compiler/fuzz/translator_fuzzer.cpp" ] include_dirs = [ "include", "src", ] deps = [ ":translator", ] cflags = [ "-fsanitize=" + getenv("SANITIZER"), "-O1", "-fno-omit-frame-pointer", "-g", "-fprofile-instr-generate", "-fcoverage-mapping", "-fsanitize=fuzzer-no-link", "-resource-dir=/usr/local/lib/clang/22", "-UANGLE_USE_ABSEIL", "-fcoverage-prefix-map=../../src/=/src/angle/src/", "-fcoverage-prefix-map=../../include/=/src/angle/include/", "-fdebug-compilation-dir=/src/angle", ] ldflags = [ "-fsanitize=" + getenv("SANITIZER"), "-fprofile-instr-generate", ] configs -= ["//build/config/compiler:thin_archive"] libs = [ "/usr/local/lib/clang/22/lib/x86_64-unknown-linux-gnu/libclang_rt.fuzzer.a", ] } } ================================================ FILE: projects/angle/project.yaml ================================================ homepage: "https://chromium.googlesource.com/angle/angle" language: c++ primary_contact: "arthur.chan@adalogics.com" auto_ccs: - "david@adalogics.com" - "arthur.chan@adalogics.com" main_repo: 'https://chromium.googlesource.com/angle/angle' fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/angular/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/angular/angular.git COPY compiler $SRC/angular/compiler COPY babel.config.json $SRC/angular WORKDIR $SRC/angular ================================================ FILE: projects/angular/babel.config.json ================================================ { "plugins": ["@babel/plugin-transform-modules-commonjs"], "ignore": ["**/@jazzer.js", "**/@babel", "**/istanbul-reports"] } ================================================ FILE: projects/angular/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ function change_type_to_commonjs() { # Find all package.json files inside the node_modules directory find "$1" -name "package.json" -type f | while read -r package_file; do # Check if the file contains the "type" field if grep -q '"type": "module"' "$package_file"; then # Replace "type": "module" with "type": "commonjs" sed -i 's/"type": "module"/"type": "commonjs"/' "$package_file" echo "Updated $package_file" fi done } function transform_dir_into_commonjs() { babel "$1" --keep-file-extension -D -d "$1"_commonjs rm -r "$1" mv "$1"_commonjs "$1" } function remove_dev_dependencies() { package_json=$(cat package.json) # Remove the "devDependencies" item from package.json new_package_json=$(echo "$package_json" | jq 'del(.devDependencies)') # Overwrite the package.json file with the updated content echo "$new_package_json" > package.json } function copy_bazel_build_into_build_dir() { local package=$1 local source_dir=$SRC/angular/dist/bin/packages/$package local destination_dir=$2 local extensions=("mjs" "d.ts") # Add the extensions you want to copy here mkdir -p "$destination_dir" cp "$SRC"/angular/babel.config.json "$destination_dir" # Copy files recursively from source directory to destination directory find "$source_dir" -type f -name "*.${extensions[0]}" -o -name "*.${extensions[1]}" | while read -r file; do # Get the relative path of the file (relative to the source directory) relative_path="${file#$source_dir}" # Remove leading slash if present relative_path="${relative_path#/}" # Create the directory structure inside the destination directory mkdir -p "$destination_dir/$(dirname "$relative_path")" # Copy the file to the destination directory cp "$file" "$destination_dir/$relative_path" done } function rename_mjs_files() { local destination_dir=$1 find "$destination_dir" -type f -name "*.mjs" | while read -r file; do filename="${file##*/}" extension="${filename##*.}" # Check if the file has the "mjs" extension if [ "$extension" = "mjs" ]; then new_filename="${file%.mjs}.js" mv "$file" "$new_filename" fi done } function build_package() { local package=$1 local package_build_dir=$SRC/$package-build yarn bazel build packages/"$package" copy_bazel_build_into_build_dir "$package" "$package_build_dir" rename_mjs_files "$package_build_dir" chmod +w "$package_build_dir" mkdir -p "$package_build_dir" cp "$SRC"/angular/packages/"$package"/package.json "$package_build_dir" pushd "$package_build_dir" remove_dev_dependencies npm install npm install --save-dev @babel/core @babel/plugin-transform-modules-commonjs npm install --save-dev @jazzer.js/core transform_dir_into_commonjs "$package_build_dir" change_type_to_commonjs "$package_build_dir" popd mkdir -p "$SRC"/angular/"$package" cp "$package_build_dir"/* "$SRC"/angular/"$package"/ -r rm "$package_build_dir" -r } npm install --global yarn patch-package husky @babel/cli yarn install mkdir "$OUT"/angular build_package compiler # Build Fuzzers. compile_javascript_fuzzer angular/compiler fuzz_tests/fuzz_parse_template --sync compile_javascript_fuzzer angular/compiler fuzz_tests/fuzz_parser --sync ================================================ FILE: projects/angular/compiler/fuzz_tests/fuzz_parse_template.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const { parseTemplate } = require('../src/render3/view/template'); module.exports.fuzz = function(data) { const provider = new FuzzedDataProvider(data); const templateContent = provider.consumeRemainingAsString(); try { parseTemplate(templateContent); } catch (error) { } }; ================================================ FILE: projects/angular/compiler/fuzz_tests/fuzz_parser.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const { Lexer } = require('../src/expression_parser/lexer'); const { Parser } = require('../src/expression_parser/parser'); function createParser() { return new Parser(new Lexer()) } function parseAction(text, location = null, offset = 0) { return createParser().parseAction(text, /* isAssignmentEvent */ false, location, offset); } function parseBinding(text, location = null, offset = 0) { return createParser().parseBinding(text, location, offset); } function parseInterpolation(text, location = null, offset = 0) { return createParser().parseInterpolation(text, location, offset, null); } function splitInterpolation(text, location = null) { return createParser().splitInterpolation(text, location, null); } function parseSimpleBinding(text, location = null, offset = 0) { return createParser().parseSimpleBinding(text, location, offset); } const parsingTasks = [ parseAction, parseBinding, parseInterpolation, parseSimpleBinding, splitInterpolation ] module.exports.fuzz = function(data) { const provider = new FuzzedDataProvider(data); const action = provider.consumeIntegralInRange(0, parsingTasks.length); const text = provider.consumeRemainingAsString(); try { parsingTasks[action](text); } catch (error) { } }; ================================================ FILE: projects/angular/project.yaml ================================================ homepage: https://angular.io/ language: javascript main_repo: https://github.com/angular/angular.git fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/angus-mail/ASCIIUtilityFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.lang.NumberFormatException; import org.eclipse.angus.mail.util.ASCIIUtility; public class ASCIIUtilityFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { byte[] input = data.consumeRemainingAsBytes(); try{ ASCIIUtility.parseInt(input, 0, input.length); ASCIIUtility.parseLong(input, 0, input.length); } catch(NumberFormatException e){} ASCIIUtility.toString(input); } } ================================================ FILE: projects/angus-mail/BASE64EncoderStreamFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.lang.NumberFormatException; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.eclipse.angus.mail.util.BASE64EncoderStream; import org.eclipse.angus.mail.util.ASCIIUtility; public class BASE64EncoderStreamFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BASE64EncoderStream b64es = new BASE64EncoderStream(baos, Integer.MAX_VALUE); try{ b64es.write(data.consumeRemainingAsBytes()); } catch(IOException e){ return; } } } ================================================ FILE: projects/angus-mail/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.6/bin/mvn RUN git clone --depth 1 https://github.com/eclipse-ee4j/angus-mail.git angus-mail COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/angus-mail ================================================ FILE: projects/angus-mail/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15 -Dmaven.javadoc.skip=true" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "core/target/angus-core-$CURRENT_VERSION.jar" $OUT/angus-core.jar ALL_JARS="angus-core.jar jakarta.mail-1.0.1-SNAPSHOT.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --instrumentation_includes=com.sun.mail.** \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/angus-mail/project.yaml ================================================ homepage: "https://eclipse-ee4j.github.io/mail" language: jvm primary_contact: "" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/eclipse-ee4j/angus-mail.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" ================================================ FILE: projects/anise/Dockerfile ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 --branch master https://github.com/nyx-space/anise anise RUN apt-get update && apt-get install -y tcsh libc++-dev libc++abi-dev && \ apt-get clean && rm -rf /var/lib/apt/lists/* && \ cd anise && ./dev-env-setup.sh ENV RUSTUP_TOOLCHAIN=nightly-2025-07-03 ENV RUSTFLAGS="-C link-arg=-lc++" WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/anise/build.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/anise/anise cargo fuzz build -O FUZZ_TARGET_OUTPUT_DIR=$SRC/anise/target/x86_64-unknown-linux-gnu/release for f in fuzz/fuzz_targets/*.rs do FUZZ_TARGET_NAME=$(basename ${f%.*}) cp "$FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME" "$OUT/" done ================================================ FILE: projects/anise/project.yaml ================================================ homepage: "https://docs.rs/anise/latest/anise/index.html" language: rust primary_contact: "christopher.rabotin@gmail.com" main_repo: "https://github.com/nyx-space/anise.git" file_github_issue: true help_url: "https://github.com/nyx-space/anise/blob/master/anise/fuzz/README.md" sanitizers: - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/aniso8601/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://codeberg.org/nielsenb-jf/aniso8601 aniso8601 COPY *.sh *py $SRC/ WORKDIR $SRC/aniso8601 ================================================ FILE: projects/aniso8601/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/aniso8601/fuzz_aniso8601.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import aniso8601 from aniso8601.date import parse_date from aniso8601.decimalfraction import normalize from aniso8601.duration import parse_duration from aniso8601.interval import parse_interval from aniso8601.timezone import parse_timezone def fuzz_date(data): fdp = atheris.FuzzedDataProvider(data) try: parse_date(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (aniso8601.exceptions.ISOFormatError, aniso8601.exceptions.RangeCheckError): pass except NotImplementedError: # https://bitbucket.org/nielsenb/aniso8601/src/8819c46cb9548298da5b59b830782c1cc37ba295/aniso8601/date.py#lines-77 pass def fuzz_decimal_fraction(data): fdp = atheris.FuzzedDataProvider(data) normalize(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) def fuzz_duration(data): fdp = atheris.FuzzedDataProvider(data) try: parse_duration(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (aniso8601.exceptions.ISOFormatError, aniso8601.exceptions.RangeCheckError): pass except NotImplementedError: # https://bitbucket.org/nielsenb/aniso8601/src/8819c46cb9548298da5b59b830782c1cc37ba295/aniso8601/date.py#lines-77 pass def fuzz_interval(data): fdp = atheris.FuzzedDataProvider(data) try: parse_interval(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (aniso8601.exceptions.ISOFormatError, aniso8601.exceptions.RangeCheckError): pass except NotImplementedError: # https://bitbucket.org/nielsenb/aniso8601/src/8819c46cb9548298da5b59b830782c1cc37ba295/aniso8601/date.py#lines-77 pass def fuzz_time(data): fdp = atheris.FuzzedDataProvider(data) try: parse_timezone(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (aniso8601.exceptions.ISOFormatError, aniso8601.exceptions.RangeCheckError): pass except NotImplementedError: # https://bitbucket.org/nielsenb/aniso8601/src/8819c46cb9548298da5b59b830782c1cc37ba295/aniso8601/date.py#lines-77 pass def TestOneInput(data): fuzz_date(data) fuzz_decimal_fraction(data) fuzz_duration(data) fuzz_interval(data) fuzz_time(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/aniso8601/project.yaml ================================================ homepage: https://bitbucket.org/nielsenb/aniso8601 main_repo: https://bitbucket.org/nielsenb/aniso8601 language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/ansible/Dockerfile ================================================ # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake build-essential RUN pip3 install --upgrade pip RUN git clone https://github.com/ansible/ansible RUN pip3 install --upgrade pip && \ pip3 install cython cryptography RUN cd ansible && \ pip3 install -r ./requirements.txt WORKDIR ansible COPY build.sh fuzz_encrypt.sh *.py $SRC/ ================================================ FILE: projects/ansible/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 ./setup.py install cd $SRC # Build parse and task fuzzers compile_python_fuzzer fuzz_parse.py --add-data ansible/lib/ansible/config:ansible/config compile_python_fuzzer fuzz_task.py --add-data ansible/lib/ansible/config:ansible/config # Build fuzz_encrypt with a specific wrapper only in non-coverage if [ "$SANITIZER" != "coverage" ]; then compile_python_fuzzer fuzz_encrypt.py --add-data ansible/lib/ansible/config:ansible/config cp $SRC/fuzz_encrypt.sh $OUT/fuzz_encrypt chmod +x $OUT/fuzz_encrypt fi cp /usr/lib/x86_64-linux-gnu/libcrypt.so.1.1.0 $OUT/libcrypt.so ================================================ FILE: projects/ansible/fuzz_encrypt.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): import crypt from ansible.plugins.filter.core import get_encrypted_password from ansible.utils import encrypt from ansible import errors @atheris.instrument_func def TestInput(input_bytes): if len(input_bytes) < 50: return fdp = atheris.FuzzedDataProvider(input_bytes) try: for h in [ "md5", "sha512", "pbkdf2_sha256", "crypt16" ]: get_encrypted_password( fdp.ConsumeString(20), h, salt=fdp.ConsumeString(20) ) except errors.AnsibleFilterError as e: pass def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ansible/fuzz_encrypt.sh ================================================ #!/bin/sh # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=$(dirname "$0") chmod +x $this_dir/fuzz_encrypt.pkg LD_PRELOAD="$this_dir/sanitizer_with_fuzzer.so $this_dir/libcrypt.so" ASAN_OPTIONS=$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=$this_dir/llvm-symbolizer:detect_leaks=0 $this_dir/fuzz_encrypt.pkg $@ ================================================ FILE: projects/ansible/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests lib/ansible/parsing/""" import atheris import sys with atheris.instrument_imports(): from ansible.errors import AnsibleError, AnsibleParserError from ansible.parsing import splitter from ansible.parsing import quoting @atheris.instrument_func def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) try: # Test splitter module args = splitter.split_args(fdp.ConsumeString(50)) splitter.join_args(args) # Test quoting module quoting.is_quoted(fdp.ConsumeString(10)) quoting.unquote(fdp.ConsumeString(10)) except (AnsibleError, AnsibleParserError) as e: pass def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ansible/fuzz_task.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests ansible.playbook.task""" import atheris import sys with atheris.instrument_imports(): from ansible.errors import ( AnsibleError, AnsibleParserError, AnsibleUndefinedVariable ) from ansible.playbook.task import Task @atheris.instrument_func def TestInput(input_bytes): if len(input_bytes) < 5: return fdp = atheris.FuzzedDataProvider(input_bytes) try: task = Task.load( { 'name': fdp.ConsumeString(10), 'shell': fdp.ConsumeString(10), 'action': fdp.ConsumeString(10), 'debug': fdp.ConsumeString(10) } ) task.get_vars() task.get_include_params() task.copy() data = task.serialize() task.deserialize(data) except ( AnsibleError, AnsibleParserError, AnsibleUndefinedVariable ) as e: pass def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ansible/project.yaml ================================================ base_os_version: ubuntu-24-04 fuzzing_engines: - libfuzzer homepage: https://github.com/ansible/ansible language: python main_repo: https://github.com/ansible/ansible sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/antlr3-java/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/antlr/antlr3.git antlr3 COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/antlr3 ================================================ FILE: projects/antlr3-java/GrammarFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.antlr.runtime.RecognitionException; import org.antlr.tool.Grammar; public class GrammarFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ new Grammar(data.consumeString(1000)); } catch (RecognitionException | UnsupportedOperationException e){ return; } } } ================================================ FILE: projects/antlr3-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export MAVEN_OPTS="-Xmx1G" MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "tool/target/antlr-$CURRENT_VERSION.jar" $OUT/antlr3.jar ALL_JARS="antlr3.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/antlr3-java/project.yaml ================================================ homepage: "https://www.antlr.org" language: jvm main_repo: "https://github.com/antlr/antlr3.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/antlr4-java/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/antlr/antlr4.git antlr4 COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/antlr4 ================================================ FILE: projects/antlr4-java/GrammarFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.LexerInterpreter; import org.antlr.v4.runtime.ParserInterpreter; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.tool.LexerGrammar; import org.antlr.v4.tool.Grammar; public class GrammarFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { LexerGrammar lg; Grammar g; try{ lg = new LexerGrammar(data.consumeString(1000)); g = new Grammar(data.consumeString(1000)); } catch (org.antlr.runtime.RecognitionException | UnsupportedOperationException e){ return; } LexerInterpreter lexEngine = lg.createLexerInterpreter(CharStreams.fromString(data.consumeRemainingAsString())); CommonTokenStream tokens = new CommonTokenStream(lexEngine); ParserInterpreter parser = g.createParserInterpreter(tokens); } } ================================================ FILE: projects/antlr4-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export MAVEN_OPTS="-Xmx1G" MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "tool/target/antlr4-$CURRENT_VERSION.jar" $OUT/antlr4.jar ALL_JARS="antlr4.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/antlr4-java/project.yaml ================================================ homepage: "https://www.antlr.org" language: jvm main_repo: "https://github.com/antlr/antlr4.git" fuzzing_engines: - libfuzzer sanitizers: - address primary_contact: "terrence.parr@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/apache-axis2/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # # install maven configuration, which is also used by gradles's publishToMavenLocal # ADD maven-settings.xml ${SRC}/ RUN apt-get install -y xmlstarlet RUN mkdir -p ~/.m2 && \ xmlstarlet ed \ -u "settings/localRepository" -v "${OUT}/m2/repository" \ < ${SRC}/maven-settings.xml > ~/.m2/settings.xml # # install maven and gradle # RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.8.7 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.8.7/apache-maven-3.8.7/bin/mvn RUN curl -L https://services.gradle.org/distributions/gradle-7.6-bin.zip -o gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE $SRC/gradle/gradle-7.6/bin/gradle ENV LIBRARY_NAME axis-axis2-java-core WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/apache/axis-axis2-java-core.git ${LIBRARY_NAME} ADD build.sh ${SRC}/ ADD ${LIBRARY_NAME}-fuzzer ${SRC}/${LIBRARY_NAME}-fuzzer/ WORKDIR ${SRC}/${LIBRARY_NAME} ================================================ FILE: projects/apache-axis2/axis-axis2-java-core-fuzzer/pom.xml ================================================ 4.0.0 ossfuzz axis-axis2-java-core-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 1.8.2 ossfuzz.HttpInterfaceFuzzer com.code-intelligence jazzer-api 0.12.0 org.apache.axis2 axis2-adb ${fuzzedLibaryVersion} org.apache.axis2 axis2-kernel ${fuzzedLibaryVersion} org.apache.axis2 axis2-jaxws ${fuzzedLibaryVersion} org.apache.axis2 axis2-transport-http ${fuzzedLibaryVersion} org.apache.axis2 axis2-transport-local ${fuzzedLibaryVersion} org.apache.httpcomponents httpclient 4.5.13 org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/apache-axis2/axis-axis2-java-core-fuzzer/src/main/java/org/apache/axis2/HttpInterfaceFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package org.apache.axis2; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.DataOutputStream; import java.io.IOException; import java.net.*; import org.apache.http.client.utils.URIBuilder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import org.apache.axis2.kernel.SimpleAxis2Server; public class HttpInterfaceFuzzer extends SimpleAxis2Server { private FuzzedDataProvider fuzzedDataProvider; public HttpInterfaceFuzzer(FuzzedDataProvider fuzzedDataProvider) throws Exception { super(null, null); this.fuzzedDataProvider = fuzzedDataProvider; deployService("samples.quickstart.service.pojo.StockQuoteService"); } void test() { // Begin cleanup try { stop(); } catch (Exception e) { e.printStackTrace(); } try { start(); var client = HttpClient.newHttpClient(); String host = "localhost"; int port = getPort(); // Get the dynamically assigned port URI uri = new URI("http://" + host + ":" + port + "/axis2/services/StockQuoteService/" + fuzzedDataProvider.consumeRemainingAsString()); var request = HttpRequest.newBuilder(uri) .GET() .build(); var reponse = client.send(request, HttpResponse.BodyHandlers.ofString()); } catch (Exception e) { e.printStackTrace(); } finally { try { stop(); } catch (Exception ex) { ex.printStackTrace(); } } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { HttpInterfaceFuzzer fixture = new HttpInterfaceFuzzer(fuzzedDataProvider); fixture.test(); fixture = null; Thread.sleep(100); // Ensure closed state ready for next instance } private int getPort() { try (ServerSocket socket = new ServerSocket(0)) { return socket.getLocalPort(); } catch (IOException e) { e.printStackTrace(); return 6060; // Backup in failure of auto assign } } } ================================================ FILE: projects/apache-axis2/axis-axis2-java-core-fuzzer/src/main/java/samples/quickstart/service/pojo/StockQuoteService.java ================================================ /* * from https://github.com/apache/axis-axis2-java-core/blob/d8237fd1058354874a3e4c2f07da780a27bcf3ff/modules/samples/quickstart/src/samples/quickstart/service/pojo/StockQuoteService.java */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package samples.quickstart.service.pojo; import java.util.HashMap; public class StockQuoteService { private HashMap map = new HashMap(); void printMap(HashMap map) { for (Object name: map.keySet()) { String key = name.toString(); String value = map.get(name).toString(); System.out.println(key + "=" + value); } } public double getPrice(String symbol) { Double price = (Double) map.get(symbol); if(price != null){ return price.doubleValue(); } return 42.00; } public void update(String symbol, double price) { map.put(symbol, new Double(price)); } } ================================================ FILE: projects/apache-axis2/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-DskipTests" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/${LIBRARY_NAME}" ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}-fuzzer" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/apache-axis2/maven-settings.xml ================================================ ${user.home}/.m2/repository ================================================ FILE: projects/apache-axis2/project.yaml ================================================ homepage: "https://axis.apache.org/axis2/java/core/" language: jvm main_repo: "https://github.com/apache/axis-axis2-java-core.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/apache-commons-bcel/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/apache/commons-bcel.git ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/commons-bcel ================================================ FILE: projects/apache-commons-bcel/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/commons-bcel" ${MVN} package ${MVN_FLAGS} ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd ${SRC} ${MVN} package -DbcelVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/bcel-fuzzer-${CURRENT_VERSION}.jar ${OUT}/bcel-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} bcel-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|'); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/apache-commons-bcel/pom.xml ================================================ 4.0.0 ossfuzz bcel-fuzzer ${bcelVersion} jar 15 15 UTF-8 ossfuzz.BcelFuzzer com.code-intelligence jazzer-api 0.12.0 org.apache.bcel bcel ${bcelVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/apache-commons-bcel/project.yaml ================================================ homepage: "https://commons.apache.org/proper/commons-bcel/" language: jvm main_repo: "https://github.com/apache/commons-bcel.git" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-bcel/remove-rat.diff ================================================ --- a/pom.xml +++ b/pom.xml @@ -361,7 +361,7 @@ - clean apache-rat:check checkstyle:check verify javadoc:javadoc + clean checkstyle:check verify javadoc:javadoc org.apache.felix ================================================ FILE: projects/apache-commons-bcel/src/main/java/ossfuzz/BcelFuzzer.java ================================================ /* * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ossfuzz; import java.io.ByteArrayInputStream; import java.io.IOException; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.bcel.classfile.*; public class BcelFuzzer { BcelFuzzer(FuzzedDataProvider fuzzedDataProvider) { } void test(FuzzedDataProvider fuzzedDataProvider) throws Exception { var m_string = fuzzedDataProvider.consumeString(10); var m_byte = fuzzedDataProvider.consumeRemainingAsBytes(); try { new ClassParser(new ByteArrayInputStream(m_byte), m_string).parse(); } catch (IOException e) { // documented ignore } catch (ClassFormatException e) { // documented ignore } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { BcelFuzzer testClosure = new BcelFuzzer(fuzzedDataProvider); testClosure.test(fuzzedDataProvider); } } ================================================ FILE: projects/apache-commons-beanutils/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/apache/commons-beanutils.git ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/commons-beanutils ================================================ FILE: projects/apache-commons-beanutils/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-DskipTests" ALL_JARS="" # install the build servers' jazzer-api into the maven repository pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/commons-beanutils" ${MVN} package ${MVN_FLAGS} ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd ${SRC} ${MVN} package -DbeanutilsVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/beanutils-fuzzer-${CURRENT_VERSION}.jar ${OUT}/beanutils-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} beanutils-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|'); # the .java was stripped by sed if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/apache-commons-beanutils/pom.xml ================================================ 4.0.0 ossfuzz beanutils-fuzzer ${beanutilsVersion} jar 15 15 UTF-8 ossfuzz.BeanutilsFuzzer com.code-intelligence jazzer-api 0.12.0 org.apache.commons commons-beanutils2 ${beanutilsVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/apache-commons-beanutils/project.yaml ================================================ homepage: "https://commons.apache.org/proper/commons-beanutils/" language: jvm main_repo: "https://github.com/apache/commons-beanutils.git" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-beanutils/src/main/java/ossfuzz/BeanutilsFuzzer.java ================================================ /* * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ossfuzz; import java.util.HashMap; import java.util.Map; import org.apache.commons.beanutils2.BasicDynaClass; import org.apache.commons.beanutils2.DynaBean; import org.apache.commons.beanutils2.DynaClass; import org.apache.commons.beanutils2.DynaProperty; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; public class BeanutilsFuzzer { String m_string; int m_int; int m_int_array[]; String m_string_array[]; boolean m_bool; double m_double; float m_float; short m_short; long m_long; Map m_map; BeanutilsFuzzer(int integer, String string, int[] intArray, boolean bool, double dbl, float flt, Map map, String string_array[], short shrt, long lng) { m_int = integer; m_string = string; m_bool = bool; m_int_array = intArray; m_double = dbl; m_float = flt; m_map = map; m_string_array = string_array; m_short = shrt; m_long = lng; } BeanutilsFuzzer(FuzzedDataProvider fuzzedDataProvider) { m_int = fuzzedDataProvider.consumeInt(); m_int_array = fuzzedIntArray(fuzzedDataProvider); m_bool = fuzzedDataProvider.consumeBoolean(); m_double = fuzzedDataProvider.consumeDouble(); m_float = fuzzedDataProvider.consumeFloat(); m_map = fuzzedMap(fuzzedDataProvider); m_string_array = fuzzedStringArray(fuzzedDataProvider); m_short = fuzzedDataProvider.consumeShort(); m_long = fuzzedDataProvider.consumeLong(); m_string = fuzzedDataProvider.consumeRemainingAsAsciiString(); } protected DynaClass createDynaClass() { final int[] intArray = new int[0]; final String[] stringArray = new String[0]; final DynaClass dynaClass = new BasicDynaClass("TestDynaClass", null, new DynaProperty[] { new DynaProperty("booleanProperty", Boolean.TYPE), new DynaProperty("booleanSecond", Boolean.TYPE), new DynaProperty("doubleProperty", Double.TYPE), new DynaProperty("floatProperty", Float.TYPE), new DynaProperty("intArray", intArray.getClass()), new DynaProperty("intProperty", Integer.TYPE), new DynaProperty("longProperty", Long.TYPE), new DynaProperty("mappedProperty", Map.class), new DynaProperty("shortProperty", Short.TYPE), new DynaProperty("stringArray", stringArray.getClass()), new DynaProperty("stringProperty", String.class), }); return dynaClass; } int[] fuzzedIntArray(FuzzedDataProvider fuzzedDataProvider) { int n = fuzzedDataProvider.consumeInt(1, 100); int array[] = new int[n]; for (int i = 0; i < n; ++i) { array[i] = fuzzedDataProvider.consumeInt(); } return array; } String[] fuzzedStringArray(FuzzedDataProvider fuzzedDataProvider) { int n = fuzzedDataProvider.consumeInt(1, 100); String array[] = new String[n]; for (int i = 0; i < n; ++i) { array[i] = fuzzedDataProvider.consumeString(16); } return array; } Map fuzzedMap(FuzzedDataProvider fuzzedDataProvider) { int n = fuzzedDataProvider.consumeInt(1, 100); Map map = new HashMap(); for (int i = 0; i < n; i++) { switch (fuzzedDataProvider.consumeInt(0, 7)) { case 0: map.put(fuzzedDataProvider.consumeString(16), new Integer(fuzzedDataProvider.consumeInt())); break; case 1: map.put(fuzzedDataProvider.consumeString(16), new Float(fuzzedDataProvider.consumeFloat())); break; case 2: map.put(fuzzedDataProvider.consumeString(16), new Double(fuzzedDataProvider.consumeDouble())); break; case 3: map.put(fuzzedDataProvider.consumeString(16), new String(fuzzedDataProvider.consumeString(16))); break; case 4: map.put(fuzzedDataProvider.consumeString(16), new Boolean(fuzzedDataProvider.consumeBoolean())); break; case 5: map.put(fuzzedDataProvider.consumeString(16), fuzzedIntArray(fuzzedDataProvider)); break; case 6: map.put(fuzzedDataProvider.consumeString(16), fuzzedMap(fuzzedDataProvider)); break; } } return map; } void test() throws Exception { final DynaClass dynaClass = createDynaClass(); DynaBean bean = dynaClass.newInstance(); bean.set("booleanProperty", new Boolean(m_bool)); bean.set("booleanSecond", new Boolean(m_bool)); if (!bean.get("booleanSecond").equals(new Boolean(m_bool))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("doubleProperty", new Double(m_double)); if (!bean.get("doubleProperty").equals(new Double(m_double))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("floatProperty", new Float(m_float)); if (!bean.get("floatProperty").equals(new Float(m_float))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("intArray", m_int_array); if (!bean.get("intArray").equals(m_int_array)) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("stringArray", m_string_array); if (!bean.get("stringArray").equals(m_string_array)) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("mappedProperty", m_map); if (!bean.get("mappedProperty").equals(m_map)) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("intProperty", new Integer(m_int)); if (!bean.get("intProperty").equals(new Integer(m_int))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("longProperty", new Long(m_long)); if (!bean.get("longProperty").equals(new Long(m_long))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } bean.set("shortProperty", new Short(m_short)); if (!bean.get("shortProperty").equals(new Short(m_short))) { throw new FuzzerSecurityIssueLow("Data corruption detected"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { BeanutilsFuzzer testClosure = new BeanutilsFuzzer(fuzzedDataProvider); testClosure.test(); } } ================================================ FILE: projects/apache-commons-cli/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/apache/commons-cli.git COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/commons-cli ================================================ FILE: projects/apache-commons-cli/ParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; public class ParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { DefaultParser parser = new DefaultParser(); parser = DefaultParser.builder().setStripLeadingAndTrailingQuotes(data.consumeBoolean()).setAllowPartialMatching(data.consumeBoolean()).build(); Options options = new Options(); options.addOption("a", "aa", true, ""); options.addOption("b", "bb", false, ""); try{ parser.parse(options, new String[]{data.consumeString(100), data.consumeRemainingAsString()}); } catch (ParseException | StringIndexOutOfBoundsException e){ return; } } } ================================================ FILE: projects/apache-commons-cli/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-cli-$CURRENT_VERSION.jar" $OUT/commons-cli.jar ALL_JARS="commons-cli.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-cli/project.yaml ================================================ homepage: "https://commons.apache.org/proper/commons-cli/" language: jvm main_repo: "https://github.com/apache/commons-cli.git" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-codec/BinaryEncodingFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.BaseNCodecInputStream; import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.codec.binary.Base32InputStream; import org.apache.commons.codec.binary.Base16InputStream; import org.apache.commons.codec.binary.BaseNCodecOutputStream; import org.apache.commons.codec.binary.Base64OutputStream; import org.apache.commons.codec.binary.Base32OutputStream; import org.apache.commons.codec.binary.Base16OutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; public class BinaryEncodingFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { int selection = data.consumeInt(1,3); BaseNCodecInputStream bis; BaseNCodecOutputStream bos; ByteArrayOutputStream baos; String encodingType; byte[] originalInput = data.consumeRemainingAsBytes(); final int SIZE = originalInput.length * 2; byte[] encoded = new byte[SIZE]; //Base32 encoding requires 5 bytes per unencoded block if(originalInput.length < 5){ return; } switch(selection){ case 1: bis = new Base16InputStream(new ByteArrayInputStream(originalInput), true); baos = new ByteArrayOutputStream(SIZE); bos = new Base16OutputStream(baos, false); encodingType = "Base16"; break; case 2: bis = new Base32InputStream(new ByteArrayInputStream(originalInput), true); baos = new ByteArrayOutputStream(SIZE); bos = new Base32OutputStream(baos, false); encodingType = "Base32"; break; case 3: bis = new Base64InputStream(new ByteArrayInputStream(originalInput), true); baos = new ByteArrayOutputStream(SIZE); bos = new Base64OutputStream(baos, false); encodingType = "Base64"; break; default: return; } try { bis.read(encoded); } catch (IOException e){ return; } try{ bos.write(encoded, 0, SIZE); } catch (IOException e){ return; } byte[] decoded = baos.toByteArray(); if(!Arrays.equals(originalInput, decoded)){ throw new IllegalStateException("Failed to decode: " + Hex.encodeHexString(originalInput) + "\n" + "Encoded using: " + "" + "\n" + "Encoded data: " + Hex.encodeHexString(encoded) + "\n" + "Decoded data: " + Hex.encodeHexString(decoded) + "\n"); } } } ================================================ FILE: projects/apache-commons-codec/ChecksumFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.zip.Checksum; import org.apache.commons.codec.digest.PureJavaCrc32; import org.apache.commons.codec.digest.PureJavaCrc32C; import org.apache.commons.codec.digest.XXHash32; /** * This fuzzer targets the methods in different Checksum implementation classes in the digest * package. */ public class ChecksumFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Checksum checksum = null; // Create objects for different checksum implementation classes switch (data.consumeInt(1, 3)) { case 1: checksum = new XXHash32(data.consumeInt()); break; case 2: checksum = new PureJavaCrc32(); break; case 3: checksum = new PureJavaCrc32C(); break; } // Fuzz methods of the Checksum implementation classes if (checksum != null) { byte[] byteArray = data.consumeRemainingAsBytes(); checksum.reset(); checksum.update(byteArray, 0, byteArray.length); checksum.getValue(); } } } ================================================ FILE: projects/apache-commons-codec/CryptFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.codec.digest.Crypt; /** This fuzzer targets the crypt methods in the Crypt class. */ public class CryptFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { if (data.consumeBoolean()) { Crypt.crypt(data.consumeRemainingAsBytes(), null); } else { Crypt.crypt(data.consumeBytes(data.remainingBytes()), data.consumeRemainingAsString()); } } catch (IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/DigestUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.commons.codec.digest.DigestUtils; /** * This fuzzer targets the static methods in the DigestUtils class for calculating the hex value of * using different hashing methods. */ public class DigestUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 12); ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); switch (choice) { case 1: DigestUtils.md2Hex(bais); break; case 2: DigestUtils.md5Hex(bais); break; case 3: DigestUtils.sha1Hex(bais); break; case 4: DigestUtils.sha256Hex(bais); break; case 5: DigestUtils.sha3_224Hex(bais); break; case 6: DigestUtils.sha3_256Hex(bais); break; case 7: DigestUtils.sha384Hex(bais); break; case 8: DigestUtils.sha512Hex(bais); break; case 9: DigestUtils.sha512_224Hex(bais); break; case 10: DigestUtils.sha512_256Hex(bais); break; case 11: DigestUtils.sha512Hex(bais); break; case 12: DigestUtils.shaHex(bais); break; } } catch (IOException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-codec.git commons-codec COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/commons-codec ================================================ FILE: projects/apache-commons-codec/HmacUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.EnumSet; import org.apache.commons.codec.digest.HmacAlgorithms; import org.apache.commons.codec.digest.HmacUtils; /** This fuzzer targets the hmacHex methods in the HmacUtils class. */ public class HmacUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 4); // Create HamcUtils object with random algorithm and key bytes HmacUtils utils = new HmacUtils( data.pickValue(EnumSet.allOf(HmacAlgorithms.class)), data.consumeBytes(data.remainingBytes())); // Fuzz different hmacHex methods in HmacUtils class switch (choice) { case 1: utils.hmacHex(data.consumeRemainingAsBytes()); break; case 2: utils.hmacHex(ByteBuffer.wrap(data.consumeRemainingAsBytes())); break; case 3: utils.hmacHex(data.consumeRemainingAsString()); break; case 4: utils.hmacHex(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; } } catch (IOException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/LanguageStringEncoderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.codec.EncoderException; import org.apache.commons.codec.StringEncoder; import org.apache.commons.codec.language.Caverphone1; import org.apache.commons.codec.language.Caverphone2; import org.apache.commons.codec.language.ColognePhonetic; import org.apache.commons.codec.language.DaitchMokotoffSoundex; import org.apache.commons.codec.language.DoubleMetaphone; import org.apache.commons.codec.language.MatchRatingApproachEncoder; import org.apache.commons.codec.language.Metaphone; import org.apache.commons.codec.language.Nysiis; import org.apache.commons.codec.language.RefinedSoundex; import org.apache.commons.codec.language.Soundex; import org.apache.commons.codec.language.bm.BeiderMorseEncoder; /** * This fuzzer targets the encode method in different StringEncoder implementation classes in the * language or language.bm package. */ public class LanguageStringEncoderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Create objects of different StringEncoder implementation classes StringEncoder strEncoder = null; switch (data.consumeInt(1, 11)) { case 1: strEncoder = new Caverphone1(); break; case 2: strEncoder = new Caverphone2(); break; case 3: strEncoder = new ColognePhonetic(); break; case 4: strEncoder = new DaitchMokotoffSoundex(data.consumeBoolean()); break; case 5: strEncoder = new DoubleMetaphone(); break; case 6: strEncoder = new MatchRatingApproachEncoder(); break; case 7: strEncoder = new Metaphone(); break; case 8: strEncoder = new Nysiis(data.consumeBoolean()); break; case 9: strEncoder = new RefinedSoundex(data.consumeString(data.remainingBytes())); break; case 10: strEncoder = new Soundex(data.consumeString(data.remainingBytes()), data.consumeBoolean()); break; case 11: strEncoder = new BeiderMorseEncoder(); break; } // Fuzz encode method of the StringEncoder object if (strEncoder != null) { strEncoder.encode(data.consumeRemainingAsString()); } } catch (EncoderException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/MurmurHashFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import org.apache.commons.codec.digest.MurmurHash2; import org.apache.commons.codec.digest.MurmurHash3; /** * This fuzzer argets different hashing methods in the MurmurHash2 and MurmurHash3 classes of the * digest package. */ public class MurmurHashFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 12); Integer seed = data.consumeInt(); byte[] byteArray = data.consumeRemainingAsBytes(); switch (choice) { case 1: MurmurHash2.hash32(byteArray, byteArray.length, seed); break; case 2: MurmurHash2.hash64(byteArray, byteArray.length, seed); break; case 3: MurmurHash3.hash32x86(byteArray, 0, byteArray.length, seed); break; case 4: MurmurHash3.hash32(ByteBuffer.wrap(byteArray).getLong(), seed); break; case 5: MurmurHash3.hash128x64(byteArray, 0, byteArray.length, seed); break; case 6: MurmurHash3.hash128(byteArray); break; } } catch (BufferUnderflowException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/NetCodecFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.codec.BinaryDecoder; import org.apache.commons.codec.BinaryEncoder; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.EncoderException; import org.apache.commons.codec.StringDecoder; import org.apache.commons.codec.StringEncoder; import org.apache.commons.codec.net.BCodec; import org.apache.commons.codec.net.PercentCodec; import org.apache.commons.codec.net.QCodec; import org.apache.commons.codec.net.QuotedPrintableCodec; import org.apache.commons.codec.net.URLCodec; /** * This fuzzer targets the encode method in different BinaryEncoder and StringEncoder implementation * classes and the decode method in different BinaryDecoder and StringDecoder implementation classes * of the net package. */ public class NetCodecFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Create objects for fuzzing the encode and decode methods BinaryEncoder binEncoder = null; BinaryDecoder binDecoder = null; StringEncoder strEncoder = null; StringDecoder strDecoder = null; switch (data.consumeInt(1, 5)) { case 1: BCodec bCodec = new BCodec(); strEncoder = bCodec; strDecoder = bCodec; break; case 2: PercentCodec pCodec = new PercentCodec(data.consumeBytes(data.remainingBytes()), data.consumeBoolean()); binEncoder = pCodec; binDecoder = pCodec; break; case 3: QCodec qCodec = new QCodec(); strEncoder = qCodec; strDecoder = qCodec; break; case 4: QuotedPrintableCodec qPCodec = new QuotedPrintableCodec(data.consumeBoolean()); binEncoder = qPCodec; binDecoder = qPCodec; strEncoder = qPCodec; strDecoder = qPCodec; break; case 5: URLCodec uCodec = new URLCodec(); binEncoder = uCodec; binDecoder = uCodec; strEncoder = uCodec; strDecoder = uCodec; break; } // Fuzz encode and decode methods if (binEncoder != null) { binEncoder.encode(data.consumeRemainingAsBytes()); } if (binDecoder != null) { binDecoder.decode(data.consumeRemainingAsBytes()); } if (strEncoder != null) { strEncoder.encode(data.consumeRemainingAsString()); } if (strDecoder != null) { strDecoder.decode(data.consumeRemainingAsString()); } } catch (EncoderException | DecoderException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/PhoneticEngineFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.EnumSet; import org.apache.commons.codec.language.bm.NameType; import org.apache.commons.codec.language.bm.PhoneticEngine; import org.apache.commons.codec.language.bm.RuleType; /** This fuzzer targets the encode method in the PhoneticEngine class of the bm package. */ public class PhoneticEngineFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { PhoneticEngine engine = new PhoneticEngine( data.pickValue(EnumSet.allOf(NameType.class)), data.pickValue(EnumSet.allOf(RuleType.class)), data.consumeBoolean(), data.consumeInt()); engine.encode(data.consumeRemainingAsString()); } catch (IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-codec/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-codec-$CURRENT_VERSION.jar" $OUT/commons-codec.jar ALL_JARS="commons-codec.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-codec/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://commons.apache.org/proper/commons-codec/ language: jvm main_repo: https://gitbox.apache.org/repos/asf/commons-codec.git primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "david@adalogics.com" - "adam@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/apache-commons-collections/CollectionsBidiMapFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.TreeBidiMap; public class CollectionsBidiMapFuzzer { void runTest(FuzzedDataProvider data) { // Initialize the BidiMap inside the method for each test run BidiMap m_bidiMap = new TreeBidiMap<>(); switch(data.consumeInt(1, 5)) { case 1: String key = data.consumeString(data.consumeInt(5, 15)); String value = data.consumeString(data.consumeInt(5, 15)); try { m_bidiMap.put(key, value); } catch (IllegalArgumentException ex) { } break; case 2: String getKey = data.consumeString(data.consumeInt(5, 15)); m_bidiMap.get(getKey); break; case 3: String getValue = data.consumeString(data.consumeInt(5, 15)); m_bidiMap.getKey(getValue); break; case 4: String removeValue = data.consumeString(data.consumeInt(5, 15)); try { m_bidiMap.removeValue(removeValue); } catch (UnsupportedOperationException ex) { } break; case 5: m_bidiMap.inverseBidiMap(); break; } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { CollectionsBidiMapFuzzer testClosure = new CollectionsBidiMapFuzzer(); testClosure.runTest(data); } } ================================================ FILE: projects/apache-commons-collections/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone https://github.com/apache/commons-collections COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/commons-collections ================================================ FILE: projects/apache-commons-collections/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests -Drat.ignoreErrors=true" ALL_JARS="" pushd "${SRC}/commons-collections" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp -v target/commons-collections4-${CURRENT_VERSION}.jar "$OUT/commons-collections4.jar" ALL_JARS="${ALL_JARS} commons-collections4.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java cp $SRC/*.class $OUT/ for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-collections/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://commons.apache.org/proper/commons-collections/ language: jvm main_repo: https://github.com/apache/commons-collections.git primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-compress/ArchiverArFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.ar.ArArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverArFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new ArArchiveInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/ArchiverArjFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverArjFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new ArjArchiveInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/ArchiverCpioFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverCpioFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new CpioArchiveInputStream(new ByteArrayInputStream(data))); } catch (IllegalArgumentException | IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/ArchiverDumpFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.dump.DumpArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverDumpFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new DumpArchiveInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/ArchiverTarStreamFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverTarStreamFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new TarArchiveInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/ArchiverZipStreamFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class ArchiverZipStreamFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzArchiveInputStream(new ZipArchiveInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/BaseTests.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.compressors.CompressorInputStream; import java.io.IOException; import java.util.logging.LogManager; // Class with common functionality shared among fuzzing harnesses public class BaseTests { public static void fuzzerInitialize() { LogManager.getLogManager().reset(); } // Fuzz archiver streams by reading every entry public static void fuzzArchiveInputStream(ArchiveInputStream is) throws IOException { ArchiveEntry entry; while ((entry = is.getNextEntry()) != null) { is.read(new byte[1024]); } is.close(); } // Fuzz compressor streams by reading them public static void fuzzCompressorInputStream(CompressorInputStream is) throws IOException { is.read(new byte[1024]); is.close(); } } ================================================ FILE: projects/apache-commons-compress/CompressSevenZFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZFile; import org.apache.commons.compress.archivers.sevenz.SevenZFileOptions; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import java.io.InputStream; import java.io.IOException; // Keeping class name the same so corpus doesn't change // See: https://google.github.io/oss-fuzz/faq/#what-happens-when-i-rename-a-fuzz-target- public class CompressSevenZFuzzer extends BaseTests { private static final SevenZFileOptions options = new SevenZFileOptions.Builder() .withMaxMemoryLimitInKb(1_000_000) .build(); public static void fuzzerTestOneInput(byte[] data) { try { SevenZFile sf = new SevenZFile(new SeekableInMemoryByteChannel(data), options); SevenZArchiveEntry entry; while((entry = sf.getNextEntry()) != null) { InputStream is = sf.getInputStream(entry); is.read(new byte[1024]); } sf.close(); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressTarFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarFile; import java.io.InputStream; import java.io.IOException; // Keeping class name the same so corpus doesn't change // See: https://google.github.io/oss-fuzz/faq/#what-happens-when-i-rename-a-fuzz-target- public class CompressTarFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { TarFile tf = new TarFile(data); for (TarArchiveEntry entry : tf.getEntries()) { InputStream is = tf.getInputStream(entry); is.read(new byte[1024]); } tf.close(); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressZipFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import java.io.InputStream; import java.io.IOException; import java.util.Enumeration; // Keeping class name the same so corpus doesn't change // See: https://google.github.io/oss-fuzz/faq/#what-happens-when-i-rename-a-fuzz-target- public class CompressZipFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { ZipFile zf = new ZipFile(new SeekableInMemoryByteChannel(data)); Enumeration entries = zf.getEntries(); while(entries.hasMoreElements()) { ZipArchiveEntry entry = entries.nextElement(); InputStream is = zf.getInputStream(entry); is.read(new byte[1024]); } zf.close(); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorBZip2Fuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorBZip2Fuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new BZip2CompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorDeflate64Fuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorDeflate64Fuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new Deflate64CompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorGzipFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorGzipFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new GzipCompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorLZ4Fuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream; import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorLZ4Fuzzer extends BaseTests { // Test both LZ4 classes public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new BlockLZ4CompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } try { fuzzCompressorInputStream(new FramedLZ4CompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorPack200Fuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorPack200Fuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new Pack200CompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorSnappyFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.snappy.FramedSnappyCompressorInputStream; import org.apache.commons.compress.compressors.snappy.SnappyCompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorSnappyFuzzer extends BaseTests { // Test both Snappy classes public static void fuzzerTestOneInput(byte[] data) { try { fuzzCompressorInputStream(new FramedSnappyCompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } try { fuzzCompressorInputStream(new SnappyCompressorInputStream(new ByteArrayInputStream(data))); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/CompressorZFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.apache.commons.compress.compressors.z.ZCompressorInputStream; import java.io.ByteArrayInputStream; import java.io.IOException; public class CompressorZFuzzer extends BaseTests { public static void fuzzerTestOneInput(byte[] data) { try { // Setting limit to avoid out of memory errors fuzzCompressorInputStream(new ZCompressorInputStream(new ByteArrayInputStream(data), 1024*1024)); } catch (IllegalArgumentException | IOException ignored) { } } } ================================================ FILE: projects/apache-commons-compress/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.5/binaries/apache-maven-3.9.5-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.5/bin/mvn # Dictionaries RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/zip.dict $SRC/CompressZipFuzzer.dict && \ mv fuzzing/dictionaries/bz2.dict $SRC/CompressorBZip2Fuzzer.dict && \ rm -rf fuzzing # Seed corpus (go-fuzz-corpus) RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j0 $SRC/CompressTarFuzzer_seed_corpus.zip go-fuzz-corpus/tar/corpus/* && \ zip -j0 $SRC/CompressZipFuzzer_seed_corpus.zip go-fuzz-corpus/zip/corpus/* && \ zip -j0 $SRC/CompressorBZip2Fuzzer_seed_corpus.zip go-fuzz-corpus/bzip2/corpus/* && \ zip -j0 $SRC/CompressorGzipFuzzer_seed_corpus.zip go-fuzz-corpus/gzip/corpus/* && \ zip -j0 $SRC/CompressorSnappyFuzzer_seed_corpus.zip go-fuzz-corpus/snappy/corpus/* && \ rm -rf go-fuzz-corpus # Checkout out Compress source code RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-compress.git # Seed corpus (Compress source code) RUN \ zip -j0 $SRC/ArchiverArFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.ar && \ zip -uj0 $SRC/ArchiverArFuzzer_seed_corpus.zip commons-compress/src/test/resources/archives/*.ar && \ zip -j0 $SRC/ArchiverArjFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.arj && \ zip -j0 $SRC/ArchiverCpioFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.cpio && \ zip -uj0 $SRC/ArchiverCpioFuzzer_seed_corpus.zip commons-compress/src/test/resources/archives/*.cpio && \ zip -j0 $SRC/ArchiverDumpFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.dump && \ zip -uj0 $SRC/ArchiverDumpFuzzer_seed_corpus.zip commons-compress/src/test/resources/org/apache/commons/compress/dump/*.dump && \ zip -j0 $SRC/CompressSevenZFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.7z && \ zip -uj0 $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.tar && \ zip -uj0 $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/archives/*.tar && \ zip -uj0 $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/longpath/*.tar && \ zip -uj0 $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/longsymlink/*.tar && \ zip -uj0 $SRC/CompressZipFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.zip RUN \ zip -uj0 $SRC/CompressorBZip2Fuzzer_seed_corpus.zip commons-compress/src/test/resources/*.bz2 && \ zip -j0 $SRC/CompressorDeflate64Fuzzer_seed_corpus.zip commons-compress/src/test/resources/*.deflate && \ zip -uj0 $SRC/CompressorGzipFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.gz && \ zip -j0 $SRC/CompressorLZ4Fuzzer_seed_corpus.zip commons-compress/src/test/resources/*lz4 && \ zip -j0 $SRC/CompressorPack200Fuzzer_seed_corpus.zip commons-compress/src/test/resources/*.pack && \ zip -uj0 $SRC/CompressorPack200Fuzzer_seed_corpus.zip commons-compress/src/test/resources/pack200/*.pack && \ zip -uj0 $SRC/CompressorSnappyFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.sz && \ zip -j0 $SRC/CompressorZFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.Z # Copy some corpuses and dictionaries RUN \ cp $SRC/CompressTarFuzzer_seed_corpus.zip $SRC/ArchiverTarStreamFuzzer_seed_corpus.zip && \ cp $SRC/CompressZipFuzzer.dict $SRC/ArchiverZipStreamFuzzer.dict && \ cp $SRC/CompressZipFuzzer_seed_corpus.zip $SRC/ArchiverZipStreamFuzzer_seed_corpus.zip # Copy build script, all fuzzers and supporting files COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-compress/README.md ================================================ Note that classes that use third party libraries are excluded. These are either being already fuzzed by oss-fuzz or cannot be fuzzed effectively. These include: * BrotliCompressorInputStream - uses Google's Brotli * DeflateCompressorInputStream - uses JDK's Inflater * LZMACompressorInputStream - uses XZ for Java * XZCompressorInputStream - uses XZ for Java * ZstdCompressorInputStream - uses zstd-jni ================================================ FILE: projects/apache-commons-compress/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT pushd "$SRC/commons-compress" MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.5.1:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.4.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-compress-$CURRENT_VERSION.jar" $OUT/commons-compress.jar popd ALL_JARS="commons-compress.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ cp $SRC/Base*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-compress/project.yaml ================================================ homepage: "https://commons.apache.org" language: jvm main_repo: "https://github.com/apache/commons-compress" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" - "brunodepaulak@gmail.com" - "peteralfredlee@gmail.com" - "boards@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/apache-commons-configuration/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # Install a working version of Maven RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -f maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn ENV TARGET_PACKAGE_PREFIX org.apache.commons.configuration2.* # Clone the commons-configuration library source code RUN git clone --depth=1 "https://gitbox.apache.org/repos/asf/commons-configuration.git" commons-configuration # Get the dictionaries RUN git clone --depth=1 "https://github.com/google/fuzzing" fuzzing RUN cp fuzzing/dictionaries/xml.dict $SRC/XMLConfigurationLoadFuzzer.dict RUN cp fuzzing/dictionaries/yaml.dict $SRC/YAMLConfigurationReadFuzzer.dict RUN cp $SRC/YAMLConfigurationReadFuzzer.dict $SRC/YAMLConfigurationWriteFuzzer.dict RUN cp fuzzing/dictionaries/json.dict $SRC/JSONConfigurationReadFuzzer.dict RUN cp $SRC/JSONConfigurationReadFuzzer.dict $SRC/JSONConfigurationWriteFuzzer.dict COPY ini.dict $SRC/INIConfigurationReadFuzzer.dict RUN cp $SRC/INIConfigurationReadFuzzer.dict $SRC/INIConfigurationWriteFuzzer.dict # Get the corpora RUN git clone --depth=1 "https://github.com/dvyukov/go-fuzz-corpus" corpora RUN zip -q $SRC/XMLConfigurationLoadFuzzer_seed_corpus.zip corpora/xml/corpus/* RUN zip -q $SRC/JSONConfigurationReadFuzzer_seed_corpus.zip corpora/json/corpus/* RUN cp $SRC/JSONConfigurationReadFuzzer_seed_corpus.zip $SRC/JSONConfigurationWriteFuzzer_seed_corpus.zip # Copy the build script and all the fuzztargets COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/commons-configuration ================================================ FILE: projects/apache-commons-configuration/INIConfigurationReadFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.IOException; import org.apache.commons.configuration2.INIConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; public class INIConfigurationReadFuzzer extends INIConfiguration { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final char commentCharacter = data.consumeChar(); final char separatorCharacter = data.consumeChar(); final byte[] byteArray = data.consumeBytes(Integer.MAX_VALUE); // Create needed objects INIConfiguration iniConfig = new INIConfiguration(); InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReader reader = new InputStreamReader(inputStream); try { iniConfig.setSeparatorUsedInInput(Character.toString(separatorCharacter)); iniConfig.setCommentLeadingCharsUsedInInput(Character.toString(commentCharacter)); iniConfig.read(reader); } catch (IOException | ConfigurationException ignored) { // expected Exceptions get ignored } } } ================================================ FILE: projects/apache-commons-configuration/INIConfigurationWriteFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.StringWriter; import java.io.IOException; import org.apache.commons.configuration2.INIConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; public class INIConfigurationWriteFuzzer extends INIConfiguration { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final char commentCharacter = data.consumeChar(); final char inputSeparatorCharacter = data.consumeChar(); final char outputSeparatorCharacter = data.consumeChar(); final byte[] byteArray = data.consumeBytes(Integer.MAX_VALUE); // Create the needed objects INIConfiguration iniConfig = new INIConfiguration(); InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReader reader = new InputStreamReader(inputStream); StringWriter writer = new StringWriter(); try { iniConfig.setSeparatorUsedInInput(Character.toString(inputSeparatorCharacter)); iniConfig.setCommentLeadingCharsUsedInInput(Character.toString(commentCharacter)); iniConfig.read(reader); iniConfig.setSeparatorUsedInOutput(Character.toString(outputSeparatorCharacter)); iniConfig.write(writer); } catch (IOException | ConfigurationException ignored) { // expected Exceptions get ignored } } } ================================================ FILE: projects/apache-commons-configuration/JSONConfigurationReadFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ByteArrayInputStream; import org.apache.commons.configuration2.JSONConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; public class JSONConfigurationReadFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final boolean useReader = data.consumeBoolean(); final byte[] byteArray = data.consumeBytes(Integer.MAX_VALUE); // Create needed objects final JSONConfiguration jsonConfig = new JSONConfiguration(); jsonConfig.setLogger(null); // disable logger final InputStream inputStream = new ByteArrayInputStream(byteArray); final InputStreamReader reader; try { if (useReader) { reader = new InputStreamReader(inputStream); jsonConfig.read(reader); } else { jsonConfig.read(inputStream); } } catch (ConfigurationException ignored) { // expected Exceptions get ignored } } } ================================================ FILE: projects/apache-commons-configuration/JSONConfigurationWriteFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ByteArrayInputStream; import java.io.StringWriter; import java.io.IOException; import org.apache.commons.configuration2.JSONConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; public class JSONConfigurationWriteFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final boolean useReader = data.consumeBoolean(); final byte[] byteArray = data.consumeBytes(Integer.MAX_VALUE); // Create needed objects JSONConfiguration jsonConfig = new JSONConfiguration(); jsonConfig.setLogger(null); // disable logger InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReader reader; StringWriter writer = new StringWriter(); try { if (useReader) { reader = new InputStreamReader(inputStream); jsonConfig.read(reader); } else { jsonConfig.read(inputStream); } jsonConfig.write(writer); } catch (IOException | ConfigurationException ignored) { // expected Exceptions get ignored } } } ================================================ FILE: projects/apache-commons-configuration/XMLConfigurationLoadFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import org.apache.commons.configuration2.XMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.io.FileHandler; public class XMLConfigurationLoadFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create needed objects final File tempFile; try { tempFile = File.createTempFile("XMLConfiguration", ".xml"); } catch (IOException ioe) { return; } final String absoluteFilepath = tempFile.getAbsolutePath(); try { final FileWriter fileWriter = new FileWriter(tempFile); fileWriter.write(data.consumeRemainingAsString()); fileWriter.close(); } catch (IOException ioe) { tempFile.delete(); return; } final XMLConfiguration xmlConfig = new XMLConfiguration(); xmlConfig.setLogger(null); // disable logger final FileHandler fileHandler = new FileHandler(xmlConfig); fileHandler.setPath(absoluteFilepath); try { fileHandler.load(); } catch (ConfigurationException ignored) { // expected Exceptions get ignored } finally { tempFile.delete(); } } } ================================================ FILE: projects/apache-commons-configuration/XMLConfigurationWriteFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import org.apache.commons.configuration2.XMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.apache.commons.configuration2.io.FileHandler; public class XMLConfigurationWriteFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create needed objects final File tempFile; try { tempFile = File.createTempFile("XMLConfiguration", ".xml"); } catch (IOException ioe) { return; } final String absoluteFilepath = tempFile.getAbsolutePath(); try { final FileWriter fileWriter = new FileWriter(tempFile); fileWriter.write(data.consumeRemainingAsString()); fileWriter.close(); } catch (IOException ioe) { tempFile.delete(); return; } final XMLConfiguration xmlConfig = new XMLConfiguration(); xmlConfig.setLogger(null); // disable the logger final FileHandler fileHandler = new FileHandler(xmlConfig); fileHandler.setPath(absoluteFilepath); try { fileHandler.load(); xmlConfig.write(new StringWriter()); } catch (ConfigurationException | IOException ignored) { // expected Exceptions get ignored } finally { tempFile.delete(); } } } ================================================ FILE: projects/apache-commons-configuration/YAMLConfigurationReadFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.configuration2.YAMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.yaml.snakeyaml.LoaderOptions; public class YAMLConfigurationReadFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final boolean useLoaderOptions = data.consumeBoolean(); // Create needed objects final YAMLConfiguration yamlConfig = new YAMLConfiguration(); yamlConfig.setLogger(null); // disable logging // the actual fuzzing starts here try { if (useLoaderOptions) { final LoaderOptions loaderOptions = createLoaderOptions(data); yamlConfig.read(new ByteArrayInputStream(data.consumeBytes(Integer.MAX_VALUE)), loaderOptions); } else { yamlConfig.read(new ByteArrayInputStream(data.consumeBytes(Integer.MAX_VALUE))); } } catch (ConfigurationException ignored) { // expected Exceptions get ignored } } private static LoaderOptions createLoaderOptions(FuzzedDataProvider data) { LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setAllowDuplicateKeys(data.consumeBoolean()); loaderOptions.setWrappedToRootException(data.consumeBoolean()); loaderOptions.setAllowRecursiveKeys(data.consumeBoolean()); loaderOptions.setProcessComments(data.consumeBoolean()); loaderOptions.setEnumCaseSensitive(data.consumeBoolean()); return loaderOptions; } } ================================================ FILE: projects/apache-commons-configuration/YAMLConfigurationWriteFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import org.apache.commons.configuration2.YAMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; import org.yaml.snakeyaml.LoaderOptions; public class YAMLConfigurationWriteFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create helper objects from fuzzer data final boolean useLoaderOptions = data.consumeBoolean(); // Create needed objects final YAMLConfiguration yamlConfig = new YAMLConfiguration(); yamlConfig.setLogger(null); // disable logging // the actual fuzzing starts here try { if (useLoaderOptions) { final LoaderOptions loaderOptions = createLoaderOptions(data); yamlConfig.read(new ByteArrayInputStream(data.consumeBytes(Integer.MAX_VALUE)), loaderOptions); } else { yamlConfig.read(new ByteArrayInputStream(data.consumeBytes(Integer.MAX_VALUE))); } yamlConfig.write(new StringWriter()); } catch (IOException | ConfigurationException ignored) { // expected Exceptions get ignored } } private static LoaderOptions createLoaderOptions(FuzzedDataProvider data) { LoaderOptions loaderOptions = new LoaderOptions(); loaderOptions.setAllowDuplicateKeys(data.consumeBoolean()); loaderOptions.setWrappedToRootException(data.consumeBoolean()); loaderOptions.setAllowRecursiveKeys(data.consumeBoolean()); loaderOptions.setProcessComments(data.consumeBoolean()); loaderOptions.setEnumCaseSensitive(data.consumeBoolean()); return loaderOptions; } } ================================================ FILE: projects/apache-commons-configuration/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Moving the corpora and dictionaries to $OUT mv $SRC/{*.zip,*.dict} $OUT # Building the library MAVEN_ARGS="--no-transfer-progress -Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 -Djdk.version=15" CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) ## maven-shade-plugin is for packaging all the dependencies into one .jar $MVN clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS cp "target/commons-configuration2-$CURRENT_VERSION.jar" "$OUT/commons-configuration.jar" ALL_JARS="commons-configuration.jar" ## The classpath at build-time includes the project jars in $OUT as well as the Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH ## All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -iname '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings:-Djava.awt.headless=true\" \ \$@" > $OUT/$fuzzer_basename # Make the execution wrapper executable chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-configuration/ini.dict ================================================ # sources: # - https://en.wikipedia.org/wiki/INI_file # - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms717987(v=vs.85) # Basics assign="=" section_left_bracket="[" section_right_bracket="]" comment_semicolon=";" comment_hash="#" apostrophe="'" double_quotes="\"" # Old section nesting symbols backslash="\\" comma="," period="." # Escape sequences escaped_backslash="\\'" escaped_double_quotes="\\"" escaped_null_byte="\\0" escaped_alert="\\a" escaped_backspace="\\b" escaped_tab="\\t" escaped_carriage_return="\\r" escaped_linefeed="\\n" escaped_semicolon="\\;" escaped_hash="\\#" escaped_equal_sign="\\=" escaped_colon="\\:" escaped_unicode_beginning="\\x" ================================================ FILE: projects/apache-commons-configuration/project.yaml ================================================ homepage: "https://commons.apache.org/proper/commons-configuration/" language: jvm main_repo: "https://gitbox.apache.org/repos/asf/commons-configuration.git" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "yoshi.weber@gmail.com" ================================================ FILE: projects/apache-commons-csv/CSVParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.List; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.io.ByteArrayInputStream; import java.io.UncheckedIOException; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVRecord; public class CSVParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { CSVFormat[] formats = { CSVFormat.DEFAULT, CSVFormat.DEFAULT.withHeader(), CSVFormat.EXCEL, CSVFormat.EXCEL.withHeader(), CSVFormat.INFORMIX_UNLOAD, CSVFormat.INFORMIX_UNLOAD.withHeader(), CSVFormat.INFORMIX_UNLOAD_CSV, CSVFormat.INFORMIX_UNLOAD_CSV.withHeader(), CSVFormat.MYSQL, CSVFormat.MYSQL.withHeader(), CSVFormat.RFC4180, CSVFormat.RFC4180.withHeader(), CSVFormat.ORACLE, CSVFormat.ORACLE.withHeader(), CSVFormat.POSTGRESQL_CSV, CSVFormat.POSTGRESQL_CSV.withHeader(), CSVFormat.POSTGRESQL_TEXT, CSVFormat.POSTGRESQL_TEXT.withHeader(), CSVFormat.TDF, CSVFormat.TDF.withHeader() }; ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); CSVFormat format = data.pickValue(formats); try{ CSVParser parser = CSVParser.parse(bais, StandardCharsets.UTF_8, format); List records = parser.getRecords(); } catch( IOException | java.io.UncheckedIOException e ){ return; } } } ================================================ FILE: projects/apache-commons-csv/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/csv.dict $SRC/csv.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/CSVParserFuzzer_seed_corpus.zip go-fuzz-corpus/csv/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/apache/commons-csv.git apache-commons-csv COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/apache-commons-csv ================================================ FILE: projects/apache-commons-csv/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15 -Dmaven.javadoc.skip=true" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-csv-$CURRENT_VERSION.jar" $OUT/commons-csv.jar ALL_JARS="commons-csv.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-csv/project.yaml ================================================ homepage: "https://github.com/apache/commons-csv" language: jvm primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - "libfuzzer" sanitizers: - "address" auto_ccs: - "security@commons.apache.org" main_repo: "https://github.com/apache/commons-csv.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-fileupload/.gitignore ================================================ project-parent/apache-commons-fileupload project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup project-parent/fuzz-targets/.cifuzz-corpus ================================================ FILE: projects/apache-commons-fileupload/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/http.dict $SRC/FileUploadFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/FileUploadFuzzer_seed_corpus.zip go-fuzz-corpus/multipart/corpus/* && \ rm -rf go-fuzz-corpus COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/apache-commons-fileupload RUN git clone --depth 1 https://github.com/apache/commons-fileupload.git $SRC/project-parent/apache-commons-fileupload COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-fileupload/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=apache-commons-fileupload PROJECT_GROUP_ID=org.apache.commons PROJECT_ARTIFACT_ID=commons-fileupload2 MAIN_REPOSITORY=https://github.com/apache/commons-fileupload.git MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -Denforcer.skip=true -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:commons-fileupload2-core -DdepVersion=$PROJECT_VERSION -DforceVersion=true) (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:commons-fileupload2-javax -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && mvn install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/apache-commons-fileupload/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.commons commons-fileupload2-core 2.0-SNAPSHOT org.apache.commons commons-fileupload2-javax 2.0-SNAPSHOT javax.servlet servlet-api 2.5 test org.junit.platform junit-platform-launcher 1.9.2 maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/apache-commons-fileupload/project-parent/fuzz-targets/src/test/java/com/example/Constants.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; /** * Constants used for testing. * * @since 1.4 */ public final class Constants { /** * The content type used in several tests. */ public static final String CONTENT_TYPE = "multipart/form-data; boundary=---1234"; private Constants() { } } ================================================ FILE: projects/apache-commons-fileupload/project-parent/fuzz-targets/src/test/java/com/example/FileUploadFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.commons.fileupload2.core.FileItem; import org.apache.commons.fileupload2.core.AbstractFileUpload; import org.apache.commons.fileupload2.core.FileUploadException; import org.apache.commons.fileupload2.core.MultipartInput; import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload2.javax.JavaxServletFileUpload; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; public class FileUploadFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) throws IOException, FileUploadException { DiskFileItemFactory factory = DiskFileItemFactory.builder() .setPath(new File("/tmp/abc").toPath()) .get(); AbstractFileUpload upload = new JavaxServletFileUpload(factory); // is set to tomcats default to approach CVE-2023-24998 upload.setMaxFileCount(10000); String contentType = data.consumeAsciiString(200); String multipartData = data.consumeRemainingAsString(); List fileItems = null; try { Util.parseUpload(upload, "-----1234\r\n" + multipartData + "-----1234--\r\n"); Util.parseUpload(upload, multipartData.getBytes(StandardCharsets.US_ASCII), contentType); } catch (Exception e) { } } } ================================================ FILE: projects/apache-commons-fileupload/project-parent/fuzz-targets/src/test/java/com/example/MockHttpServletRequest.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import org.apache.commons.fileupload2.core.AbstractFileUpload; import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.*; import java.security.Principal; import java.util.Enumeration; import java.util.Locale; import java.util.Map; public class MockHttpServletRequest implements HttpServletRequest { private final InputStream mmRequestData; private long length; private final String mStrContentType; private int readLimit = -1; private final Map mHeaders = new java.util.HashMap<>(); /** * Creates a new instance with the given request data * and content type. */ public MockHttpServletRequest( final byte[] requestData, final String strContentType) { this(new ByteArrayInputStream(requestData), requestData.length, strContentType); } /** * Creates a new instance with the given request data * and content type. */ public MockHttpServletRequest( final InputStream requestData, final long requestLength, final String strContentType) { mmRequestData = requestData; length = requestLength; mStrContentType = strContentType; mHeaders.put(AbstractFileUpload.CONTENT_TYPE, strContentType); } /** * @see HttpServletRequest#getAuthType() */ @Override public String getAuthType() { return null; } /** * @see HttpServletRequest#getCookies() */ @Override public Cookie[] getCookies() { return null; } /** * @see HttpServletRequest#getDateHeader(String) */ @Override public long getDateHeader(final String arg0) { return 0; } /** * @see HttpServletRequest#getHeader(String) */ @Override public String getHeader(final String headerName) { return mHeaders.get(headerName); } /** * @see HttpServletRequest#getHeaders(String) */ @Override public Enumeration getHeaders(final String arg0) { // todo - implement return null; } /** * @see HttpServletRequest#getHeaderNames() */ @Override public Enumeration getHeaderNames() { // todo - implement return null; } /** * @see HttpServletRequest#getIntHeader(String) */ @Override public int getIntHeader(final String arg0) { return 0; } /** * @see HttpServletRequest#getMethod() */ @Override public String getMethod() { return null; } /** * @see HttpServletRequest#getPathInfo() */ @Override public String getPathInfo() { return null; } /** * @see HttpServletRequest#getPathTranslated() */ @Override public String getPathTranslated() { return null; } /** * @see HttpServletRequest#getContextPath() */ @Override public String getContextPath() { return null; } /** * @see HttpServletRequest#getQueryString() */ @Override public String getQueryString() { return null; } /** * @see HttpServletRequest#getRemoteUser() */ @Override public String getRemoteUser() { return null; } /** * @see HttpServletRequest#isUserInRole(String) */ @Override public boolean isUserInRole(final String arg0) { return false; } /** * @see HttpServletRequest#getUserPrincipal() */ @Override public Principal getUserPrincipal() { return null; } /** * @see HttpServletRequest#getRequestedSessionId() */ @Override public String getRequestedSessionId() { return null; } /** * @see HttpServletRequest#getRequestURI() */ @Override public String getRequestURI() { return null; } /** * @see HttpServletRequest#getRequestURL() */ @Override public StringBuffer getRequestURL() { return null; } /** * @see HttpServletRequest#getServletPath() */ @Override public String getServletPath() { return null; } /** * @see HttpServletRequest#getSession(boolean) */ @Override public HttpSession getSession(final boolean arg0) { return null; } /** * @see HttpServletRequest#getSession() */ @Override public HttpSession getSession() { return null; } /** * @see HttpServletRequest#isRequestedSessionIdValid() */ @Override public boolean isRequestedSessionIdValid() { return false; } /** * @see HttpServletRequest#isRequestedSessionIdFromCookie() */ @Override public boolean isRequestedSessionIdFromCookie() { return false; } /** * @see HttpServletRequest#isRequestedSessionIdFromURL() */ @Override public boolean isRequestedSessionIdFromURL() { return false; } /** * @see HttpServletRequest#isRequestedSessionIdFromUrl() * @deprecated */ @Override @Deprecated public boolean isRequestedSessionIdFromUrl() { return false; } /** * @see javax.servlet.ServletRequest#getAttribute(String) */ @Override public Object getAttribute(final String arg0) { return null; } /** * @see javax.servlet.ServletRequest#getAttributeNames() */ @Override public Enumeration getAttributeNames() { return null; } /** * @see javax.servlet.ServletRequest#getCharacterEncoding() */ @Override public String getCharacterEncoding() { return null; } /** * @see javax.servlet.ServletRequest#setCharacterEncoding(String) */ @Override public void setCharacterEncoding(final String arg0) throws UnsupportedEncodingException { } /** * @see javax.servlet.ServletRequest#getContentLength() */ @Override public int getContentLength() { int iLength; if (null == mmRequestData) { iLength = -1; } else { if (length > Integer.MAX_VALUE) { throw new RuntimeException("Value '" + length + "' is too large to be converted to int"); } iLength = (int) length; } return iLength; } /** * For testing attack scenarios in SizesTest. */ public void setContentLength(final long length) { this.length = length; } /** * @see javax.servlet.ServletRequest#getContentType() */ @Override public String getContentType() { return mStrContentType; } /** * @see javax.servlet.ServletRequest#getInputStream() */ @Override public ServletInputStream getInputStream() throws IOException { return new MyServletInputStream(mmRequestData, readLimit); } /** * Sets the read limit. This can be used to limit the number of bytes to read ahead. * * @param readLimit the read limit to use */ public void setReadLimit(final int readLimit) { this.readLimit = readLimit; } /** * @see javax.servlet.ServletRequest#getParameter(String) */ @Override public String getParameter(final String arg0) { return null; } /** * @see javax.servlet.ServletRequest#getParameterNames() */ @Override public Enumeration getParameterNames() { return null; } /** * @see javax.servlet.ServletRequest#getParameterValues(String) */ @Override public String[] getParameterValues(final String arg0) { return null; } /** * @see javax.servlet.ServletRequest#getParameterMap() */ @Override public Map getParameterMap() { return null; } /** * @see javax.servlet.ServletRequest#getProtocol() */ @Override public String getProtocol() { return null; } /** * @see javax.servlet.ServletRequest#getScheme() */ @Override public String getScheme() { return null; } /** * @see javax.servlet.ServletRequest#getServerName() */ @Override public String getServerName() { return null; } /** * @see javax.servlet.ServletRequest#getLocalName() */ @Override @SuppressWarnings("javadoc") // This is a Servlet 2.4 method public String getLocalName() { return null; } /** * @see javax.servlet.ServletRequest#getServerPort() */ @Override public int getServerPort() { return 0; } /** * @see javax.servlet.ServletRequest#getLocalPort() */ @Override @SuppressWarnings("javadoc") // This is a Servlet 2.4 method public int getLocalPort() { return 0; } /** * @see javax.servlet.ServletRequest#getRemotePort() */ @Override @SuppressWarnings("javadoc") // This is a Servlet 2.4 method public int getRemotePort() { return 0; } /** * @see javax.servlet.ServletRequest#getReader() */ @Override public BufferedReader getReader() throws IOException { return null; } /** * @see javax.servlet.ServletRequest#getRemoteAddr() */ @Override public String getRemoteAddr() { return null; } /** * @see javax.servlet.ServletRequest#getLocalAddr() */ @Override @SuppressWarnings("javadoc") // This is a Servlet 2.4 method public String getLocalAddr() { return null; } /** * @see javax.servlet.ServletRequest#getRemoteHost() */ @Override public String getRemoteHost() { return null; } /** * @see javax.servlet.ServletRequest#setAttribute(String, Object) */ @Override public void setAttribute(final String arg0, final Object arg1) { } /** * @see javax.servlet.ServletRequest#removeAttribute(String) */ @Override public void removeAttribute(final String arg0) { } /** * @see javax.servlet.ServletRequest#getLocale() */ @Override public Locale getLocale() { return null; } /** * @see javax.servlet.ServletRequest#getLocales() */ @Override public Enumeration getLocales() { return null; } /** * @see javax.servlet.ServletRequest#isSecure() */ @Override public boolean isSecure() { return false; } /** * @see javax.servlet.ServletRequest#getRequestDispatcher(String) */ @Override public RequestDispatcher getRequestDispatcher(final String arg0) { return null; } /** * @see javax.servlet.ServletRequest#getRealPath(String) * @deprecated */ @Override @Deprecated public String getRealPath(final String arg0) { return null; } private static class MyServletInputStream extends ServletInputStream { private final InputStream in; private final int readLimit; /** * Creates a new instance, which returns the given * streams data. */ public MyServletInputStream(final InputStream pStream, final int readLimit) { in = pStream; this.readLimit = readLimit; } @Override public int read() throws IOException { return in.read(); } @Override public int read(final byte[] b, final int off, final int len) throws IOException { if (readLimit > 0) { return in.read(b, off, Math.min(readLimit, len)); } return in.read(b, off, len); } } } ================================================ FILE: projects/apache-commons-fileupload/project-parent/fuzz-targets/src/test/java/com/example/Util.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import org.apache.commons.fileupload2.core.FileItem; import org.apache.commons.fileupload2.core.AbstractFileUpload; import org.apache.commons.fileupload2.core.FileUploadException; import org.apache.commons.fileupload2.core.DiskFileItemFactory; import org.apache.commons.fileupload2.javax.JavaxServletFileUpload; import org.apache.commons.fileupload2.javax.JavaxServletRequestContext; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; /** * Test utility methods. * * @since 1.4 */ public class Util { public static List parseUpload(final AbstractFileUpload upload, final byte[] bytes) throws FileUploadException { return parseUpload(upload, bytes, Constants.CONTENT_TYPE); } public static List parseUpload(final AbstractFileUpload upload, final byte[] bytes, final String contentType) throws FileUploadException { final HttpServletRequest request = new MockHttpServletRequest(bytes, contentType); return upload.parseRequest(new JavaxServletRequestContext(request)); } public static List parseUpload(final AbstractFileUpload upload, final String content) throws UnsupportedEncodingException, FileUploadException { final byte[] bytes = content.getBytes(StandardCharsets.US_ASCII); return parseUpload(upload, bytes, Constants.CONTENT_TYPE); } /** * Return a list of {@link AbstractFileUpload} implementations for parameterized tests. * @return a list of {@link AbstractFileUpload} implementations */ public static List fileUploadImplementations() { DiskFileItemFactory factory = DiskFileItemFactory.builder().get(); return Arrays.asList( new JavaxServletFileUpload(factory)); } } ================================================ FILE: projects/apache-commons-fileupload/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom apache-commons-fileupload fuzz-targets ================================================ FILE: projects/apache-commons-fileupload/project.yaml ================================================ homepage: "https://commons.apache.org/proper/commons-fileupload/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/commons-fileupload.git" primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-geometry/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn # Geometry RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-geometry.git # Copy build script and all fuzzers COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-geometry/GeometryObjFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.UncheckedIOException; import org.apache.commons.geometry.io.core.input.StreamGeometryInput; import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D; import org.apache.commons.geometry.io.euclidean.threed.obj.ObjBoundaryReadHandler3D; import org.apache.commons.numbers.core.Precision; public class GeometryObjFuzzer { public static void fuzzerTestOneInput(final byte[] data) { try { final BoundaryReadHandler3D handler = new ObjBoundaryReadHandler3D(); final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20); // check standard read handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); // check mesh read handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) { // expected exception types; ignore } } } ================================================ FILE: projects/apache-commons-geometry/GeometryStlBinaryFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.UncheckedIOException; import org.apache.commons.geometry.io.core.input.StreamGeometryInput; import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D; import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryReadHandler3D; import org.apache.commons.numbers.core.Precision; public class GeometryStlBinaryFuzzer { public static void fuzzerTestOneInput(final byte[] data) { try { final BoundaryReadHandler3D handler = new StlBoundaryReadHandler3D(); final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20); // check standard read handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); // check mesh read handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) { // expected exception types; ignore } } } ================================================ FILE: projects/apache-commons-geometry/GeometryStlTextFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.nio.charset.StandardCharsets; import java.io.ByteArrayInputStream; import java.io.UncheckedIOException; import org.apache.commons.geometry.io.core.input.StreamGeometryInput; import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D; import org.apache.commons.geometry.io.euclidean.threed.stl.StlBoundaryReadHandler3D; import org.apache.commons.numbers.core.Precision; public class GeometryStlTextFuzzer { public static void fuzzerTestOneInput(final byte[] data) { // prepend the "solid" STL keyword to the input to ensure it is interpreted // as text STL input final byte[] dataWithPrefix = join("solid ".getBytes(StandardCharsets.US_ASCII), data); try { final BoundaryReadHandler3D handler = new StlBoundaryReadHandler3D(); final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20); // check standard read handler.read(new StreamGeometryInput(new ByteArrayInputStream(dataWithPrefix)), precision); // check mesh read handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(dataWithPrefix)), precision); } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) { // expected exception types; ignore } } private static byte[] join(final byte[] a, final byte[] b) { final byte[] result = new byte[a.length + b.length]; System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; } } ================================================ FILE: projects/apache-commons-geometry/GeometryTextFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.UncheckedIOException; import org.apache.commons.geometry.io.core.input.StreamGeometryInput; import org.apache.commons.geometry.io.euclidean.threed.BoundaryReadHandler3D; import org.apache.commons.geometry.io.euclidean.threed.txt.TextBoundaryReadHandler3D; import org.apache.commons.numbers.core.Precision; public class GeometryTextFuzzer { public static void fuzzerTestOneInput(final byte[] data) { try { final BoundaryReadHandler3D handler = new TextBoundaryReadHandler3D(); final Precision.DoubleEquivalence precision = Precision.doubleEquivalenceOfEpsilon(1e-20); // check standard read handler.read(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); // check mesh read handler.readTriangleMesh(new StreamGeometryInput(new ByteArrayInputStream(data)), precision); } catch (UncheckedIOException | IllegalArgumentException | IllegalStateException ignored) { // expected exception types; ignore } } } ================================================ FILE: projects/apache-commons-geometry/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd "$SRC/commons-geometry" MAVEN_ARGS="-DskipTests -Djavac.src.version=8 -Djavac.target.version=8" $MVN install $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) # Run shade plugin on io-euclidean module specifically with package phase $MVN -pl commons-geometry-io-euclidean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS cp "commons-geometry-io-euclidean/target/commons-geometry-io-euclidean-$CURRENT_VERSION.jar" $OUT/commons-geometry.jar popd ALL_JARS="commons-geometry.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-geometry/project.yaml ================================================ homepage: "https://commons.apache.org" language: jvm main_repo: "https://github.com/apache/commons-geometry" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" - "brunodepaulak@gmail.com" - "peteralfredlee@gmail.com" - "boards@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/apache-commons-imaging/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn # Dictionaries RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/gif.dict $SRC/ImagingGifFuzzer.dict && \ mv fuzzing/dictionaries/jpeg.dict $SRC/ImagingJpegFuzzer.dict && \ mv fuzzing/dictionaries/png.dict $SRC/ImagingPngFuzzer.dict && \ mv fuzzing/dictionaries/tiff.dict $SRC/ImagingTiffFuzzer.dict && \ rm -rf fuzzing # Seed corpus (go-fuzz-corpus) RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/ImagingBmpFuzzer_seed_corpus.zip go-fuzz-corpus/bmp/corpus/* && \ zip -j $SRC/ImagingGifFuzzer_seed_corpus.zip go-fuzz-corpus/gif/corpus/* && \ zip -j $SRC/ImagingJpegFuzzer_seed_corpus.zip go-fuzz-corpus/jpeg/corpus/* && \ zip -j $SRC/ImagingPngFuzzer_seed_corpus.zip go-fuzz-corpus/png/corpus/* && \ zip -j $SRC/ImagingTiffFuzzer_seed_corpus.zip go-fuzz-corpus/tiff/corpus/* && \ rm -rf go-fuzz-corpus # Imaging RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-imaging.git # Copy build script and all fuzzers COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-imaging/ImagingBmpFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.IOException; import org.apache.commons.imaging.bytesource.ByteSource; import org.apache.commons.imaging.formats.bmp.BmpImageParser; public class ImagingBmpFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { new BmpImageParser().getBufferedImage(ByteSource.array(input), null); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-imaging/ImagingGifFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.IOException; import org.apache.commons.imaging.bytesource.ByteSource; import org.apache.commons.imaging.formats.gif.GifImageParser; public class ImagingGifFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { new GifImageParser().getBufferedImage(ByteSource.array(input), null); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-imaging/ImagingJpegFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.IOException; import org.apache.commons.imaging.bytesource.ByteSource; import org.apache.commons.imaging.formats.jpeg.JpegImageParser; public class ImagingJpegFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { new JpegImageParser().getBufferedImage(ByteSource.array(input), null); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-imaging/ImagingPngFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.IOException; import org.apache.commons.imaging.bytesource.ByteSource; import org.apache.commons.imaging.formats.png.PngImageParser; public class ImagingPngFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { new PngImageParser().getBufferedImage(ByteSource.array(input), null); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-imaging/ImagingTiffFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.IOException; import org.apache.commons.imaging.bytesource.ByteSource; import org.apache.commons.imaging.formats.tiff.TiffImageParser; public class ImagingTiffFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { new TiffImageParser().getBufferedImage(ByteSource.array(input), null); } catch (IOException ignored) { } } } ================================================ FILE: projects/apache-commons-imaging/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT pushd "$SRC/commons-imaging" MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 --no-transfer-progress" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-imaging-$CURRENT_VERSION.jar" $OUT/commons-imaging.jar popd ALL_JARS="commons-imaging.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings:-Djava.awt.headless=true\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-imaging/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://commons.apache.org" language: jvm main_repo: "https://github.com/apache/commons-imaging" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" - "brunodepaulak@gmail.com" - "peteralfredlee@gmail.com" - "boards@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "norbert.schneider@code-intelligence.com" - "ggregory@apache.org" - "garydgregory@gmail.com" ================================================ FILE: projects/apache-commons-io/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/xml.dict $SRC/XmlFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/XmlFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/apache/commons-io.git commons-io COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/commons-io ================================================ FILE: projects/apache-commons-io/FileComparatorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Comparator; import java.util.LinkedList; import java.util.List; import org.apache.commons.io.comparator.CompositeFileComparator; import org.apache.commons.io.comparator.DefaultFileComparator; import org.apache.commons.io.comparator.DirectoryFileComparator; import org.apache.commons.io.comparator.ExtensionFileComparator; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.io.comparator.NameFileComparator; import org.apache.commons.io.comparator.PathFileComparator; import org.apache.commons.io.comparator.SizeFileComparator; /** This fuzzer targets the different Comparator classes for files in the comparator package. */ public class FileComparatorFuzzer { private static File file1; private static File file2; public static void fuzzerInitialize() { try { file1 = File.createTempFile("OSS-Fuzz-", "-OSS-Fuzz"); file2 = File.createTempFile("OSS-Fuzz-", "-OSS-Fuzz"); } catch (IOException e) { throw new RuntimeException(e); } } public static void fuzzerTearDown() { file1.delete(); file2.delete(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Randomize file content FileWriter writer = new FileWriter(file1); writer.write(data.consumeString(data.remainingBytes())); writer.close(); writer = new FileWriter(file2); writer.write(data.consumeString(data.remainingBytes())); writer.close(); // Create list of files List files = new LinkedList(); files.add(file1); files.add(file2); // Create objects of comparator Integer comparatorCount = data.consumeInt(1, 10); List> delegates = new LinkedList>(); for (Integer i = 0; i < comparatorCount; i++) { switch (data.consumeInt(1, 28)) { case 1: delegates.add(DefaultFileComparator.DEFAULT_COMPARATOR); break; case 2: delegates.add(DefaultFileComparator.DEFAULT_REVERSE); break; case 3: delegates.add(DirectoryFileComparator.DIRECTORY_COMPARATOR); break; case 4: delegates.add(DirectoryFileComparator.DIRECTORY_REVERSE); break; case 5: delegates.add(ExtensionFileComparator.EXTENSION_COMPARATOR); break; case 6: delegates.add(ExtensionFileComparator.EXTENSION_REVERSE); break; case 7: delegates.add(ExtensionFileComparator.EXTENSION_INSENSITIVE_COMPARATOR); break; case 8: delegates.add(ExtensionFileComparator.EXTENSION_INSENSITIVE_REVERSE); break; case 9: delegates.add(ExtensionFileComparator.EXTENSION_SYSTEM_COMPARATOR); break; case 10: delegates.add(ExtensionFileComparator.EXTENSION_SYSTEM_REVERSE); break; case 11: delegates.add(LastModifiedFileComparator.LASTMODIFIED_COMPARATOR); break; case 12: delegates.add(LastModifiedFileComparator.LASTMODIFIED_REVERSE); break; case 13: delegates.add(NameFileComparator.NAME_COMPARATOR); break; case 14: delegates.add(NameFileComparator.NAME_REVERSE); break; case 15: delegates.add(NameFileComparator.NAME_INSENSITIVE_COMPARATOR); break; case 16: delegates.add(NameFileComparator.NAME_INSENSITIVE_REVERSE); break; case 17: delegates.add(NameFileComparator.NAME_SYSTEM_COMPARATOR); break; case 18: delegates.add(NameFileComparator.NAME_SYSTEM_REVERSE); break; case 19: delegates.add(PathFileComparator.PATH_COMPARATOR); break; case 20: delegates.add(PathFileComparator.PATH_REVERSE); break; case 21: delegates.add(PathFileComparator.PATH_INSENSITIVE_COMPARATOR); break; case 22: delegates.add(PathFileComparator.PATH_INSENSITIVE_REVERSE); break; case 23: delegates.add(PathFileComparator.PATH_SYSTEM_COMPARATOR); break; case 24: delegates.add(PathFileComparator.PATH_SYSTEM_REVERSE); break; case 25: delegates.add(SizeFileComparator.SIZE_COMPARATOR); break; case 26: delegates.add(SizeFileComparator.SIZE_REVERSE); break; case 27: delegates.add(SizeFileComparator.SIZE_SUMDIR_COMPARATOR); break; case 28: delegates.add(SizeFileComparator.SIZE_SUMDIR_REVERSE); break; } } // Fuzz the comparator by calling sort method of the file list files.sort(new CompositeFileComparator(delegates)); } catch (IOException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/FileFilterFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import org.apache.commons.io.filefilter.CanExecuteFileFilter; import org.apache.commons.io.filefilter.CanReadFileFilter; import org.apache.commons.io.filefilter.CanWriteFileFilter; import org.apache.commons.io.filefilter.EmptyFileFilter; import org.apache.commons.io.filefilter.FileEqualsFileFilter; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.HiddenFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.commons.io.filefilter.WildcardFileFilter; /** * This fuzzer targets the accept method of different FileFilter implementation classes in the * filefilter package. */ public class FileFilterFuzzer { private static File file; public static void fuzzerInitialize() { try { file = File.createTempFile("OSS-Fuzz-", "-OSS-Fuzz"); } catch (IOException e) { throw new RuntimeException(e); } } public static void fuzzerTearDown() { file.delete(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Randomize file content FileWriter writer = new FileWriter(file); writer.write(data.consumeString(data.remainingBytes())); writer.close(); // Create objects of IOFileFilter Integer filterCount = data.consumeInt(1, 10); IOFileFilter[] filters = new IOFileFilter[filterCount]; for (Integer i = 0; i < filterCount; i++) { Boolean negate = data.consumeBoolean(); IOFileFilter filter = null; switch (data.consumeInt(1, 19)) { case 1: filter = FileFilterUtils.ageFileFilter(data.consumeLong(), data.consumeBoolean()); break; case 2: filter = FileFilterUtils.directoryFileFilter(); break; case 3: filter = FileFilterUtils.falseFileFilter(); break; case 4: filter = FileFilterUtils.fileFileFilter(); break; case 5: filter = FileFilterUtils.magicNumberFileFilter(data.consumeBytes(data.remainingBytes())); break; case 6: filter = FileFilterUtils.nameFileFilter(data.consumeString(data.remainingBytes())); break; case 7: filter = FileFilterUtils.prefixFileFilter(data.consumeString(data.remainingBytes())); break; case 8: filter = FileFilterUtils.sizeFileFilter(data.consumeLong(), data.consumeBoolean()); break; case 9: filter = FileFilterUtils.sizeRangeFileFilter(data.consumeLong(), data.consumeLong()); break; case 10: filter = FileFilterUtils.suffixFileFilter(data.consumeString(data.remainingBytes())); break; case 11: filter = CanExecuteFileFilter.CAN_EXECUTE; break; case 12: filter = CanReadFileFilter.CAN_READ; break; case 13: filter = CanReadFileFilter.READ_ONLY; break; case 14: filter = CanWriteFileFilter.CAN_WRITE; break; case 15: filter = EmptyFileFilter.EMPTY; break; case 16: filter = new FileEqualsFileFilter(file); break; case 17: filter = HiddenFileFilter.HIDDEN; break; case 18: filter = TrueFileFilter.INSTANCE; break; case 19: filter = WildcardFileFilter.builder() .setWildcards(data.consumeString(data.remainingBytes())) .get(); break; } if (filter != null) { if (negate) { filters[i] = FileFilterUtils.notFileFilter(filter); } else { filters[i] = filter; } } } // Fuzz the accept methods of the filter list wrapped by AndFileFilter or OrFileFilter if ((filterCount % 2) == 0) { FileFilterUtils.filter(FileFilterUtils.and(filters), file); } else { FileFilterUtils.filter(FileFilterUtils.or(filters), file); } } catch (IOException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/FileUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.LocalDate; import org.apache.commons.io.FileUtils; /** This fuzzer targets the static methods of the File related Utils class in the base package. */ public class FileUtilsFuzzer { private static final String PREFIX = "OSS-Fuzz"; private static Path srcPath; private static Path dstPath; private static Path srcFile; private static Path dstFile; public static void fuzzerInitialize() { try { srcPath = Files.createTempDirectory(PREFIX); dstPath = Files.createTempDirectory(PREFIX); srcFile = Files.createTempFile(srcPath, PREFIX, PREFIX); dstFile = Files.createTempFile(dstPath, PREFIX, PREFIX); } catch (IOException e) { throw new RuntimeException(e); } } public static void fuzzerTearDown() { try { Files.deleteIfExists(srcFile); Files.deleteIfExists(dstFile); Files.deleteIfExists(srcPath); Files.deleteIfExists(dstPath); } catch (IOException e) { // Known exception } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Randomize file content FileWriter writer = new FileWriter(srcFile.toFile()); writer.write(data.consumeString(data.remainingBytes())); writer.close(); switch (data.consumeInt(1, 16)) { case 1: FileUtils.byteCountToDisplaySize(data.consumeLong()); break; case 2: FileUtils.checksumCRC32(srcFile.toFile()); break; case 3: FileUtils.contentEquals(srcFile.toFile(), dstFile.toFile()); break; case 4: FileUtils.contentEqualsIgnoreEOL(srcFile.toFile(), dstFile.toFile(), null); break; case 5: FileUtils.copyDirectoryToDirectory(srcPath.toFile(), dstPath.toFile()); break; case 6: FileUtils.copyFile(srcFile.toFile(), dstFile.toFile()); break; case 7: FileUtils.copyFileToDirectory(srcFile.toFile(), dstPath.toFile()); break; case 8: FileUtils.copyToDirectory(srcFile.toFile(), dstPath.toFile()); break; case 9: FileUtils.isFileNewer(dstFile.toFile(), LocalDate.now()); break; case 10: FileUtils.isFileOlder(dstFile.toFile(), LocalDate.now()); break; case 11: FileUtils.lastModified(srcFile.toFile()); break; case 12: FileUtils.lineIterator(srcFile.toFile()); break; case 13: FileUtils.moveFile(srcFile.toFile(), dstFile.toFile()); break; case 14: FileUtils.streamFiles(srcPath.toFile(), true, null); break; case 15: FileUtils.toFiles(srcFile.toUri().toURL()); break; case 16: FileUtils.toURLs(srcFile.toFile()); break; } } catch (IOException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/GeneralUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import java.time.Duration; import org.apache.commons.io.ByteOrderParser; import org.apache.commons.io.CopyUtils; import org.apache.commons.io.EndianUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.ThreadUtils; /** This fuzzer targets the static methods of the Utils classes in the base package. */ public class GeneralUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { byte[] outArray = new byte[data.remainingBytes()]; ByteArrayOutputStream baos = new ByteArrayOutputStream(data.remainingBytes()); switch (data.consumeInt(1, 24)) { case 1: ByteOrderParser.parseByteOrder(data.consumeRemainingAsString()); break; case 2: CopyUtils.copy( data.consumeRemainingAsString(), baos, Charset.defaultCharset().displayName()); break; case 3: EndianUtils.readSwappedDouble(data.consumeRemainingAsBytes(), 0); break; case 4: EndianUtils.readSwappedFloat(data.consumeRemainingAsBytes(), 0); break; case 5: EndianUtils.readSwappedShort(data.consumeRemainingAsBytes(), 0); break; case 6: IOUtils.consume(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; case 7: byte[] equals = data.consumeRemainingAsBytes(); IOUtils.contentEquals(new ByteArrayInputStream(equals), new ByteArrayInputStream(equals)); break; case 8: IOUtils.copy(new ByteArrayInputStream(data.consumeRemainingAsBytes()), baos); break; case 9: IOUtils.read( new ByteArrayInputStream(data.consumeRemainingAsBytes()), outArray, 0, outArray.length); break; case 10: IOUtils.readFully(new ByteArrayInputStream(data.consumeRemainingAsBytes()), outArray); break; case 11: IOUtils.resourceToByteArray(data.consumeRemainingAsString()); break; case 12: IOUtils.resourceToString(data.consumeRemainingAsString(), Charset.defaultCharset()); break; case 13: Long skip = data.consumeLong(); IOUtils.skip(new ByteArrayInputStream(data.consumeRemainingAsBytes()), skip); break; case 14: IOUtils.toByteArray(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; case 15: byte[] case15 = data.consumeRemainingAsBytes(); IOUtils.contentEquals( new InputStreamReader(new ByteArrayInputStream(case15)), new InputStreamReader(new ByteArrayInputStream(case15))); break; case 16: byte[] case16 = data.consumeRemainingAsBytes(); IOUtils.contentEqualsIgnoreEOL( new InputStreamReader(new ByteArrayInputStream(case16)), new InputStreamReader(new ByteArrayInputStream(case16))); break; case 17: IOUtils.copy( new ByteArrayInputStream(data.consumeRemainingAsBytes()), new OutputStreamWriter(baos), Charset.defaultCharset().name()); break; case 18: IOUtils.copy( new InputStreamReader(new ByteArrayInputStream(data.consumeRemainingAsBytes())), new OutputStreamWriter(baos)); break; case 19: IOUtils.copyLarge( new ByteArrayInputStream(data.consumeRemainingAsBytes()), baos, 0, outArray.length); break; case 20: IOUtils.copyLarge( new InputStreamReader(new ByteArrayInputStream(data.consumeRemainingAsBytes())), new OutputStreamWriter(baos), 0, outArray.length); break; case 21: IOUtils.readFully( new ByteArrayInputStream(data.consumeRemainingAsBytes()), outArray.length); break; case 22: IOUtils.readLines( new ByteArrayInputStream(data.consumeRemainingAsBytes()), Charset.defaultCharset()); break; case 23: Long skip23 = data.consumeLong(); IOUtils.skip( new InputStreamReader(new ByteArrayInputStream(data.consumeRemainingAsBytes())), skip23); break; case 24: ThreadUtils.sleep(Duration.ofSeconds(data.consumeInt(-5, 5))); break; } } catch (IOException | IllegalArgumentException | InterruptedException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/InputStreamFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; import java.security.NoSuchAlgorithmException; import org.apache.commons.io.input.AutoCloseInputStream; import org.apache.commons.io.input.BOMInputStream; import org.apache.commons.io.input.BoundedInputStream; import org.apache.commons.io.input.BrokenInputStream; import org.apache.commons.io.input.CharSequenceInputStream; import org.apache.commons.io.input.CircularInputStream; import org.apache.commons.io.input.ClassLoaderObjectInputStream; import org.apache.commons.io.input.CloseShieldInputStream; import org.apache.commons.io.input.ClosedInputStream; import org.apache.commons.io.input.CountingInputStream; import org.apache.commons.io.input.DemuxInputStream; import org.apache.commons.io.input.InfiniteCircularInputStream; import org.apache.commons.io.input.MarkShieldInputStream; import org.apache.commons.io.input.MemoryMappedFileInputStream; import org.apache.commons.io.input.MessageDigestInputStream; import org.apache.commons.io.input.NullInputStream; import org.apache.commons.io.input.QueueInputStream; import org.apache.commons.io.input.ReadAheadInputStream; import org.apache.commons.io.input.SwappedDataInputStream; import org.apache.commons.io.input.TaggedInputStream; import org.apache.commons.io.input.TeeInputStream; import org.apache.commons.io.input.UncheckedFilterInputStream; import org.apache.commons.io.input.UnixLineEndingInputStream; import org.apache.commons.io.input.UnsynchronizedBufferedInputStream; import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.commons.io.input.UnsynchronizedFilterInputStream; import org.apache.commons.io.input.WindowsLineEndingInputStream; import org.apache.commons.io.input.buffer.PeekableInputStream; import org.apache.commons.io.serialization.ValidatingObjectInputStream; /** * This fuzzer targets the read method of different InputStream implementation classes in the input * or input.buffer packages. */ public class InputStreamFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { InputStream is = null; Integer size = data.remainingBytes(); Boolean boolValue = data.consumeBoolean(); Integer choice = data.consumeInt(1, 29); byte[] srcBuffer = data.consumeRemainingAsBytes(); InputStream bais = new ByteArrayInputStream(srcBuffer); // Randomly create an InputStream implementation object switch (choice) { case 1: is = new PeekableInputStream(bais); ((PeekableInputStream) is).peek(srcBuffer); break; case 2: is = AutoCloseInputStream.builder().setInputStream(bais).get(); break; case 3: is = BOMInputStream.builder() .setInputStream(bais) .setByteOrderMarks() .setInclude(boolValue) .get(); break; case 4: is = new BoundedInputStream(bais); break; case 5: is = BrokenInputStream.INSTANCE; break; case 6: is = CharSequenceInputStream.builder() .setInputStream(bais) .setCharset(Charset.defaultCharset()) .get(); break; case 7: is = new CircularInputStream(srcBuffer, (long) srcBuffer.length); break; case 8: is = new ClassLoaderObjectInputStream(InputStreamFuzzer.class.getClassLoader(), bais); break; case 9: is = CloseShieldInputStream.wrap(bais); break; case 10: is = ClosedInputStream.INSTANCE; break; case 11: is = new CountingInputStream(bais); break; case 12: is = new DemuxInputStream().bindStream(bais); break; case 13: is = new InfiniteCircularInputStream(srcBuffer); break; case 14: is = new MarkShieldInputStream(bais); break; case 15: is = MemoryMappedFileInputStream.builder().setInputStream(bais).get(); break; case 16: is = MessageDigestInputStream.builder() .setInputStream(bais) .setMessageDigest("SHA-256") .get(); break; case 17: is = new NullInputStream(); break; case 18: is = QueueInputStream.builder() .setInputStream(bais) .setBlockingQueue(null) .setTimeout(null) .get(); break; case 19: is = ReadAheadInputStream.builder().setInputStream(bais).get(); break; case 20: is = new SwappedDataInputStream(bais); break; case 21: is = new TaggedInputStream(bais); break; case 22: OutputStream baos = new ByteArrayOutputStream(srcBuffer.length); is = new TeeInputStream(bais, baos, boolValue); break; case 23: is = UncheckedFilterInputStream.builder().setInputStream(bais).get(); break; case 24: is = new UnixLineEndingInputStream(bais, boolValue); break; case 25: is = UnsynchronizedBufferedInputStream.builder().setInputStream(bais).get(); break; case 26: is = UnsynchronizedByteArrayInputStream.builder().setByteArray(srcBuffer).get(); break; case 27: is = UnsynchronizedFilterInputStream.builder().setByteArray(srcBuffer).get(); break; case 28: is = new WindowsLineEndingInputStream(bais, boolValue); break; case 29: is = new ValidatingObjectInputStream(bais); break; } if (is != null) { // Fuzz the read method of the created InputStream object byte[] buffer = new byte[size + 1]; is.reset(); if (is.available() > 0) { is.read(buffer, 0, size + 1); } is.close(); } } catch (IOException | IllegalArgumentException | NoSuchAlgorithmException | UnsupportedOperationException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/InputXmlFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.IOException; import java.io.ByteArrayInputStream; import org.apache.commons.io.input.XmlStreamReader; public class InputXmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ boolean lenient = data.consumeBoolean(); ByteArrayInputStream is = new ByteArrayInputStream(data.consumeRemainingAsBytes()); XmlStreamReader xsr = new XmlStreamReader(is, lenient); } catch (IOException e){ return; } } } ================================================ FILE: projects/apache-commons-io/OutputStreamFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.nio.charset.Charset; import org.apache.commons.io.output.AppendableOutputStream; import org.apache.commons.io.output.BrokenOutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.commons.io.output.ChunkedOutputStream; import org.apache.commons.io.output.CloseShieldOutputStream; import org.apache.commons.io.output.ClosedOutputStream; import org.apache.commons.io.output.CountingOutputStream; import org.apache.commons.io.output.DemuxOutputStream; import org.apache.commons.io.output.NullOutputStream; import org.apache.commons.io.output.ProxyOutputStream; import org.apache.commons.io.output.QueueOutputStream; import org.apache.commons.io.output.TaggedOutputStream; import org.apache.commons.io.output.TeeOutputStream; import org.apache.commons.io.output.ThresholdingOutputStream; import org.apache.commons.io.output.UncheckedFilterOutputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.commons.io.output.WriterOutputStream; /** * This fuzzer targets the read method of different OutputStream implementation classes in the * output package. */ public class OutputStreamFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { OutputStream os = null; Integer choice = data.consumeInt(1, 16); OutputStream baos = new ByteArrayOutputStream(1024); // Randomly create an OutputStream implementation object switch (choice) { case 1: os = new AppendableOutputStream(new StringBuffer()); break; case 2: os = BrokenOutputStream.INSTANCE; break; case 3: os = ChunkedOutputStream.builder().setOutputStream(baos).get(); break; case 4: os = CloseShieldOutputStream.wrap(baos); break; case 5: os = ClosedOutputStream.INSTANCE; break; case 6: os = new CountingOutputStream(baos); break; case 7: os = new DemuxOutputStream().bindStream(baos); break; case 8: os = NullOutputStream.INSTANCE; break; case 9: os = new ProxyOutputStream(baos); break; case 10: os = new QueueOutputStream(); break; case 11: os = new TaggedOutputStream(baos); break; case 12: OutputStream branch = new ByteArrayOutputStream(1024); os = new TeeOutputStream(baos, branch); break; case 13: os = new ThresholdingOutputStream(data.consumeInt()); break; case 14: os = UncheckedFilterOutputStream.builder().setOutputStream(baos).get(); break; case 15: os = UnsynchronizedByteArrayOutputStream.builder().setOutputStream(baos).get(); break; case 16: OutputStreamWriter writer = new OutputStreamWriter(baos); os = WriterOutputStream.builder() .setWriter(writer) .setCharset(Charset.defaultCharset()) .setWriteImmediately(data.consumeBoolean()) .get(); break; } if (os != null) { // Fuzz the write method of the created OutStream object byte[] srcBuffer = data.consumeRemainingAsBytes(); os.write(srcBuffer, 0, srcBuffer.length); os.flush(); os.close(); } } catch (IOException | IllegalArgumentException | UnsupportedOperationException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/PathUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import org.apache.commons.io.file.PathUtils; /** This fuzzer targets the static methods of the PathUtils class in the file package. */ public class PathUtilsFuzzer { private static Path srcPath; private static Path dstPath; private static Path file; public static void fuzzerInitialize() { try { srcPath = Files.createTempDirectory("OSS-Fuzz-"); dstPath = Files.createTempDirectory("OSS-Fuzz-"); file = Files.createTempFile(srcPath, "OSS-Fuzz-", "-OSS-Fuzz"); } catch (IOException e) { throw new RuntimeException(e); } } public static void fuzzerTearDown() { try { Files.deleteIfExists(srcPath); Files.deleteIfExists(dstPath); Files.deleteIfExists(file); } catch (IOException e) { // Known exception } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Randomize file content FileWriter writer = new FileWriter(file.toFile()); writer.write(data.consumeString(data.remainingBytes())); writer.close(); switch (data.consumeInt(1, 8)) { case 1: PathUtils.cleanDirectory(dstPath); break; case 2: PathUtils.copyDirectory(srcPath, dstPath); break; case 3: PathUtils.copyFileToDirectory(file, dstPath); break; case 4: PathUtils.countDirectory(dstPath); break; case 5: PathUtils.createParentDirectories(dstPath); break; case 6: PathUtils.directoryAndFileContentEquals(srcPath, dstPath); break; case 7: PathUtils.directoryContentEquals(srcPath, dstPath); break; case 8: PathUtils.fileContentEquals(srcPath, dstPath); break; } } catch (IOException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/ReaderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; import org.apache.commons.io.input.BoundedReader; import org.apache.commons.io.input.BrokenReader; import org.apache.commons.io.input.CharSequenceReader; import org.apache.commons.io.input.CharacterFilterReader; import org.apache.commons.io.input.CharacterSetFilterReader; import org.apache.commons.io.input.CloseShieldReader; import org.apache.commons.io.input.ClosedReader; import org.apache.commons.io.input.NullReader; import org.apache.commons.io.input.SequenceReader; import org.apache.commons.io.input.TaggedReader; import org.apache.commons.io.input.TeeReader; import org.apache.commons.io.input.UncheckedBufferedReader; import org.apache.commons.io.input.UncheckedFilterReader; import org.apache.commons.io.input.XmlStreamReader; /** * This fuzzer targets the read method of different Reader implementation classes in the input * package. */ public class ReaderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Reader reader = null; Integer size = data.remainingBytes(); Integer intValue = data.consumeInt(); Integer choice = data.consumeInt(1, 14); byte[] srcBuffer = data.consumeRemainingAsBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(srcBuffer); Reader srcReader = new InputStreamReader(bais); // Randomly create a Reader implementation object switch (choice) { case 1: reader = new BoundedReader(srcReader, size); break; case 2: reader = BrokenReader.INSTANCE; break; case 3: reader = new CharSequenceReader(new String(srcBuffer, Charset.defaultCharset())); break; case 4: reader = new CharacterFilterReader(srcReader, intValue); break; case 5: reader = new CharacterSetFilterReader(srcReader, intValue); break; case 6: reader = CloseShieldReader.wrap(srcReader); break; case 7: reader = ClosedReader.INSTANCE; break; case 8: reader = NullReader.INSTANCE; break; case 9: reader = new SequenceReader(srcReader); break; case 10: reader = new TaggedReader(srcReader); break; case 11: Writer writer = new OutputStreamWriter(new ByteArrayOutputStream(size)); reader = new TeeReader(srcReader, writer); break; case 12: reader = UncheckedBufferedReader.builder().setReader(srcReader).get(); break; case 13: reader = UncheckedFilterReader.builder().setReader(srcReader).get(); break; case 14: reader = XmlStreamReader.builder().setInputStream(bais).get(); break; } if (reader != null) { // Fuzz the read method of the created Reader object char[] buffer = new char[size + 1]; if (reader.ready()) { reader.read(buffer, 0, size + 1); } reader.close(); } } catch (IOException | IllegalArgumentException | UnsupportedOperationException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/WriterFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; import org.apache.commons.io.output.AppendableWriter; import org.apache.commons.io.output.BrokenWriter; import org.apache.commons.io.output.ChunkedWriter; import org.apache.commons.io.output.CloseShieldWriter; import org.apache.commons.io.output.ClosedWriter; import org.apache.commons.io.output.FileWriterWithEncoding; import org.apache.commons.io.output.LockableFileWriter; import org.apache.commons.io.output.NullWriter; import org.apache.commons.io.output.ProxyCollectionWriter; import org.apache.commons.io.output.ProxyWriter; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.io.output.TaggedWriter; import org.apache.commons.io.output.TeeWriter; import org.apache.commons.io.output.UncheckedFilterWriter; import org.apache.commons.io.output.XmlStreamWriter; /** * This fuzzer targets the read method of different Writer implementation classes in the output * package. */ public class WriterFuzzer { private static File file; public static void fuzzerInitialize() { try { file = File.createTempFile("OSS-Fuzz-", "-OSS-Fuzz"); } catch (IOException e) { throw new RuntimeException(e); } } public static void fuzzerTearDown() { file.delete(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Writer writer = null; Integer choice = data.consumeInt(1, 15); OutputStream os = new ByteArrayOutputStream(1024); Writer outWriter = new OutputStreamWriter(os); // Randomly create a Writer implementation object switch (choice) { case 1: writer = new AppendableWriter(new StringBuffer()); break; case 2: writer = BrokenWriter.INSTANCE; break; case 3: writer = new ChunkedWriter(outWriter); break; case 4: writer = CloseShieldWriter.wrap(outWriter); break; case 5: writer = ClosedWriter.INSTANCE; break; case 6: writer = FileWriterWithEncoding.builder() .setAppend(data.consumeBoolean()) .setCharset(Charset.defaultCharset()) .setFile(file) .get(); break; case 7: writer = LockableFileWriter.builder() .setAppend(data.consumeBoolean()) .setCharset(Charset.defaultCharset()) .setFile(file) .setLockDirectory((String) null) .get(); break; case 8: writer = NullWriter.INSTANCE; break; case 9: writer = new ProxyCollectionWriter(outWriter); break; case 10: writer = new ProxyWriter(outWriter); break; case 11: writer = new StringBuilderWriter(1024); break; case 12: writer = new TaggedWriter(outWriter); break; case 13: writer = new TeeWriter(outWriter); break; case 14: writer = UncheckedFilterWriter.builder().setWriter(outWriter).get(); break; case 15: writer = XmlStreamWriter.builder() .setOutputStream(os) .setCharset(Charset.defaultCharset()) .get(); break; } if (writer != null) { // Fuzz the write method of the created Writer object String source = data.consumeRemainingAsString(); writer.write(source, 0, source.length()); writer.flush(); writer.close(); } } catch (IOException | IllegalArgumentException | UnsupportedOperationException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-io/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-io-$CURRENT_VERSION.jar" $OUT/commons-io.jar ALL_JARS="commons-io.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-io/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://commons.apache.org/proper/commons-io/ language: jvm main_repo: https://gitbox.apache.org/repos/asf/commons-io.git primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" - "garydgregory@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "david@adalogics.com" - "adam@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/apache-commons-jxpath/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/xml.dict $SRC/JXPathFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JXPathFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/apache/commons-jxpath.git COPY build.sh $SRC/ COPY JXPathFuzzer.java $SRC/ WORKDIR $SRC/commons-jxpath ================================================ FILE: projects/apache-commons-jxpath/JXPathFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.StringReader; import java.io.IOException; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.JXPathException; public class JXPathFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { DocumentBuilder builder = null; Document doc = null; try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setValidating(data.consumeBoolean()); factory.setNamespaceAware(data.consumeBoolean()); factory.setExpandEntityReferences(data.consumeBoolean()); builder = factory.newDocumentBuilder(); } catch (Exception parserConfigurationException) { } try { doc = builder.parse(new InputSource(new StringReader(data.consumeString(2000)))); } catch (SAXException | IOException e) { } JXPathContext context = JXPathContext.newContext(doc); try { context.selectNodes(data.consumeRemainingAsString()); } catch (JXPathException e) { } } } ================================================ FILE: projects/apache-commons-jxpath/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-jxpath-$CURRENT_VERSION.jar" $OUT/commons-jxpath.jar ALL_JARS="commons-jxpath.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-jxpath/project.yaml ================================================ base_os_version: ubuntu-24-04 fuzzing_engines: - libfuzzer homepage: https://github.com/apache/commons-jxpath.git language: jvm main_repo: https://github.com/apache/commons-jxpath.git primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - yakdan@code-intelligence.com - patrice.salathe@code-intelligence.com - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-lang/AnnotationUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.util.HashSet; import java.util.Set; import org.apache.commons.lang3.AnnotationUtils; import org.apache.commons.lang3.exception.UncheckedException; /** This fuzzer targets the methods of the AnnotationUtils class. */ public class AnnotationUtilsFuzzer extends ClassFuzzerBase { private static Set annotationSet; public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { AnnotationUtils.isValidAnnotationMemberType(data.pickValue(classSet)); initializeAnnotationSet(); // Randomly pick 2 annotations object Annotation annotation1 = data.pickValue(annotationSet); Annotation annotation2 = data.pickValue(annotationSet); switch (data.consumeInt(1, 3)) { case 1: AnnotationUtils.toString(annotation1); AnnotationUtils.toString(annotation2); break; case 2: AnnotationUtils.equals(annotation1, annotation2); break; case 3: AnnotationUtils.hashCode(annotation1); AnnotationUtils.hashCode(annotation2); break; } } catch (UncheckedException e) { // Known exception } } private static void initializeAnnotationSet() { if ((annotationSet == null) || (annotationSet.size() == 0)) { annotationSet = new HashSet(); for (Class cls : classSet) { try { Set elements = new HashSet(); elements.add(cls); elements.add(cls.getPackage()); elements.addAll(Set.of(cls.getConstructors())); elements.addAll(Set.of(cls.getMethods())); elements.addAll(Set.of(cls.getFields())); for (AnnotatedElement element : elements) { annotationSet.addAll(Set.of(element.getAnnotations())); } } catch (LinkageError e) { // Ignore failing classes } } } } } ================================================ FILE: projects/apache-commons-lang/ArrayUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.lang3.ArrayFill; import org.apache.commons.lang3.ArraySorter; import org.apache.commons.lang3.ArrayUtils; /** This fuzzer targets the methods of the ArrayUtils class in the base package. */ public class ArrayUtilsFuzzer { private static boolean[] boolArray; private static byte[] byteArray; private static char[] charArray; private static double[] doubleArray; private static float[] floatArray; private static int[] intArray; private static long[] longArray; private static short[] shortArray; private static String[] strArray; public static void fuzzerInitialize() { boolArray = new boolean[1]; byteArray = new byte[1]; charArray = new char[1]; doubleArray = new double[1]; floatArray = new float[1]; intArray = new int[1]; longArray = new long[1]; shortArray = new short[1]; strArray = new String[1]; } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { cleanLargeArray(); for (Integer count = 0; count < data.consumeInt(1, 10); count++) { switch (data.consumeInt(1, 143)) { case 1: ArrayUtils.add(boolArray, data.consumeBoolean()); break; case 2: ArrayUtils.add(byteArray, data.consumeByte()); break; case 3: ArrayUtils.add(charArray, data.consumeChar()); break; case 4: ArrayUtils.add(doubleArray, data.consumeDouble()); break; case 5: ArrayUtils.add(floatArray, data.consumeFloat()); break; case 6: ArrayUtils.add(intArray, data.consumeInt()); break; case 7: ArrayUtils.add(longArray, data.consumeLong()); break; case 8: ArrayUtils.add(shortArray, data.consumeShort()); break; case 9: ArrayUtils.add(strArray, data.consumeString(10)); break; case 10: ArrayUtils.addAll(boolArray, data.consumeBoolean()); break; case 11: ArrayUtils.addAll(byteArray, data.consumeByte()); break; case 12: ArrayUtils.addAll(charArray, data.consumeChar()); break; case 13: ArrayUtils.addAll(doubleArray, data.consumeDouble()); break; case 14: ArrayUtils.addAll(floatArray, data.consumeFloat()); break; case 15: ArrayUtils.addAll(intArray, data.consumeInt()); break; case 16: ArrayUtils.addAll(longArray, data.consumeLong()); break; case 17: ArrayUtils.addAll(shortArray, data.consumeShort()); break; case 18: ArrayUtils.addAll(strArray, data.consumeString(10)); break; case 19: ArrayUtils.addFirst(boolArray, data.consumeBoolean()); break; case 20: ArrayUtils.addFirst(byteArray, data.consumeByte()); break; case 21: ArrayUtils.addFirst(charArray, data.consumeChar()); break; case 22: ArrayUtils.addFirst(doubleArray, data.consumeDouble()); break; case 23: ArrayUtils.addFirst(floatArray, data.consumeFloat()); break; case 24: ArrayUtils.addFirst(intArray, data.consumeInt()); break; case 25: ArrayUtils.addFirst(longArray, data.consumeLong()); break; case 26: ArrayUtils.addFirst(shortArray, data.consumeShort()); break; case 27: ArrayUtils.addFirst(strArray, data.consumeString(10)); break; case 28: ArrayUtils.reverse(boolArray); break; case 29: ArrayUtils.reverse(byteArray); break; case 30: ArrayUtils.reverse(charArray); break; case 31: ArrayUtils.reverse(doubleArray); break; case 32: ArrayUtils.reverse(floatArray); break; case 33: ArrayUtils.reverse(intArray); break; case 34: ArrayUtils.reverse(longArray); break; case 35: ArrayUtils.reverse(shortArray); break; case 36: ArrayUtils.reverse(strArray); break; case 37: ArrayUtils.shift(boolArray, 10); break; case 38: ArrayUtils.shift(byteArray, 10); break; case 39: ArrayUtils.shift(charArray, 10); break; case 40: ArrayUtils.shift(doubleArray, 10); break; case 41: ArrayUtils.shift(floatArray, 10); break; case 42: ArrayUtils.shift(intArray, 10); break; case 43: ArrayUtils.shift(longArray, 10); break; case 44: ArrayUtils.shift(shortArray, 10); break; case 45: ArrayUtils.shift(strArray, 10); break; case 46: ArrayUtils.shuffle(boolArray); break; case 47: ArrayUtils.shuffle(byteArray); break; case 48: ArrayUtils.shuffle(charArray); break; case 49: ArrayUtils.shuffle(doubleArray); break; case 50: ArrayUtils.shuffle(floatArray); break; case 51: ArrayUtils.shuffle(intArray); break; case 52: ArrayUtils.shuffle(longArray); break; case 53: ArrayUtils.shuffle(shortArray); break; case 54: ArrayUtils.shuffle(strArray); break; case 55: ArrayUtils.swap(boolArray, 0, 1); break; case 56: ArrayUtils.swap(byteArray, 0, 1); break; case 57: ArrayUtils.swap(charArray, 0, 1); break; case 58: ArrayUtils.swap(doubleArray, 0, 1); break; case 59: ArrayUtils.swap(floatArray, 0, 1); break; case 60: ArrayUtils.swap(intArray, 0, 1); break; case 61: ArrayUtils.swap(longArray, 0, 1); break; case 62: ArrayUtils.swap(shortArray, 0, 1); break; case 63: ArrayUtils.swap(strArray, 0, 1); break; case 64: ArrayUtils.toPrimitive(ArrayUtils.toObject(boolArray)); break; case 65: ArrayUtils.toPrimitive(ArrayUtils.toObject(byteArray)); break; case 66: ArrayUtils.toPrimitive(ArrayUtils.toObject(charArray)); break; case 67: ArrayUtils.toPrimitive(ArrayUtils.toObject(doubleArray)); break; case 68: ArrayUtils.toPrimitive(ArrayUtils.toObject(floatArray)); break; case 69: ArrayUtils.toPrimitive(ArrayUtils.toObject(intArray)); break; case 70: ArrayUtils.toPrimitive(ArrayUtils.toObject(longArray)); break; case 71: ArrayUtils.toPrimitive(ArrayUtils.toObject(shortArray)); break; case 72: ArrayUtils.removeElement(boolArray, data.consumeBoolean()); break; case 73: ArrayUtils.removeElement(byteArray, data.consumeByte()); break; case 74: ArrayUtils.removeElement(charArray, data.consumeChar()); break; case 75: ArrayUtils.removeElement(doubleArray, data.consumeDouble()); break; case 76: ArrayUtils.removeElement(floatArray, data.consumeFloat()); break; case 77: ArrayUtils.removeElement(intArray, data.consumeInt()); break; case 78: ArrayUtils.removeElement(longArray, data.consumeLong()); break; case 79: ArrayUtils.removeElement(shortArray, data.consumeShort()); break; case 80: ArrayUtils.removeElement(strArray, data.consumeString(10)); break; case 81: ArrayUtils.subarray(boolArray, 0, 1); break; case 82: ArrayUtils.subarray(byteArray, 0, 1); break; case 83: ArrayUtils.subarray(charArray, 0, 1); break; case 84: ArrayUtils.subarray(doubleArray, 0, 1); break; case 85: ArrayUtils.subarray(floatArray, 0, 1); break; case 86: ArrayUtils.subarray(intArray, 0, 1); break; case 87: ArrayUtils.subarray(longArray, 0, 1); break; case 88: ArrayUtils.subarray(shortArray, 0, 1); break; case 89: ArrayUtils.subarray(strArray, 0, 1); break; case 90: ArrayUtils.contains(boolArray, data.consumeBoolean()); break; case 91: ArrayUtils.contains(byteArray, data.consumeByte()); break; case 92: ArrayUtils.contains(charArray, data.consumeChar()); break; case 93: ArrayUtils.contains(doubleArray, data.consumeDouble()); break; case 94: ArrayUtils.contains(floatArray, data.consumeFloat()); break; case 95: ArrayUtils.contains(intArray, data.consumeInt()); break; case 96: ArrayUtils.contains(longArray, data.consumeLong()); break; case 97: ArrayUtils.contains(shortArray, data.consumeShort()); break; case 98: ArrayUtils.contains(strArray, data.consumeString(10)); break; case 99: ArrayUtils.indexesOf(boolArray, data.consumeBoolean()); break; case 100: ArrayUtils.indexesOf(byteArray, data.consumeByte()); break; case 101: ArrayUtils.indexesOf(charArray, data.consumeChar()); break; case 102: ArrayUtils.indexesOf(doubleArray, data.consumeDouble()); break; case 103: ArrayUtils.indexesOf(floatArray, data.consumeFloat()); break; case 104: ArrayUtils.indexesOf(intArray, data.consumeInt()); break; case 105: ArrayUtils.indexesOf(longArray, data.consumeLong()); break; case 106: ArrayUtils.indexesOf(shortArray, data.consumeShort()); break; case 107: ArrayUtils.indexesOf(strArray, data.consumeString(10)); break; case 108: ArrayUtils.isSorted(boolArray); break; case 109: ArrayUtils.isSorted(byteArray); break; case 110: ArrayUtils.isSorted(charArray); break; case 111: ArrayUtils.isSorted(doubleArray); break; case 112: ArrayUtils.isSorted(floatArray); break; case 113: ArrayUtils.isSorted(intArray); break; case 114: ArrayUtils.isSorted(longArray); break; case 115: ArrayUtils.isSorted(shortArray); break; case 116: ArrayUtils.isSorted(strArray); break; case 117: ArrayUtils.lastIndexOf(boolArray, data.consumeBoolean()); break; case 118: ArrayUtils.lastIndexOf(byteArray, data.consumeByte()); break; case 119: ArrayUtils.lastIndexOf(charArray, data.consumeChar()); break; case 120: ArrayUtils.lastIndexOf(doubleArray, data.consumeDouble()); break; case 121: ArrayUtils.lastIndexOf(floatArray, data.consumeFloat()); break; case 122: ArrayUtils.lastIndexOf(intArray, data.consumeInt()); break; case 123: ArrayUtils.lastIndexOf(longArray, data.consumeLong()); break; case 124: ArrayUtils.lastIndexOf(shortArray, data.consumeShort()); break; case 125: ArrayUtils.lastIndexOf(strArray, data.consumeString(10)); break; case 126: ArrayUtils.removeAllOccurrences(boolArray, data.consumeBoolean()); break; case 127: ArrayUtils.removeAllOccurrences(byteArray, data.consumeByte()); break; case 128: ArrayUtils.removeAllOccurrences(charArray, data.consumeChar()); break; case 129: ArrayUtils.removeAllOccurrences(doubleArray, data.consumeDouble()); break; case 130: ArrayUtils.removeAllOccurrences(floatArray, data.consumeFloat()); break; case 131: ArrayUtils.removeAllOccurrences(intArray, data.consumeInt()); break; case 132: ArrayUtils.removeAllOccurrences(longArray, data.consumeLong()); break; case 133: ArrayUtils.removeAllOccurrences(shortArray, data.consumeShort()); break; case 134: ArrayUtils.removeAllOccurrences(strArray, data.consumeString(10)); break; case 135: ArrayUtils.removeElements(boolArray, boolArray); break; case 136: ArrayUtils.removeElements(byteArray, byteArray); break; case 137: ArrayUtils.removeElements(charArray, charArray); break; case 138: ArrayUtils.removeElements(doubleArray, doubleArray); break; case 139: ArrayUtils.removeElements(floatArray, floatArray); break; case 140: ArrayUtils.removeElements(intArray, intArray); break; case 141: ArrayUtils.removeElements(longArray, longArray); break; case 142: ArrayUtils.removeElements(shortArray, shortArray); break; case 143: ArrayUtils.removeElements(strArray, strArray); break; } } } catch (IllegalArgumentException e) { // Known exception } } private static void cleanLargeArray() { if (boolArray.length > 256) { boolArray = new boolean[1]; } if (byteArray.length > 256) { byteArray = new byte[1]; ArrayFill.fill(byteArray, (byte) 0); } if (charArray.length > 256) { charArray = new char[1]; ArrayFill.fill(charArray, (char) 0); } if (doubleArray.length > 256) { doubleArray = new double[1]; ArrayFill.fill(doubleArray, 0d); } if (floatArray.length > 256) { floatArray = new float[1]; ArrayFill.fill(floatArray, 0f); } if (intArray.length > 256) { intArray = new int[1]; ArrayFill.fill(intArray, 0); } if (longArray.length > 256) { longArray = new long[1]; ArrayFill.fill(longArray, 0l); } if (shortArray.length > 256) { shortArray = new short[1]; ArrayFill.fill(shortArray, (short) 0); } if (strArray.length > 256) { strArray = new String[1]; ArrayFill.fill(strArray, ""); } sortArray(); } private static void sortArray() { ArraySorter.sort(byteArray); ArraySorter.sort(charArray); ArraySorter.sort(doubleArray); ArraySorter.sort(floatArray); ArraySorter.sort(intArray); ArraySorter.sort(longArray); ArraySorter.sort(shortArray); ArraySorter.sort(strArray); } } ================================================ FILE: projects/apache-commons-lang/BuilderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.lang3.builder.Builder; import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.commons.lang3.builder.DiffBuilder; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ReflectionDiffBuilder; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; /** This fuzzer targets the methods of the classes in the buidler package */ public class BuilderFuzzer { private static final ToStringStyle[] styles = { ToStringStyle.DEFAULT_STYLE, ToStringStyle.JSON_STYLE, ToStringStyle.MULTI_LINE_STYLE, ToStringStyle.NO_CLASS_NAME_STYLE, ToStringStyle.NO_FIELD_NAMES_STYLE, ToStringStyle.SHORT_PREFIX_STYLE, ToStringStyle.SIMPLE_STYLE }; private static CompareToBuilder compareTo; private static DiffBuilder diff; private static EqualsBuilder equals; private static HashCodeBuilder hashCode; private static ReflectionDiffBuilder reflectionDiff; private static ReflectionToStringBuilder reflectionToString; public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Builder builder = null; ToStringStyle styleChoice = data.pickValue(styles); Integer choice = data.consumeInt(1, 10); Object obj1 = getRandomObject(data); Object obj2 = getRandomObject(data); initializeBuilder(obj1, obj2, styleChoice); switch (choice) { case 1: CompareToBuilder.reflectionCompare(obj1, obj2); break; case 2: builder = compareTo.append(Object.class.cast(obj1), Object.class.cast(obj2)); break; case 3: builder = diff.append( data.consumeRemainingAsString(), Object.class.cast(obj1), Object.class.cast(obj2)); break; case 4: EqualsBuilder.reflectionEquals(obj1, obj2, data.consumeBoolean()); break; case 5: builder = equals.append(Object.class.cast(obj1), Object.class.cast(obj2)); break; case 6: HashCodeBuilder.reflectionHashCode(obj1, data.consumeBoolean()); HashCodeBuilder.reflectionHashCode(obj2, data.consumeBoolean()); break; case 7: builder = hashCode.append(Object.class.cast(obj1)).append(Object.class.cast(obj2)); break; case 8: builder = reflectionDiff; break; case 9: ReflectionToStringBuilder.toString(obj1, styleChoice); ReflectionToStringBuilder.toString(obj2, styleChoice); break; case 10: builder = reflectionToString.reflectionAppendArray(obj1).reflectionAppendArray(obj2); break; } if (builder != null) { builder.build(); } } catch (IllegalArgumentException | ClassCastException e) { // Known exception } } private static void initializeBuilder(Object obj1, Object obj2, ToStringStyle style) { compareTo = new CompareToBuilder(); diff = new DiffBuilder(obj1, obj2, style); equals = new EqualsBuilder(); hashCode = new HashCodeBuilder(); reflectionDiff = new ReflectionDiffBuilder(obj1, obj2, style); reflectionToString = new ReflectionToStringBuilder(obj1, style); } private static Object getRandomObject(FuzzedDataProvider data) { Object obj = null; switch (data.consumeInt(1, 18)) { case 1: obj = data.consumeBoolean(); break; case 2: obj = data.consumeBooleans(data.remainingBytes()); break; case 3: obj = data.consumeBytes(data.remainingBytes()); break; case 4: obj = data.consumeByte(); break; case 5: obj = data.consumeChar(); break; case 6: obj = data.consumeString(data.remainingBytes()).toCharArray(); break; case 7: obj = data.consumeDouble(); break; case 8: double[] doubleArray = new double[data.consumeInt(1, 5)]; for (Integer i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } obj = doubleArray; break; case 9: obj = data.consumeFloat(); break; case 10: float[] floatArray = new float[data.consumeInt(1, 5)]; for (Integer i = 0; i < floatArray.length; i++) { floatArray[i] = data.consumeFloat(); } obj = floatArray; break; case 11: obj = data.consumeInt(); break; case 12: obj = data.consumeInts(data.remainingBytes()); break; case 13: obj = data.consumeLong(); break; case 14: obj = data.consumeLongs(data.remainingBytes()); break; case 15: obj = data.consumeShort(); break; case 16: obj = data.consumeShorts(data.remainingBytes()); break; case 17: obj = data.consumeString(data.remainingBytes()); break; case 18: String[] strArray = new String[data.consumeInt(1, 5)]; for (Integer i = 0; i < strArray.length; i++) { strArray[i] = data.consumeString(data.remainingBytes()); } obj = strArray; break; } return obj; } } ================================================ FILE: projects/apache-commons-lang/CharUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.lang3.CharSequenceUtils; import org.apache.commons.lang3.CharSetUtils; import org.apache.commons.lang3.CharUtils; /** This fuzzer targets the methods of the Char related utils classes. */ public class CharUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 10); switch (choice) { case 1: CharSequenceUtils.subSequence(data.consumeRemainingAsString(), 0); break; case 2: CharSequenceUtils.toCharArray(data.consumeRemainingAsString()); break; case 3: CharSetUtils.containsAny( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 4: CharSetUtils.count( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 5: CharSetUtils.delete( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 6: CharSetUtils.keep( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 7: CharSetUtils.squeeze( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 8: CharUtils.isAsciiAlphanumeric(data.consumeChar()); break; case 9: CharUtils.toCharacterObject(data.consumeRemainingAsString()); break; case 10: CharUtils.unicodeEscaped(data.consumeChar()); break; } } catch (IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-lang/ClassFuzzerBase.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.google.common.reflect.ClassPath; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** This is the base class for fuzzers requiring random class type objects */ public abstract class ClassFuzzerBase { private static final Integer MAX_CLASS = 64; public static Set classSet; public static void fuzzerInitialize() throws IOException { Set all = getAllClasses(); classSet = new HashSet(); classSet.add(Object.class); classSet.add(Throwable.class); classSet.add(String.class); classSet.add(Integer.class); classSet.add(ArrayList.class); classSet.add(Collections.class); classSet.add(HashSet.class); classSet.add(List.class); classSet.add(Set.class); classSet.add(Collectors.class); classSet.add(ClassPath.class); if (all != null) { classSet.addAll(all); } } public static void fuzzerTearDown() { classSet.clear(); classSet = null; } public static Set getAllClasses() throws IOException { ClassLoader loader = ClassLoader.getSystemClassLoader(); Set set = new HashSet(); List classInfoList = ClassPath.from(loader).getAllClasses().stream().collect(Collectors.toList()); Collections.shuffle(classInfoList); for (ClassPath.ClassInfo c : classInfoList) { if (set.size() >= MAX_CLASS) { break; } Class cls = null; try { cls = c.load(); } catch (LinkageError e) { // Ignore } if (cls != null) { set.add(cls); } } return set; } } ================================================ FILE: projects/apache-commons-lang/ConversionFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.lang3.Conversion; /** This fuzzer targets the methods of the Conversion class */ public class ConversionFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 15); Integer size = data.consumeInt(1, 5); Integer remaining = data.remainingBytes(); switch (choice) { case 1: Conversion.binaryBeMsb0ToHexDigit(data.consumeBooleans(data.consumeInt(1, 5))); break; case 2: Conversion.binaryToByte(data.consumeBooleans(size), 0, (byte) 0, 0, size); break; case 3: Conversion.binaryToHexDigit(data.consumeBooleans(data.consumeInt(1, 5))); break; case 4: Conversion.binaryToHexDigitMsb0_4bits(data.consumeBooleans(data.consumeInt(1, 5))); break; case 5: Conversion.binaryToInt(data.consumeBooleans(data.consumeInt(1, 5)), 0, 0, 0, size); break; case 6: Conversion.binaryToLong(data.consumeBooleans(data.consumeInt(1, 5)), 0, 0l, 0, size); break; case 7: Conversion.binaryToShort( data.consumeBooleans(data.consumeInt(1, 5)), 0, (short) 0, 0, size); break; case 8: Conversion.byteArrayToInt(data.consumeRemainingAsBytes(), 0, 0, 0, remaining); break; case 9: Conversion.byteArrayToLong(data.consumeRemainingAsBytes(), 0, 0l, 0, remaining); break; case 10: Conversion.byteArrayToShort(data.consumeRemainingAsBytes(), 0, (short) 0, 0, remaining); break; case 11: Conversion.byteArrayToUuid(data.consumeRemainingAsBytes(), 0); break; case 12: Conversion.hexToByte(data.consumeRemainingAsString(), 0, (byte) 0, 0, remaining); break; case 13: Conversion.hexToInt(data.consumeRemainingAsString(), 0, 0, 0, remaining); break; case 14: Conversion.hexToLong(data.consumeRemainingAsString(), 0, 0l, 0, remaining); break; case 15: Conversion.hexToShort(data.consumeRemainingAsString(), 0, (short) 0, 0, remaining); break; } } catch (IllegalArgumentException | NullPointerException | IndexOutOfBoundsException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-lang/DateUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import java.util.Locale; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DurationFormatUtils; /** This fuzzer targets the methods of the classes in the time package. */ public class DateUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Calendar calendar = Calendar.getInstance(); Date date = new Date(); Integer choice = data.consumeInt(1, 13); switch (choice) { case 1: DateFormatUtils.format(calendar, data.consumeRemainingAsString()); break; case 2: DateFormatUtils.formatUTC(date, data.consumeRemainingAsString()); break; case 3: DateUtils.parseDate( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 4: DateUtils.parseDate( data.consumeString(data.remainingBytes()), Locale.getDefault(), data.consumeRemainingAsString()); break; case 5: DateUtils.parseDateStrictly( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); break; case 6: DateUtils.parseDateStrictly( data.consumeString(data.remainingBytes()), Locale.getDefault(), data.consumeRemainingAsString()); break; case 7: DateUtils.round(date, data.consumeInt()); break; case 8: DateUtils.round(calendar, data.consumeInt()); break; case 9: DateUtils.truncatedEquals( calendar, DateUtils.truncate(calendar, data.consumeInt()), data.consumeInt()); break; case 10: DateUtils.truncatedEquals( date, DateUtils.truncate(date, data.consumeInt()), data.consumeInt()); break; case 11: DurationFormatUtils.formatDuration(data.consumeLong(), data.consumeRemainingAsString()); break; case 12: DurationFormatUtils.formatDurationWords( data.consumeLong(), data.consumeBoolean(), data.consumeBoolean()); break; case 13: DurationFormatUtils.formatPeriod( data.consumeLong(), data.consumeLong(), data.consumeRemainingAsString()); break; } } catch (ParseException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-lang/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN git clone --depth 1 https://github.com/google/fuzzing RUN cat fuzzing/dictionaries/json.dict \ fuzzing/dictionaries/xml.dict \ > $SRC/StringEscapeUtilsFuzzer.dict RUN mv fuzzing/dictionaries/html.dict $SRC/EscapeHtmlFuzzer.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/EscapeHtmlFuzzer_seed_corpus.zip go-fuzz-corpus/htmltemplate/corpus/* && \ zip -q $SRC/StringEscapeUtilsFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* go-fuzz-corpus/csv/corpus/* ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone --depth 1 https://github.com/apache/commons-lang commons-lang COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/commons-lang ================================================ FILE: projects/apache-commons-lang/EscapeHtmlFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.lang3.StringEscapeUtils; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import java.util.regex.*; public class EscapeHtmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String safeHtml = StringEscapeUtils.escapeHtml3(data.consumeString(50)); assert !safeHtml.contains(" 0) { StringUtils.join(string1.toCharArray(), string2.toCharArray()[0], 0, string1.length()); } break; case 40: if (string2.length() > 0) { StringUtils.joinWith(string1, string2.toCharArray()); } break; case 41: StringUtils.lastIndexOf(string1, string2); break; case 42: StringUtils.lastIndexOfAny(string1, string2); break; case 43: StringUtils.lastIndexOfIgnoreCase(string1, string2); break; case 44: StringUtils.left(string1, string1.length()); break; case 45: StringUtils.leftPad(string1, string1.length() + 10); break; case 46: StringUtils.mid(string1, 0, string1.length()); break; case 47: StringUtils.normalizeSpace(string1); break; case 48: StringUtils.overlay(string1, string2, 0, string1.length()); break; case 49: StringUtils.right(string1, string1.length()); break; case 50: StringUtils.rightPad(string1, string1.length() + 10); break; case 51: StringUtils.rotate(string1, string1.length()); break; case 52: StringUtils.split(string1); break; case 53: StringUtils.splitByCharacterType(string1); break; case 54: StringUtils.splitByCharacterTypeCamelCase(string1); break; case 55: StringUtils.splitByWholeSeparator(string1, string2); break; case 56: StringUtils.splitPreserveAllTokens(string1); break; case 57: StringUtils.swapCase(string1); break; case 58: StringUtils.truncate(string1, string1.length()); break; case 59: StringUtils.uncapitalize(string1); break; case 60: StringUtils.wrap(string1, string2); break; case 61: // TODO verify if regex injection is real // Validate.matchesPattern(string1, string2); break; } } catch (IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/apache-commons-lang/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -Dmaven.javadoc.skip=true -DskipTests -Drat.ignoreErrors=true" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/commons-lang3-$CURRENT_VERSION.jar" "$OUT/commons-lang.jar" mkdir -p $OUT/dependency wget -O $OUT/dependency/guava.jar https://repo1.maven.org/maven2/com/google/guava/guava/32.1.3-jre/guava-32.1.3-jre.jar # Compile ClassFuzzerBase javac -cp $OUT/dependency/guava.jar $SRC/ClassFuzzerBase.java jar cvf $OUT/class-fuzzer-base.jar -C $SRC ClassFuzzerBase.class ALL_JARS="commons-lang.jar class-fuzzer-base.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$OUT/dependency/guava.jar:$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir/dependency/guava.jar:\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-lang/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/apache/commons-lang language: jvm main_repo: https://github.com/apache/commons-lang.git primary_contact: "fuzz-testing@commons.apache.org" sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "david@adalogics.com" - "adam@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/apache-commons-logging/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone https://github.com/apache/commons-logging COPY build.sh $SRC/ COPY *.java *.xml $SRC/ COPY Package $SRC/Package/ WORKDIR $SRC/commons-logging ================================================ FILE: projects/apache-commons-logging/LoggingBasicFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class LoggingBasicFuzzer { public LoggingBasicFuzzer(FuzzedDataProvider data) { } void runTest(FuzzedDataProvider data) { Log logger = LogFactory.getLog(LoggingBasicFuzzer.class); logger.isDebugEnabled(); logger.isErrorEnabled(); logger.isFatalEnabled(); logger.isInfoEnabled(); logger.isTraceEnabled(); logger.isWarnEnabled(); logger.debug(data.consumeString(10)); logger.error(data.consumeString(10)); logger.fatal(data.consumeString(10)); logger.info(data.consumeString(10)); logger.warn(data.consumeString(10)); logger.debug(data.consumeString(10), new NullPointerException()); logger.error(data.consumeString(10), new NullPointerException()); logger.fatal(data.consumeString(10), new NullPointerException()); logger.info(data.consumeString(10), new NullPointerException()); logger.warn(data.consumeString(10), new NullPointerException()); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { LoggingBasicFuzzer testClosure = new LoggingBasicFuzzer(data); testClosure.runTest(data); } } ================================================ FILE: projects/apache-commons-logging/Package/MyAppender.java ================================================ package Package; import java.time.Instant; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.config.plugins.PluginFactory; @Plugin( name = "MyAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) public class MyAppender extends AbstractAppender { public MyAppender(String name, Filter filter) { super(name, filter, null); } @PluginFactory public static MyAppender createAppender( @PluginAttribute("name") String name, @PluginElement("Filter") Filter filter) { return new MyAppender(name, filter); } @Override public void append(LogEvent event) { } } ================================================ FILE: projects/apache-commons-logging/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests -Drat.ignoreErrors=true" ALL_JARS="" pushd "${SRC}/commons-logging" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp -v target/commons-logging-${CURRENT_VERSION}.jar "$OUT/commons-logging.jar" ALL_JARS="${ALL_JARS} commons-logging.jar" popd LOG4J_VERSION=$(curl -s 'https://api.github.com/repos/apache/logging-log4j2/tags?per_page=20' | jq -r '.[].name' | grep -E '^rel/2\.[0-9]+\.[0-9]+$' | head -1 | sed 's/^rel\///') curl "https://archive.apache.org/dist/logging/log4j/$LOG4J_VERSION/apache-log4j-$LOG4J_VERSION-bin.zip" -o apache-log4j-bin.zip unzip -q -o apache-log4j-bin.zip -d $SRC/apache-log4j-$LOG4J_VERSION-bin unlink apache-log4j-bin.zip for jarFile in ${SRC}/apache-log4j-$LOG4J_VERSION-bin/log4j-api-$LOG4J_VERSION.jar ${SRC}/apache-log4j-$LOG4J_VERSION-bin/log4j-core-$LOG4J_VERSION.jar ${SRC}/apache-log4j-$LOG4J_VERSION-bin/log4j-1.2-api-$LOG4J_VERSION.jar ; do cp -v ${jarFile} "$OUT/$(basename ${jarFile})" ALL_JARS="${ALL_JARS} $(basename ${jarFile})" done # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java $SRC/Package/*.java mkdir -p $OUT/Package cp -vr $SRC/Package/*.class $OUT/Package cp -v $SRC/*.class $OUT/ cp -v $SRC/*.xml $OUT/ for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-logging/log4j2-test.xml ================================================ ================================================ FILE: projects/apache-commons-logging/project.yaml ================================================ homepage: https://commons.apache.org/proper/commons-collections/ language: jvm main_repo: https://gitbox.apache.org/repos/asf/commons-logging.git primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-math/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN=$SRC/maven/apache-maven-3.9.9/bin/mvn # Math RUN git clone --depth 1 https://github.com/apache/commons-math.git # Copy build script and all fuzzers COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-math/MathClusteringFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.ArrayList; import org.apache.commons.math4.legacy.exception.ConvergenceException; import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException; import org.apache.commons.math4.legacy.exception.NotPositiveException; import org.apache.commons.math4.legacy.ml.clustering.Clusterer; import org.apache.commons.math4.legacy.ml.clustering.DBSCANClusterer; import org.apache.commons.math4.legacy.ml.clustering.DoublePoint; import org.apache.commons.math4.legacy.ml.clustering.ElkanKMeansPlusPlusClusterer; import org.apache.commons.math4.legacy.ml.clustering.FuzzyKMeansClusterer; import org.apache.commons.math4.legacy.ml.clustering.KMeansPlusPlusClusterer; import org.apache.commons.math4.legacy.ml.clustering.MultiKMeansPlusPlusClusterer; public class MathClusteringFuzzer { protected int m_clustersToFind; protected int m_iterations; protected double m_fuzziness; protected int m_multiKMeansMaxTrials; protected double m_dbscanMaxRadius; protected int m_dbscanMinPoints; protected ArrayList m_data; public MathClusteringFuzzer(FuzzedDataProvider fuzzedDataProvider) { m_clustersToFind = fuzzedDataProvider.consumeInt(1, 10); // let's be "sane" ... for the beginning m_iterations = fuzzedDataProvider.consumeInt(1, 10000); // again m_fuzziness = fuzzedDataProvider.consumeRegularDouble(); m_multiKMeansMaxTrials = fuzzedDataProvider.consumeInt(0, 10); m_dbscanMaxRadius = fuzzedDataProvider.consumeRegularDouble(); m_dbscanMinPoints = fuzzedDataProvider.consumeInt(); int dimension = 2; int inputLength = (fuzzedDataProvider.remainingBytes() / 8 /*sizeof(double)*/) / dimension; if (inputLength < 1) { inputLength = 1; } m_data = new ArrayList(inputLength); for (int i = 0; i < inputLength; ++i) { double dataPoint[] = new double[dimension]; for (int n = 0; n < dataPoint.length; ++n) { dataPoint[n] = fuzzedDataProvider.consumeRegularDouble(); } m_data.add( new DoublePoint(dataPoint) ); } } void runDBSCAN() { try { DBSCANClusterer clusterer = new DBSCANClusterer(m_dbscanMaxRadius, m_dbscanMinPoints); clusterer.cluster(m_data); } catch (NotPositiveException ex) { /* documented, ignore */ } } void runElkanKMeansPlusPlus() { try { ElkanKMeansPlusPlusClusterer clusterer = new ElkanKMeansPlusPlusClusterer(m_clustersToFind); clusterer.cluster(m_data); } catch (MathIllegalArgumentException ex) { /* documented, ignore */ } catch (ConvergenceException ex) { /* documented, ignore */ } catch (IllegalArgumentException ex) { } } void runKMeansPlusPlus() { try { KMeansPlusPlusClusterer clusterer = new KMeansPlusPlusClusterer(m_clustersToFind, m_iterations); clusterer.cluster(m_data); } catch (MathIllegalArgumentException ex) { /* documented, ignore */ } catch (ConvergenceException ex) { /* documented, ignore */ } catch (IllegalArgumentException ex) { } } void runFuzzyKMeans() { try { FuzzyKMeansClusterer clusterer = new FuzzyKMeansClusterer(m_clustersToFind, m_fuzziness); clusterer.cluster(m_data); } catch (MathIllegalArgumentException ex) { /* documented, ignore */ } catch (ConvergenceException ex) { /* documented, ignore */ } catch (IllegalArgumentException ex) { } } void runMultiKMeans() { try { KMeansPlusPlusClusterer kmeans = new KMeansPlusPlusClusterer(m_clustersToFind, m_iterations); MultiKMeansPlusPlusClusterer clusterer = new MultiKMeansPlusPlusClusterer(kmeans, m_multiKMeansMaxTrials); clusterer.cluster(m_data); } catch (MathIllegalArgumentException ex) { /* documented, ignore */ } catch (ConvergenceException ex) { /* documented, ignore */ } catch (IllegalArgumentException ex) { } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { MathClusteringFuzzer testClosure = new MathClusteringFuzzer(data); testClosure.runDBSCAN(); testClosure.runKMeansPlusPlus(); testClosure.runFuzzyKMeans(); testClosure.runElkanKMeansPlusPlus(); testClosure.runMultiKMeans(); } } ================================================ FILE: projects/apache-commons-math/MathDistanceMeasureFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.ArrayList; import org.apache.commons.math4.legacy.exception.DimensionMismatchException; import org.apache.commons.math4.legacy.ml.distance.CanberraDistance; import org.apache.commons.math4.legacy.ml.distance.ChebyshevDistance; import org.apache.commons.math4.legacy.ml.distance.EarthMoversDistance; import org.apache.commons.math4.legacy.ml.distance.EuclideanDistance; import org.apache.commons.math4.legacy.ml.distance.ManhattanDistance; public class MathDistanceMeasureFuzzer { double m_x0[]; double m_x1[]; public MathDistanceMeasureFuzzer(FuzzedDataProvider fuzzedDataProvider) { m_x0 = new double[fuzzedDataProvider.consumeInt(1,100)]; m_x1 = new double[fuzzedDataProvider.consumeInt(1,100)]; for (int i = 0; i < m_x0.length; ++i) { m_x0[i] = fuzzedDataProvider.consumeRegularDouble(); } for (int i = 0; i < m_x1.length; ++i) { m_x1[i] = fuzzedDataProvider.consumeRegularDouble(); } } void computeDistances() { try { new CanberraDistance().compute(m_x0, m_x1); new ChebyshevDistance().compute(m_x0, m_x1); new EarthMoversDistance().compute(m_x0, m_x1); new EuclideanDistance().compute(m_x0, m_x1); new ManhattanDistance().compute(m_x0, m_x1); } catch (DimensionMismatchException ex) { /* documented, ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { MathDistanceMeasureFuzzer testClosure = new MathDistanceMeasureFuzzer(data); testClosure.computeDistances(); } } ================================================ FILE: projects/apache-commons-math/MathSimplexSolverFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.ArrayList; import org.apache.commons.math4.legacy.exception.DimensionMismatchException; import org.apache.commons.math4.legacy.exception.TooManyIterationsException; import org.apache.commons.math4.legacy.optim.linear.NoFeasibleSolutionException; import org.apache.commons.math4.legacy.optim.linear.UnboundedSolutionException; import org.apache.commons.math4.legacy.optim.PointValuePair; import org.apache.commons.math4.legacy.optim.linear.LinearConstraint; import org.apache.commons.math4.legacy.optim.linear.LinearConstraintSet; import org.apache.commons.math4.legacy.optim.linear.LinearObjectiveFunction; import org.apache.commons.math4.legacy.optim.linear.NonNegativeConstraint; import org.apache.commons.math4.legacy.optim.linear.PivotSelectionRule; import org.apache.commons.math4.legacy.optim.linear.SimplexSolver; import org.apache.commons.math4.legacy.optim.linear.Relationship; import org.apache.commons.math4.legacy.optim.nonlinear.scalar.GoalType; import org.apache.commons.math4.legacy.optim.MaxIter; public class MathSimplexSolverFuzzer { protected LinearObjectiveFunction m_function; protected ArrayList m_constraints; protected GoalType m_goal; protected PivotSelectionRule m_pivotSelectionRule; double[] coefficients(FuzzedDataProvider fuzzedDataProvider) { return new double[]{ fuzzedDataProvider.consumeRegularDouble(), fuzzedDataProvider.consumeRegularDouble(), fuzzedDataProvider.consumeRegularDouble() }; } double rightHandSide(FuzzedDataProvider fuzzedDataProvider) { return fuzzedDataProvider.consumeRegularDouble(); } Relationship relation(FuzzedDataProvider fuzzedDataProvider) { Relationship available[] = { Relationship.EQ, Relationship.GEQ, Relationship.LEQ }; return available[fuzzedDataProvider.consumeInt(0, available.length-1)]; } GoalType goalType(FuzzedDataProvider fuzzedDataProvider) { GoalType available[] = { GoalType.MAXIMIZE, GoalType.MINIMIZE }; return available[fuzzedDataProvider.consumeInt(0, available.length-1)]; } PivotSelectionRule pivotSelectionRule(FuzzedDataProvider fuzzedDataProvider) { PivotSelectionRule available[] = { PivotSelectionRule.DANTZIG, PivotSelectionRule.BLAND }; return available[fuzzedDataProvider.consumeInt(0, available.length-1)]; } public MathSimplexSolverFuzzer(FuzzedDataProvider fuzzedDataProvider) { m_function = new LinearObjectiveFunction(coefficients(fuzzedDataProvider), 0); m_constraints = new ArrayList<>(); m_constraints.add(new LinearConstraint(coefficients(fuzzedDataProvider), relation(fuzzedDataProvider), rightHandSide(fuzzedDataProvider))); m_constraints.add(new LinearConstraint(coefficients(fuzzedDataProvider), relation(fuzzedDataProvider), rightHandSide(fuzzedDataProvider))); m_constraints.add(new LinearConstraint(coefficients(fuzzedDataProvider), relation(fuzzedDataProvider), rightHandSide(fuzzedDataProvider))); m_goal = goalType(fuzzedDataProvider); m_pivotSelectionRule = pivotSelectionRule(fuzzedDataProvider); } void solve() { SimplexSolver solver = new SimplexSolver(); try { solver.optimize( new MaxIter(1000), m_function, new LinearConstraintSet(m_constraints), m_goal, new NonNegativeConstraint(true), m_pivotSelectionRule ); } catch(TooManyIterationsException ex) { /* documented, ignore */ } catch(NoFeasibleSolutionException ex) { /* documented? */ } catch(UnboundedSolutionException ex) { /* documented? */ } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { MathSimplexSolverFuzzer testClosure = new MathSimplexSolverFuzzer(data); testClosure.solve(); } } ================================================ FILE: projects/apache-commons-math/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd "$SRC/commons-math" MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 -Dmoditect.skip=true -pl commons-math-legacy -am" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "commons-math-legacy/target/commons-math4-legacy-$CURRENT_VERSION.jar" $OUT/commons-math.jar popd ALL_JARS="commons-math.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-math/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://commons.apache.org" language: jvm main_repo: "https://github.com/apache/commons-math" primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "security@commons.apache.org" - "brunodepaulak@gmail.com" - "peteralfredlee@gmail.com" - "boards@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/apache-commons-net/Base64Fuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.net.util.Base64; public class Base64Fuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ Base64 b64 = new Base64(data.consumeInt(), data.consumeBytes(1000), data.consumeBoolean()); b64.encode(data.consumeBytes(4000)); b64.decode(data.consumeBytes(4000)); } catch (java.lang.IllegalArgumentException e) {} } } ================================================ FILE: projects/apache-commons-net/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/apache/commons-net.git commons-net WORKDIR commons-net COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/apache-commons-net/MLSxEntryParserFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.net.ftp.parser.*; import org.apache.commons.net.ftp.FTPFileEntryParser; public class MLSxEntryParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ FTPFileEntryParser parser = MLSxEntryParser.getInstance(); parser.parseFTPEntry(data.consumeRemainingAsString()); } catch (java.lang.NumberFormatException e) {} catch (java.lang.StringIndexOutOfBoundsException e) {} } } ================================================ FILE: projects/apache-commons-net/NTFTPEntryParserFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.apache.commons.net.ftp.parser.NTFTPEntryParser; public class NTFTPEntryParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ FTPFileEntryParser parser = new NTFTPEntryParser(); parser.parseFTPEntry(data.consumeRemainingAsString()); } catch (java.lang.NumberFormatException e) {} } } ================================================ FILE: projects/apache-commons-net/OS400FTPEntryParserFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.net.ftp.FTPFileEntryParser; import org.apache.commons.net.ftp.parser.OS400FTPEntryParser; public class OS400FTPEntryParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { FTPFileEntryParser parser = new OS400FTPEntryParser(); parser.parseFTPEntry(data.consumeRemainingAsString()); } } ================================================ FILE: projects/apache-commons-net/TelnetOptionFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.net.telnet.TelnetOption; public class TelnetOptionFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ TelnetOption.getOption(data.consumeInt()); TelnetOption.isValidOption(data.consumeInt()); } catch (java.lang.ArrayIndexOutOfBoundsException e) {} } } ================================================ FILE: projects/apache-commons-net/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dpropguard.skip -DskipTests -Dmaven.javadoc.skip=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True" $MVN clean package $MAVEN_ARGS org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) find ./ -name "commons-net-$CURRENT_VERSION.jar" -exec mv {} $OUT/commons-net.jar \; ALL_JARS="commons-net.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac -cp $BUILD_CLASSPATH ${SRC}/*.java install ${SRC}/*.class ${OUT}/ for fuzzer in $(find $SRC -name '*Fuzzer.java' -maxdepth 1); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-net/project.yaml ================================================ homepage: "https://github.com/apache/commons-net" language: jvm primary_contact: "fuzz-testing@commons.apache.org" auto_ccs: - "security@commons.apache.org" - "irali@google.com" main_repo: "https://github.com/apache/commons-net.git" file_github_issue: false fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/apache-commons-text/.gitignore ================================================ project-parent/apache-commons-text project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/apache-commons-text/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.12/binaries/apache-maven-3.9.12-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.12/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/apache-commons-text RUN git clone --depth 1 https://github.com/apache/commons-text.git $SRC/project-parent/apache-commons-text COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-commons-text/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=apache-commons-text MODULE=org.apache.commons:commons-text PROJECT_GROUP_ID=org.apache.commons PROJECT_ARTIFACT_ID=commons-text MAIN_REPOSITORY=https://github.com/apache/commons-text/ MVN_FLAGS="--no-transfer-progress" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN ${MVN_FLAGS} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN ${MVN_FLAGS} versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency # install # skip RAT license check to avoid build error mvn -pl $MODULE install -DskipTests -Drat.skip=true mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency # install # skip RAT license check to avoid build error $MVN ${MVN_FLAGS} -pl $MODULE install -DskipTests -Drat.skip=true -Dmaven.repo.local=$OUT/m2 $MVN ${MVN_FLAGS} -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN ${MVN_FLAGS} -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/apache-commons-text/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.commons commons-text Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/apache-commons-text/project-parent/fuzz-targets/src/test/java/com/example/StringSubstitutorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.util.*; import org.apache.commons.text.*; public class StringSubstitutorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Map valuesMap = new HashMap<>(); valuesMap.put("parameter1", data.consumeRemainingAsString()); String templateString = "The ${parameter1} was fuzzed"; StringSubstitutor sub = new StringSubstitutor(valuesMap); String resolvedString = sub.replace(templateString); } } ================================================ FILE: projects/apache-commons-text/project-parent/fuzz-targets/src/test/java/com/example/StringSubstitutorInterpolatorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.util.*; import org.apache.commons.text.*; public class StringSubstitutorInterpolatorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { final StringSubstitutor interpolator = StringSubstitutor.createInterpolator(); String out = interpolator.replace(data.consumeRemainingAsString()); } catch (IllegalArgumentException e){ } } } ================================================ FILE: projects/apache-commons-text/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom apache-commons-text fuzz-targets ================================================ FILE: projects/apache-commons-text/project.yaml ================================================ homepage: "https://github.com/apache/commons-text/" language: jvm primary_contact: "fuzz-testing@commons.apache.org" fuzzing_engines: - "libfuzzer" main_repo: "https://github.com/apache/commons-text/" sanitizers: - "address" auto_ccs: - "security@commons.apache.org" vendor_ccs: - "michael.nothhard@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-commons-validator/CreditCardValidatorFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.validator.routines.CreditCardValidator; public class CreditCardValidatorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { CreditCardValidator validator = new CreditCardValidator(data.consumeLong()); validator.isValid(data.consumeRemainingAsString()); validator.validate(data.consumeRemainingAsString()); } } ================================================ FILE: projects/apache-commons-validator/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/apache/commons-validator.git commons-validator WORKDIR commons-validator COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/apache-commons-validator/IBANValidatorFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.validator.routines.IBANValidator; public class IBANValidatorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { IBANValidator validator = IBANValidator.getInstance(); validator.isValid(data.consumeRemainingAsString()); } } ================================================ FILE: projects/apache-commons-validator/UrlValidator2Fuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.validator.UrlValidator; public class UrlValidator2Fuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { UrlValidator validator = new UrlValidator(data.consumeInt()); validator.isValid(data.consumeRemainingAsString()); } } ================================================ FILE: projects/apache-commons-validator/UrlValidatorFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.commons.validator.routines.UrlValidator; public class UrlValidatorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { UrlValidator validator = UrlValidator.getInstance(); validator.isValid(data.consumeRemainingAsString()); } } ================================================ FILE: projects/apache-commons-validator/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dpropguard.skip -DskipTests -Dmaven.javadoc.skip=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True" $MVN clean package $MAVEN_ARGS org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) find ./ -name "commons-validator-$CURRENT_VERSION.jar" -exec mv {} $OUT/commons-validator.jar \; ALL_JARS="commons-validator.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac -cp $BUILD_CLASSPATH ${SRC}/*.java install ${SRC}/*.class ${OUT}/ for fuzzer in $(find $SRC -name '*Fuzzer.java' -maxdepth 1); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-commons-validator/project.yaml ================================================ homepage: "https://github.com/apache/commons-validator" language: jvm primary_contact: "fuzz-testing@commons.apache.org" auto_ccs: - "security@commons.apache.org" - "irali@google.com" main_repo: "https://github.com/apache/commons-validator.git" file_github_issue: false fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/apache-cxf/.gitignore ================================================ project-parent/cxf project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/apache-cxf/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/xml.dict $SRC/XMLStreamReadersFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/XMLStreamReadersFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/cxf RUN apt update && apt install -y openjdk-17-jdk RUN git clone --depth 1 https://github.com/apache/cxf/ $SRC/project-parent/cxf COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/apache-cxf/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=cxf PROJECT_GROUP_ID=org.apache.cxf PROJECT_ARTIFACT_ID=cxf MAIN_REPOSITORY=https://github.com/apache/cxf/ MAVEN_ARGS="-Djavac.src.version=17 -Djavac.target.version=17 -Denforcer.skip=true -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) FUZZ_TARGET_DEPENDENCIES=":cxf-core :cxf-rt-frontend-jaxrs :cxf-rt-transports-http :cxf-rt-rs-client :cxf-rt-rs-json-basic" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent/fuzz-targets -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi this_dir=\$(dirname \"\$0\") JAVA_HOME=\"\$this_dir/open-jdk-17/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-17/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/apache-cxf/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 17 17 17 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.cxf cxf-core Fuzzing-SNAPSHOT org.apache.cxf cxf-rt-frontend-jaxrs Fuzzing-SNAPSHOT org.apache.cxf cxf-rt-transports-http Fuzzing-SNAPSHOT org.apache.cxf cxf-rt-rs-client Fuzzing-SNAPSHOT org.apache.cxf cxf-rt-rs-json-basic Fuzzing-SNAPSHOT test jakarta.mail jakarta.mail-api 2.1.1 test jakarta.xml.soap jakarta.xml.soap-api 2.0.1 test maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/apache-cxf/project-parent/fuzz-targets/src/test/java/com/example/AttachmentDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.io.*; import java.util.Collection; import java.util.Iterator; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.cxf.message.Attachment; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.ExchangeImpl; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.attachment.AttachmentDeserializer; import org.apache.cxf.attachment.HeaderSizeExceededException; public class AttachmentDeserializerFuzzer { static MessageImpl msg; @FuzzTest void myFuzzTest(FuzzedDataProvider data) { msg = new MessageImpl(); Exchange exchange = new ExchangeImpl(); msg.setExchange(exchange); String ct = data.consumeString(500); byte [] input = data.consumeRemainingAsBytes(); InputStream rawInputStream = new ByteArrayInputStream(input); MessageImpl message = new MessageImpl(); message.setContent(InputStream.class, rawInputStream); message.put(Message.CONTENT_TYPE, ct); try { new AttachmentDeserializer(message).initializeAttachments(); InputStream inputStreamWithoutAttachments = message.getContent(InputStream.class); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(inputStreamWithoutAttachments, new DefaultHandler()); inputStreamWithoutAttachments.close(); rawInputStream.close(); } catch (IOException | ParserConfigurationException | SAXException | StringIndexOutOfBoundsException | HeaderSizeExceededException | ArrayIndexOutOfBoundsException e) { } } } ================================================ FILE: projects/apache-cxf/project-parent/fuzz-targets/src/test/java/com/example/AttachmentSerializerDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import jakarta.activation.DataHandler; import jakarta.mail.util.ByteArrayDataSource; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.message.Attachment; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageImpl; import org.apache.cxf.attachment.AttachmentImpl; import org.apache.cxf.attachment.AttachmentSerializer; import org.apache.cxf.attachment.AttachmentDeserializer; import org.apache.cxf.attachment.HeaderSizeExceededException; public class AttachmentSerializerDeserializerFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { MessageImpl in = new MessageImpl(); MessageImpl msg = new MessageImpl(); Collection atts = new ArrayList<>(); String str0 = data.consumeString(250); AttachmentImpl a = new AttachmentImpl(str0); byte [] byteArr = data.consumeBytes(250); InputStream is = new ByteArrayInputStream(byteArr); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayDataSource ds = null; String str1 = data.consumeString(250); try { ds = new ByteArrayDataSource(is, str1); } catch (IOException e) { return; } a.setDataHandler(new DataHandler(ds)); atts.add(a); in.setAttachments(atts); String str2 = data.consumeString(250); in.put(Message.CONTENT_TYPE, str2); in.setContent(OutputStream.class, out); AttachmentSerializer serializer = new AttachmentSerializer(in); boolean xop = data.consumeBoolean(); if (!xop) { serializer.setXop(xop); } byte [] byteArr2 = data.consumeBytes(250); try { serializer.writeProlog(); out.write(byteArr2); serializer.writeAttachments(); out.flush(); } catch (IOException | StringIndexOutOfBoundsException | IllegalArgumentException e) { return; } String str3 = data.consumeString(250); msg.put(Message.CONTENT_TYPE, str3); ByteArrayOutputStream baos = (ByteArrayOutputStream)in.getContent(OutputStream.class); try { ByteArrayInputStream content = new ByteArrayInputStream(baos.toByteArray()); msg.setContent(InputStream.class, content); AttachmentDeserializer deserializer = new AttachmentDeserializer(msg); deserializer.initializeAttachments(); Collection attsCollection = msg.getAttachments(); Iterator itr = attsCollection.iterator(); Attachment att = itr.next(); // check the cached output stream InputStream attBody = msg.getContent(InputStream.class); ByteArrayOutputStream attOut = new ByteArrayOutputStream(); IOUtils.copy(attBody, attOut); is.close(); } catch (IOException | HeaderSizeExceededException | IndexOutOfBoundsException e) { } } } ================================================ FILE: projects/apache-cxf/project-parent/fuzz-targets/src/test/java/com/example/JsonMapObjectReaderWriterFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.util.*; import java.io.Serializable; import java.io.UncheckedIOException; import java.text.ParseException; import java.text.SimpleDateFormat; import org.apache.cxf.jaxrs.json.basic.JsonMapObject; import org.apache.cxf.jaxrs.json.basic.JsonMapObjectReaderWriter; public class JsonMapObjectReaderWriterFuzzer { static int cn = 29; static JsonMapObjectReaderWriter jsonMapObjectReaderWriter = new JsonMapObjectReaderWriter(); @FuzzTest void myFuzzTest(FuzzedDataProvider data) { int dummyNum = data.consumeInt(0, 2^cn - 1); try { Map map = new LinkedHashMap<>(); for (int i = 0; i < data.consumeInt(0, 50); ++i) { DummyClass dummyClass = getDummyClass(data, dummyNum); map.put(data.consumeString(50), dummyClass); } String json = jsonMapObjectReaderWriter.toJson(map); String json2 = jsonMapObjectReaderWriter.toJson(new JsonMapObject(map)); jsonMapObjectReaderWriter.fromJson(json); jsonMapObjectReaderWriter.fromJson(json2); jsonMapObjectReaderWriter.fromJsonAsList(json); jsonMapObjectReaderWriter.fromJsonAsList(json2); jsonMapObjectReaderWriter.fromJsonToJsonObject(json); jsonMapObjectReaderWriter.fromJsonToJsonObject(json2); } catch (NumberFormatException | StringIndexOutOfBoundsException | UncheckedIOException e) { } } public static DummyClass getDummyClass (FuzzedDataProvider data, int dummyNum) { DummyClass dummyClass = new DummyClass(); for (int bit = 0; bit < cn; ++bit) { if (((dummyNum >> bit) & 1) == 1) { switch (bit) { case 0: for (int i = 0; i < data.consumeInt(0, 50); i++) { try { dummyClass._treeMap.put(data.consumeString(50), data.consumeInt()); } catch (NullPointerException e) { } } break; case 1: for (int i = 0; i < data.consumeInt(0, 50); i++) { try { dummyClass._arrayList.add(data.consumeString(50)); } catch (NullPointerException e) { } } break; case 2: for (int i = 0; i < data.consumeInt(0, 50); i++) { try { dummyClass._hashSet.add(data.consumeString(50)); } catch (NullPointerException e) { } } break; case 3: for (int i = 0; i < data.consumeInt(0, 50); i++) { try { dummyClass._hashMap.put(data.consumeString(50), data.consumeString(50)); } catch (NullPointerException e) { } } break; case 4: Integer[] integerArr = new Integer[data.consumeInt(0, 50)]; for (int i = 0; i < integerArr.length; i++) { integerArr[i] = data.consumeInt(); } dummyClass._asList = Arrays.asList(integerArr); break; case 5: dummyClass._intArray = data.consumeInts(50); break; case 6: dummyClass._longArray = data.consumeLongs(50); break; case 7: dummyClass._shortArray = data.consumeShorts(50); break; case 8: float[] floatArr = new float[data.consumeInt(0, 50)]; for (int i = 0; i < floatArr.length; i++) { floatArr[i] = data.consumeFloat(); } dummyClass._floatArray = floatArr; break; case 9: double[] doubleArr = new double[data.consumeInt(0, 50)]; for (int i = 0; i < doubleArr.length; i++) { doubleArr[i] = data.consumeDouble(); } dummyClass._doubleArray = doubleArr; break; case 10: dummyClass._byteArray = data.consumeBytes(50); break; case 11: char[] charArr = new char[data.consumeInt(0, 50)]; for (int i = 0; i < charArr.length; i++) { charArr[i] = data.consumeChar(); } dummyClass._charArray = charArr; break; case 12: dummyClass._boolArray = data.consumeBooleans(50); break; case 13: String[] strArr = new String[data.consumeInt(0, 50)]; for (int i = 0; i < strArr.length; i++) { strArr[i] = data.consumeString(50); } dummyClass._stringArray = strArr; break; case 14: BitSet bitSet = BitSet.valueOf(data.consumeLongs(50)); dummyClass._bitSet = bitSet; break; case 15: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { dummyClass._date = dateFormat.parse(data.consumeString(50)); } catch (ParseException e) { } break; case 16: TimeZone tz = TimeZone.getTimeZone(data.consumeString(50)); dummyClass._timeZone = tz; break; case 17: Calendar calendar = new GregorianCalendar(data.consumeInt(),data.consumeInt(),data.consumeInt()); dummyClass._calendar = calendar; break; case 18: Locale locale = new Locale(data.consumeString(50)); dummyClass._locale = locale; break; case 19: Integer[] integerArr2 = new Integer[data.consumeInt(0, 50)]; for (int i = 0; i < integerArr2.length; i++) { integerArr2[i] = data.consumeInt(); } dummyClass._integerArray = integerArr2; break; case 20: dummyClass._boolean = data.consumeBoolean(); break; case 21: dummyClass._char = data.consumeChar(); break; case 22: dummyClass._byte = data.consumeByte(); break; case 23: dummyClass._short = data.consumeShort(); break; case 24: dummyClass._int = data.consumeInt(); break; case 25: dummyClass._float = data.consumeFloat(); break; case 26: dummyClass._long = data.consumeLong(); break; case 27: dummyClass._double = data.consumeDouble(); break; case 28: dummyClass._string = data.consumeString(50); break; } } } return dummyClass; } public static class DummyClass implements Serializable { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList; public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public boolean[] _boolArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; public Long _long; public Double _double; public String _string; } } ================================================ FILE: projects/apache-cxf/project-parent/fuzz-targets/src/test/java/com/example/XMLStreamReadersFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.cxf.staxutils.*; import java.io.ByteArrayOutputStream; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.w3c.dom.Document; public class XMLStreamReadersFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { int i1 = data.consumeInt(); int i2 = data.consumeInt(); int i3 = data.consumeInt(); String str1 = data.consumeString(250); String str2 = data.consumeString(250); String str3 = data.consumeString(250); String str4 = data.consumeString(250); String str5 = data.consumeString(250); String str6 = data.consumeString(250); String str7 = data.consumeString(250); Map map = new HashMap<>(); map.put(str3, str4); map.put(str5, str6); try { XMLStreamReader reader = StaxUtils.createXMLStreamReader(new StringReader(str7)); XMLStreamReader xmlStreamReaders [] = { reader, new DepthRestrictingStreamReader(reader, i1, i2, i3), new DepthXMLStreamReader(reader), new PartialXMLStreamReader(reader, new QName(str1, str2)), new FragmentStreamReader(reader), new PropertiesExpandingStreamReader(reader, map) }; DepthRestrictingStreamReader depthRestrictingStreamReader = new DepthRestrictingStreamReader(data.pickValue(xmlStreamReaders), i1, i2, i3); Document doc = StaxUtils.read(depthRestrictingStreamReader); ByteArrayOutputStream bos = new ByteArrayOutputStream(); XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(bos); StaxUtils.copy(doc, writer); writer.flush(); DepthXMLStreamReader depthXMLStreamReader = new DepthXMLStreamReader(data.pickValue(xmlStreamReaders)); doc = StaxUtils.read(depthXMLStreamReader); bos = new ByteArrayOutputStream(); writer = StaxUtils.createXMLStreamWriter(bos); StaxUtils.copy(doc, writer); writer.flush(); FragmentStreamReader fragmentStreamReader = new FragmentStreamReader(data.pickValue(xmlStreamReaders)); doc = StaxUtils.read(depthXMLStreamReader); bos = new ByteArrayOutputStream(); writer = StaxUtils.createXMLStreamWriter(bos); StaxUtils.copy(doc, writer); writer.flush(); PartialXMLStreamReader partialXMLStreamReader = new PartialXMLStreamReader(data.pickValue(xmlStreamReaders), new QName(str1, str2)); doc = StaxUtils.read(partialXMLStreamReader); bos = new ByteArrayOutputStream(); writer = StaxUtils.createXMLStreamWriter(bos); StaxUtils.copy(doc, writer); writer.flush(); PropertiesExpandingStreamReader propertiesExpandingStreamReader = new PropertiesExpandingStreamReader(data.pickValue(xmlStreamReaders), map); doc = StaxUtils.read(partialXMLStreamReader); bos = new ByteArrayOutputStream(); writer = StaxUtils.createXMLStreamWriter(bos); StaxUtils.copy(doc, writer); writer.flush(); } catch (XMLStreamException | RuntimeException e) { } } } ================================================ FILE: projects/apache-cxf/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom cxf fuzz-targets ================================================ FILE: projects/apache-cxf/project.yaml ================================================ homepage: "https://cxf.apache.org/" language: jvm main_repo: "https://github.com/apache/cxf/" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/apache-doris/project.yaml ================================================ homepage: "https://doris.apache.org" language: c++ primary_contact: "dataroaring@gmail.com" main_repo: "https://github.com/apache/doris.git" ================================================ FILE: projects/apache-felix-dev/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm ENV JAVA_HOME $JAVA_15_HOME ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server ENV PATH $JAVA_HOME/bin:$PATH RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/apache/felix-dev.git apache-felix-dev # or use other version control RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/json.dict $SRC/JSONParserFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/JSONParserFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR apache-felix-dev ================================================ FILE: projects/apache-felix-dev/JSONParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.List; import java.util.Map; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.felix.utils.json.JSONParser; public class JSONParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { boolean switchConstructor = data.consumeBoolean(); int switchEncoding = data.consumeInt(0,2); String string = data.consumeRemainingAsString(); try { JSONParser jSONParser; if (switchConstructor){ CharSequence charSeq = string; jSONParser = new JSONParser(charSeq); } else { String encoding = "UTF_8"; switch (switchEncoding) { case 0: break; case 1: encoding = "UTF_16"; break; case 2: encoding = "UTF_32"; break; } InputStream inputStream = new ByteArrayInputStream(string.getBytes(encoding)); jSONParser = new JSONParser(inputStream); } List res = jSONParser.getParsedList(); Map parsed = jSONParser.getParsed(); } catch(IllegalArgumentException | IOException e){ } } } ================================================ FILE: projects/apache-felix-dev/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $MVN -f utils/ clean install -Dmaven.test.skip=true cp ./utils/target/org.apache.felix.utils-1.11.9-SNAPSHOT.jar $OUT/felix.utils.jar ALL_JARS="felix.utils.jar" # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-felix-dev/project.yaml ================================================ homepage: "https://felix.apache.org/" language: jvm main_repo: "https://github.com/apache/felix-dev.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/apache-httpd/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool wget \ uuid-dev pkg-config libtool-bin \ libbsd-dev RUN git clone https://github.com/PCRE2Project/pcre2 pcre2 && \ cd pcre2 && \ ./autogen.sh && \ ./configure && \ make && \ make install RUN git clone https://github.com/AdaLogics/fuzz-headers RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-2.4.1.tar.gz && \ tar -xf expat-2.4.1.tar.gz && \ cd expat-2.4.1 && \ ./configure && \ make && \ make install RUN git clone --depth=1 https://github.com/apache/httpd WORKDIR httpd COPY build.sh $SRC/ COPY fuzz_*.c $SRC/ ================================================ FILE: projects/apache-httpd/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ unset CPP INITIAL_CXX=$CXX unset CXX export LDFLAGS="-l:libbsd.a" # Download apr and place in httpd srclib folder. Apr-2.0 includes apr-utils svn checkout https://svn.apache.org/repos/asf/apr/apr/trunk/ srclib/apr # Build httpd ./buildconf ./configure --with-included-apr --enable-pool-debug make -j$( nproc ) static_pcre=($(find /src/pcre2 -name "libpcre2-8.a")) # Build the fuzzers for fuzzname in utils parse tokenize addr_parse uri request preq; do $CC $CFLAGS -c \ -I$SRC/fuzz-headers/lang/c -I./include -I./os/unix \ -I./srclib/apr/include -I./srclib/apr-util/include/ \ $SRC/fuzz_${fuzzname}.c $INITIAL_CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_${fuzzname}.o -o $OUT/fuzz_${fuzzname} \ ./modules.o buildmark.o \ -Wl,--start-group ./server/.libs/libmain.a \ ./modules/core/.libs/libmod_so.a \ ./modules/http/.libs/libmod_http.a \ ./server/mpm/event/.libs/libevent.a \ ./os/unix/.libs/libos.a \ ./srclib/apr/.libs/libapr-2.a \ -Wl,--end-group -luuid -lcrypt -lexpat -l:libbsd.a ${static_pcre} done ================================================ FILE: projects/apache-httpd/fuzz_addr_parse.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "apr_network_io.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { apr_pool_t *pool; apr_pool_initialize(); if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { abort(); } char *addr = NULL; char *scope_id = NULL; apr_port_t port = 0; char *input_string = strndup((const char *)data, size); apr_parse_addr_port(&addr, &scope_id, &port, input_string, pool); free(input_string); apr_pool_destroy(pool); apr_pool_terminate(); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_parse.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "apr.h" #include "apr_file_io.h" #include "apr_poll.h" #include "apr_portable.h" #include "apr_proc_mutex.h" #include "apr_signal.h" #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" #define APR_WANT_STRFUNC #include "apr_file_io.h" #include "apr_fnmatch.h" #include "apr_want.h" #include "apr_poll.h" #include "apr_want.h" #include "ap_config.h" #include "ap_expr.h" #include "ap_listen.h" #include "ap_provider.h" #include "ap_regex.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *new_str = (char *)malloc(size + 1); if (new_str == NULL) { return 0; } memcpy(new_str, data, size); new_str[size] = '\0'; apr_pool_initialize(); apr_pool_t *v = NULL; apr_pool_create(&v, NULL); int only_ascii = 1; for (int i = 0; i < size; i++) { // Avoid unnessary exits because of non-ascii characters. if (new_str[i] < 0x01 || new_str[i] > 0x7f) { only_ascii = 0; } // Avoid forced exits beause of, e.g. unsupported characters or recursion // depth if (new_str[i] == 0x5c || new_str[i] == '{') { only_ascii = 0; } } // Now parse if (only_ascii) { ap_expr_info_t val; ap_expr_parse(v, v, &val, new_str, NULL); } apr_pool_terminate(); free(new_str); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_preq.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "apr.h" #include "apr_file_io.h" #include "apr_poll.h" #include "apr_portable.h" #include "apr_proc_mutex.h" #include "apr_signal.h" #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" #define APR_WANT_STRFUNC #include "apr_file_io.h" #include "apr_fnmatch.h" #include "apr_want.h" #include "apr_poll.h" #include "apr_want.h" #include "ap_config.h" #include "ap_expr.h" #include "ap_listen.h" #include "ap_provider.h" #include "ap_regex.h" #include "ada_fuzz_header.h" #include "apreq_parser.h" apr_status_t hookfunc(apreq_hook_t *hook, apreq_param_t *param, apr_bucket_brigade *bb) { return 0; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { af_gb_init(); const uint8_t *data2 = data; size_t size2 = size; /* get random data for the fuzzer */ char *new_str = af_gb_get_null_terminated(&data2, &size2); char *new_str2 = af_gb_get_null_terminated(&data2, &size2); if (new_str != NULL && new_str2 != NULL) { apr_pool_initialize(); apr_pool_t *v = NULL; apr_pool_create(&v, NULL); apr_bucket_alloc_t *bucket = apr_bucket_alloc_create(v); apr_bucket_brigade *brigade = apr_brigade_create(v, bucket); apr_brigade_write(brigade, NULL, NULL, new_str, strlen(new_str)); apreq_parser_t parser; parser.content_type = new_str2; parser.temp_dir = "/tmp/"; parser.brigade_limit = 10; parser.pool = v; parser.ctx = NULL; parser.bucket_alloc = bucket; parser.hook = apreq_hook_make(parser.pool, hookfunc, NULL, parser.ctx); apr_table_t *table = apr_table_make(parser.pool, 10); if (af_get_short(&data2, &size2) % 2 == 0) { apreq_parse_multipart(&parser, table, brigade); } else { apreq_parse_urlencoded(&parser, table, brigade); } apr_pool_terminate(); } af_gb_cleanup(); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_request.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "apr.h" #include "apr_file_io.h" #include "apr_poll.h" #include "apr_portable.h" #include "apr_proc_mutex.h" #include "apr_signal.h" #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" #include "http_core.h" #define APR_WANT_STRFUNC #include "apr_file_io.h" #include "apr_fnmatch.h" #include "apr_want.h" #include "apr_poll.h" #include "apr_want.h" #include "ap_config.h" #include "ap_expr.h" #include "ap_listen.h" #include "ap_provider.h" #include "ap_regex.h" #include "http_log.h" #include "http_protocol.h" #include "ada_fuzz_header.h" static const char *http_scheme2(const request_rec *r) { /* * The http module shouldn't return anything other than * "http" (the default) or "https". */ if (r->server->server_scheme && (strcmp(r->server->server_scheme, "https") == 0)) return "https"; return "http"; } extern request_rec *ap_create_request(conn_rec *conn); extern int read_request_line(request_rec *r, apr_bucket_brigade *bb); int LLVMFuzzerInitialize(int *argc, char ***argv) { apr_pool_create(&apr_hook_global_pool, NULL); ap_open_stderr_log(apr_hook_global_pool); ap_hook_http_scheme(http_scheme2, NULL, NULL, APR_HOOK_REALLY_LAST); return 0; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { af_gb_init(); const uint8_t *data2 = data; size_t size2 = size; /* get random data for the fuzzer */ char *new_str = af_gb_get_null_terminated(&data2, &size2); char *new_str2 = af_gb_get_null_terminated(&data2, &size2); char *new_str3 = af_gb_get_null_terminated(&data2, &size2); char *new_str4 = af_gb_get_null_terminated(&data2, &size2); char *new_str5 = af_gb_get_null_terminated(&data2, &size2); if (new_str != NULL && new_str2 != NULL && new_str3 != NULL && new_str4 != NULL && new_str5 != NULL) { /* this is the main fuzzing logic */ apr_pool_initialize(); apr_pool_t *v = NULL; apr_pool_create(&v, NULL); conn_rec conn; conn.pool = v; server_rec base_server; conn.base_server = &base_server; conn.bucket_alloc = apr_bucket_alloc_create(conn.pool); ap_method_registry_init(conn.pool); //server_rec server; /* Simulate ap_read_request */ request_rec *r = NULL; r = ap_create_request(&conn); /* create a logs array for the request */ struct ap_logconf logs = {}; char *log_levels = calloc(1000, 1); memset(log_levels, 0, 1000); logs.module_levels = log_levels; r->log = &logs; if (r != NULL) { apr_bucket_brigade *tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); conn.keepalive = AP_CONN_UNKNOWN; ap_run_pre_read_request(r, &conn); core_server_config conf_mod; conf_mod.http_conformance = (char)af_get_short(&data2, &size2); conf_mod.http09_enable = (char)af_get_short(&data2, &size2); conf_mod.http_methods = (char)af_get_short(&data2, &size2); void **module_config_arr = malloc(1000); module_config_arr[0] = &conf_mod; r->server->module_config = module_config_arr; ap_set_core_module_config(r->server->module_config, &conf_mod); /* randomise content of request */ r->unparsed_uri = new_str; r->uri = new_str2; r->server->server_scheme = new_str3; r->method = new_str4; r->the_request = new_str5; /* main target */ ap_parse_request_line(r); free(module_config_arr); } free(log_levels); apr_pool_terminate(); } af_gb_cleanup(); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_tokenize.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "apr_strings.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { apr_pool_t *pool; apr_pool_initialize(); if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { abort(); } char *arg_str = strndup((const char *)data, size); char **argv_out; apr_tokenize_to_argv(arg_str, &argv_out, pool); free(arg_str); apr_pool_destroy(pool); apr_pool_terminate(); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_uri.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "apr.h" #include "apr_file_io.h" #include "apr_poll.h" #include "apr_portable.h" #include "apr_proc_mutex.h" #include "apr_signal.h" #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" #define APR_WANT_STRFUNC #include "apr_file_io.h" #include "apr_fnmatch.h" #include "apr_want.h" #include "apr_poll.h" #include "apr_want.h" #include "apr_uri.h" #include "ap_config.h" #include "ap_expr.h" #include "ap_listen.h" #include "ap_provider.h" #include "ap_regex.h" #include "ada_fuzz_header.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { af_gb_init(); const uint8_t *data2 = data; size_t size2 = size; // Get a NULL terminated string char *cstr = af_gb_get_null_terminated(&data2, &size2); // Fuzz URI routines if (cstr && apr_pool_initialize() == APR_SUCCESS) { apr_pool_t *pool = NULL; apr_pool_create(&pool, NULL); apr_uri_t tmp_uri; if (apr_uri_parse(pool, cstr, &tmp_uri) == APR_SUCCESS) { apr_uri_unparse(pool, &tmp_uri, 0); } apr_uri_parse_hostinfo(pool, cstr, &tmp_uri); // Cleanup apr_pool_terminate(); } af_gb_cleanup(); return 0; } ================================================ FILE: projects/apache-httpd/fuzz_utils.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "apr.h" #include "apr_file_io.h" #include "apr_poll.h" #include "apr_portable.h" #include "apr_proc_mutex.h" #include "apr_signal.h" #include "apr_strings.h" #include "apr_thread_mutex.h" #include "apr_thread_proc.h" #define APR_WANT_STRFUNC #include "apr_file_io.h" #include "apr_fnmatch.h" #include "apr_want.h" #include "apr_poll.h" #include "apr_want.h" #include "ap_config.h" #include "ap_expr.h" #include "ap_listen.h" #include "ap_provider.h" #include "ap_regex.h" #include #include #include "ada_fuzz_header.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Initialize fuzzing garbage collector. We use this to easily // get data types seeded with random input from the fuzzer. af_gb_init(); const uint8_t *data2 = data; size_t size2 = size; char *new_str = af_gb_get_null_terminated(&data2, &size2); char *new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_str != NULL && new_dst != NULL) { size_t new_str_len = strlen(new_str); // Targets that do not require a pool ap_cstr_casecmp(new_str, new_dst); if (new_str_len > 2) { ap_cstr_casecmpn(new_str, new_str + 2, new_str_len - 2); } ap_strcmp_match(new_str, new_dst); ap_strcasecmp_match(new_str, new_dst); ap_strcasestr(new_str, new_dst); apr_interval_time_t timeout; ap_timeout_parameter_parse(new_str, &timeout, "ms"); new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_getparents(new_dst); } new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_no2slash(new_dst); } new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_unescape_url(new_dst); } new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_unescape_urlencoded(new_dst); } new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_content_type_tolower(new_dst); } new_dst = malloc(new_str_len*3+1); // big enough for worst-case URL-escaped (%nn) ap_escape_path_segment_buffer(new_dst, new_str); free(new_dst); new_dst = malloc(new_str_len*4+1); // big enough for worst-case log-escaped (\xnn) ap_escape_errorlog_item(new_dst, new_str, new_str_len*4+1); free(new_dst); // Pool initialisation if (apr_pool_initialize() == APR_SUCCESS) { apr_pool_t *pool = NULL; apr_pool_create(&pool, NULL); // Targets that require a pool new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { ap_make_dirstr_parent(pool, new_dst); } ap_field_noparam(pool, new_str); ap_escape_shell_cmd(pool, new_str); ap_os_escape_path(pool, new_str, 0); ap_escape_html2(pool, new_str, 0); ap_escape_logitem(pool, new_str); // This line causes some issues if something bad is allocated ap_escape_quotes(pool, new_str); // base64 ap_pbase64decode(pool, new_str); ap_pbase64encode(pool, new_str); new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { char *d; apr_size_t dlen; ap_pbase64decode_strict(pool, new_dst, &d, &dlen); } // List functions const char *tmp_s = new_str; ap_get_list_item(pool, &tmp_s); ap_find_list_item(pool, new_str, "kjahsdfkj"); ap_find_token(pool, new_str, "klsjdfk"); ap_find_last_token(pool, new_str, "sdadf"); apr_array_header_t *offers = NULL; ap_parse_token_list_strict(pool, new_str, &offers, 0); tmp_s = new_str; ap_get_token(pool, &tmp_s, 1); tmp_s = NULL; ap_pstr2_alnum(pool, new_str, &tmp_s); ap_is_chunked(pool, new_str); // Word functions tmp_s = new_str; ap_getword(pool, &tmp_s, 0); tmp_s = new_str; ap_getword_conf2(pool, &tmp_s); new_dst = af_gb_get_null_terminated(&data2, &size2); if (new_dst != NULL) { char *d = new_dst; ap_getword_white_nc(pool, &d); } ap_escape_urlencoded(pool, new_str); char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); fwrite(data, size, 1, fp); fclose(fp); // Fuzzer logic here ap_configfile_t *cfg; ap_pcfg_openfile(&cfg, pool, filename); char tmp_line[100]; if ((af_get_short(&data2, &size2) % 2) == 0) { ap_cfg_getline(tmp_line, 100, cfg); } else { cfg->getstr = NULL; ap_cfg_getline(tmp_line, 100, cfg); } // Fuzzer logic end unlink(filename); // Cleanup apr_pool_terminate(); } } // Cleanup all of the memory allocated by the fuzz headers. af_gb_cleanup(); return 0; } ================================================ FILE: projects/apache-httpd/project.yaml ================================================ homepage: "https://httpd.apache.org/" language: c primary_contact: "david@adalogics.com" auto_ccs: - "stefan.eissing@gmail.com" - "covener@gmail.com" - "ylavic.dev@gmail.com" main_repo: "https://github.com/apache/httpd" base_os_version: ubuntu-24-04 ================================================ FILE: projects/apache-logging-log4cxx/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Log4cxx build dependencies: https://logging.apache.org/log4cxx/latest_stable/build-cmake.html RUN apt-get update && apt-get install -y build-essential libapr1-dev libaprutil1-dev gzip zip RUN git clone --quiet --depth 1 --branch master --single-branch https://github.com/apache/logging-log4cxx COPY run_tests.sh build.sh $SRC/ WORKDIR $SRC/logging-log4cxx ================================================ FILE: projects/apache-logging-log4cxx/README.adoc ================================================ //// Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. //// Log4cxx fuzz tests are distributed as a part of https://github.com/apache/logging-log4cxx[the official project sources]. Here we only store the `Dockerfile` to build the container image to build and run fuzz tests. Likewise, `build.sh` simply delegates to a build script distributed with the Log4j source code. ================================================ FILE: projects/apache-logging-log4cxx/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./src/fuzzers/bash/oss-fuzz-build.sh "$OUT" # Add seed corpus zip $OUT/DOMConfiguratorFuzzer_seed_corpus.zip $SRC/logging-log4cxx/src/test/resources/input/xml/*.xml mkdir build-tests cd build-tests cmake .. make ================================================ FILE: projects/apache-logging-log4cxx/project.yaml ================================================ homepage: "https://logging.apache.org/log4cxx" main_repo: "https://github.com/apache/logging-log4cxx" language: c++ fuzzing_engines: - afl - honggfuzz - libfuzzer - centipede sanitizers: - address - undefined # Apache Logging Services PMC members[1] that contribute the fuzz tests. # We cannot share `security@logging.apache.org` here, since it must be associated with a Google account[2]. # # [1] https://logging.apache.org/team-list.html # [2] https://google.github.io/oss-fuzz/getting-started/new-project-guide/#primary primary_contact: volkan@yazi.ci auto_ccs: - piotr.karwasz@gmail.com - osfan6313@gmail.com - adam@adalogics.com - swebb2066@gmail.com ================================================ FILE: projects/apache-logging-log4cxx/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Exclude deallocation mismatch and memory leak sanitizer export ASAN_OPTIONS="alloc_dealloc_mismatch=0:detect_leaks=0" # Exclude these failing test case temporarily ctest --test-dir build-tests/ --output-on-failure -E "filetestcase|optionconvertertestcase|stringtokenizertestcase|xloggertestcase" ================================================ FILE: projects/apache-poi/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # Newer Maven release are listed at https://archive.apache.org/dist/maven/maven-3/ RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.12/binaries/apache-maven-3.9.12-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.9.12 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.9.12/apache-maven-3.9.12/bin/mvn ENV TARGET_PACKAGE_PREFIX org.apache.poi.*:org.apache.xmlbeans.* # Newer JDK releases are listed at https://github.com/adoptium/temurin11-binaries/releases/ RUN curl -L https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.29%2B7/OpenJDK11U-jdk_x64_linux_hotspot_11.0.29_7.tar.gz -o OpenJDK11U-jdk_x64_linux_hotspot_11.0.29_7.tar.gz && \ tar xvf OpenJDK11U-jdk_x64_linux_hotspot_11.0.29_7.tar.gz && \ rm -rf OpenJDK11U-jdk_x64_linux_hotspot_11.0.29_7.tar.gz ENV JAVA_HOME_11 $SRC/jdk-11.0.29+7 WORKDIR ${SRC} # # clone repository # RUN git clone --depth 1 https://github.com/apache/poi.git # install packages required for font-handling and other code in java.awt.* RUN apt-get update && apt-get install -y libxext6 libx11-6 libxrender1 libxtst6 libxi6 libxcb1 libxau6 libxdmcp6 libfreetype6 libpng16-16 \ && apt-get clean autoclean \ && apt-get autoremove --yes \ && rm -rf /var/lib/{apt,dpkg,cache,log}/ # Remove unused code-parts to speed up introspection # Need to keep some test-code which is used in the poi-integration module RUN cd ${SRC}/poi && rm `find \ jenkins \ osgi \ poi/src/test/ \ poi-examples/src/test \ poi-excelant/src/test \ poi-ooxml/src/test \ poi-scratchpad/src/test \ src \ \ -name *.java -a ! -name *DataSamples*.java -a ! -name Biff*.java` # run a small Gradle task to perform the downloading of Gradle distribution here # this avoids this step when using the Docker image later RUN cd ${SRC}/poi && chmod a+x gradlew && JAVA_HOME=$JAVA_HOME_11 ./gradlew wrapper ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/poi ================================================ FILE: projects/apache-poi/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="--no-transfer-progress -DskipTests" ALL_JARS="" LIBRARY_NAME="poi" GRADLE_FLAGS="-x javadoc -x test -Dfile.encoding=UTF-8 -Porg.gradle.java.installations.fromEnv=JAVA_HOME_11 --console=plain" echo Copy libraries for java.awt in place ls /usr/lib/x86_64-linux-gnu/ cp /usr/lib/x86_64-linux-gnu/libXext.so.6* \ /usr/lib/x86_64-linux-gnu/libX11.so.6* \ /usr/lib/x86_64-linux-gnu/libXrender.so.1* \ /usr/lib/x86_64-linux-gnu/libXtst.so.6* \ /usr/lib/x86_64-linux-gnu/libXi.so.6* \ /usr/lib/x86_64-linux-gnu/libxcb.so.1* \ /usr/lib/x86_64-linux-gnu/libXau.so.6* \ /usr/lib/x86_64-linux-gnu/libXdmcp.so.6* \ /usr/lib/x86_64-linux-gnu/libfreetype.so.6* \ /usr/lib/x86_64-linux-gnu/libpng16.so.16* \ ${OUT}/ echo Main Java ${JAVA_HOME}/bin/java -version echo Java 11 ${JAVA_HOME_11}/bin/java -version # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.29.1" \ -Dpackaging=jar \ ${MVN_FLAGS} popd pushd "${SRC}/${LIBRARY_NAME}" # build and publish current binaries ./gradlew publishToMavenLocal :poi-integration:testJar :poi-fuzz:jar ${GRADLE_FLAGS} # determine current version-tag CURRENT_VERSION=$(./gradlew properties ${GRADLE_FLAGS} | sed -nr "s/^version:\ (.*)/\1/p") # additionally publish the testJar to MavenLocal ${MVN} install:install-file -Dfile=build/dist/maven/poi-integration-tests/poi-integration-${CURRENT_VERSION}-tests.jar \ -DgroupId=org.apache.poi \ -DartifactId=poi-integration \ -Dversion=${CURRENT_VERSION} \ -Dpackaging=jar # additionally publish the fuzz-targets to MavenLocal ${MVN} install:install-file -Dfile=build/dist/maven/poi-fuzz/poi-fuzz-${CURRENT_VERSION}.jar \ -DgroupId=org.apache.poi \ -DartifactId=poi-fuzz \ -Dversion=${CURRENT_VERSION} \ -Dpackaging=jar # prepare some seed-corpus archives based on the test-data of Apache POI # we cannot do this automatically as there is not a 1:1 match of fuzz targets and formats zip -r $OUT/POIFileHandlerFuzzer_seed_corpus.zip test-data zip -r $OUT/POIFuzzer_seed_corpus.zip test-data zip -jr $OUT/POIHDGFFuzzer_seed_corpus.zip test-data/diagram/*.vsd zip -jr $OUT/POIHMEFFuzzer_seed_corpus.zip test-data/hmef/* zip -jr $OUT/POIHPBFFuzzer_seed_corpus.zip test-data/publisher/* zip -jr $OUT/POIHPSFFuzzer_seed_corpus.zip test-data/hpsf/* zip -jr $OUT/POIHSLFFuzzer_seed_corpus.zip test-data/slideshow/*.ppt zip -jr $OUT/POIHSMFFuzzer_seed_corpus.zip test-data/hsmf/* zip -jr $OUT/POIHSSFFuzzer_seed_corpus.zip test-data/spreadsheet/*.xls zip -jr $OUT/POIHWPFFuzzer_seed_corpus.zip test-data/document/*.doc test-data/document/*.DOC zip -jr $OUT/POIOldExcelFuzzer_seed_corpus.zip test-data/spreadsheet/*.xls test-data/spreadsheet/*.bin zip -jr $OUT/POIVisioFuzzer_seed_corpus.zip test-data/diagram/* zip -jr $OUT/POIXSLFFuzzer_seed_corpus.zip test-data/slideshow/* test-data/integration/*.pptx zip -jr $OUT/POIXSSFFuzzer_seed_corpus.zip test-data/spreadsheet/* test-data/integration/*.xslx zip -jr $OUT/POIXWPFFuzzer_seed_corpus.zip test-data/document/* test-data/integration/*.docx zip -jr $OUT/XLSX2CSVFuzzer_seed_corpus.zip test-data/spreadsheet/* popd pushd "${SRC}" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} mkdir -p ${OUT}/dependency install -v target/assembly/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar install -v target/assembly/${LIBRARY_NAME}-fuzzer-libs-${CURRENT_VERSION}.jar ${OUT}/dependency/${LIBRARY_NAME}-fuzzer-libs-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar dependency/${LIBRARY_NAME}-fuzzer-libs-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(unzip -l ${OUT}/dependency/${LIBRARY_NAME}-fuzzer-libs-${CURRENT_VERSION}.jar | \ grep Fuzzer.class | \ sed -e 's|^.*\(org/apache/poi/fuzz/.*\).class$|\1|g'); do # Get fuzzer-name from .class file-name in jar stripped_path=$(echo ${fuzzer} | sed -e 's|^org/apache/poi/fuzz/\(.*\).class$|\1|'); fuzzer_basename=$(basename ${fuzzer}) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --instrumentation_includes=org.apache.poi.**:org.apache.xmlbeans.** \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx1024m:-Dorg.apache.poi.ss.ignoreMissingFontSystem=true\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/apache-poi/pom.xml ================================================ 4.0.0 ossfuzz poi-fuzzer ${fuzzedLibaryVersion} jar 17 17 UTF-8 5.5.1 org.apache.poi.XLSX2CSVFuzzer central Maven Central https://repo.maven.apache.org/maven2/ apache-staging Apache Staging https://repository.apache.org/content/repositories/staging com.code-intelligence jazzer-api 0.29.1 org.apache.poi poi ${fuzzedLibaryVersion} org.apache.poi poi-ooxml ${fuzzedLibaryVersion} org.apache.poi poi-scratchpad ${fuzzedLibaryVersion} org.apache.poi poi-examples ${fuzzedLibaryVersion} org.apache.poi poi-integration ${fuzzedLibaryVersion} org.apache.poi poi-fuzz ${fuzzedLibaryVersion} org.junit.jupiter junit-jupiter-api 5.13.4 org.apache.logging.log4j log4j-core 2.25.3 com.github.luben zstd-jni 1.5.7-4 org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA META-INF/LICENSE* META-INF/NOTICE* META-INF/DEPENDENCIES shade-poi package shade target/assembly/${project.artifactId}-${fuzzedLibaryVersion}.jar org.apache.poi:poi org.apache.poi:poi-ooxml org.apache.poi:poi-scratchpad shade-non-poi package shade target/assembly/${project.artifactId}-libs-${fuzzedLibaryVersion}.jar org.apache.poi:poi org.apache.poi:poi-ooxml org.apache.poi:poi-scratchpad ================================================ FILE: projects/apache-poi/project.yaml ================================================ homepage: "https://poi.apache.org/" language: jvm main_repo: "https://github.com/apache/poi.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "centic@apache.org" - "dominik.stadler@gmail.com" ================================================ FILE: projects/apache-poi/src/main/resources/log4j2.xml ================================================ ================================================ FILE: projects/apache-tika/.gitignore ================================================ project-parent/tika project-parent/fuzz-targets/target project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/apache-tika/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM ghcr.io/aixcc-finals/base-builder-jvm:v1.3.0 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN=$SRC/maven/apache-maven-3.9.11/bin/mvn COPY project-parent $SRC/project-parent/ RUN git clone --depth 1 https://github.com/apache/tika/ $SRC/project-parent/tika COPY build.sh build_seeds.sh $SRC/ RUN cd $SRC && ./build_seeds.sh WORKDIR $SRC/project-parent/tika ================================================ FILE: projects/apache-tika/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=tika MAIN_REPOSITORY=https://github.com/apache/tika/ MAVEN_ARGS="-Djavac.src.version=17 -Djavac.target.version=17 -DskipTests -Dcheckstyle.skip -Dossindex.skip --no-transfer-progress -am -pl :tika-app" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN --no-transfer-progress versions:use-dep-version -Dexcludes=com.code-intelligence:jazzer -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd $SRC/project-parent set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN --no-transfer-progress -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath cp $SRC/project-parent/fuzz-targets/target/fuzz-targets-0.0.1-SNAPSHOT.jar $OUT/fuzz-targets.jar RUNTIME_CLASSPATH_ABSOLUTE="$OUT/fuzz-targets.jar" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") cp ${SRC}/seeds/*_seed_corpus.zip ${OUT}/ for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # skip helper class which is not a fuzz-target if [ "$fuzzer_basename" == "ParserFuzzer"]; then continue; fi # Create an execution wrapper for every fuzztarget # This bumps memory to > 2gb to get around new byte[Integer.MAX_VALUE] single # allocation issues that plague audio, video, image and other parsers. # if we're able to get an oom > 2gb, we should really fix that. echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") mem_settings='-Xmx3000m:-Xss1024k' LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ -rss_limit_mb=3600mb \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/apache-tika/build_seeds.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir ${SRC}/seeds #This packages the unit test files based on file extension from within the Tika project #we could also pull in other seeds from other parser projects. find ${SRC}/project-parent/tika -name "*-webm.noext" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*-mkv.noext" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.aif" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.au" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.flv" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.m4a" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.mkv" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.mp3" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.wav" -print0 | xargs -0 zip -u ${SRC}/seeds/AudioVideoParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.Z" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.bz2" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.gz" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.tbz2" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.tgz" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.zst" -print0 | xargs -0 zip -u ${SRC}/seeds/CompressorParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.html" -print0 | xargs -0 zip ${SRC}/seeds/HtmlParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.avif" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.bmp" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.bpg" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.gif" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.heic" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.icns" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.jp2" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.jb2" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.jpg" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.jxl" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.png" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.psd" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.tif" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.webp" -print0 | xargs -0 zip -u ${SRC}/seeds/ImageParsersFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.mdb" -print0 | xargs -0 zip ${SRC}/seeds/JackcessParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.accdb" -print0 | xargs -0 zip ${SRC}/seeds/JackcessParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.one" -print0 | xargs -0 zip ${SRC}/seeds/OneNoteParserFuzzer_seed_corpus.zip #we could get more seeds by cloning POI find ${SRC}/project-parent/tika -name "*.msg" -print0 | xargs -0 zip -u ${SRC}/seeds/OfficeParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.doc" -print0 | xargs -0 zip -u ${SRC}/seeds/OfficeParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.ppt" -print0 | xargs -0 zip -u ${SRC}/seeds/OfficeParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.xls" -print0 | xargs -0 zip -u ${SRC}/seeds/OfficeParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.docm" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.docx" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.pptm" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.pptx" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.xlsm" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.xlsx" -print0 | xargs -0 zip -u ${SRC}/seeds/OOXMLParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.7z" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.ar" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.jar" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.rar" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.tar" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.zip" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.zlib" -print0 | xargs -0 zip -u ${SRC}/seeds/PackageParserFuzzer_seed_corpus.zip #we could get more seeds by cloning PDFBox or...? find ${SRC}/project-parent/tika -name "*.pdf" -print0 | xargs -0 zip ${SRC}/seeds/PDFParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.eml" -print0 | xargs -0 zip ${SRC}/seeds/RFC822ParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.rtf" -print0 | xargs -0 zip ${SRC}/seeds/RTFParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.txt" -print0 | xargs -0 zip ${SRC}/seeds/TextAndCSVParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.tsv" -print0 | xargs -0 zip -u ${SRC}/seeds/TextAndCSVParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.csv" -print0 | xargs -0 zip -u ${SRC}/seeds/TextAndCSVParserFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -name "*.xml" -print0 | xargs -0 zip ${SRC}/seeds/XMLReaderUtilsFuzzer_seed_corpus.zip find ${SRC}/project-parent/tika -path '*/test-documents/*' -type f | xargs -n1 -d '\n' zip ${SRC}/seeds/AutoDetectParserFuzzer_seed_corpus.zip cp ${SRC}/seeds/*_seed_corpus.zip ${OUT}/ ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 17 17 17 com.code-intelligence jazzer 0.24.0 provided org.apache.tika tika-core Fuzzing-SNAPSHOT org.apache.tika tika-parsers-standard-package Fuzzing-SNAPSHOT org.apache.maven.plugins maven-shade-plugin 3.6.1 package shade false org.apache.tika:tika-parsers-standard-package:jar: *:* META-INF/maven/plugin.xml module-info.class META-INF/* LICENSE.txt NOTICE.txt CHANGES README builddef.lst javax/**/* true META-INF/LICENSE target/classes/META-INF/LICENSE META-INF/NOTICE target/classes/META-INF/NOTICE META-INF/DEPENDENCIES target/classes/META-INF/DEPENDENCIES META-INF/cxf/bus-extensions.txt ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/AudioVideoParsersFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.Parser; import org.apache.tika.parser.audio.AudioParser; import org.apache.tika.parser.audio.MidiParser; import org.apache.tika.parser.mp3.Mp3Parser; import org.apache.tika.parser.mp4.MP4Parser; import org.apache.tika.parser.video.FLVParser; import org.apache.tika.sax.ToTextContentHandler; class AudioVideoParsersFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser[] parsers = new Parser[] { new AudioParser(), new MidiParser(), new Mp3Parser(), new MP4Parser(), new FLVParser() }; Parser p = new AutoDetectParser(parsers); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/AutoDetectParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.Parser; import org.apache.tika.sax.ToTextContentHandler; class AutoDetectParserFuzzer { private static final Parser AUTO_DETECT_PARSER = new AutoDetectParser(); public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { try { ParserFuzzer.parseOne(AUTO_DETECT_PARSER, bytes); } catch (AssertionError | RuntimeException | IOException | TikaException | SAXException e) { //swallow } //now try rmeta try { ParserFuzzer.parseRMetaFile(AUTO_DETECT_PARSER, bytes); } catch (AssertionError | RuntimeException | IOException | TikaException | SAXException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/CompressorParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.parser.pkg.CompressorParser; import org.apache.tika.parser.Parser; class CompressorParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new CompressorParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (NullPointerException | TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/HtmlParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.Parser; import org.apache.tika.parser.html.JSoupParser; import org.xml.sax.SAXException; final class HtmlParserFuzzer { public static void fuzzerTestOneInput(final byte[] bytes) throws Throwable { Parser p = new JSoupParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { // swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/ImageParsersFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.Parser; import org.apache.tika.parser.image.BPGParser; import org.apache.tika.parser.image.ImageParser; import org.apache.tika.parser.image.PSDParser; import org.apache.tika.parser.image.TiffParser; import org.apache.tika.parser.image.WebPParser; import org.apache.tika.parser.image.JpegParser; import org.apache.tika.parser.image.HeifParser; import org.apache.tika.parser.image.ICNSParser; import org.apache.tika.parser.image.JXLParser; class ImageParsersFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser[] parsers = new Parser[] { new BPGParser(), new ImageParser(), new PSDParser(), new TiffParser(), new WebPParser(), new JpegParser(), new HeifParser(), new ICNSParser(), new JXLParser() }; Parser p = new AutoDetectParser(parsers); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/JackcessParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.parser.microsoft.JackcessParser; import org.apache.tika.parser.Parser; class JackcessParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new JackcessParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (IllegalArgumentException | TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/OOXMLParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.microsoft.OfficeParserConfig; import org.apache.tika.parser.microsoft.ooxml.OOXMLParser; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.sax.ToTextContentHandler; class OOXMLParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new OOXMLParser(); ParseContext parseContext = new ParseContext(); OfficeParserConfig officeParserConfig = new OfficeParserConfig(); officeParserConfig.setExtractMacros(true); parseContext.set(OfficeParserConfig.class, officeParserConfig); try { ParserFuzzer.parseOne(p, bytes, parseContext); } catch (org.apache.poi.ooxml.POIXMLException | org.apache.poi.util.RecordFormatException | AssertionError | IllegalStateException | TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/OfficeParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.microsoft.OfficeParser; import org.apache.tika.parser.microsoft.OfficeParserConfig; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.sax.ToTextContentHandler; class OfficeParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new OfficeParser(); ParseContext parseContext = new ParseContext(); OfficeParserConfig officeParserConfig = new OfficeParserConfig(); officeParserConfig.setExtractMacros(true); parseContext.set(OfficeParserConfig.class, officeParserConfig); try { ParserFuzzer.parseOne(p, bytes, parseContext); } catch ( org.apache.poi.util.RecordFormatException | org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException | org.apache.poi.hslf.exceptions.HSLFException | IndexOutOfBoundsException | AssertionError | IllegalArgumentException | IllegalStateException | java.util.NoSuchElementException | java.nio.BufferUnderflowException | NegativeArraySizeException | NullPointerException | TikaException | SAXException | IOException e) { //swallow //org.apache.poi.hssf.OldExcelFormatException subclasses IllegalArgumentException } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/OneNoteParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.microsoft.onenote.OneNoteParser; import org.apache.tika.parser.Parser; class OneNoteParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new OneNoteParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/PDFParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.pdf.PDFParser; import org.apache.tika.parser.pdf.PDFParserConfig; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; class PDFParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new PDFParser(); PDFParserConfig config = new PDFParserConfig(); //what else do we want to exercise? config.setExtractActions(true); ParseContext parseContext = new ParseContext(); parseContext.set(PDFParserConfig.class, config); try { ParserFuzzer.parseOne(p, bytes, parseContext); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/PackageParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.parser.pkg.PackageParser; import org.apache.tika.parser.Parser; class PackageParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new PackageParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (IllegalArgumentException | TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/ParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.InputStream; import org.xml.sax.ContentHandler; import org.apache.tika.io.TikaInputStream; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.parser.RecursiveParserWrapper; import org.apache.tika.sax.BasicContentHandlerFactory; import org.apache.tika.sax.RecursiveParserWrapperHandler; import org.apache.tika.sax.ToTextContentHandler; class ParserFuzzer { public static void parseOne(Parser parser, byte[] bytes, ParseContext parseContext) throws Throwable { parseBytes(parser, bytes, parseContext); parseFile(parser, bytes, parseContext); } public static void parseOne(Parser parser, byte[] bytes) throws Throwable { parseBytes(parser, bytes, new ParseContext()); parseFile(parser, bytes, new ParseContext()); } public static void parseRMetaFile(Parser parser, byte[] bytes) throws Throwable { RecursiveParserWrapper wrapper = new RecursiveParserWrapper(parser); RecursiveParserWrapperHandler rpwh = new RecursiveParserWrapperHandler( new BasicContentHandlerFactory(BasicContentHandlerFactory.HANDLER_TYPE.XML, -1)); try (TikaInputStream tis = TikaInputStream.get(bytes)) { tis.getPath(); wrapper.parse(tis, rpwh, new Metadata(), new ParseContext()); } } public static void parseBytes(Parser parser, byte[] bytes, ParseContext parseContext) throws Throwable { ContentHandler handler = new ToTextContentHandler(); //make sure that other parsers cannot be invoked parseContext.set(Parser.class, parser); //try first with bytes try (TikaInputStream is = TikaInputStream.get(bytes)) { parser.parse(is, handler, new Metadata(), parseContext); } } public static void parseFile(Parser parser, byte[] bytes, ParseContext parseContext) throws Throwable { ContentHandler handler = new ToTextContentHandler(); //make sure that other parsers cannot be invoked parseContext.set(Parser.class, parser); try (TikaInputStream tis = TikaInputStream.get(bytes)) { //force writing to tmp file tis.getPath(); parser.parse(tis, handler, new Metadata(), parseContext); } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/RFC822ParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.parser.mail.RFC822Parser; import org.apache.tika.parser.Parser; class RFC822ParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new RFC822Parser(); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/RTFParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.parser.microsoft.rtf.RTFParser; import org.apache.tika.sax.ToTextContentHandler; class RTFParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new RTFParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (AssertionError | TikaException | SAXException | IOException | org.apache.tika.metadata.PropertyTypeException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/TextAndCSVParserFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.ParseContext; import org.apache.tika.parser.Parser; import org.apache.tika.parser.csv.TextAndCSVParser; import org.apache.tika.sax.ToTextContentHandler; class TextAndCSVParserFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Throwable { Parser p = new TextAndCSVParser(); try { ParserFuzzer.parseOne(p, bytes); } catch (TikaException | SAXException | IOException e) { //swallow } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/java/com/example/XMLReaderUtilsFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.IOException; import java.io.InputStream; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Comparator; import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import org.w3c.dom.Document; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.apache.tika.exception.TikaException; import org.apache.tika.io.TikaInputStream; import org.apache.tika.parser.ParseContext; import org.apache.tika.sax.ToTextContentHandler; import org.apache.tika.utils.XMLReaderUtils; class XMLReaderUtilsFuzzer { public static void fuzzerTestOneInput(byte[] bytes) throws Exception { try { parseOne(bytes); } catch (java.io.FileNotFoundException e) { //this should be rethrown because it could signal an XMLParser looking for a DTD throw e; } catch (TikaException | IOException | SAXException e) { e.printStackTrace(); } } private static void parseOne(byte[] bytes) throws TikaException, IOException, SAXException { //dom try (InputStream is = TikaInputStream.get(bytes)) { Document doc = XMLReaderUtils.buildDOM(is, new ParseContext()); } catch (SAXParseException e) { //swallow } //sax try (InputStream is = TikaInputStream.get(bytes)) { ToTextContentHandler toTextContentHandler = new ToTextContentHandler(); XMLReaderUtils.parseSAX(is, toTextContentHandler, new ParseContext()); } catch (SAXException e) { //swallow } //stax try (InputStream is = TikaInputStream.get(bytes)) { XMLStreamReader reader = XMLReaderUtils.getXMLInputFactory(new ParseContext()) .createXMLStreamReader(is); while (reader.hasNext()) { reader.next(); } } catch (java.util.MissingResourceException | XMLStreamException e) { //MissingResourceException can be thrown when an internal DTD has an InvalidCharInDTD //throw new TikaException("xml stream", e); } } } ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/resources/log4j2.xml ================================================ ================================================ FILE: projects/apache-tika/project-parent/fuzz-targets/src/main/resources/tika-config.xml ================================================ false false ================================================ FILE: projects/apache-tika/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom tika fuzz-targets ================================================ FILE: projects/apache-tika/project.yaml ================================================ homepage: "https://tika.apache.org/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/tika/" sanitizers: - address vendor_ccs: - "dev-owner@tika.apache.org" - "tallison@apache.org" - "tallison314159@gmail.com" ================================================ FILE: projects/aptos-core/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libclang-dev libtool pkg-config libudev-dev RUN git clone --depth=1 https://github.com/aptos-labs/aptos-core.git ENV RUSTUP_TOOLCHAIN nightly-2024-09-05 WORKDIR aptos-core COPY build.sh $SRC ================================================ FILE: projects/aptos-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd testsuite/fuzzer bash fuzz.sh build-oss-fuzz $OUT ================================================ FILE: projects/aptos-core/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://aptos.dev" language: rust primary_contact: "andrea.cappa@aptoslabs.com" main_repo: "https://github.com/aptos-labs/aptos-core" auto_ccs: - "oss-fuzz-notifications@aptoslabs.com" - "security@aptoslabs.com" - "marco.ilardi@aptoslabs.com" - "george@aptoslabs.com" sanitizers: - address fuzzing_engines: - libfuzzer coverage_extra_args: -ignore-filename-regex=.*/rustc/.* ================================================ FILE: projects/archaius-core/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/Netflix/archaius COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ COPY pom-core.xml $SRC/archaius/archaius-core/pom.xml WORKDIR $SRC/archaius ================================================ FILE: projects/archaius-core/DynamicPropertyFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.netflix.config.*; import java.util.*; public class DynamicPropertyFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String property = data.consumeString(50); String value = data.consumeString(100); DynamicLongProperty dpLong = new DynamicLongProperty(property, data.consumeLong()); dpLong.get(); DynamicFloatProperty dpFloat = new DynamicFloatProperty(property, data.consumeFloat()); dpFloat.get(); DynamicStringProperty dpString = new DynamicStringProperty(property, value); dpString.get(); DynamicStringSetProperty dpStringSet = new DynamicStringSetProperty(property, value); dpStringSet.get(); DynamicStringMapProperty dpStringMap = new DynamicStringMapProperty(property, value); dpStringMap.get(); DynamicStringListProperty dpStringList = new DynamicStringListProperty(property, value); dpStringList.get(); DynamicContextualProperty dpContextual = new DynamicContextualProperty(property, value); } } ================================================ FILE: projects/archaius-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd archaius-core MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/archaius-core-$CURRENT_VERSION-jar-with-dependencies.jar" "$OUT/archaius-core.jar" ALL_JARS="archaius-core.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/archaius-core/pom-core.xml ================================================ archaius-core 4.0.0 com.netflix.archaius archaius-core 0.6.0 jar org.apache.maven.plugins maven-assembly-plugin package single jar-with-dependencies 1.7 1.7 javax.annotation javax.annotation-api 1.3.2 com.google.code.findbugs jsr305 3.0.2 commons-configuration commons-configuration 1.8 org.slf4j slf4j-api 1.6.2 org.slf4j slf4j-nop 1.7.5 com.google.guava guava 16.0 com.fasterxml.jackson.core jackson-annotations 2.4.3 com.fasterxml.jackson.core jackson-core 2.4.3 com.fasterxml.jackson.core jackson-databind 2.4.3 org.apache.derby derby 10.8.2.2 test commons-io commons-io 1.3.2 test org.mockito mockito-core 1.9.5 test junit junit 4.11 test archaius-core https://github.com/Netflix/archaius ================================================ FILE: projects/archaius-core/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/Netflix/archaius" language: jvm main_repo: "https://github.com/Netflix/archaius.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/arduinojson/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make zip git RUN git clone --depth 1 https://github.com/bblanchon/ArduinoJson.git arduinojson WORKDIR arduinojson COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/arduinojson/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzzers cd extras/fuzzing make # Build unit testing if [[ "$SANITIZER" == "memory" ]] then # Unit test building with MSAN requires explicit sanitizer flags. export LDFLAGS="-fsanitize=$SANITIZER" fi mkdir $SRC/arduinojson/build-tests cd $SRC/arduinojson/build-tests cmake .. -DCMAKE_CXX_FLAGS="-Wno-error=deprecated-literal-operator" make -C "extras/tests/" -j$(nproc) make -C "extras/fuzzing/" -j$(nproc) ================================================ FILE: projects/arduinojson/project.yaml ================================================ homepage: "https://github.com/bblanchon/ArduinoJson" language: c++ primary_contact: "benoit.blanchon@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/bblanchon/ArduinoJson.git' ================================================ FILE: projects/arduinojson/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [[ "$SANITIZER" == "memory" ]] then # Unit test will failed on these test cases because of uninitialized memory, thus skipping them. ctest --test-dir $SRC/arduinojson/build-tests -j$(nproc) -E \ "Cpp17|Cpp20|Deprecated|IntegrationTests|JsonArray|JsonArrayConst|JsonDeserializer|JsonDocument|JsonObject|JsonObjectConst|JsonSerializer|JsonVariant|JsonVariantConst|ResourceManager|Misc|MixedConfiguration|MsgPackDeserializer|MsgPackSerializer|Numbers|TextFormatter|json_fuzzer|msgpack_fuzzer" else ctest --test-dir $SRC/arduinojson/build-tests -j$(nproc) fi ================================================ FILE: projects/argcomplete/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/kislyuk/argcomplete argcomplete COPY *.sh *py $SRC/ WORKDIR $SRC/argcomplete ================================================ FILE: projects/argcomplete/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/argcomplete/fuzz_shlex.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Targets the lexical routines used by argcomplete.""" import sys import atheris import argcomplete def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: argcomplete.split_line(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (argcomplete.ArgcompleteException): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/argcomplete/project.yaml ================================================ homepage: https://github.com/kislyuk/argcomplete main_repo: https://github.com/kislyuk/argcomplete language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/argo/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN apt-get update && apt-get install -y wget zip RUN git clone --depth 1 https://github.com/argoproj/argo-cd RUN git clone --depth 1 https://github.com/argoproj/argo-workflows RUN git clone --depth 1 https://github.com/argoproj/argo-events RUN git clone --depth 1 https://github.com/argoproj/gitops-engine RUN git clone --depth 1 https://github.com/argoproj/argo-rollouts RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN wget https://github.com/facebook/zstd/releases/download/v1.4.2/zstd-1.4.2.tar.gz && \ tar xzf zstd-1.4.2.tar.gz && \ cd zstd-1.4.2 && \ export CC=clang && \ export CXX=clang++ && \ export CXXFLAGS="-stdlib=libc++" && \ make -j$(nproc) COPY build.sh $SRC/ WORKDIR $SRC/argo-cd ================================================ FILE: projects/argo/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/argo/build.sh ================================================ FILE: projects/argo/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://argoproj.github.io/" main_repo: "https://github.com/argoproj" primary_contact: "terrytangyuan@gmail.com" auto_ccs : - "adam@adalogics.com" - "david@adalogics.com" - "henrik.blixt@gmail.com" - "jfischer@redhat.com" - "alexander_matyushentsev@intuit.com" - "qianbo_huai@intuit.com" - "alex_collins@intuit.com" - "derek_wang@intuit.com" - "saravanan_balasubramanian@intuit.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/args/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y \ make \ cmake RUN git clone --depth 1 https://github.com/Taywee/args.git $SRC/args/ COPY build.sh run_tests.sh $SRC/ WORKDIR $SRC/args/ ================================================ FILE: projects/args/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release -DARGS_BUILD_TESTS=ON .. make -j4 for fuzzer in $(find $SRC/args/fuzz/ -name "*_fuzzer.cpp"); do fuzzer_basename=$(basename -s .cpp $fuzzer) $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ -I$SRC/args \ $fuzzer \ -o $OUT/$fuzzer_basename done ================================================ FILE: projects/args/project.yaml ================================================ homepage: "https://taywee.github.io/args/" main_repo: "https://github.com/Taywee/args" language: c++ primary_contact: "taylor@axfive.net" ================================================ FILE: projects/args/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ cd build ctest --output-on-failure ================================================ FILE: projects/args4j/CmdLineParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.kohsuke.args4j.*; import org.kohsuke.args4j.spi.StringArrayOptionHandler; import java.io.File; import java.util.*; public class CmdLineParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ParserProperties props = ParserProperties.defaults(); try { props.withAtSyntax(data.consumeBoolean()); props.withShowDefaults(data.consumeBoolean()); props.withUsageWidth(data.consumeInt()); props.withOptionValueDelimiter(data.consumeString(100)); } catch (IllegalArgumentException e) {} Collection args = new HashSet(); for (int i = 0; i < data.consumeInt(0, 50); i++) { args.add(data.consumeString(100)); } CmdLineParser parser = new CmdLineParser(DummyClass.class); try { parser.parseArgument(args); } catch (CmdLineException e) {} } static class DummyClass { @Option(name="-str",usage="set a string") public String str = "pretty string"; @Option(name="-req",usage="set a string", required = true) public String req = "required"; @Option(name="-noDefault") public String noDefault; @Option(name="-noDefaultReq", required = true) public String noDefaultReq; @Option(name="-byteVal", usage = "my favorite byte") public byte byteVal; @Option(name="-strArray", usage="my favorite strarr") public String strArray[] = new String[] { "san", "dra", "chen"}; public enum DrinkName { BEER, WHISKEY, SCOTCH, BOURBON, BRANDY }; @Option(name="-drinkArray", usage="my favorite drinks") public DrinkName drinkArray[] = new DrinkName[] { DrinkName.BEER, DrinkName.BOURBON }; @Option(name="-drink", usage="my favorite drink") public DrinkName drink = DrinkName.BEER; @Option(name="-drinkList", usage="my favorite drinks") public List drinkList = Arrays.asList(DrinkName.BEER, DrinkName.BRANDY); @Argument public String arguments[] = new String[] { "foo", "bar" }; @Option(name="-o", usage="output to this file", metaVar="OUTPUT") private File out = new File("."); @Option(name="-hidden-str", hidden=true, usage="hidden option") private String hiddenStr = "(default value)"; @Option(name="-n", usage="repeat times\n") private int num = -1; @Option(name="-boolean") public boolean _boolean; @Option(name="-byte") public byte _byte; @Option(name="-char") public char _char; @Option(name="-double") public double _double; @Option(name="-float") public float _float; @Option(name="-int") public int _int; @Option(name="-long") public long _long; @Option(name="-short") public short _short; @Option(name = "-z", depends ={"-y"}) int a; @Option(name = "-y", depends ={"-z"}) int b; @Option(name = "-a", aliases="--alpha") int w; @Option(name = "-b", aliases="--bravo") int x; @Option(name = "-c", depends ={"--alpha"}) int y; @Option(name = "-d", depends ={"-b", "-c"}) int z; @Option(name = "-h", forbids ={"-a", "-b"}) int o; @Option(name="-list") List list; @Option(name="-string") String string; @Option(name="-array") String[] array; @Option(name="-multivalued-array", handler = StringArrayOptionHandler.class) String[] multiValuedArray; } } ================================================ FILE: projects/args4j/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/kohsuke/args4j $SRC/args4j RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/args4j ================================================ FILE: projects/args4j/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) $MVN package -pl -args4j-tools -pl -args4j-maven-plugin -pl -args4j-maven-plugin-example cp "../args4j/args4j/target/args4j-$CURRENT_VERSION.jar" $OUT/ ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/args4j/project.yaml ================================================ homepage: "https://github.com/kohsuke/args4j" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/kohsuke/args4j" sanitizers: - address vendor_ccs: ================================================ FILE: projects/arrow/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update -y -q && \ apt-get install -y -q --no-install-recommends \ bison \ flex \ ninja-build ARG boost_version=1.89.0 # uuid and locale needed for Thrift source build ARG boost_components=filesystem;system;process;multiprecision;crc;uuid;locale RUN wget https://github.com/boostorg/boost/releases/download/boost-${boost_version}/boost-${boost_version}-cmake.tar.gz && \ tar -xf boost-${boost_version}-cmake.tar.gz && \ cd boost-${boost_version}/ && \ mkdir -p build / && \ cd build/ && \ cmake .. -GNinja -DBOOST_INCLUDE_LIBRARIES="${boost_components}" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF && \ cmake --build . --target install RUN git clone --depth=1 --recurse-submodules \ https://github.com/apache/arrow.git $SRC/arrow COPY *.sh $SRC/ ================================================ FILE: projects/arrow/build.sh ================================================ #!/bin/bash -eux # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # 1. Build instrumented OpenSSL OPENSSL_VERSION=3.5.4 cd ${SRC} wget https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz tar -xf openssl-${OPENSSL_VERSION}.tar.gz cd openssl-${OPENSSL_VERSION} # Assembler snippets would not be instrumented, disable them ./Configure no-apps no-docs no-tests no-shared no-asm make -j make install # 2. Build Arrow C++ proper ARROW=${SRC}/arrow/cpp BUILD_DIR=${SRC}/build-dir mkdir -p ${BUILD_DIR} cd ${BUILD_DIR} cmake ${ARROW} -GNinja \ -DCMAKE_BUILD_TYPE=Release \ -DARROW_DEPENDENCY_SOURCE=BUNDLED \ -DARROW_OPENSSL_USE_SHARED=off \ -DBOOST_SOURCE=SYSTEM \ -DARROW_BOOST_USE_SHARED=off \ -DCMAKE_C_FLAGS="${CFLAGS}" \ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \ -DARROW_EXTRA_ERROR_CONTEXT=off \ \ -DARROW_BUILD_SHARED=off \ -DARROW_BUILD_STATIC=on \ -DARROW_BUILD_BENCHMARKS=off \ -DARROW_BUILD_EXAMPLES=off \ -DARROW_BUILD_INTEGRATION=off \ -DARROW_BUILD_TESTS=on \ -DARROW_BUILD_UTILITIES=off \ -DARROW_TEST_LINKAGE=static \ -DPARQUET_BUILD_EXAMPLES=off \ -DPARQUET_BUILD_EXECUTABLES=off \ -DPARQUET_REQUIRE_ENCRYPTION=on \ \ -DARROW_CSV=on \ -DARROW_JEMALLOC=off \ -DARROW_MIMALLOC=off \ -DARROW_PARQUET=on \ -DARROW_WITH_BROTLI=on \ -DARROW_WITH_BZ2=off \ -DARROW_WITH_LZ4=on \ -DARROW_WITH_SNAPPY=on \ -DARROW_WITH_ZLIB=on \ -DARROW_WITH_ZSTD=on \ \ -DARROW_USE_ASAN=off \ -DARROW_USE_UBSAN=off \ -DARROW_USE_TSAN=off \ -DARROW_FUZZING=on \ cmake --build . -j$(nproc) ${ARROW}/build-support/fuzzing/generate_corpuses.sh ${BUILD_DIR}/release # Copy fuzz targets find . -executable -name "*-fuzz" -exec cp -a -v '{}' ${OUT} \; # Copy seed corpuses find . -name "*-fuzz_seed_corpus.zip" -exec cp -a -v '{}' ${OUT} \; ================================================ FILE: projects/arrow/project.yaml ================================================ homepage: "https://arrow.apache.org/" language: c++ primary_contact: "antoine@python.org" auto_ccs: - "bengilgit@gmail.com" - "dewey.dunnington@gmail.com" - "emkornfield@gmail.com" - "felipekde@gmail.com" - "fsaintjacques@gmail.com" - "jinpengz@google.com" - "maplewish117@gmail.com" - "micahk@google.com" - "muraken@gmail.com" - "panahi@google.com" - "raulcumplido@gmail.com" - "szucs.krisztian@gmail.com" - "wesmckinn@gmail.com" - "xhochy@gmail.com" - "ustcwg@gmail.com" - "will.jones127@gmail.com" - "zanmato1984@gmail.com" - "zotthewizard@gmail.com" main_repo: 'https://github.com/apache/arrow.git' ================================================ FILE: projects/arrow/replay_build.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ARROW=${SRC}/arrow/cpp BUILD_DIR=${SRC}/build-dir cd ${BUILD_DIR} cmake --build . -j$(nproc) # Copy fuzz targets find . -executable -name "*-fuzz" -exec cp -a -v '{}' ${OUT} \; ================================================ FILE: projects/arrow/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### set -eux cd $SRC/build-dir export PARQUET_TEST_DATA=$SRC/arrow/cpp/submodules/parquet-testing/data/ export ARROW_TEST_DATA=$SRC/arrow/testing/data ASAN_OPTIONS="detect_leaks=0" ctest -j$(nproc) ================================================ FILE: projects/arrow-java/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 ENV JAVA_HOME=$JAVA_15_HOME ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server ENV PATH=$JAVA_HOME/bin:$PATH RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN=$SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone https://github.com/apache/arrow-java.git $SRC/arrow-java RUN git clone https://github.com/apache/arrow-testing.git $SRC/arrow-testing # Seed corpus RUN zip -j $SRC/FuzzIpcFile_seed_corpus.zip $SRC/arrow-testing/data/arrow-ipc-file/clusterfuzz-testcase-arrow-ipc-file-fuzz-* && \ zip -j $SRC/FuzzIpcStream_seed_corpus.zip $SRC/arrow-testing/data/arrow-ipc-stream/clusterfuzz-testcase-arrow-ipc-stream-fuzz-* # Copy build script and all fuzzers COPY build.sh $SRC/ COPY Fuzz*.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/arrow-java/FuzzIpcFile.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.vector.VectorSchemaRoot; import org.apache.arrow.vector.ipc.ArrowFileReader; import org.apache.arrow.vector.ipc.InvalidArrowFileException; import org.apache.arrow.vector.ipc.SeekableReadChannel; import org.apache.arrow.vector.util.ByteArrayReadableSeekableByteChannel; import org.apache.arrow.vector.util.ValueVectorUtility; public class FuzzIpcFile { public static void fuzzerTestOneInput(byte[] data) { BufferAllocator allocator = new RootAllocator(Integer.MAX_VALUE); try (SeekableReadChannel channel = new SeekableReadChannel(new ByteArrayReadableSeekableByteChannel(data)); ArrowFileReader reader = new ArrowFileReader(channel, allocator)) { VectorSchemaRoot root = reader.getVectorSchemaRoot(); // validate schema ValueVectorUtility.validate(root); while (reader.loadNextBatch()) { ValueVectorUtility.validateFull(root); } } catch (IOException | InvalidArrowFileException e) {} } } ================================================ FILE: projects/arrow-java/FuzzIpcStream.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.memory.RootAllocator; import org.apache.arrow.vector.VectorSchemaRoot; import org.apache.arrow.vector.ipc.ArrowStreamReader; import org.apache.arrow.vector.util.ValueVectorUtility; public class FuzzIpcStream { public static void fuzzerTestOneInput(byte[] data) { BufferAllocator allocator = new RootAllocator(Integer.MAX_VALUE); try (ArrowStreamReader reader = new ArrowStreamReader(new ByteArrayInputStream(data), allocator)) { VectorSchemaRoot root = reader.getVectorSchemaRoot(); // validate schema ValueVectorUtility.validate(root); while (reader.loadNextBatch()) { ValueVectorUtility.validateFull(root); } } catch (IOException e) {} } } ================================================ FILE: projects/arrow-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Only build the Java module MAVEN_ARGS="-DskipTests" cd arrow-java $MVN install ${MAVEN_ARGS} # copy dependencies $MVN dependency:copy-dependencies -DoutputDirectory=$OUT # setup class path ALL_JARS="" for jar in $(find $OUT -name '*.jar'); do jar_name=$(basename $jar) ALL_JARS=$ALL_JARS" "$jar_name done cd ../.. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -name 'Fuzz*.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. export JAVA_HOME=$JAVA_15_HOME export JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server export PATH=$JAVA_HOME/bin:$PATH this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/arrow-java/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://arrow.apache.org/" language: jvm primary_contact: "liya.fan03@gmail.com" auto_ccs: - "emkornfield@gmail.com" - "jacques@apache.org" - "wesmckinn@gmail.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/arrow-java" sanitizers: - address ================================================ FILE: projects/arrow-py/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/arrow-py/arrow arrow COPY *.sh *py $SRC/ WORKDIR $SRC/arrow ================================================ FILE: projects/arrow-py/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/arrow-py/fuzz_datetime.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1 # Imports by the generated code import arrow def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) datetime_string = fdp.ConsumeUnicodeNoSurrogates( fdp.ConsumeIntInRange(1, 4096)) # Class target. try: c1 = arrow.parser.DateTimeParser() c1.parse_iso(datetime_string) except ( arrow.parser.ParserMatchError, arrow.parser.ParserError, ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/arrow-py/fuzz_tzinfo.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1 # Imports by the generated code import arrow def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) tzinfo_string = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 4096)) # Class target. try: c1 = arrow.parser.TzinfoParser() c1.parse(tzinfo_string) except (arrow.parser.ParserError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/arrow-py/project.yaml ================================================ homepage: https://github.com/arrow-py/arrow main_repo: https://github.com/arrow-py/arrow language: python fuzzing_engines: - libfuzzer sanitizers: - address primary_contact: me@krisfremen.com vendor_ccs: - david@adalogics.com ================================================ FILE: projects/askama/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 --recurse-submodules --shallow-submodules https://github.com/askama-rs/askama.git askama WORKDIR askama/fuzzing # The current default toolchain used by OSS-Fuzz (1.81) is too old for askama v0.15, # which needs at least 1.88. ENV RUSTUP_TOOLCHAIN nightly-2025-07-04 COPY build.sh $SRC/ ================================================ FILE: projects/askama/build.sh ================================================ #!/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -euxo pipefail target_out_dir=target/x86_64-unknown-linux-gnu/release cargo fuzz build --release cargo fuzz list | while read i; do zip --recurse-paths --junk-paths --quiet "${OUT}/${i}_seed_corpus.zip" "./fuzz/corpus/${i}/" mv -t "${OUT}/" "$target_out_dir/${i}" done ================================================ FILE: projects/askama/project.yaml ================================================ homepage: "https://askama.readthedocs.io/" main_repo: "https://github.com/askama-rs/askama" language: rust primary_contact: "rene.kijewski@fu-berlin.de" auto_ccs: - "guillaume1.gomez@gmail.com" sanitizers: - address fuzzing_engines: - libfuzzer coverage_extra_args: > -ignore-filename-regex=.*/rustc/.* -ignore-filename-regex=.*/rust/.* ================================================ FILE: projects/asn1crypto/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/wbond/asn1crypto asn1crypto WORKDIR asn1crypto COPY build.sh *.py $SRC/ ================================================ FILE: projects/asn1crypto/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/asn1crypto/fuzz_parse.py ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ import sys import atheris from asn1crypto import parser def TestOneInput(data): try: parser.parse(data) except (ValueError, TypeError) as e: # Raises ValueError and TypeError: # https://github.com/wbond/asn1crypto/blob/b5f03e6f9797c691a3b812a5bb1acade3a1f4eeb/asn1crypto/parser.py#L91-L92 pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/asn1crypto/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/wbond/asn1crypto language: python main_repo: https://github.com/wbond/asn1crypto sanitizers: - address primary_contact: "will@wbond.net" vendor_ccs: - david@adalogics.com ================================================ FILE: projects/aspectj/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn ENV TARGET_PACKAGE_PREFIX org.aspectj.* WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/eclipse/org.aspectj ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/org.aspectj ================================================ FILE: projects/aspectj/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-Dmaven.compiler.source=15 -Dmaven.compiler.target=15 -DskipTests" ALL_JARS="" # install the build servers' jazzer-api into the maven repository pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/org.aspectj" ${MVN} package ${MVN_FLAGS} ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd ${SRC} ${MVN} package -DaspectjVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/aspectj-fuzzer-${CURRENT_VERSION}.jar ${OUT}/aspectj-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} aspectj-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|'); # the .java was stripped by sed if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/aspectj/pom.xml ================================================ 4.0.0 ossfuzz aspectj-fuzzer ${aspectjVersion} jar 15 15 ossfuzz.ASTFuzzer UTF-8 com.code-intelligence jazzer-api 0.12.0 org.aspectj aspectjrt ${aspectjVersion} org.aspectj aspectjtools ${aspectjVersion} org.aspectj aspectjweaver ${aspectjVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/aspectj/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.eclipse.org/aspectj/" language: jvm main_repo: "https://github.com/eclipse/org.aspectj" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/aspectj/src/main/java/ossfuzz/ASTFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.HashMap; import org.aspectj.org.eclipse.jdt.core.dom.AST; import org.aspectj.org.eclipse.jdt.core.dom.ASTParser; import org.aspectj.org.eclipse.jdt.core.dom.CompilationUnit; public class ASTFuzzer { // Valid AST JLS levels supported by AspectJ/Eclipse JDT private static final int[] VALID_AST_LEVELS = { AST.JLS2, // 2 AST.JLS3, // 3 AST.JLS4, // 4 AST.JLS8, // 8 AST.JLS9, // 9 AST.JLS10, // 10 AST.JLS11, // 11 AST.JLS12, // 12 AST.JLS13, // 13 AST.JLS14, // 14 AST.JLS15, // 15 AST.JLS16, // 16 AST.JLS17, // 17 AST.JLS18, // 18 AST.JLS19, // 19 AST.JLS20, // 20 }; public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { try { int astlevel = fuzzedDataProvider.pickValue(VALID_AST_LEVELS); String source = fuzzedDataProvider.consumeRemainingAsString(); ASTParser parser = ASTParser.newParser(astlevel); parser.setSource(source.toCharArray()); parser.setCompilerOptions(new HashMap()); CompilationUnit cu = (CompilationUnit) parser.createAST(null); cu.getAST(); } catch (IllegalArgumentException | VerifyError | NoClassDefFoundError ex) { /* ignore - IllegalArgumentException for invalid inputs, VerifyError/NoClassDefFoundError for bytecode issues during class loading */ } } } ================================================ FILE: projects/aspell/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/gnuaspell/aspell.git $SRC/aspell RUN git clone --depth 1 -b master https://github.com/gnuaspell/aspell-fuzz.git $SRC/aspell-fuzz WORKDIR $SRC/aspell-fuzz COPY build.sh $SRC/ ================================================ FILE: projects/aspell/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the fuzzer project. pushd $SRC/aspell-fuzz ./ossfuzz.sh popd ================================================ FILE: projects/aspell/project.yaml ================================================ homepage: "https://github.com/GNUAspell/aspell" language: c++ primary_contact: "kevina@gnu.org" auto_ccs: - "kevinatkn@gmail.com" - "cmeister2@gmail.com" sanitizers: - address - undefined - memory: experimental: true main_repo: 'https://github.com/gnuaspell/aspell.git' ================================================ FILE: projects/assimp/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake ninja-build zip RUN git clone --depth 1 --recursive https://github.com/assimp/assimp.git WORKDIR assimp COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/assimp/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build directory mkdir -p build cd build # Configure cmake .. \ -G Ninja \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_C_FLAGS="${CFLAGS}" \ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \ -DASSIMP_BUILD_ZLIB=ON \ -DASSIMP_BUILD_TESTS=OFF \ -DASSIMP_BUILD_ASSIMP_TOOLS=OFF \ -DBUILD_SHARED_LIBS=OFF \ -DASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT=ON \ -DASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT=ON # Build the library ninja # Helper function to build fuzzers build_fuzzer() { local fuzzer_name=$1 local source_file=$2 echo "Building $fuzzer_name..." $CXX $CXXFLAGS -I../include -I../build/include -c "$source_file" -o "${fuzzer_name}.o" $CXX $CXXFLAGS $LIB_FUZZING_ENGINE "${fuzzer_name}.o" -o "$OUT/${fuzzer_name}" \ ./lib/libassimp.a \ ./contrib/zlib/libzlibstatic.a \ -lpthread -ldl } # 1. Generic Fuzzer build_fuzzer "assimp_fuzzer" "../fuzz/assimp_fuzzer.cc" # Corpus for generic fuzzer (all models) (cd ../test/models && zip -q -r $OUT/assimp_fuzzer_seed_corpus.zip .) # Dictionary cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer.dict || true # 2. OBJ Fuzzer build_fuzzer "assimp_fuzzer_obj" "../fuzz/assimp_fuzzer_obj.cc" if [ -d "../test/models/OBJ" ]; then (cd ../test/models/OBJ && zip -q -r $OUT/assimp_fuzzer_obj_seed_corpus.zip .) fi cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_obj.dict || true # 3. GLTF Fuzzer (text format only, glTF and glTF2 versions) build_fuzzer "assimp_fuzzer_gltf" "../fuzz/assimp_fuzzer_gltf.cc" mkdir -p gltf_corpus [ -d "../test/models/glTF" ] && cp -r ../test/models/glTF/* gltf_corpus/ [ -d "../test/models/glTF2" ] && cp -r ../test/models/glTF2/* gltf_corpus/ if [ -d "gltf_corpus" ] && [ "$(ls -A gltf_corpus)" ]; then (cd gltf_corpus && zip -q -r $OUT/assimp_fuzzer_gltf_seed_corpus.zip .) fi rm -rf gltf_corpus cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_gltf.dict || true # 4. GLB Fuzzer (binary glTF format) build_fuzzer "assimp_fuzzer_glb" "../fuzz/assimp_fuzzer_glb.cc" mkdir -p glb_corpus # GLB files can be found in glTF and glTF2 directories [ -d "../test/models/glTF" ] && find ../test/models/glTF -name "*.glb" -exec cp {} glb_corpus/ \; 2>/dev/null || true [ -d "../test/models/glTF2" ] && find ../test/models/glTF2 -name "*.glb" -exec cp {} glb_corpus/ \; 2>/dev/null || true if [ -d "glb_corpus" ] && [ "$(ls -A glb_corpus)" ]; then (cd glb_corpus && zip -q -r $OUT/assimp_fuzzer_glb_seed_corpus.zip .) fi rm -rf glb_corpus cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_glb.dict || true # 5. FBX Fuzzer build_fuzzer "assimp_fuzzer_fbx" "../fuzz/assimp_fuzzer_fbx.cc" if [ -d "../test/models/FBX" ]; then (cd ../test/models/FBX && zip -q -r $OUT/assimp_fuzzer_fbx_seed_corpus.zip .) fi cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_fbx.dict || true # 6. Collada Fuzzer build_fuzzer "assimp_fuzzer_collada" "../fuzz/assimp_fuzzer_collada.cc" if [ -d "../test/models/Collada" ]; then (cd ../test/models/Collada && zip -q -r $OUT/assimp_fuzzer_collada_seed_corpus.zip .) fi cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_collada.dict || true # 7. STL Fuzzer build_fuzzer "assimp_fuzzer_stl" "../fuzz/assimp_fuzzer_stl.cc" if [ -d "../test/models/STL" ]; then (cd ../test/models/STL && zip -q -r $OUT/assimp_fuzzer_stl_seed_corpus.zip .) fi cp ../fuzz/assimp_fuzzer.dict $OUT/assimp_fuzzer_stl.dict || true ================================================ FILE: projects/assimp/project.yaml ================================================ homepage: "https://github.com/assimp/assimp" main_repo: "https://github.com/assimp/assimp" language: c++ primary_contact: "kim.kulling@assimp.org" auto_ccs: - "kim.kulling@googlemail.com" - "realmccoy+ossfuzz@fastmail.com" sanitizers: - address - undefined - memory fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/assimp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ bin/unit ================================================ FILE: projects/astc-encoder/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/ARM-software/astc-encoder WORKDIR astc-encoder/Source COPY build.sh $SRC/ ================================================ FILE: projects/astc-encoder/build.sh ================================================ # !/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project and project-hosted fuzzers sed -i 's/c++14/c++17/g' $SRC/astc-encoder/Source/Fuzzers/build.sh $SRC/astc-encoder/Source/Fuzzers/build.sh ================================================ FILE: projects/astc-encoder/project.yaml ================================================ homepage: "https://github.com/ARM-software/astc-encoder" language: c++ primary_contact: "peter.harris@arm.com" main_repo: 'https://github.com/ARM-software/astc-encoder' ================================================ FILE: projects/asteval/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/newville/asteval asteval COPY *.sh *py $SRC/ WORKDIR $SRC/asteval ================================================ FILE: projects/asteval/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/asteval/fuzz_eval.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1 # Imports by the generated code import asteval def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) fuzz_expr = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 4096)) # Class target. try: interpreter = asteval.asteval.Interpreter() interpreter.eval(fuzz_expr) except (ValueError, OSError): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/asteval/project.yaml ================================================ homepage: https://github.com/newville/asteval main_repo: https://github.com/newville/asteval language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/astro-compiler/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/withastro/compiler.git RUN go install github.com/AdamKorcz/go-118-fuzz-build@latest COPY build.sh $SRC/ WORKDIR $SRC/compiler ================================================ FILE: projects/astro-compiler/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Fuzz internal/transform printf "package transform\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > $SRC/compiler/internal/transform/registerfuzzdep.go go mod tidy go get -u github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer $SRC/compiler/internal/transform FuzzScopeHTML fuzz_scope_html compile_native_go_fuzzer $SRC/compiler/internal/transform FuzzTransformScoping fuzz_transform_scoping ================================================ FILE: projects/astro-compiler/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/withastro/compiler" language: go main_repo: "https://github.com/withastro/compiler" primary_contact: "cable023@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "nate@astro.build" ================================================ FILE: projects/astroid/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --disable-pip-version-check --no-cache-dir pip==25.1.1 RUN git clone --depth=1 --no-tags https://github.com/pylint-dev/astroid COPY *.py *.sh "$SRC/" WORKDIR "$SRC/astroid" ================================================ FILE: projects/astroid/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done # Build a fuzz_parse seed corpus consisting of all the .py files from the astroid repo CORPUS_DIR="$WORK/corpus" mkdir -p "$CORPUS_DIR" FILES=$(find "$SRC/astroid" -type f -iname "*.py") for file in $FILES; do cp "$file" "$CORPUS_DIR/$(md5sum "$file" | cut -f 1 -d ' ').py" done zip -r "$OUT/fuzz_parse_seed_corpus.zip" "$CORPUS_DIR"/* ================================================ FILE: projects/astroid/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import astroid def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) code = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) try: astroid.builder.parse(code) except ( astroid.exceptions._NonDeducibleTypeHierarchy, astroid.modutils.NoSourceFile, astroid.exceptions.AstroidError, astroid.exceptions.UseInferenceDefault, RecursionError, ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/astroid/project.yaml ================================================ homepage: https://github.com/pylint-dev/astroid main_repo: https://github.com/pylint-dev/astroid language: python primary_contact: "jacobtylerwalls@gmail.com" auto_ccs: - "correctmost@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "david@adalogics.com" ================================================ FILE: projects/asttokens/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/gristlabs/asttokens asttokens COPY *.sh *py $SRC/ WORKDIR $SRC/asttokens ================================================ FILE: projects/asttokens/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/asttokens/fuzz_asttokens.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import asttokens, ast import atheris def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) source_to_parse = fdp.ConsumeUnicodeNoSurrogates(4196) try: ast.parse(source_to_parse) except: # Avoid anything that throws any issues in ast.parse. return try: atok = asttokens.ASTTokens(source_to_parse, parse=True) except SyntaxError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/asttokens/project.yaml ================================================ homepage: https://github.com/gristlabs/asttokens main_repo: https://github.com/gristlabs/asttokens language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/async-http-client/.gitignore ================================================ project-parent/async-http-client project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/async-http-client/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cat fuzzing/dictionaries/http.dict fuzzing/dictionaries/url.dict > $SRC/AsyncHttpClientFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/AsyncHttpClientFuzzer_seed_corpus.zip go-fuzz-corpus/httpreq/corpus/* && \ zip -uj $SRC/AsyncHttpClientFuzzer_seed_corpus.zip go-fuzz-corpus/http2/corpus/* && \ zip -uj $SRC/AsyncHttpClientFuzzer_seed_corpus.zip go-fuzz-corpus/url/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/async-http-client RUN apt update && apt install -y openjdk-11-jdk RUN git clone --depth 1 https://github.com/AsyncHttpClient/async-http-client/ $SRC/project-parent/async-http-client COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/async-http-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=async-http-client PROJECT_GROUP_ID=org.asynchttpclient PROJECT_ARTIFACT_ID=async-http-client MAIN_REPOSITORY=https://github.com/AsyncHttpClient/async-http-client/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -Denforcer.skip=true -DskipTests -Dgpg.skip" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT export JAVA_HOME="$OUT/open-jdk-11" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip --exclude 'lib/security/blacklisted.certs' "/usr/lib/jvm/java-11-openjdk-amd64/" "$JAVA_HOME" set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-11/\" \ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/async-http-client/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.asynchttpclient async-http-client Fuzzing-SNAPSHOT org.eclipse.jetty.toolchain jetty-jakarta-servlet-api 5.0.2 test org.eclipse.jetty jetty-server 11.0.14 test maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/async-http-client/project-parent/fuzz-targets/src/test/java/com/example/AsyncHttpClientFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.asynchttpclient.Response; import org.asynchttpclient.AsyncHttpClient; import org.asynchttpclient.util.HttpConstants; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.DefaultHttpHeaders; import io.netty.handler.codec.http.cookie.DefaultCookie; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import java.util.*; import java.io.IOException; import java.io.ByteArrayInputStream; import java.util.concurrent.ExecutionException; import static org.asynchttpclient.Dsl.*; class AsyncHttpClientFuzzer { static Server server; static int port1 = -1; static String [] methods = { HttpConstants.Methods.CONNECT, HttpConstants.Methods.DELETE, HttpConstants.Methods.GET, HttpConstants.Methods.HEAD, HttpConstants.Methods.OPTIONS, HttpConstants.Methods.PATCH, HttpConstants.Methods.POST, HttpConstants.Methods.PUT, HttpConstants.Methods.TRACE }; @BeforeAll static void setUp() { server = new Server(); ServerConnector connector1 = addHttpConnector(server); try { server.start(); } catch (Exception e) { return; } port1 = connector1.getLocalPort(); } @AfterAll static void cleanUp() { if (server != null) { try { server.stop(); } catch (Exception e) { } } } @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try (AsyncHttpClient client = asyncHttpClient()) { HttpHeaders httpHeaders = new DefaultHttpHeaders(); for (int i = 0; i < data.consumeInt(0, 50); ++i) { httpHeaders.add(data.consumeString(500), data.consumeString(500)); } Map> formParams = new HashMap<>(); for (int i = 0; i < data.consumeInt(0, 50); i++) { formParams.put(data.consumeString(500), Collections.singletonList(data.consumeString(500))); } Map> queryParams = new HashMap<>(); for (int i = 0; i < data.consumeInt(0, 50); i++) { queryParams.put(data.consumeString(500), Collections.singletonList(data.consumeString(500))); } Collection cookies = new ArrayList<>(); for (int i = 0; i < data.consumeInt(0, 50); i++) { io.netty.handler.codec.http.cookie.Cookie cookie = new DefaultCookie(data.consumeString(500), data.consumeString(500)); cookie.setDomain(data.consumeString(500)); cookie.setPath(data.consumeString(500)); cookie.setMaxAge(data.consumeInt()); cookie.setSecure(data.consumeBoolean()); cookie.setHttpOnly(data.consumeBoolean()); cookies.add(cookie); } Response resp = client.prepare(data.pickValue(methods), data.consumeString(500)) .setCookies(cookies) .setHeaders(httpHeaders) .setFormParams(formParams) .setQueryParams(queryParams) .setVirtualHost(data.consumeString(500)) .setBody(new ByteArrayInputStream(data.consumeRemainingAsBytes())) .execute() .get(); } catch (IOException | InterruptedException | ExecutionException | IllegalArgumentException | IllegalStateException e) { } } public static ServerConnector addHttpConnector(Server server) { ServerConnector connector = new ServerConnector(server); server.addConnector(connector); return connector; } } ================================================ FILE: projects/async-http-client/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom async-http-client fuzz-targets ================================================ FILE: projects/async-http-client/project.yaml ================================================ homepage: "https://github.com/AsyncHttpClient/async-http-client/" language: jvm primary_contact: "aayush@shieldblaze.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/AsyncHttpClient/async-http-client/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/atomic/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/uber-go/atomic WORKDIR $SRC/atomic COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/atomic/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./ go mod tidy printf "package atomic\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy compile_native_go_fuzzer go.uber.org/atomic FuzzTest FuzzTest ================================================ FILE: projects/atomic/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package atomic import ( "testing" ) func FuzzTest(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte, oldS, newS string) { s := &String{} s.UnmarshalText(data) s.MarshalText() s.CompareAndSwap(oldS, newS) s.Load() }) } ================================================ FILE: projects/atomic/project.yaml ================================================ homepage: "https://github.com/uber-go/atomic" language: go main_repo: "https://github.com/uber-go/atomic" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/attrs/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/python-attrs/attrs.git COPY *.sh *py $SRC/ WORKDIR $SRC/attrs ================================================ FILE: projects/attrs/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --hidden-import=html.parser done ================================================ FILE: projects/attrs/fuzz_attrs.py ================================================ #!/usr/bin/python3 # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris import attrs from string import ascii_letters def consumeIdentifier(fdp): return fdp.ConsumeUnicode(8) @atheris.instrument_func def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) clsname = consumeIdentifier(fdp) attrcount = fdp.ConsumeIntInRange(0, 12) attrnames = [consumeIdentifier(fdp) for _ in range(attrcount)] attrvalues = [None] * attrcount # Create class from attrs.make_class try: C0 = attrs.make_class(clsname, attrnames) except Exception as e: if any(not name.isidentifier() for name in [clsname] + attrnames): return raise c0 = C0(**{k: v for k, v in zip(attrnames, attrvalues)}) d0 = attrs.asdict(c0) c0_p = C0(**d0) assert c0 == c0_p # Create class from attrs.define C1 = attrs.define(type(clsname, (), {f: attrs.field() for f in attrnames})) c1 = C1(**{k: v for k, v in zip(attrnames, attrvalues)}) d1 = attrs.asdict(c1) c1_p = C1(**d1) assert c1 == c1_p def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/attrs/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://www.attrs.org language: python main_repo: https://github.com/python-attrs/attrs.git sanitizers: - address vendor_ccs: - sergesanspaille@free.fr ================================================ FILE: projects/augeas/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y libreadline-dev libselinux1-dev \ libxml2-dev make autoconf automake libtool pkg-config bison flex RUN git clone --depth 1 https://github.com/hercules-team/augeas WORKDIR augeas COPY run_tests.sh build.sh $SRC/ COPY augeas_escape_name_fuzzer.cc $SRC/ COPY augeas_fa_fuzzer.cc $SRC/ COPY augeas_api_fuzzer.cc $SRC/ ================================================ FILE: projects/augeas/augeas_api_fuzzer.cc ================================================ /* # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include "config.h" #include "augeas.h" #include "internal.h" #include "memory.h" #include "syntax.h" #include "transform.h" #include "errcode.h" #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if(size<3){ return 0; } char *loadpath = NULL; const char *value; const char *label; char *new_str = (char *)malloc(size+1); if (new_str == NULL){ return 0; } memcpy(new_str, data, size); new_str[size] = '\0'; struct augeas *aug = aug_init(new_str, loadpath, AUG_NO_STDINC|AUG_NO_LOAD); aug_defvar(aug, new_str, &new_str[1]); aug_get(aug, new_str, &value); aug_label(aug, new_str, &label); aug_rename(aug, new_str, &new_str[1]); aug_text_store(aug, &new_str[1], new_str, &new_str[2]); aug_print(aug, stdout, new_str); aug_setm(aug, new_str, NULL, &new_str[1]); free(new_str); aug_close(aug); return 0; } ================================================ FILE: projects/augeas/augeas_escape_name_fuzzer.cc ================================================ /* # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include int escape_match(const uint8_t *data, size_t size){ augeas *aug = aug_init(NULL, NULL, AUG_NONE); std::string data_string(reinterpret_cast(data), size); char *out = NULL; aug_escape_name(aug, data_string.c_str(), &out); if (out != NULL){ aug_match(aug, out, NULL); } else{ aug_match(aug, data_string.c_str(), NULL); } aug_close(aug); free(out); return 0; } // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { escape_match(Data, Size); return 0; } ================================================ FILE: projects/augeas/augeas_fa_fuzzer.cc ================================================ /* # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include // Augea includes #include "augeas.h" #include "config.h" #include "fa.h" #include "internal.h" /* * FA fuzzer. */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size){ if(Size<3){ return 0; } char *new_str = (char *)malloc(Size+1); if (new_str == NULL){ return 0; } memcpy(new_str, Data, Size); new_str[Size] = '\0'; int intSize = (int)Size; char *s; size_t len; int r = fa_expand_nocase(new_str, intSize, &s, &len); struct fa *fa2 = NULL; int r2 = fa_compile(new_str, intSize, &fa2); struct fa *fa1 = NULL; fa_compile(&new_str[1], intSize, &fa1); struct fa *fa_min; fa_min = fa_minus(fa1, fa2); if (fa2 != NULL) { char* word = NULL; size_t word_len = 0; fa_example(fa2, &word, &word_len); if(word != NULL) free(word); fa_json(stdout, fa2); fa_minimize(fa2); fa_dot(stdout, fa2); } struct fa *fa_b = fa_make_basic(intSize); // cleanup if (s != NULL) free(s); if (new_str != NULL) free(new_str); if (fa_b != NULL) fa_free(fa_b); if (fa_min != NULL) fa_free(fa_min); if (fa1 != NULL) fa_free(fa1); if (fa2 != NULL) fa_free(fa2); return 0; } ================================================ FILE: projects/augeas/build.sh ================================================ #!/bin/bash -eu # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./autogen.sh ./configure --enable-static --disable-shared --without-selinux make -j$(nproc) # Add extern "C" guards for C++ compilation using awk # This handles both the opening and closing guards awk ' /#define FA_H_/ { print print "" print "#ifdef __cplusplus" print "extern \"C\" {" print "#endif" print "" next } /^#endif$/ && !done { print "" print "#ifdef __cplusplus" print "}" print "#endif" print "" done = 1 } { print } ' src/fa.h > src/fa.h.tmp && mv src/fa.h.tmp src/fa.h ASAN_OPTIONS=detect_leaks=0 cp $SRC/augeas_escape_name_fuzzer.cc . cp $SRC/augeas_fa_fuzzer.cc . cp $SRC/augeas_api_fuzzer.cc . for fuzzer in augeas_api_fuzzer augeas_escape_name_fuzzer augeas_fa_fuzzer; do $CXX $CXXFLAGS -std=c++11 -Isrc/ `xml2-config --cflags` \ $fuzzer.cc -o $OUT/$fuzzer $LIB_FUZZING_ENGINE \ src/.libs/libaugeas.a src/.libs/libfa.a ./gnulib/lib/.libs/libgnu.a \ /usr/lib/x86_64-linux-gnu/libxml2.a done ================================================ FILE: projects/augeas/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: https://github.com/hercules-team/augeas language: c++ primary_contact: lutter@watzmann.net auto_ccs: - hhan@redhat.com - adam@adalogics.com sanitizers: - address - undefined main_repo: 'https://github.com/hercules-team/augeas' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/augeas/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable leak sanitizer/null return check and run unit testing export ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1" make check -j$(nproc) -C $SRC/augeas/tests ================================================ FILE: projects/autoflake/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://www.github.com/PyCQA/autoflake autoflake COPY *.sh *py $SRC/ WORKDIR $SRC/autoflake ================================================ FILE: projects/autoflake/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/autoflake/fuzz_fix_code.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import autoflake def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) source_code = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) autoflake.fix_code(source_code) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/autoflake/project.yaml ================================================ homepage: https://www.github.com/PyCQA/autoflake main_repo: https://www.github.com/PyCQA/autoflake language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/autopep8/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/hhatto/autopep8 autopep8 COPY *.sh *py $SRC/ WORKDIR $SRC/autopep8 ================================================ FILE: projects/autopep8/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/autopep8/fuzz_fix_file.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-3 # Imports by the generated code import autopep8 def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) fuzz_file = '/tmp/random_file.txt' with open(fuzz_file, 'wb') as f: f.write(fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 4096))) autopep8.fix_file(fuzz_file) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/autopep8/project.yaml ================================================ homepage: https://github.com/hhatto/autopep8 main_repo: https://github.com/hhatto/autopep8 language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/avahi/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN git clone --depth 1 https://github.com/avahi/avahi WORKDIR avahi COPY build.sh $SRC/ ================================================ FILE: projects/avahi/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ fuzz/oss-fuzz.sh ================================================ FILE: projects/avahi/project.yaml ================================================ homepage: "https://avahi.org/" language: c++ primary_contact: trent@lloyd.id.au auto_ccs: - alex.gaynor@gmail.com - evverx@gmail.com - msekleta@redhat.com - pemensik@redhat.com sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/avahi/avahi' fuzzing_engines: - afl - honggfuzz - libfuzzer file_github_issue: True builds_per_day: 4 base_os_version: ubuntu-24-04 ================================================ FILE: projects/avro/.gitignore ================================================ project-parent/avro project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/avro/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.2/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/avro RUN git clone --depth 1 https://github.com/apache/avro/ $SRC/project-parent/avro COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/avro/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=avro PROJECT_GROUP_ID=org.apache.avro PROJECT_ARTIFACT_ID=avro MAIN_REPOSITORY=https://github.com/apache/avro/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets FUZZ_TARGET_DEPENDENCIES=":avro :avro-mapred" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/avro/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.avro avro Fuzzing-SNAPSHOT test org.apache.avro avro-mapred Fuzzing-SNAPSHOT test org.apache.hadoop hadoop-client 3.3.5 maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/avro/project-parent/fuzz-targets/src/test/java/com/example/AvroSerializationFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.avro.Schema; import org.apache.avro.mapred.AvroKey; import org.apache.avro.mapred.AvroValue; import org.apache.avro.mapreduce.AvroJob; import org.apache.avro.mapred.AvroWrapper; import org.apache.avro.generic.GenericData; import org.apache.avro.AvroRuntimeException; import org.apache.avro.hadoop.io.AvroSerialization; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.util.ReflectionUtils; import org.apache.hadoop.io.serializer.Serializer; import org.apache.hadoop.io.serializer.Deserializer; import org.junit.jupiter.api.BeforeAll; import java.io.IOException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; class AvroSerializationFuzzer { static Job job = null; Class [] classes = {AvroKey.class, AvroValue.class}; @BeforeAll static void setUp(){ try { job = new Job(new Configuration()); } catch (IOException e) { } } @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { int opt = 7; int num = data.consumeInt(0, 2^opt - 1); for (int bit = 0; bit < opt; ++bit) { if (((num >> bit) & 1) == 1) { switch (bit) { case 0: AvroJob.setMapOutputKeySchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 1: AvroJob.setMapOutputValueSchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 2: AvroJob.setInputKeySchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 3: AvroJob.setInputValueSchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 4: AvroJob.setOutputKeySchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 5: AvroJob.setOutputValueSchema(job, data.pickValue(new Schema[]{Schema.create(data.pickValue(Schema.Type.values())), new Schema.Parser().parse(data.consumeString(1000))})); break; case 6: AvroJob.setDataModelClass(job, GenericData.class); break; } } } AvroSerialization serialization = ReflectionUtils.newInstance(AvroSerialization.class, job.getConfiguration()); Serializer serializer = serialization.getSerializer(data.pickValue(classes)); Deserializer deserializer = serialization.getDeserializer(data.pickValue(classes)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); serializer.open(baos); serializer.serialize(data.consumeBytes(1000)); serializer.close(); ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); deserializer.open(bais); AvroWrapper result = null; deserializer.deserialize(result); deserializer.close(); } catch (IOException e) { } catch (AvroRuntimeException | UnsupportedOperationException | ClassCastException | IllegalArgumentException | NullPointerException e) { // Need to catch to find more interesting findings. } } } ================================================ FILE: projects/avro/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom avro fuzz-targets ================================================ FILE: projects/avro/project.yaml ================================================ homepage: "https://avro.apache.org/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/avro" sanitizers: - address primary_contact: "martin.grigorov@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/azure-sdk-for-python/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/azure/azure-sdk-for-python azure-sdk-for-python COPY *.sh *py $SRC/ WORKDIR $SRC/azure-sdk-for-python ================================================ FILE: projects/azure-sdk-for-python/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/azure-sdk-for-python/sdk/core/azure-core pip3 install . cd $SRC/azure-sdk-for-python/sdk/dynatrace/azure-mgmt-dynatrace/ pip3 install . compile_python_fuzzer $SRC/fuzz_mgmt_serialization.py ================================================ FILE: projects/azure-sdk-for-python/fuzz_mgmt_serialization.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import json import atheris from azure.mgmt.dynatrace import _serialization from azure.mgmt.dynatrace.models import _models_py3 from azure.core.exceptions import ( DeserializationError, SerializationError ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: payload = json.loads(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024))) except: return model = _models_py3.AccountInfo() # Overwrite the types, this is easier than creating a new class. model._attribute_map = payload try: serialized_data = model.serialize() serialized = True except SerializationError: serialized = False deserializer = _serialization.Deserializer() if serialized: # Anything serialized should be unserializable deserializer._deserialize(model, serialized_data) else: # Otherwise we deserialize random data and catch exceptions try: deserializer._deserialize( model, fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)) ) except DeserializationError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/azure-sdk-for-python/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/azure/azure-sdk-for-python language: python main_repo: https://github.com/azure/azure-sdk-for-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/babel/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip && pip3 install cython RUN git clone https://github.com/python-babel/babel babel COPY *.sh *py $SRC/ WORKDIR $SRC/babel ================================================ FILE: projects/babel/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/babel/fuzz_lexer.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from babel.messages.jslexer import tokenize import babel def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: l1 = list(tokenize(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize))) except ( babel.messages.pofile.PoFileError, babel.core.UnknownLocaleError, babel.messages.catalog.TranslationError, babel.numbers.UnknownCurrencyError, babel.plural.RuleError ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/babel/fuzz_profile.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from babel.messages.pofile import read_po import babel def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: read_po(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except ( babel.messages.pofile.PoFileError, babel.core.UnknownLocaleError, babel.messages.catalog.TranslationError, babel.plural.RuleError ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/babel/project.yaml ================================================ homepage: https://github.com/python-babel/babel main_repo: https://github.com/python-babel/babel language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/bad_example/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool # Using a real zlib project, but with broken build script and/or fuzz target. RUN git clone --depth 1 https://github.com/madler/zlib.git WORKDIR zlib COPY build.sh bad_example_fuzzer.cc $SRC/ ================================================ FILE: projects/bad_example/bad_example_fuzzer.cc ================================================ // Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "zlib.h" static Bytef buffer[256 * 1024] = { 0 }; #ifdef INTENTIONAL_STARTUP_CRASH void bad_term_handler(int signum) { _exit(0); } #endif // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { #ifdef INTENTIONAL_STARTUP_CRASH // Simulates the worst case, fuzz target silently dies without any error. struct sigaction action = { 0 }; action.sa_handler = bad_term_handler; sigaction(SIGTERM, &action, NULL); // Cannot call _exit(0) directly, as it's even worse -- sancov does not print // any coverage information in that case. kill(getpid(), SIGTERM); #endif uLongf buffer_length = static_cast(sizeof(buffer)); if (Z_OK != uncompress(buffer, &buffer_length, data, static_cast(size))) { return 0; } return 0; } ================================================ FILE: projects/bad_example/build.sh ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #!/bin/bash -eu # Testcase 1. Valid fuzzer build. ################################################################################ ./configure make -j$(nproc) clean make -j$(nproc) all $CXX $CXXFLAGS -std=c++11 -I. \ $SRC/bad_example_fuzzer.cc -o $OUT/bad_example_valid_build \ $LIB_FUZZING_ENGINE ./libz.a # Testcase 2. Silent startup crash. ################################################################################ ./configure make -j$(nproc) clean make -j$(nproc) all $CXX $CXXFLAGS -std=c++11 -I. -DINTENTIONAL_STARTUP_CRASH \ $SRC/bad_example_fuzzer.cc -o $OUT/bad_example_startup_crash \ $LIB_FUZZING_ENGINE ./libz.a # The latest two examples won't work for coverage or introspector, bail out. if [[ $SANITIZER = *coverage* || $SANITIZER = *introspector* ]]; then exit 0 fi # Testcase 3. Partially ignore the flags provided by OSS-Fuzz. ################################################################################ export CFLAGS_ORIG="$CFLAGS" export CFLAGS="-O1" export CXXFLAGS_ORIG="$CXXFLAGS" export CXXFLAGS="-O1 -stdlib=libc++" # We need to pass static as zlib fails to build shared lib in OSS-Fuzz env. ./configure --static make -j$(nproc) clean make -j$(nproc) all $CXX -fsanitize=$SANITIZER $CXXFLAGS_ORIG -std=c++11 -I. \ $SRC/bad_example_fuzzer.cc -o $OUT/bad_example_partial_instrumentation \ $LIB_FUZZING_ENGINE ./libz.a # Testcase 4. Completely ignore the flags provided by OSS-Fuzz. ################################################################################ # We need to pass static as zlib fails to build shared lib in OSS-Fuzz env. ./configure --static make -j$(nproc) clean make -j$(nproc) all $CXX -fsanitize=$SANITIZER $CXXFLAGS -std=c++11 -I. \ $SRC/bad_example_fuzzer.cc -o $OUT/bad_example_no_instrumentation \ $LIB_FUZZING_ENGINE ./libz.a # Testcase 5. Enable multiple sanitizers. ################################################################################ # Add UBSan to ASan or MSan build. Add ASan to UBSan build. EXTRA_SANITIZER="undefined" if [[ $SANITIZER = *undefined* ]]; then EXTRA_SANITIZER="address" fi export CFLAGS="$CFLAGS_ORIG -fsanitize=$EXTRA_SANITIZER" export CXXFLAGS="$CXXFLAGS_ORIG -fsanitize=$EXTRA_SANITIZER" ./configure make -j$(nproc) clean make -j$(nproc) all $CXX $CXXFLAGS -std=c++11 -I. \ $SRC/bad_example_fuzzer.cc -o $OUT/bad_example_mixed_sanitizers \ $LIB_FUZZING_ENGINE ./libz.a ================================================ FILE: projects/bad_example/project.yaml ================================================ base_os_version: ubuntu-24-04 disabled: true homepage: http://www.zlib.net/ language: c++ main_repo: https://github.com/madler/zlib sanitizers: - address - memory - undefined vendor_ccs: [] fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/bazel-rules-fuzzing-test/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y python-is-python3 RUN git clone https://github.com/bazelbuild/rules_fuzzing.git WORKDIR $SRC/rules_fuzzing/ COPY build.sh $SRC/ ================================================ FILE: projects/bazel-rules-fuzzing-test/build.sh ================================================ #!/bin/bash -eu # # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Work around https://github.com/bazelbuild/bazel/issues/21592: # The `layering_check` feature does not work with `--spawn_strategy=standalone`, # which is the default for OSS-Fuzz builds. export BAZEL_EXTRA_BUILD_FLAGS="--spawn_strategy=sandboxed" bazel_build_fuzz_tests ================================================ FILE: projects/bazel-rules-fuzzing-test/project.yaml ================================================ homepage: "https://github.com/bazelbuild/rules_fuzzing" main_repo: "https://github.com/bazelbuild/rules_fuzzing" language: c++ primary_contact: "test@example.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory # This is a test project. disabled: true ================================================ FILE: projects/bazel-rules-fuzzing-test-java/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && \ apt-get install -y python-is-python3 RUN git clone https://github.com/bazelbuild/rules_fuzzing.git WORKDIR $SRC/rules_fuzzing/ COPY build.sh $SRC/ ================================================ FILE: projects/bazel-rules-fuzzing-test-java/build.sh ================================================ #!/bin/bash -eu # # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Work around https://github.com/bazelbuild/bazel/issues/21592: # The `layering_check` feature does not work with `--spawn_strategy=standalone`, # which is the default for OSS-Fuzz builds. export BAZEL_EXTRA_BUILD_FLAGS="--spawn_strategy=sandboxed" bazel_build_fuzz_tests ================================================ FILE: projects/bazel-rules-fuzzing-test-java/project.yaml ================================================ homepage: "https://github.com/bazelbuild/rules_fuzzing" main_repo: "https://github.com/bazelbuild/rules_fuzzing" language: jvm primary_contact: "test@example.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined # This is a test project. disabled: true ================================================ FILE: projects/bc-gh/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make RUN git clone --depth 1 https://github.com/gavinhoward/bc.git bc-gh WORKDIR bc-gh COPY build.sh $SRC/ ================================================ FILE: projects/bc-gh/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./configure -Z make -j$(nproc) all cp bin/*_fuzzer_* $OUT/ ================================================ FILE: projects/bc-gh/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: https://git.gavinhoward.com/gavin/bc main_repo: https://github.com/gavinhoward/bc language: c primary_contact: gavin.d.howard@gmail.com fuzzing_engines: - libfuzzer - afl - honggfuzz - centipede disabled: true ================================================ FILE: projects/bc-java/CMSEnvelopedDataParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.bouncycastle.cms.CMSEnvelopedDataParser; import org.bouncycastle.cms.CMSEnvelopedDataGenerator; import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; import org.bouncycastle.cms.test.CMSTestUtil; import org.bouncycastle.cms.CMSAlgorithm; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSProcessableByteArray; import org.bouncycastle.cms.CMSEnvelopedData; import org.bouncycastle.operator.OperatorCreationException; import java.io.IOException; import java.security.cert.X509Certificate; import java.security.KeyPair; import java.security.GeneralSecurityException; import java.security.cert.CertificateEncodingException; public class CMSEnvelopedDataParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { X509Certificate _reciCert; String _signDN = "O=Bouncy Castle, C=AU"; KeyPair _signKP = CMSTestUtil.makeKeyPair(); String _reciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU"; KeyPair _reciKP = CMSTestUtil.makeKeyPair(); try{ _reciCert = CMSTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN); } catch(GeneralSecurityException | IOException | OperatorCreationException e){ return; } try{ CMSTypedData msg = new CMSProcessableByteArray(data.consumeRemainingAsBytes()); CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator(); try{ edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(_reciCert).setProvider("BC")) ; } catch(CertificateEncodingException e){ return; } CMSEnvelopedData ed = edGen.generate( msg, new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC) .setProvider("BC").build()); CMSEnvelopedDataParser cedp = new CMSEnvelopedDataParser(ed.getEncoded()); cedp.getEncryptionAlgParams(); } catch (CMSException | IOException e){ return; } } } ================================================ FILE: projects/bc-java/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN wget https://services.gradle.org/distributions/gradle-8.10-bin.zip -O gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE=$SRC/gradle/gradle-8.10/bin/gradle RUN git clone --depth 1 https://github.com/bcgit/bc-java.git bc-java COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/bc-java ================================================ FILE: projects/bc-java/EncodingFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.bouncycastle.util.encoders.Base64; import org.bouncycastle.util.encoders.Hex; import java.lang.StringBuffer; import java.util.Arrays; public class EncodingFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { byte[] originalInput = data.consumeRemainingAsBytes(); byte[] encodedB64 = Base64.encode(originalInput); byte[] decodedB64 = Base64.decode(encodedB64); if(!Arrays.equals(originalInput, decodedB64)){ throw new IllegalStateException("Base64 encoding / decoding failure\n" + "Original input: " + encodeHexString(originalInput) + "\n" + "Encoded data: " + encodeHexString(encodedB64) + "\n" + "Decoded data: " + encodeHexString(decodedB64) + "\n"); } byte[] encodedHex = Hex.encode(originalInput); byte[] decodedHex = Hex.decode(encodedHex); if(!Arrays.equals(originalInput, decodedHex)){ throw new IllegalStateException("Hex encoding / decoding failure\n" + "Original input: " + encodeHexString(originalInput) + "\n" + "Encoded data: " + encodeHexString(encodedHex) + "\n" + "Decoded data: " + encodeHexString(decodedHex) + "\n"); } } // These two methods were taken from: https://www.baeldung.com/java-byte-arrays-hex-strings private static String encodeHexString(byte[] byteArray) { StringBuffer hexStringBuffer = new StringBuffer(); for (int i = 0; i < byteArray.length; i++) { hexStringBuffer.append(byteToHex(byteArray[i])); } return hexStringBuffer.toString(); } private static String byteToHex(byte num) { char[] hexDigits = new char[2]; hexDigits[0] = Character.forDigit((num >> 4) & 0xF, 16); hexDigits[1] = Character.forDigit((num & 0xF), 16); return new String(hexDigits); } } ================================================ FILE: projects/bc-java/PEMParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.Reader; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.ByteArrayInputStream; import org.bouncycastle.openssl.PEMParser; import java.io.IOException; import org.bouncycastle.util.encoders.DecoderException; public class PEMParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); Reader reader = new BufferedReader(new InputStreamReader(bais)); PEMParser pemparser = new PEMParser(reader); try{ while (pemparser.readObject() != null){ //empty body } } catch(IOException | DecoderException e){ return; } } } ================================================ FILE: projects/bc-java/X509CertPairParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.IOException; import org.bouncycastle.x509.util.StreamParsingException; import org.bouncycastle.jce.provider.X509CertPairParser; import java.io.ByteArrayInputStream; public class X509CertPairParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { X509CertPairParser xcpp = new X509CertPairParser(); xcpp.engineInit(new ByteArrayInputStream(data.consumeRemainingAsBytes())); try{ xcpp.engineRead(); } catch (StreamParsingException e){ return; } } } ================================================ FILE: projects/bc-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Set encoding to UTF-8 for Java compilation export JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8" # Disable ErrorProne by removing it from annotation processor path # ErrorProne requires Java 21+ but the base image has Java 17 cat > /tmp/disable-errorprone.gradle << 'EOF' allprojects { afterEvaluate { tasks.withType(JavaCompile).configureEach { options.errorprone.enabled = false options.compilerArgs.removeAll { it.startsWith('-Xplugin:ErrorProne') } } // Remove errorprone from annotation processor configuration configurations.matching { it.name.toLowerCase().contains('errorprone') }.all { dependencies.clear() } } } EOF # Build only Java 8/11/15/17 compatible versions, skip Java 25 tasks $GRADLE jar -x compileJava25Java -x java25Classes --init-script /tmp/disable-errorprone.gradle find . -name "core*.jar" -exec cp {} $OUT/core.jar \; find . -name "bcpkix*.jar" -exec cp {} $OUT/bcpkix.jar \; find . -name "bcutil*.jar" -exec cp {} $OUT/bcutil.jar \; find . -name "bcprov*.jar" -exec cp {} $OUT/bcprov.jar \; ALL_JARS="core.jar bcpkix.jar bcutil.jar bcprov.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH:/src/bc-java/pkix/src/test/java/ # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -encoding UTF-8 -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --keep_going=20 \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done mkdir -p $OUT/org/bouncycastle/cms/test cp -r /src/bc-java/pkix/src/test/java/org $OUT ================================================ FILE: projects/bc-java/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.bouncycastle.org/" language: jvm primary_contact: "" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/bcgit/bc-java.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" ================================================ FILE: projects/bearssl/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool wget python RUN git clone --depth 1 https://www.bearssl.org/git/BearSSL RUN git clone --depth 1 --branch 3.10.0 https://github.com/randombit/botan.git RUN git clone --depth 1 https://github.com/MozillaSecurity/cryptofuzz RUN wget https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 COPY build.sh $SRC/ ================================================ FILE: projects/bearssl/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Not using OpenSSL export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -Wno-deprecated-literal-operator" # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ # Generate lookup tables. This only needs to be done once. cd $SRC/cryptofuzz python gen_repository.py # Only test primitives which BearSSL supports rm extra_options.h echo -n '"' >>extra_options.h echo -n '--force-module=BearSSL ' >>extra_options.h echo -n '--digests=MD5,SHA1,SHA224,SHA256,SHA384,SHA512,MD5_SHA1,SHAKE128,SHAKE256 ' >>extra_options.h echo -n '--ciphers=AES_128_GCM,AES_192_GCM,AES_256_GCM,AES_128_CCM,AES_192_CCM,AES_256_CCM,CHACHA20,CHACHA20_POLY1305 ' >>extra_options.h echo -n '--operations=Digest,HMAC,SymmetricEncrypt,SymmetricDecrypt,KDF_HKDF,KDF_TLS1_PRF,ECC_GenerateKeyPair,ECC_PrivateToPublic,ECDSA_Verify,ECDSA_Sign' >>extra_options.h echo -n '"' >>extra_options.h # Compile BearSSL cd $SRC/BearSSL/ sed -i '/^CC = /d' conf/Unix.mk sed -i '/^CFLAGS = /d' conf/Unix.mk make -j$(nproc) lib export BEARSSL_INCLUDE_PATH=$(realpath inc/) export LIBBEARSSL_A_PATH=$(realpath ./build/libbearssl.a) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BEARSSL" # Compile Cryptofuzz BearSSL module cd $SRC/cryptofuzz/modules/bearssl make -B # Compile Botan cd $SRC/botan if [[ $CFLAGS != *-m32* ]] then if [[ $CFLAGS != *sanitize=memory* ]] then ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation else ./configure.py --disable-asm --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation fi else ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN" export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a" export BOTAN_INCLUDE_PATH="$SRC/botan/build/include" # Compile Cryptofuzz Botan module cd $SRC/cryptofuzz/modules/botan make -B # Compile Cryptofuzz cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make -B -j$(nproc) >/dev/null # Generate dictionary ./generate_dict # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-bearssl # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-bearssl.dict ================================================ FILE: projects/bearssl/project.yaml ================================================ homepage: "https://bearssl.org/" language: c++ primary_contact: "guidovranken@gmail.com" main_repo: "https://www.bearssl.org/git/BearSSL" auto_ccs: - "pornin@gmail.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 ================================================ FILE: projects/behaviortreecpp/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool cmake pkg-config wget libsodium-dev libgtest-dev RUN git clone --depth 1 https://github.com/BehaviorTree/BehaviorTree.CPP.git behaviortreecpp WORKDIR behaviortreecpp COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/behaviortreecpp/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="${CXXFLAGS} -std=c++17 -stdlib=libstdc++" # ===== BUILD Sqlite ===== SQLITE_VER=sqlite-autoconf-3480000 wget https://www.sqlite.org/2025/${SQLITE_VER}.tar.gz tar xzf ${SQLITE_VER}.tar.gz cd ${SQLITE_VER} ./configure --enable-static --disable-shared make -j"$(nproc)" make install cd .. # ===== BUILD zeroMQ ===== git clone https://github.com/zeromq/libzmq.git cd libzmq mkdir build && cd build cmake .. -DBUILD_SHARED=OFF -DBUILD_STATIC=ON -DZMQ_BUILD_TESTS=OFF make -j"$(nproc)" make install cd ../.. # ===== Build BehaviorTree.CPP ===== mkdir build && cd build CMAKE_FLAGS=( "-DCMAKE_BUILD_TYPE=Release" "-DENABLE_FUZZING=ON" "-DFORCE_STATIC_LINKING=ON" ) cmake .. "${CMAKE_FLAGS[@]}" make -j"$(nproc)" for fuzzer in bt_fuzzer script_fuzzer bb_fuzzer; do cp $fuzzer "$OUT/" if [ -d ../fuzzing/corpus/${fuzzer} ]; then zip -j "$OUT/${fuzzer}_seed_corpus.zip" ../fuzzing/corpus/${fuzzer}/* fi done ================================================ FILE: projects/behaviortreecpp/project.yaml ================================================ homepage: "https://www.behaviortree.dev/" language: c++ primary_contact: "christopher.krah@tii.ae" main_repo: "https://github.com/BehaviorTree/BehaviorTree.CPP" file_github_issue: true vendor_ccs: - "dfaconti@aurynrobotics.com" fuzzing_engines: - libfuzzer - afl sanitizers: - address - undefined ================================================ FILE: projects/behaviortreecpp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build ================================================ FILE: projects/bignum-fuzzer/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e # ! Project pinned after a clang update and an afl link error. Log: https://oss-fuzz-gcb-logs.storage.googleapis.com/log-6083635a-3f72-444d-80ef-3a0a26670cf7.txt RUN apt-get update && apt-get install -y software-properties-common curl sudo mercurial autoconf bison texinfo libboost-all-dev cmake wget lzip RUN wget https://go.dev/dl/go1.17.5.linux-amd64.tar.gz && rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.5.linux-amd64.tar.gz && ldconfig ENV PATH=$PATH:/usr/local/go/bin RUN apt-get update && apt-get install -y \ python-all-dev \ python3-all-dev \ python3-pip # mbedtls needs jsonschema which needs rpds-py which needs pip>=20 # or a Rust toolchain. RUN pip3 install 'pip>=20' RUN git clone --depth 1 --recurse-submodules -b mbedtls-3.6 https://github.com/Mbed-TLS/mbedtls # Install Python packages from PyPI RUN pip3 install -r $SRC/mbedtls/scripts/basic.requirements.txt RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-4.0.0.tar.gz RUN git clone --depth 1 https://github.com/guidovranken/bignum-fuzzer RUN git clone --depth 1 https://github.com/openssl/openssl RUN git clone https://boringssl.googlesource.com/boringssl RUN hg clone https://gmplib.org/repo/gmp/ libgmp/ || \ (wget 'https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.lz' && tar xf gmp-6.2.1.tar.lz && mv $SRC/gmp-6.2.1/ $SRC/libgmp/) COPY build.sh $SRC/ ================================================ FILE: projects/bignum-fuzzer/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install Rust nightly #curl https://sh.rustup.rs -sSf | sh -s -- -y #source $HOME/.cargo/env # Build libmpdec tar zxf mpdecimal-4.0.0.tar.gz cd mpdecimal-4.0.0 ./configure && make -j$(nproc) cd $SRC/openssl if [[ $CFLAGS = *sanitize=memory* ]] then CFLAGS+=" -DOPENSSL_NO_ASM=1" fi ./config --debug no-fips no-shared no-tests make -j$(nproc) # Build libgmp cd $SRC/libgmp autoreconf -ivf ./configure --enable-maintainer-mode make -j$(nproc) # Build OpenSSL module cd $SRC/bignum-fuzzer/modules/openssl OPENSSL_INCLUDE_PATH=$SRC/openssl/include OPENSSL_LIBCRYPTO_A_PATH=$SRC/openssl/libcrypto.a make # Build Go module cd $SRC/bignum-fuzzer/modules/go make # Build Rust module #cd $SRC/bignum-fuzzer/modules/rust #make # Build C++-Boost module cd $SRC/bignum-fuzzer/modules/cpp_boost make # Build libgmp module cd $SRC/bignum-fuzzer/modules/libgmp LIBGMP_INCLUDE_PATH=$SRC/libgmp LIBGMP_A_PATH=$SRC/libgmp/.libs/libgmp.a make # Build libmpdec module cd $SRC/bignum-fuzzer/modules/libmpdec LIBMPDEC_A_PATH=$SRC/mpdecimal-4.0.0/libmpdec/libmpdec.a LIBMPDEC_INCLUDE_PATH=$SRC/mpdecimal-4.0.0/libmpdec make BASE_CXXFLAGS=$CXXFLAGS # Build OpenSSL/Go fuzzer cd $SRC/bignum-fuzzer ./config-modules.sh openssl go CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NO_NEGATIVE=1 -DBNFUZZ_FLAG_NUM_LEN=1200 -DBNFUZZ_FLAG_ALL_OPERATIONS=1" LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy OpenSSL/Go fuzzer to the designated location cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_openssl_go_no_negative_num_len_1200_all_operations # Build OpenSSL/Rust fuzzer #cd $SRC/bignum-fuzzer #make clean #./config-modules.sh openssl rust #CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NUM_LEN=1200 -DBNFUZZ_FLAG_ALL_OPERATIONS=1 -DBNFUZZ_FLAG_NUM_LOOPS=1" #LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy OpenSSL/Rust fuzzer to the designated location #cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_openssl_rust_num_len_1200_all_operations_num_loops_1 # Build OpenSSL/C++-Boost fuzzer cd $SRC/bignum-fuzzer make clean ./config-modules.sh openssl cpp_boost CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NUM_LEN=1200 -DBNFUZZ_FLAG_ALL_OPERATIONS=1 -DBNFUZZ_FLAG_NUM_LOOPS=1" LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy OpenSSL/C++-Boost fuzzer to the designated location cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_openssl_cpp_boost_num_len_1200_all_operations_num_loops_1 # Build OpenSSL/libgmp fuzzer cd $SRC/bignum-fuzzer make clean ./config-modules.sh openssl libgmp CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NUM_LEN=1200 -DBNFUZZ_FLAG_ALL_OPERATIONS=1 -DBNFUZZ_FLAG_NUM_LOOPS=1" LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy OpenSSL/libgmp fuzzer to the designated location cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_openssl_libgmp_num_len_1200_all_operations_num_loops_1 # Build mbedtls cd $SRC/mbedtls make lib -j$(nproc) # Build BoringSSL cd $SRC/boringssl mkdir build cd build cmake -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_C_FLAGS="$CFLAGS" -DBORINGSSL_ALLOW_CXX_RUNTIME=1 .. make -j$(nproc) # Build BoringSSL module cd $SRC/bignum-fuzzer/modules/openssl make clean CFLAGS="$CFLAGS -DBIGNUM_FUZZER_BORINGSSL" OPENSSL_INCLUDE_PATH=$SRC/boringssl/include OPENSSL_LIBCRYPTO_A_PATH=$SRC/boringssl/build/crypto/libcrypto.a make # Build mbedtls module cd $SRC/bignum-fuzzer/modules/mbedtls MBEDTLS_LIBMBEDCRYPTO_A_PATH=$SRC/mbedtls/library/libmbedcrypto.a MBEDTLS_INCLUDE_PATH=$SRC/mbedtls/include make # Build BoringSSL/mbedtls fuzzer cd $SRC/bignum-fuzzer make clean ./config-modules.sh boringssl mbedtls CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NUM_LEN=100 -DBNFUZZ_FLAG_ALL_OPERATIONS=1 -DBNFUZZ_FLAG_NUM_LOOPS=1" LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy BoringSSL/mbedtls fuzzer to the designated location cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_boringssl_mbedtls_num_len_100_all_operations_num_loops_1 # Build BoringSSL/libmpdec fuzzer cd $SRC/bignum-fuzzer make clean ./config-modules.sh boringssl libmpdec CXXFLAGS="$BASE_CXXFLAGS -DBNFUZZ_FLAG_NUM_LEN=100 -DBNFUZZ_FLAG_ALL_OPERATIONS=1 -DBNFUZZ_FLAG_NUM_LOOPS=1" LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make # Copy BoringSSL/libmpdec fuzzer to the designated location cp $SRC/bignum-fuzzer/fuzzer $OUT/fuzzer_boringssl_libmpdec_num_len_100_all_operations_num_loops_1 # Copy seed corpora to the designated location cp $SRC/bignum-fuzzer/corpora/fuzzer_openssl_go_no_negative_num_len_1200_all_operations_seed_corpus.zip $OUT #cp $SRC/bignum-fuzzer/corpora/fuzzer_openssl_rust_num_len_1200_all_operations_num_loops_1_seed_corpus.zip $OUT cp $SRC/bignum-fuzzer/corpora/fuzzer_openssl_cpp_boost_num_len_1200_all_operations_num_loops_1_seed_corpus.zip $OUT cp $SRC/bignum-fuzzer/corpora/fuzzer_openssl_libgmp_num_len_1200_all_operations_num_loops_1_seed_corpus.zip $OUT cp $SRC/bignum-fuzzer/corpora/fuzzer_boringssl_mbedtls_num_len_100_all_operations_num_loops_1_seed_corpus.zip $OUT cp $SRC/bignum-fuzzer/corpora/fuzzer_boringssl_mbedtls_num_len_100_all_operations_num_loops_1_seed_corpus.zip $OUT/fuzzer_boringssl_libmpdec_num_len_100_all_operations_num_loops_1_seed_corpus.zip ================================================ FILE: projects/bignum-fuzzer/project.yaml ================================================ homepage: "https://github.com/guidovranken/bignum-fuzzer" language: c++ primary_contact: "guidovranken@gmail.com" auto_ccs: - "martin.swende@ethereum.org" - "cdetrio@ethereum.org" - "openssl-security@openssl.org" - "kurt@roeckx.be" - "caswell.matt@googlemail.com" - "jz.maddock@gmail.com" - "jz.maddock@googlemail.com" - "agl@google.com" - "davidben@google.com" - "svaldez@google.com" - "mbed-tls-security@lists.trustedfirmware.org" - "libmpdec4@gmail.com" - "richard@levitte.org" main_repo: 'https://github.com/guidovranken/bignum-fuzzer' fuzzing_engines: - libfuzzer - honggfuzz ================================================ FILE: projects/bincode/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust as builder RUN apt-get update RUN git clone --depth 1 https://git.sr.ht/~stygianentity/bincode ENV RUSTUP_TOOLCHAIN nightly-2025-01-10 COPY build.sh $SRC/ ================================================ FILE: projects/bincode/build.sh ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/bincode cargo fuzz build -O cp $SRC/bincode/fuzz/target/x86_64-unknown-linux-gnu/release/compat $OUT/ cp $SRC/bincode/fuzz/target/x86_64-unknown-linux-gnu/release/roundtrip $OUT/ ================================================ FILE: projects/bincode/project.yaml ================================================ homepage: "https://git.sr.ht/~stygianentity/bincode" language: rust primary_contact: "nathan@mccarty.io" auto_ccs: - "zoey@dos.cafe" - "github@trangar.com" - "ty@pre-alpha.com" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: 'https://git.sr.ht/~stygianentity/bincode' ================================================ FILE: projects/bind9/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 ENV DEBIAN_FRONTEND noninteractive RUN apt-get -y update && apt-get -y dist-upgrade RUN apt-get -y install \ autoconf \ automake \ autotools-dev \ bison \ build-essential \ libcap-dev \ libnghttp2-dev \ libssl-dev \ libtool \ libtool-bin \ liburcu-dev \ libuv1-dev \ pkg-config \ zip \ libcmocka-dev && \ python3 -m pip install -U meson ninja RUN git clone --depth 1 https://gitlab.isc.org/isc-projects/bind9.git WORKDIR bind9 COPY *.sh *.diff $SRC/ ================================================ FILE: projects/bind9/build.sh ================================================ #!/bin/sh -eu # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CFLAGS="${CFLAGS} -fPIC -Wl,--allow-multiple-definition" export CXXFLAGS="${CXXFLAGS} -fPIC -Wl,--allow-multiple-definition" git apply --ignore-space-change --ignore-whitespace $SRC/patch.diff # Use valid value for -Dfuzzing (enabled/disabled/auto) meson setup build -Dfuzzing=enabled -Dcmocka=enabled \ -Dc_link_args="$CFLAGS" -Dcpp_link_args="$CXXFLAGS" \ -Dc_args="$CFLAGS" -Dcpp_args="$CXXFLAGS" \ -Ddefault_library=static -Dprefer_static=true \ -Db_lto=false \ -Dnamed-lto=disabled meson compile -C build fuzz_dns_master_load fuzz_dns_message_checksig fuzz_dns_message_parse fuzz_dns_name_fromtext_target fuzz_dns_name_fromwire fuzz_dns_qp fuzz_dns_qpkey_name fuzz_dns_rdata_fromtext fuzz_dns_rdata_fromwire_text fuzz_isc_lex_getmastertoken fuzz_isc_lex_gettoken --verbose for fuzzname in fuzz_dns_master_load fuzz_dns_message_checksig fuzz_dns_message_parse fuzz_dns_name_fromtext_target fuzz_dns_name_fromwire fuzz_dns_qp fuzz_dns_qpkey_name fuzz_dns_rdata_fromtext fuzz_dns_rdata_fromwire_text fuzz_isc_lex_getmastertoken fuzz_isc_lex_gettoken; do fuzzer_basename="${fuzzname:5}" fuzzer_name="${fuzzname:5}_fuzzer" cp build/${fuzzname} $OUT/${fuzzer_name} zip -j "${OUT}/${fuzzer_name}_seed_corpus.zip" ./fuzz/${fuzzer_basename}.in/* || true done ================================================ FILE: projects/bind9/patch.diff ================================================ diff --git a/meson.build b/meson.build index d4a675b..f5cb72a 100644 --- a/meson.build +++ b/meson.build @@ -1584,7 +1584,7 @@ foreach name, sources : fuzz_binaries implicit_include_directories: true, install: false, c_args: ['-Wno-vla'], - link_args: fuzz_link_args, + link_args: fuzz_link_args + ['-fsanitize=fuzzer'], dependencies: [ libdns_dep, libisc_dep, diff --git a/tests/meson.build b/tests/meson.build index 416ba51..6feb638 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -15,7 +15,7 @@ test_inc = include_directories( '..' / 'lib' / 'dns', ) -libtest = shared_library( +libtest = static_library( 'bindtest', files( 'libtest/dns.c', ================================================ FILE: projects/bind9/project.yaml ================================================ homepage: "https://gitlab.isc.org/isc-projects/bind9" language: c primary_contact: "ondrej@isc.org" auto_ccs: - "artem@isc.org" - "aram@isc.org" - "each@isc.org" - "marka@isc.org" - "matthijs@isc.org" - "michal@isc.org" - "mnowak@isc.org" - "pspacek@isc.org" sanitizers: - address main_repo: 'https://gitlab.isc.org/isc-projects/bind9.git' fuzzing_engines: - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/bind9/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### meson test -C build ================================================ FILE: projects/binutils/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make texinfo libgmp-dev libmpfr-dev RUN apt-get install -y flex bison RUN git clone --depth=1 https://github.com/DavidKorczynski/binary-samples binary-samples RUN git clone --recursive --depth 1 git://sourceware.org/git/binutils-gdb.git binutils-gdb WORKDIR $SRC COPY build.sh $SRC/ COPY fuzz_*.c $SRC/ ================================================ FILE: projects/binutils/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project if [ "$SANITIZER" = undefined ]; then export CFLAGS="$CFLAGS -fno-sanitize=unsigned-integer-overflow" export CXXFLAGS="$CXXFLAGS -fno-sanitize=unsigned-integer-overflow" fi cd binutils-gdb # Comment out the lines of logging to stderror from elfcomm.c # This is to make it nicer to read the output of libfuzzer. cd binutils sed -i 's/vfprintf (stderr/\/\//' elfcomm.c sed -i 's/fprintf (stderr/\/\//' elfcomm.c # Fix a dlltool leak, which won't be fixed upstream because it uses a # non-posix yacc feature. It also isn't seen as a direct leak when # running dlltool stand-alone. sed -i '/^%%$/i%destructor { free (\$\$); } ID' defparse.y cd ../ ./configure --disable-gdb --disable-gdbserver --disable-gdbsupport \ --disable-libdecnumber --disable-readline --disable-sim \ --disable-libbacktrace --disable-gas --disable-ld --disable-werror \ --enable-targets=all make clean make MAKEINFO=true -j$(nproc) && true # Make fuzzer directory mkdir fuzz cp ../fuzz_*.c fuzz/ cd fuzz LIBS="../opcodes/libopcodes.a ../libctf/.libs/libctf.a ../bfd/.libs/libbfd.a ../zlib/libz.a ../libsframe/.libs/libsframe.a ../libiberty/libiberty.a" for i in fuzz_disassemble fuzz_bfd fuzz_bfd_ext; do $CC $CFLAGS -I ../include -I ../bfd -I ../opcodes -c $i.c -o $i.o $CXX $CXXFLAGS $i.o -o $OUT/$i $LIB_FUZZING_ENGINE -Wl,--start-group ${LIBS} -Wl,--end-group done # Build targeted disassembly fuzzers if [ -n "${OSS_FUZZ_CI-}" ] then echo "Skipping specialised disassembly fuzzers in CI to reduce build time" else for ARCH_TARGET in bfd_arch_arm bfd_arch_mips bfd_arch_i386 bfd_arch_arc bfd_arch_csky bfd_arch_mep; do $CC $CFLAGS -I ../include -I ../bfd -I ../opcodes -c fuzz_disas_ext.c -DFUZZ_TARGET_ARCH=$ARCH_TARGET \ -o fuzz_disas_ext-$ARCH_TARGET.o $CXX $CXXFLAGS fuzz_disas_ext-$ARCH_TARGET.o -o $OUT/fuzz_disas_ext-$ARCH_TARGET $LIB_FUZZING_ENGINE \ -Wl,--start-group ${LIBS} -Wl,--end-group done fi # Now compile the src/binutils fuzzers cd ../binutils # Compile the fuzzers. # The general strategy is to remove main functions such that the fuzzer (which has its own main) # can link against the code. # # Patching # # First do readelf. We do this by changing readelf.c to readelf.h - the others will be changed # to fuzz_readelf.h where readelf is their respective name. The reason it's different for readelf # is because readelf does not have a header file so we can use readelf.h instead, and changing it # might cause an annoyance on monorail since bugs will be relocated as the files will be different. cp ../../fuzz_*.c . sed 's/main (int argc/old_main (int argc, char **argv);\nint old_main (int argc/' readelf.c >> readelf.h # Special handling of dlltool sed 's/main (int ac/old_main32 (int ac, char **av);\nint old_main32 (int ac/' dlltool.c > fuzz_dlltool.h # Patch the rest for i in objdump nm objcopy windres strings addr2line; do sed -i 's/strip_main/strip_mian/g' $i.c sed -i 's/copy_main/copy_mian/g' $i.c sed 's/main (int argc/old_main32 (int argc, char **argv);\nint old_main32 (int argc/' $i.c > fuzz_$i.h sed -i 's/copy_mian/copy_main/g' fuzz_$i.h done # # Compile fuzzers # fuzz_compile () { src=$1 dst=$2 extraflags=$3 $CC $CFLAGS ${extraflags} -DHAVE_CONFIG_H -DOBJDUMP_PRIVATE_VECTORS="" -I. -I../bfd -I./../bfd -I./../include \ -I./../zlib -DLOCALEDIR="\"/usr/local/share/locale\"" \ -Dbin_dummy_emulation=bin_vanilla_emulation -W -Wall -MT \ fuzz_$dst.o -MD -MP -c -o fuzz_$dst.o fuzz_$src.c } for i in objdump readelf nm objcopy windres ranlib_simulation strings addr2line dwarf; do fuzz_compile $i $i "" done # Fuzzers that need additional flags fuzz_compile dlltool dlltool "-DDLLTOOL_I386 -DDLLTOOL_DEFAULT_I386" fuzz_compile objdump objdump_safe "-DOBJDUMP_SAFE" fuzz_compile readelf readelf_pef "-DREADELF_TARGETED=\"pef\"" fuzz_compile readelf readelf_elf32_bigarm "-DREADELF_TARGETED=\"elf32-bigarm\"" fuzz_compile readelf readelf_elf32_littlearm "-DREADELF_TARGETED=\"elf32-littlearm\"" fuzz_compile readelf readelf_elf64_mmix "-DREADELF_TARGETED=\"elf64-mmix\"" fuzz_compile readelf readelf_elf32_csky "-DREADELF_TARGETED=\"elf32-csky\"" # # Link fuzzers # # Link the files, but only if everything went well, which we verify by checking # the presence of some object files. LINK_LIBS="-Wl,--start-group ${LIBS} -Wl,--end-group" OBJ1="bucomm.o version.o filemode.o" OBJ2="version.o unwind-ia64.o dwarf.o elfcomm.o demanguse.o" OBJ3="dwarf.o prdbg.o rddbg.o unwind-ia64.o debug.o stabs.o rdcoff.o bucomm.o version.o filemode.o elfcomm.o od-xcoff.o demanguse.o" declare -A fl fl["readelf"]=${OBJ2} fl["readelf_pef"]=${OBJ2} fl["readelf_elf32_bigarm"]=${OBJ2} fl["readelf_elf32_littlearm"]=${OBJ2} fl["readelf_elf64_mmix"]=${OBJ2} fl["readelf_elf32_csky"]=${OBJ2} fl["objdump"]=${OBJ3} fl["objdump_safe"]=${OBJ3} fl["dwarf"]=${OBJ3} fl["addr2line"]=${OBJ1} fl["objcopy"]="rename.o rddbg.o debug.o stabs.o rdcoff.o wrstabs.o ${OBJ1}" fl["nm"]="${OBJ1} demanguse.o" fl["dlltool"]="defparse.o deflex.o ${OBJ1}" fl["windres"]="resrc.o rescoff.o resbin.o rcparse.o rclex.o winduni.o resres.o ${OBJ1}" fl["ranlib_simulation"]=" " fl["strings"]=${OBJ1} for fuzzer in ${!fl[@]}; do $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib \ -o $OUT/fuzz_${fuzzer} fuzz_${fuzzer}.o \ ${fl[${fuzzer}]} ${LINK_LIBS} done # Build GAS fuzzer. Will keep this here in case GAS fuzzer is used in the future. if [ "$FUZZING_ENGINE" != "afl" ] then cd ../gas ./configure --enable-leak-check make -j$(nproc) sed 's/main (int argc/old_main32 (int argc, char **argv);\nint old_main32 (int argc/' as.c > fuzz_as.h rm as.o || true ar r libar.a *.o $CC $CFLAGS -DHAVE_CONFIG_H -I. -I. -I. -I../bfd -I./config -I./../include -I./.. -I./../bfd \ -DLOCALEDIR="\"/usr/local/share/locale\"" -I./../zlib -c $SRC/fuzz_as.c -o fuzz_as.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -I./../zlib -o $OUT/fuzz_as ./fuzz_as.o \ libar.a config/tc-i386.o config/obj-elf.o config/atof-ieee.o \ ../opcodes/.libs/libopcodes.a ../bfd/.libs/libbfd.a \ -L/src/binutils-gdb/zlib ../libsframe/.libs/libsframe.a ../libiberty/libiberty.a -lz fi # Copy seeds out for fuzzname in readelf_pef readelf_elf32_csky readelf_elf64_mmix readelf_elf32_littlearm readelf_elf32_bigarm objdump objdump_safe nm objcopy bfd windres addr2line dwarf; do cp $SRC/binary-samples/oss-fuzz-binutils/general_seeds.zip $OUT/fuzz_${fuzzname}_seed_corpus.zip done # Seed targeted the pef file format cp $SRC/binary-samples/oss-fuzz-binutils/fuzz_bfd_ext_seed_corpus.zip $OUT/fuzz_bfd_ext_seed_corpus.zip # Copy options files for ft in readelf readelf_pef readelf_elf32_csky readelf_elf64_mmix readelf_elf32_littlearm readelf_elf32_bigarm objcopy objdump dlltool disas_ext-bfd_arch_csky nm as windres objdump_safe ranlib_simulation addr2line dwarf; do echo "[libfuzzer]" > $OUT/fuzz_${ft}.options echo "detect_leaks=0" >> $OUT/fuzz_${ft}.options done ================================================ FILE: projects/binutils/fuzz_addr2line.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert addr2line.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_addr2line.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); program_name = filename; char **c2 = xmalloc(sizeof(char*)*6); c2[0] = xstrdup("AAABC"); c2[1] = xstrdup("BBC"); c2[2] = xstrdup("0xbeefbeef"); c2[3] = xstrdup("0xcafebabe"); c2[4] = xstrdup("5123423"); c2[5] = NULL; naddr = 5; addr = c2; // Main fuzz entrypoint in addr2line.c process_file(filename, NULL, NULL); for (int i = 5; --i >= 0; ) free(c2[i]); free(c2); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_as.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert as.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include /* Don't allow cleanups. libiberty's function of the same name adds cleanups to a list without any means of clearing the list. The list must be clear at the start if LLVMFuzzerTestOneInput is to run more than once, otherwise we will get multiple copies of the same cleanup on the list which leads to double frees if xexit is called. Also a cleanup from the first run can result in use-after-free errors when as_fatal is hit as in issue 56429. */ int xatexit (void (*fn) (void) ATTRIBUTE_UNUSED) { return 0; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 1024) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer-%d.s", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); reg_section = NULL; char *fakeArgv[3]; fakeArgv[0] = "fuzz_as"; fakeArgv[1] = filename; // Assemble our fake source file. fakeArgv[2] = NULL; int argc = 2; char **argv = fakeArgv; gas_early_init (&argc, &argv); out_file_name = "/tmp/tmp-out"; gas_init (); // Main fuzzer target. Assemble our random data. perform_an_assembly_pass (argc, argv); // Cleanup cond_finish_check (-1); codeview_finish (); dwarf2_finish (); cfi_finish (); input_scrub_end (); keep_it = 0; output_file_close (); free_notes (); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_bfd.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "sysdep.h" #include "bfd.h" #include #include #include static int bufferToFile(char * name, const uint8_t *Data, size_t Size) { int fd = mkstemp(name); if (fd < 0) { printf("failed mkstemp, errno=%d\n", errno); return -2; } if (write (fd, Data, Size) != Size) { printf("failed write, errno=%d\n", errno); close(fd); return -3; } close(fd); return 0; } //TODO? part of fuzzing char *target = NULL; int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size > 16384) return 0; char tmpfilename[32]; if (bfd_init() != BFD_INIT_MAGIC) abort(); strncpy(tmpfilename, "/tmp/fuzz.bfd-XXXXXX", 31); if (bufferToFile(tmpfilename, Data, Size) < 0) { return 0; } bfd *file = bfd_openr (tmpfilename, target); if (file == NULL) { remove(tmpfilename); return 0; } bfd_check_format (file, bfd_archive); //TODO loop over subfiles and more processing bfd_close (file); remove(tmpfilename); return 0; } ================================================ FILE: projects/binutils/fuzz_bfd_ext.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * This is an example fuzzer targeted a given architecture. The point of this is * that the general fuzz_bfd fuzzer has too large reacability which makes it * difficult to reach the entire codebase in practice. The goal is to create * more targeted fuzzers that are more likely to explore a given code area. * */ #include "sysdep.h" #include "bfd.h" #include "libbfd.h" #include #include #include static int bufferToFile(char *name, const uint8_t *Data, size_t Size) { int fd = mkstemp(name); if (fd < 0) { printf("failed mkstemp, errno=%d\n", errno); return -2; } if (write(fd, Data, Size) != Size) { printf("failed write, errno=%d\n", errno); close(fd); return -3; } close(fd); return 0; } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size > 16384) return 0; char tmpfilename[32]; if (bfd_init() != BFD_INIT_MAGIC) abort(); /* char **names = bfd_target_list(); while (*names != NULL) { printf("Name: %s\n", *names); names++; } */ bfd_cleanup cleanup = NULL; strncpy(tmpfilename, "/tmp/fuzz.bfd-XXXXXX", 31); if (bufferToFile(tmpfilename, Data, Size) < 0) { return 0; } // bfd *file = bfd_openr (tmpfilename, "elf32-frv"); bfd *file = bfd_openr(tmpfilename, "pef"); if (file == NULL) { remove(tmpfilename); return 0; } if (!bfd_read_p(file) || (unsigned int)file->format >= (unsigned int)bfd_type_end) { bfd_close(file); return 0; } bool doAnalysis = false; if (bfd_seek(file, (file_ptr)0, SEEK_SET) == 0) { file->format = bfd_object; cleanup = BFD_SEND_FMT(file, _bfd_check_format, (file)); if (cleanup) { doAnalysis = true; cleanup(file); } file->format = bfd_unknown; } if (file != NULL) { bfd_close(file); } if (doAnalysis) { // We have a file with the target data we want. // Let's open as a write file this time, which should trigger // more actions on the code when calling bfd_close. // TODO: do more processing on this, e.g. use the file as // input to some of the other utilities. bfd *wFile = bfd_openw(tmpfilename, "pef"); if (file != NULL) { bfd_close(wFile); } } remove(tmpfilename); return 0; } ================================================ FILE: projects/binutils/fuzz_disas_ext.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * This disassemble fuzzer can be used for targetting specific architectures * and also initilises the target architecture with a random options string. * This is useful, for example, to hit architectures the general disassembly * fuzzer may not be hitting, and also to fuzz disassemblers in different * settings. This fuzzer also targets both big and small endianness. Down * the line this fuzzer can be expanded on, e.g. to include symobls and data * in the memory that is to be disassembled. */ #include "sysdep.h" #include "bfd.h" #include "dis-asm.h" #include "disassemble.h" #include #define MAX_TEXT_SIZE 256 typedef struct { char *buffer; size_t pos; } SFILE; static int fuzz_disasm_null_styled_printf (void *stream, enum disassembler_style style, const char *format, ...) { return 0; } static int objdump_sprintf (void *vf, const char *format, ...) { SFILE *f = (SFILE *) vf; size_t n; va_list args; va_start (args, format); if (f->pos >= MAX_TEXT_SIZE){ printf("buffer needs more space\n"); //reset f->pos=0; return 0; } n = vsnprintf (f->buffer + f->pos, MAX_TEXT_SIZE - f->pos, format, args); //vfprintf(stdout, format, args); va_end (args); f->pos += n; return n; } char options[100]; // Enable the disassemblers to have random options. void disassemble_architecture(int arch, const uint8_t *Data, size_t Size, int big) { char AssemblyText[MAX_TEXT_SIZE]; struct disassemble_info disasm_info; SFILE s; init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf, fuzz_disasm_null_styled_printf); disasm_info.fprintf_func = objdump_sprintf; disasm_info.print_address_func = generic_print_address; disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; disasm_info.buffer = (bfd_byte *) Data; disasm_info.buffer_vma = 0x1000; disasm_info.buffer_length = Size-10; disasm_info.insn_info_valid = 0; disasm_info.disassembler_options = options; disasm_info.created_styled_output = false; s.buffer = AssemblyText; s.pos = 0; disasm_info.stream = &s; disasm_info.bytes_per_line = 0; disasm_info.flags |= USER_SPECIFIED_MACHINE_TYPE; disasm_info.arch = arch; disasm_info.mach = bfd_getl64(&Data[Size-9]); disasm_info.flavour = Data[Size-10]; if (bfd_lookup_arch (disasm_info.arch, disasm_info.mach) != NULL) { disassembler_ftype disasfunc = disassembler(disasm_info.arch, big, disasm_info.mach, NULL); if (disasfunc != NULL) { disassemble_init_for_target(&disasm_info); while (1) { s.pos = 0; int octets = disasfunc(disasm_info.buffer_vma, &disasm_info); if (octets < (int) disasm_info.octets_per_byte) break; if (disasm_info.buffer_length <= (size_t) octets) break; disasm_info.buffer += octets; disasm_info.buffer_vma += octets / disasm_info.octets_per_byte; disasm_info.buffer_length -= octets; } disassemble_free_target(&disasm_info); } } } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size < 110 || Size > 16394) { // 110 bytes for options // 16394 limit code to prevent timeouts return 0; } char arch = *Data; // Create a random options string memcpy(options, Data, 100); options[99] = '\0'; Data += 100; Size -= 100; // FUZZ_TARGET_ARCH must be defined and should be the architecture // you target. disassemble_architecture(FUZZ_TARGET_ARCH, Data, Size, 1); disassemble_architecture(FUZZ_TARGET_ARCH, Data, Size, 0); return 0; } ================================================ FILE: projects/binutils/fuzz_disassemble.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "sysdep.h" #include "bfd.h" #include "dis-asm.h" #include "disassemble.h" #include #define MAX_TEXT_SIZE 256 typedef struct { char *buffer; size_t pos; } SFILE; static int fuzz_disasm_null_styled_printf (void *stream, enum disassembler_style style, const char *format, ...) { return 0; } static int objdump_sprintf (void *vf, const char *format, ...) { SFILE *f = (SFILE *) vf; size_t n; va_list args; va_start (args, format); if (f->pos >= MAX_TEXT_SIZE){ printf("buffer needs more space\n"); //reset f->pos=0; return 0; } n = vsnprintf (f->buffer + f->pos, MAX_TEXT_SIZE - f->pos, format, args); //vfprintf(stdout, format, args); va_end (args); f->pos += n; return n; } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { char AssemblyText[MAX_TEXT_SIZE]; struct disassemble_info disasm_info; SFILE s; if (Size < 10 || Size > 16394) { // 10 bytes for options // 16394 limit code to prevent timeouts return 0; } init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf, fuzz_disasm_null_styled_printf); disasm_info.fprintf_func = objdump_sprintf; disasm_info.print_address_func = generic_print_address; disasm_info.display_endian = disasm_info.endian = BFD_ENDIAN_LITTLE; disasm_info.buffer = (bfd_byte *) Data; disasm_info.buffer_vma = 0x1000; disasm_info.buffer_length = Size-10; disasm_info.insn_info_valid = 0; disasm_info.created_styled_output = false; s.buffer = AssemblyText; s.pos = 0; disasm_info.stream = &s; disasm_info.bytes_per_line = 0; disasm_info.flags |= USER_SPECIFIED_MACHINE_TYPE; disasm_info.arch = Data[Size-1]; disasm_info.mach = bfd_getl64(&Data[Size-9]); disasm_info.flavour = Data[Size-10]; if (bfd_lookup_arch (disasm_info.arch, disasm_info.mach) != NULL) { disassembler_ftype disasfunc = disassembler(disasm_info.arch, 0, disasm_info.mach, NULL); if (disasfunc != NULL) { disassemble_init_for_target(&disasm_info); while (1) { s.pos = 0; int octets = disasfunc(disasm_info.buffer_vma, &disasm_info); if (octets < (int) disasm_info.octets_per_byte) break; if (disasm_info.buffer_length <= (size_t) octets) break; disasm_info.buffer += octets; disasm_info.buffer_vma += octets / disasm_info.octets_per_byte; disasm_info.buffer_length -= octets; } disassemble_free_target(&disasm_info); } } return 0; } ================================================ FILE: projects/binutils/fuzz_dlltool.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert dlltool.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_dlltool.h" void init_dlltool_global_state() { import_list = NULL; as_name = NULL; as_flags = ""; tmp_prefix = NULL; exp_name = NULL; imp_name = NULL; delayimp_name = NULL; identify_imp_name = NULL; identify_strict = false; head_label = NULL; imp_name_lab = NULL; dll_name = NULL; dll_name_set_by_exp_name = 0; add_indirect = 0; add_underscore = 0; add_stdcall_underscore = 0; leading_underscore = "_"; dontdeltemps = 0; do_default_excludes = true; use_nul_prefixed_import_tables = false; def_file = NULL; } void callIntoDlltool(char *, char*, bool); void callIntoDlltool(char *deffile, char *objfile, bool var_export_all_symbols) { init_dlltool_global_state(); program_name = "fuzz_dlltool"; mname = "mcore-elf"; export_all_symbols = var_export_all_symbols; // At the moment we focus on the def file processing def_file = deffile; process_def_file(deffile); scan_obj_file(objfile); } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 512 || size > 16384) return 0; /* def file */ char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, 412, 1, fp); fclose(fp); data += 412; size -= 412; char filename2[256]; sprintf(filename2, "/tmp/libfuzzer-2.%d", getpid()); FILE *fp2 = fopen(filename2, "wb"); if (!fp2) { return 0; } fwrite(data, size, 1, fp2); fclose(fp2); callIntoDlltool(filename, filename2, true); callIntoDlltool(filename, filename2, false); unlink(filename); unlink(filename2); return 0; } ================================================ FILE: projects/binutils/fuzz_dwarf.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * Fuzzer that targets load_separate_debug_files in dwarf.c * To do this we rely on some of the logic in objdump.c */ #include "fuzz_objdump.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); bfd *file = bfd_openr (filename, NULL); if (file) { if (bfd_check_format (file, bfd_object)) { load_separate_debug_files (file, bfd_get_filename (file)); free_debug_memory (); } bfd_close_all_done (file); } unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_nm.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert nm.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_nm.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); // Globals line_numbers = 1; no_sort = 0; sort_numerically = 1; sort_by_size = 0; filename_per_symbol = 1; // Main fuzz entrypoint in nm.c display_file(filename); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_objcopy.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert objcopy.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #define is_strip 0 #include "fuzz_objcopy.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); void init_objcopy_global_state() { // status is a global variable that is set to 0 initially, // and we should ensure the state is not maintained for each iteration. status = 0; pe_file_alignment = (bfd_vma) -1; pe_heap_commit = (bfd_vma) -1; pe_heap_reserve = (bfd_vma) -1; pe_image_base = (bfd_vma) -1; pe_section_alignment = (bfd_vma) -1; pe_stack_commit = (bfd_vma) -1; pe_stack_reserve = (bfd_vma) -1; pe_subsystem = -1; pe_major_subsystem_version = -1; pe_minor_subsystem_version = -1; section_rename_list = NULL; isympp = NULL; osympp = NULL; copy_byte = -1; interleave = 0; copy_width = 1; keep_section_symbols = false; deterministic = -1; status = 0; merge_notes = false; strip_symbols = STRIP_UNDEF; change_sections = NULL; change_start = 0; set_start_set = false; change_section_address = 0; gap_fill_set = false; gap_fill = 0; pad_to_set = false; use_alt_mach_code = 0; add_sections = NULL; update_sections = NULL; dump_sections = NULL; gnu_debuglink_filename = NULL; convert_debugging = false; change_leading_char = false; remove_leading_char = false; wildcard = false; localize_hidden = false; strip_specific_htab = NULL; strip_unneeded_htab = NULL; keep_specific_htab = NULL; localize_specific_htab = NULL; globalize_specific_htab = NULL; keepglobal_specific_htab = NULL; weaken_specific_htab = NULL; redefine_specific_htab = NULL; redefine_specific_reverse_htab = NULL; add_sym_tail = &add_sym_list; add_symbols = 0; strip_specific_buffer = NULL; strip_unneeded_buffer = NULL; keep_specific_buffer = NULL; localize_specific_buffer = NULL; globalize_specific_buffer = NULL; keepglobal_specific_buffer = NULL; weaken_specific_buffer = NULL; weaken = false; keep_file_symbols = false; prefix_symbols_string = 0; prefix_sections_string = 0; prefix_alloc_sections_string = 0; extract_symbol = false; create_symbol_htabs(); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); program_name = filename; if (bfd_init() != BFD_INIT_MAGIC) abort(); set_default_bfd_target(); init_objcopy_global_state(); /* glibc getopt has internal static state. Setting optind to zero reinitialises it. Do this every second run, which effectively alternates objcopy with options then objcopy without options. (optind will be 9 when copy_main returns.) */ static int iter; if (++iter & 1) optind = 0; char *fakeArgv[12]; fakeArgv[0] = "fuzz_objcopy"; fakeArgv[1] = "-S"; fakeArgv[2] = "--decompress-debug-sections"; fakeArgv[3] = "--extract-dwo"; fakeArgv[4] = "--merge-notes"; fakeArgv[5] = "--pure"; fakeArgv[6] = "--debugging"; fakeArgv[7] = "--compress-debug-sections"; fakeArgv[8] = "--extract-symbol"; fakeArgv[9] = filename; fakeArgv[10] = "/tmp/random.out"; fakeArgv[11] = NULL; copy_main(11, fakeArgv); // Cleanup free (strip_specific_buffer); free (strip_unneeded_buffer); free (keep_specific_buffer); free (localize_specific_buffer); free (globalize_specific_buffer); free (keepglobal_specific_buffer); free (weaken_specific_buffer); delete_symbol_htabs (); unlink(filename); remove("/tmp/random.out"); return 0; } ================================================ FILE: projects/binutils/fuzz_objdump.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert objdump.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_objdump.h" void objdump_reset() { process_links = true; do_follow_links = true; dump_section_contents = true; dump_section_headers = true; dump_private_headers = true; dump_ar_hdrs = true; dump_dwarf_section_info = true; // We must call both dwarf_select_sections_by_letters and dwarf_select_sections_all // since dwarf_select_sections_all does not set do_debug_lines |= FLAG_DEBUG_LINES_DECODED; dwarf_select_sections_by_letters("L"); dwarf_select_sections_all (); dump_debugging = true; dump_stab_section_info = true; disassemble_all = true; } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); program_name = filename; objdump_reset(); // These flags contain a large set of calls to bfd_fatal (which calls // exit), so to enable fuzzing of objdump with a fuzzer that lives for // a longer period of time (more than 10 seconds) define // OBJDUMP_SAFE #ifndef OBJDUMP_SAFE dump_reloc_info = true; // ctf section and reloc are simply too quick to exit and disrupts // fuzzing too much. Will leave this commented out for now. //dump_dynamic_reloc_info = true; //dump_ctf_section_info = true; disassemble = true; #endif // Main fuzz entrypoint in objdump.c display_file(filename, NULL); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_ranlib_simulation.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * The goal of this fuzzer is to simulate the logic for ranlib. We implement the * fuzzer without calling ar.c itself in order to avoid bfd_fatal calls. */ #include "sysdep.h" #include "bfd.h" #include "libiberty.h" #include "getopt.h" #include "aout/ar.h" #include "bucomm.h" #include "arsup.h" #include "filenames.h" #include "binemul.h" #include "plugin-api.h" #include "plugin.h" #include "ansidecl.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); int f; bfd *arch; f = open (filename, O_RDWR | O_BINARY, 0); if (f < 0) { return 0; } arch = bfd_fdopenr (filename, (const char *) NULL, f); if (arch == NULL) { close(f); return 0; } if (! bfd_check_format (arch, bfd_archive)) { bfd_close(arch); return 0; } if (! bfd_has_map (arch)) { bfd_close(arch); return 0; } bfd_is_thin_archive (arch); bfd_update_armap_timestamp(arch); bfd_close(arch); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_readelf.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert readelf.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "readelf.h" #include "bfd.h" #include "libbfd.h" int check_architecture(char *tmpfilename, char *arch_string) { bfd_cleanup cleanup = NULL; bfd *file = bfd_openr(tmpfilename, arch_string); if (file == NULL) { remove(tmpfilename); return 0; } if (!bfd_read_p(file) || (unsigned int)file->format >= (unsigned int)bfd_type_end) { bfd_close(file); return 0; } bool doAnalysis = false; if (bfd_seek(file, (file_ptr)0, SEEK_SET) == 0) { file->format = bfd_object; cleanup = BFD_SEND_FMT(file, _bfd_check_format, (file)); if (cleanup) { doAnalysis = true; cleanup(file); } file->format = bfd_unknown; } if (file != NULL) { bfd_close(file); } // return 1 if the architecture matches. if (doAnalysis) { return 1; } return 0; } // int gb=0; int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) return 0; /* Code to quickly extract target list. * This is used to identify new targets but should * not be in the fuzz code. if (gb == 0) { char **doublel = bfd_target_list(); while (*doublel != NULL) { printf("Target: %s\n", *doublel); doublel++; } gb=1; } exit(0); */ #ifdef READELF_TARGETED if (check_architecture(filename, READELF_TARGETED) == 0) { unlink(filename); return 0; } #endif fwrite(data, size, 1, fp); fclose(fp); do_syms = true; do_reloc = true; do_unwind = true; do_dynamic = true; do_header = true; do_sections = true; do_section_groups = true; do_segments = true; do_version = true; do_histogram = true; do_arch = true; do_notes = true; // Enable DWARF analysis // We must call both dwarf_select_sections_by_letters and // dwarf_select_sections_all since dwarf_select_sections_all does not set // do_debug_lines |= FLAG_DEBUG_LINES_DECODED; dwarf_select_sections_by_letters("L"); dwarf_select_sections_all(); // Main fuzz entrypoint process_file(filename); unlink(filename); free(dump_ctf_symtab_name); dump_ctf_symtab_name = NULL; free(dump_ctf_strtab_name); dump_ctf_strtab_name = NULL; free(dump_ctf_parent_name); dump_ctf_parent_name = NULL; return 0; } ================================================ FILE: projects/binutils/fuzz_strings.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert strings.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_strings.h" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); program_name = "fuzz_strings"; string_min = 4; encoding = 's'; encoding_bytes = 1; datasection_only = true; // Main fuzz entrypoint in strings.c strings_object_file(filename); unlink(filename); return 0; } ================================================ FILE: projects/binutils/fuzz_windres.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * We convert windres.c into a header file to make convenient for fuzzing. * We do this for several of the binutils applications when creating * the binutils fuzzers. */ #include "fuzz_windres.h" /* * * This fuzzer performs initial checks on the data * that are similar to what the windres application does, however * with the caveat that windres will fatally exit and the fuzzer simply returns, i.e. * fuzzing continues. The purpose is to enable further analysis. * * Down the line, perhaps it makes sense to chage binutils to have less fatals and * more graceful exits. This would be useful for the fuzzing. */ static enum res_format fuzz_format_check_from_mem(const uint8_t *data, size_t size) { int magic; if (size < 2) { return RES_FORMAT_UNKNOWN; } if (data[0] == 0x4d && data[1] == 0x5a) { return RES_FORMAT_COFF; } magic = data[0] << 8 | data[1]; if (magic == 0x14c || magic == 0x166 || magic == 0x184 || magic == 0x268 || magic == 0x1f0 || magic == 0x290) { return RES_FORMAT_COFF; } return RES_FORMAT_UNKNOWN; } int fuzz_check_coff_rsrc (const char *filename, const char *target) { int retval = 0; bfd *abfd; windres_bfd wrbfd; asection *sec; abfd = bfd_openr (filename, target); if (abfd == NULL) { return 0; } if (! bfd_check_format (abfd, bfd_object)) { retval = 0; goto cleanup; } sec = bfd_get_section_by_name (abfd, ".rsrc"); if (sec == NULL || sec->size == 0) { retval = 0; goto cleanup; } set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD); bfd_size_type filesize = get_file_size (filename); if ((ufile_ptr) sec->filepos > filesize || sec->size > filesize - sec->filepos) { retval = 0; goto cleanup; } retval = 1; cleanup: bfd_close (abfd); return retval; } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size > 16384) return 0; enum res_format input_format; input_format = fuzz_format_check_from_mem(data, size);; if (input_format != RES_FORMAT_COFF) { return 0; } char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); program_name = "fuzz_windres"; // For now we only check FORMAT_COFF, this can be extended to // the two additional formats later. if (input_format == RES_FORMAT_COFF) { if (fuzz_check_coff_rsrc(filename, NULL) != 0) { res_init (); read_coff_rsrc (filename, NULL); obstack_free (&res_obstack, NULL); } } unlink(filename); return 0; } ================================================ FILE: projects/binutils/project.yaml ================================================ homepage: "https://www.gnu.org/software/binutils/" main_repo: "https://github.com/bminor/binutils-gdb" language: c++ primary_contact: "bug-binutils@gnu.org" auto_ccs : - "p.antoine@catenacyber.fr" - "nickc@redhat.com" - "amodra@gmail.com" - "david@adalogics.com" sanitizers: - address - undefined - memory fuzzing_engines: - libfuzzer - honggfuzz - centipede ================================================ FILE: projects/bios-bmc-smm-error-logger/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install --reinstall -y patchelf make ninja-build meson libgtest-dev libgmock-dev pkg-config libsystemd-dev python3-pip libboost-all-dev && pip3 install inflection pyyaml mako jsonschema --break-system-packages RUN git clone https://github.com/openbmc/bios-bmc-smm-error-logger COPY *.sh *.diff $SRC/ WORKDIR $SRC/bios-bmc-smm-error-logger RUN git clone https://github.com/google/googletest.git --branch v1.15.2 subprojects/googletest RUN git clone https://github.com/openbmc/libbej subprojects/libbej RUN git clone https://github.com/nlohmann/json.git subprojects/nlohmann_json RUN git clone https://github.com/openbmc/phosphor-dbus-interfaces.git subprojects/phosphor-dbus-interfaces ================================================ FILE: projects/bios-bmc-smm-error-logger/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git apply --ignore-space-change --ignore-whitespace $SRC/fuzz-patch.diff # Remove system gtest/gmock to force using the subproject (built with libc++) # This fixes linker errors due to ABI mismatch (libstdc++ vs libc++) apt-get remove -y libgtest-dev libgmock-dev googletest google-mock || true rm -rf /usr/src/googletest rm -rf /usr/src/gtest rm -rf /usr/src/gmock # Ensure cmake is installed for the subproject build apt-get update && apt-get install -y cmake # Download subprojects explicitly so we can patch them meson subprojects download # Force googletest to build statically by patching its CMakeLists.txt # This is more reliable than trying to patch test/meson.build to pass cmake options if [ -d "subprojects/googletest" ]; then find subprojects/googletest -name CMakeLists.txt -exec sed -i '1i set(BUILD_SHARED_LIBS OFF CACHE BOOL "Force static" FORCE)' {} + fi # Fix bug in test/meson.build where 'cmake' variable is used but not defined sed -i "s/gtest_proj = cmake.subproject(/gtest_proj = import('cmake').subproject(/g" test/meson.build # Configure the build # -Dtests=enabled: to build the fuzzer defined in test/meson.build # -Ddefault_library=static: to build static libraries (good for fuzzing) # -Dfuzz_engine: pass the fuzzing engine flags to the fuzzer executable rm -rf build meson setup build \ -Dtests=enabled \ -Ddefault_library=static \ -Dgoogletest:default_library=static \ -Dcpp_args="-stdlib=libc++ -Wno-error=character-conversion -Wno-error=deprecated-declarations $CXXFLAGS" \ -Dc_args="$CFLAGS" \ -Dcpp_link_args="${LDFLAGS:-$CXXFLAGS}" \ -Dfuzz_engine="$LIB_FUZZING_ENGINE" # Patch stdexec to fix missing header (provides std::launder) if [ -f subprojects/stdexec/include/stdexec/__detail/__utility.hpp ]; then sed -i '1i#include ' subprojects/stdexec/include/stdexec/__detail/__utility.hpp fi # Patch stdplus to fix missing includes and ambiguous references if [ -f subprojects/stdplus/include/stdplus/function_view.hpp ]; then sed -i '1i#include \n#include \n#include \n#include ' subprojects/stdplus/include/stdplus/function_view.hpp fi if [ -f subprojects/stdplus/include/stdplus/debug/lifetime.hpp ]; then sed -i '1i#include ' subprojects/stdplus/include/stdplus/debug/lifetime.hpp fi if [ -f subprojects/stdplus/include/stdplus/hash.hpp ]; then sed -i '1i#include ' subprojects/stdplus/include/stdplus/hash.hpp # Remove conflicting forward declaration of std::hash in namespace std # Use ^namespace std$ to avoid matching namespace stdplus sed -i '/^namespace std$/,/}/ { /template /d; /struct hash;/d; }' subprojects/stdplus/include/stdplus/hash.hpp fi if [ -f subprojects/stdplus/include/stdplus/net/addr/ip.hpp ]; then sed -i '1i#include ' subprojects/stdplus/include/stdplus/net/addr/ip.hpp # Remove conflicting forward declaration of std::formatter sed -i '/template /d' subprojects/stdplus/include/stdplus/net/addr/ip.hpp sed -i '/struct formatter;/d' subprojects/stdplus/include/stdplus/net/addr/ip.hpp fi if [ -f subprojects/stdplus/include/stdplus/net/addr/subnet.hpp ]; then sed -i '1i#include ' subprojects/stdplus/include/stdplus/net/addr/subnet.hpp # Remove conflicting forward declaration of std::formatter sed -i '/template /d' subprojects/stdplus/include/stdplus/net/addr/subnet.hpp sed -i '/struct formatter;/d' subprojects/stdplus/include/stdplus/net/addr/subnet.hpp fi if [ -f subprojects/stdplus/include/stdplus/str/cat.hpp ]; then sed -i '1i#include ' subprojects/stdplus/include/stdplus/str/cat.hpp fi if [ -f subprojects/sdbusplus/include/sdbusplus/asio/connection.hpp ]; then sed -i 's/std::move_only_function/std::function/g' subprojects/sdbusplus/include/sdbusplus/asio/connection.hpp fi # Build everything ninja -C build -v # Copy the fuzzer to $OUT cp build/test/rde_fuzz $OUT/ ================================================ FILE: projects/bios-bmc-smm-error-logger/fuzz-patch.diff ================================================ diff --git a/include/read_loop.hpp b/include/read_loop.hpp new file mode 100644 index 0000000..30d1515 --- /dev/null +++ b/include/read_loop.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "buffer.hpp" +#include "rde/rde_handler.hpp" + +#include +#include + +#include + +namespace bios_bmc_smm_error_logger +{ + +void readLoop(boost::asio::steady_timer* t, + const std::shared_ptr& bufferInterface, + const std::shared_ptr& rdeCommandHandler, + const boost::system::error_code& error); + +} // namespace bios_bmc_smm_error_logger diff --git a/meson.build b/meson.build index 9c08597..e18021c 100644 --- a/meson.build +++ b/meson.build @@ -35,4 +35,4 @@ if get_option('tests').allowed() endif # installation of systemd service files -subdir('service_files') +# subdir('service_files') diff --git a/meson.options b/meson.options index ce07181..85aaa1a 100644 --- a/meson.options +++ b/meson.options @@ -67,3 +67,5 @@ option( value: 4, description: 'Magic Number array[3] for validity, consists of 4 * uint32_t', ) + +option('fuzz_engine', type: 'string', value: '', description: 'Fuzzing engine flags') diff --git a/src/main.cpp b/src/main.cpp index 97f7bcb..c36dc7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include "buffer.hpp" #include "pci_handler.hpp" +#include "read_loop.hpp" #include "rde/external_storer_file.hpp" #include "rde/external_storer_interface.hpp" #include "rde/rde_handler.hpp" @@ -24,8 +25,8 @@ namespace { constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS); -constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE; -constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET; +[[maybe_unused]] constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE; +[[maybe_unused]] constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET; constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION; constexpr uint16_t queueSize = QUEUE_REGION_SIZE; constexpr uint16_t ueRegionSize = UE_REGION_SIZE; @@ -36,6 +37,9 @@ static constexpr std::array magicNumber = { using namespace bios_bmc_smm_error_logger; +namespace bios_bmc_smm_error_logger +{ + void readLoop(boost::asio::steady_timer* t, const std::shared_ptr& bufferInterface, const std::shared_ptr& rdeCommandHandler, @@ -168,6 +172,9 @@ void readLoop(boost::asio::steady_timer* t, std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler)); } +} // namespace bios_bmc_smm_error_logger + +#ifndef BIOS_BMC_FUZZING int main() { boost::asio::io_context io; @@ -207,3 +214,4 @@ int main() return 0; } +#endif diff --git a/src/meson.build b/src/meson.build index 58a8040..56aaa5b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,6 @@ bios_bmc_smm_error_logger_pre = declare_dependency( include_directories: [root_inc, bios_bmc_smm_error_logger_inc], - dependencies: [dependency('threads'), dependency('stdplus')], + dependencies: [dependency('threads'), dependency('stdplus'), dependency('boost')], ) bios_bmc_smm_error_logger_lib = static_library( @@ -8,7 +8,7 @@ bios_bmc_smm_error_logger_lib = static_library( 'pci_handler.cpp', 'buffer.cpp', implicit_include_directories: false, - dependencies: bios_bmc_smm_error_logger_pre, + dependencies: [bios_bmc_smm_error_logger_pre, rde_dep], ) bios_bmc_smm_error_logger_dep = declare_dependency( diff --git a/test/meson.build b/test/meson.build index 18f7732..ae63cce 100644 --- a/test/meson.build +++ b/test/meson.build @@ -42,6 +42,16 @@ foreach t : gtests build_by_default: false, implicit_include_directories: false, dependencies: test_dep, + cpp_args: ['-Wno-error=character-conversion', '-Wno-error=sign-compare'], ), ) endforeach + +executable( + 'rde_fuzz', + ['rde_fuzz.cpp', '../src/main.cpp'], + dependencies: [rde_dep, bios_bmc_smm_error_logger_dep], + install: true, + link_args: get_option('fuzz_engine').split(), + cpp_args: ['-DBIOS_BMC_FUZZING'], +) diff --git a/test/rde_fuzz.cpp b/test/rde_fuzz.cpp new file mode 100644 index 0000000..c3c736d --- /dev/null +++ b/test/rde_fuzz.cpp @@ -0,0 +1,150 @@ +#include "config.h" + +#include "buffer.hpp" +#include "pci_handler.hpp" +#include "read_loop.hpp" +#include "rde/external_storer_file.hpp" +#include "rde/external_storer_interface.hpp" +#include "rde/rde_handler.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS); +constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE; +constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET; +constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION; +constexpr uint16_t queueSize = QUEUE_REGION_SIZE; +constexpr uint16_t ueRegionSize = UE_REGION_SIZE; +static constexpr std::array magicNumber = { + MAGIC_NUMBER_BYTE1, MAGIC_NUMBER_BYTE2, MAGIC_NUMBER_BYTE3, + MAGIC_NUMBER_BYTE4}; +} // namespace + +using namespace bios_bmc_smm_error_logger; + +// Mock PciDataHandler to use a file instead of /dev/mem +class MockPciDataHandler : public PciDataHandler +{ + public: + MockPciDataHandler(uint32_t /*regionAddress*/, size_t regionSize, + stdplus::ManagedFd fd) : + PciDataHandler(0, regionSize, + std::make_unique(std::move(fd))) + {} +}; + +// Mock ExternalStorerInterface to avoid DBus calls +class MockExternalStorerInterface : public rde::ExternalStorerInterface +{ + public: + MockExternalStorerInterface() = default; + + bool publishJson(std::string_view /*json*/) override + { + return true; + } +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + // Create a temporary file to simulate memory region + std::string tempFileName = "/tmp/fuzz_mem_XXXXXX"; + int fd = mkstemp(tempFileName.data()); + if (fd == -1) + { + return 0; + } + + // Write fuzz data to the temporary file + // Ensure the file is at least as large as the memory region + std::vector buffer(memoryRegionSize, 0); + if (size > memoryRegionSize) + { + size = memoryRegionSize; + } + std::memcpy(buffer.data(), data, size); + + // Patch the header to ensure it passes validation + if (buffer.size() >= sizeof(CircularBufferHeader)) + { + auto* header = reinterpret_cast(buffer.data()); + + // Fix magic number + for (size_t i = 0; i < 4; ++i) + { + header->magicNumber[i] = + boost::endian::native_to_little(magicNumber[i]); + } + + // Fix sizes + header->queueSize = boost::endian::native_to_little(queueSize); + header->ueRegionSize = boost::endian::native_to_little(ueRegionSize); + header->bmcInterfaceVersion = + boost::endian::native_to_little(bmcInterfaceVersion); + + // Fix pointers to be within bounds + // maxOffset calculation from BufferImpl::getMaxOffset() + size_t maxOffset = + queueSize - ueRegionSize - sizeof(struct CircularBufferHeader); + + uint32_t writePtr = + boost::endian::little_to_native(header->biosWritePtr); + header->biosWritePtr = + boost::endian::native_to_little(writePtr % (maxOffset + 1)); + + uint32_t readPtr = boost::endian::little_to_native(header->bmcReadPtr); + header->bmcReadPtr = + boost::endian::native_to_little(readPtr % (maxOffset + 1)); + } + + write(fd, buffer.data(), memoryRegionSize); + lseek(fd, 0, SEEK_SET); + + // Setup Boost ASIO + boost::asio::io_context io; + boost::asio::steady_timer t(io, readIntervalinMs); + + // Setup Buffer Interface with Mock PciDataHandler + stdplus::ManagedFd managedFd(std::move(fd)); + std::unique_ptr pciDataHandler = + std::make_unique(memoryRegionOffset, + memoryRegionSize, + std::move(managedFd)); + std::shared_ptr bufferHandler = + std::make_shared(std::move(pciDataHandler)); + + // Setup RDE Command Handler with Mock ExternalStorerInterface + std::unique_ptr exFileIface = + std::make_unique(); + std::shared_ptr rdeCommandHandler = + std::make_unique(std::move(exFileIface)); + + // Do NOT call initialize(), as it wipes the buffer. + // Instead, we rely on the patched header we wrote to the file. + + // Run readLoop once + readLoop(&t, bufferHandler, rdeCommandHandler, boost::system::error_code()); + + // Cleanup + std::filesystem::remove(tempFileName); + + return 0; +} diff --git a/test/rde_handler_test.cpp b/test/rde_handler_test.cpp index c13feaa..fa26e60 100644 --- a/test/rde_handler_test.cpp +++ b/test/rde_handler_test.cpp @@ -773,7 +773,7 @@ TEST_F(RdeHandlerTest, DictionaryStartAndEndTest) EXPECT_THAT(rdeH->getDictionaryCount(), 2); // Send the encoded payload. - EXPECT_CALL(*mockExStorerPtr, publishJson(exJson)).WillOnce(Return(true)); + EXPECT_CALL(*mockExStorerPtr, publishJson(std::string_view(exJson))).WillOnce(Return(true)); EXPECT_THAT(rdeH->decodeRdeCommand(std::span(mInitOp), RdeCommandType::RdeOperationInitRequest), RdeDecodeStatus::RdeOk); @@ -802,7 +802,7 @@ TEST_F(RdeHandlerTest, DictionaryStartThenEndTest) EXPECT_THAT(rdeH->getDictionaryCount(), 2); // Send the encoded payload. - EXPECT_CALL(*mockExStorerPtr, publishJson(exJson)).WillOnce(Return(true)); + EXPECT_CALL(*mockExStorerPtr, publishJson(std::string_view(exJson))).WillOnce(Return(true)); EXPECT_THAT(rdeH->decodeRdeCommand(std::span(mInitOp), RdeCommandType::RdeOperationInitRequest), RdeDecodeStatus::RdeOk); @@ -847,7 +847,7 @@ TEST_F(RdeHandlerTest, DictionaryStartMidEndTest) EXPECT_THAT(rdeH->getDictionaryCount(), 2); // Send the encoded payload. - EXPECT_CALL(*mockExStorerPtr, publishJson(exJson)).WillOnce(Return(true)); + EXPECT_CALL(*mockExStorerPtr, publishJson(std::string_view(exJson))).WillOnce(Return(true)); EXPECT_THAT(rdeH->decodeRdeCommand(std::span(mInitOp), RdeCommandType::RdeOperationInitRequest), RdeDecodeStatus::RdeOk); ================================================ FILE: projects/bios-bmc-smm-error-logger/project.yaml ================================================ homepage: "https://github.com/openbmc/docs/blob/master/designs/bios-bmc-smm-error-logging.md" language: c++ primary_contact: "javanlacerda@google.com" auto_ccs: - pedroysb@google.com - cloud-ti-fuzzing+bugs@google.com main_repo: "https://github.com/javanlacerda/bios-bmc-smm-error-logger" fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: ubuntu-24-04 ================================================ FILE: projects/bitcoin-core/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Packages taken from: # * https://github.com/bitcoin/bitcoin/blob/master/doc/build-unix.md#dependency-build-instructions # * https://github.com/bitcoin/bitcoin/blob/master/depends/README.md#for-linux-including-i386-arm-cross-compilation RUN apt-get update && apt-get install -y \ build-essential curl g++-multilib make \ patch pkgconf python3 wget zip RUN git clone --depth=1 https://github.com/bitcoin/bitcoin.git bitcoin-core RUN git clone --depth=1 https://github.com/bitcoin-core/qa-assets bitcoin-core/assets && \ rm -rf bitcoin-core/assets/.git # Remove git history to save storage RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git WORKDIR bitcoin-core COPY build.sh $SRC/ ================================================ FILE: projects/bitcoin-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Print date to embed it into build logs date cd $SRC/bitcoin-core/ # Build dependencies # This will also force static builds if [ "$ARCHITECTURE" = "i386" ]; then export BUILD_TRIPLET="i386-linux-gnu" else export BUILD_TRIPLET="x86_64-pc-linux-gnu" fi export CFLAGS="$CFLAGS -flto=full" export CXXFLAGS="$CXXFLAGS -flto=full" # Use lld to workaround referenced in
of /tmp/lto-llvm-*.o: defined in discarded section export LDFLAGS="-fuse-ld=lld -flto=full" export CPPFLAGS="-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG -DBOOST_MULTI_INDEX_ENABLE_SAFE_MODE" ( cd depends sed -i --regexp-extended '/.*rm -rf .*extract_dir.*/d' ./funcs.mk # Keep extracted source # Disable IPC until a fuzz test actually needs it # At that point, as workaround can be added to remove capnps # internal oss-fuzz detection: https://github.com/google/oss-fuzz/pull/14203#issuecomment-3461008642 make HOST=$BUILD_TRIPLET DEBUG=1 NO_QT=1 NO_ZMQ=1 NO_USDT=1 \ NO_IPC=1 \ AR=llvm-ar NM=llvm-nm RANLIB=llvm-ranlib STRIP=llvm-strip \ -j$(nproc) ) # Build the fuzz targets sed -i "s|PROVIDE_FUZZ_MAIN_FUNCTION|NEVER_PROVIDE_MAIN_FOR_OSS_FUZZ|g" "./src/test/fuzz/util/CMakeLists.txt" # OSS-Fuzz will provide CC, CXX, etc. So only set: # * -DBUILD_FOR_FUZZING=ON, see https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md # * --toolchain, see https://github.com/bitcoin/bitcoin/blob/master/depends/README.md EXTRA_BUILD_OPTIONS= if [ "$SANITIZER" = "memory" ]; then # _FORTIFY_SOURCE is not compatible with MSAN. EXTRA_BUILD_OPTIONS="-DAPPEND_CPPFLAGS='-U_FORTIFY_SOURCE'" fi cmake -B build_fuzz \ --toolchain depends/${BUILD_TRIPLET}/toolchain.cmake \ `# Setting these flags to an empty string ensures that the flags set by an OSS-Fuzz environment remain unaltered` \ -DCMAKE_C_FLAGS_RELWITHDEBINFO="" \ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="" \ -DBUILD_FOR_FUZZING=ON \ -DFUZZ_LIBS="$LIB_FUZZING_ENGINE" \ $EXTRA_BUILD_OPTIONS cmake --build build_fuzz -j$(nproc) WRITE_ALL_FUZZ_TARGETS_AND_ABORT="/tmp/a" "./build_fuzz/bin/fuzz" || true readarray FUZZ_TARGETS < "/tmp/a" if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space FUZZ_TARGETS=( ${FUZZ_TARGETS[@]:0:2} ) fi # OSS-Fuzz requires a separate and self-contained binary for each fuzz target. # To inject the fuzz target name in the finished binary, compile the fuzz # executable with a "magic string" as the name of the fuzz target. # # An alternative to mocking the string in the finished binary would be to # replace the string in the source code and re-invoke 'cmake --build'. This is slower, # so use the hack. export MAGIC_STR="b5813eee2abc9d3358151f298b75a72264ffa119d2f71ae7fefa15c4b70b4bc5b38e87e3107a730f25891ea428b2b4fabe7a84f5bfa73c79e0479e085e4ff157" sed -i "s|std::getenv(\"FUZZ\")|\"$MAGIC_STR\"|g" "./src/test/fuzz/fuzz.cpp" cmake --build build_fuzz -j$(nproc) # Replace the magic string with the actual name of each fuzz target for fuzz_target in ${FUZZ_TARGETS[@]}; do df --human-readable ./src python3 -c "c_str_target=b\"${fuzz_target}\x00\";c_str_magic=b\"$MAGIC_STR\";dat=open('./build_fuzz/bin/fuzz','rb').read();dat=dat.replace(c_str_magic, c_str_target+c_str_magic[len(c_str_target):]);open(\"$OUT/$fuzz_target\",'wb').write(dat)" chmod +x "$OUT/$fuzz_target" ( cd assets/fuzz_corpora if [ -d "$fuzz_target" ]; then zip --recurse-paths --quiet --junk-paths "$OUT/${fuzz_target}_seed_corpus.zip" "${fuzz_target}" fi ) done cp assets/fuzz_dicts/*.dict $OUT/ ================================================ FILE: projects/bitcoin-core/descriptor_parse.options ================================================ [libfuzzer] dict = descriptors.dict ================================================ FILE: projects/bitcoin-core/i2p.options ================================================ [libfuzzer] dict = i2p.dict ================================================ FILE: projects/bitcoin-core/miniscript_string.options ================================================ [libfuzzer] dict = descriptors.dict ================================================ FILE: projects/bitcoin-core/process_messages.options ================================================ [libfuzzer] dict = net_processing.dict ================================================ FILE: projects/bitcoin-core/project.yaml ================================================ homepage: "https://bitcoincore.org/" main_repo: 'https://github.com/bitcoin/bitcoin.git' language: c++ primary_contact: "macro.fuzzing.uxuga@aleeas.com" auto_ccs: - "fanquake@gmail.com" - "jonas@chaincode.com" - "pieter@chaincode.com" - "n.goeggi@gmail.com" - "achow101@gmail.com" sanitizers: - address - undefined - memory architectures: - x86_64 # - i386 disabled for now: https://github.com/google/clusterfuzz/pull/4773 selective_unpack: true # Required to avoid out-of-space when executing AFL on clusterfuzz bots fuzzing_engines: - afl # - centipede # temporarily disabled due to spurious "Step #22 - "build-check-centipede-none-x86_64": OSError: [Errno 28] No space left on device" - libfuzzer - honggfuzz ================================================ FILE: projects/black/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/psf/black black COPY *.sh *py $SRC/ WORKDIR $SRC/black ================================================ FILE: projects/black/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data 'src/blib2to3:blib2to3' done ================================================ FILE: projects/black/fuzz_format_filecontents.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import black def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: black.format_file_contents(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 2048)), mode=black.Mode(), fast=fdp.ConsumeBool()) except black.InvalidInput: pass except black.NothingChanged: pass except AssertionError: pass except KeyError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/black/fuzz_lib2to3_parse.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import black def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: black.lib2to3_parse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except black.InvalidInput: pass except AssertionError: pass except KeyError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/black/fuzz_raw_format_filecontents.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import black def TestOneInput(data): if len(data) < 50: return fdp = atheris.FuzzedDataProvider(data) try: black.format_file_contents(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize), mode=black.Mode(), fast=False) except black.InvalidInput: pass except black.NothingChanged: pass except AssertionError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/black/project.yaml ================================================ homepage: https://github.com/psf/black main_repo: https://github.com/psf/black language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/blackfriday/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 --branch v2 https://github.com/russross/blackfriday RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.23.4.linux-amd64.tar.gz COPY build.sh render_fuzzer.go $SRC/ WORKDIR $SRC/blackfriday ================================================ FILE: projects/blackfriday/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/render_fuzzer.go . rm go.mod go mod init github.com/russross/blackfriday compile_go_fuzzer github.com/russross/blackfriday Fuzz render_fuzzer ================================================ FILE: projects/blackfriday/project.yaml ================================================ homepage: "https://github.com/russross/blackfriday" main_repo: "https://github.com/russross/blackfriday" primary_contact: "security-tps@google.com" auto_ccs : - "Adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/blackfriday/render_fuzzer.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package blackfriday func Fuzz(data []byte) int { Run(data) return 0 } ================================================ FILE: projects/bleach/Dockerfile ================================================ # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone \ --depth 1 \ --branch main \ https://github.com/mozilla/bleach.git WORKDIR bleach RUN git clone --depth 1 https://github.com/google/fuzzing COPY build.sh sanitize_fuzzer.py linkify_fuzzer.py $SRC/ ================================================ FILE: projects/bleach/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do compile_python_fuzzer $fuzzer done # Copy fuzzer dictionaries to $OUT cp fuzzing/dictionaries/html.dict "$OUT/linkify_fuzzer.dict" cp fuzzing/dictionaries/html.dict "$OUT/sanitize_fuzzer.dict" ================================================ FILE: projects/bleach/linkify_fuzzer.py ================================================ #!/usr/bin/python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import bleach def TestOneInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) data = fdp.ConsumeUnicode(atheris.ALL_REMAINING) bleach.linkify(data) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/bleach/project.yaml ================================================ homepage: "https://github.com/mozilla/bleach" main_repo: "https://github.com/mozilla/bleach" language: python primary_contact: "wkahngreene@mozilla.com" auto_ccs: - "ipudney@google.com" - "gguthe@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined ================================================ FILE: projects/bleach/sanitize_fuzzer.py ================================================ #!/usr/bin/python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import bleach def TestOneInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) data = fdp.ConsumeUnicode(atheris.ALL_REMAINING) bleach.clean(data) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/bloaty/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake ninja-build g++ libz-dev RUN git clone --depth 1 https://github.com/google/bloaty.git bloaty WORKDIR bloaty COPY build.sh $SRC/ ================================================ FILE: projects/bloaty/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $WORK cmake -G Ninja -DBUILD_TESTING=false $SRC/bloaty ninja -j$(nproc) cp fuzz_target $OUT zip -j $OUT/fuzz_target_seed_corpus.zip $SRC/bloaty/tests/testdata/fuzz_corpus/* ================================================ FILE: projects/bloaty/project.yaml ================================================ homepage: "https://github.com/google/bloaty" language: c++ primary_contact: "jhaberman@gmail.com" architectures: - x86_64 - i386 main_repo: 'https://github.com/google/bloaty.git' file_github_issue: True ================================================ FILE: projects/bls-signatures/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool wget python lzip libgmp-dev RUN git clone --depth 1 https://github.com/MozillaSecurity/cryptofuzz RUN git clone --depth 1 https://github.com/supranational/blst RUN git clone --depth 1 https://github.com/herumi/mcl.git RUN git clone --depth 1 https://github.com/randombit/botan.git RUN git clone --depth 1 https://github.com/mratsim/constantine RUN wget -q https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 RUN wget -q https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.lz RUN wget -q https://nim-lang.org/download/nim-2.0.8-linux_x64.tar.xz RUN wget -q https://nim-lang.org/download/nim-2.0.8-linux_x32.tar.xz COPY build.sh $SRC/ ================================================ FILE: projects/bls-signatures/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -D_LIBCPP_DEBUG=1" if [[ "$SANITIZER" = "memory" ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" export LINK_FLAGS="" # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ # Configure Cryptofuzz cd $SRC/cryptofuzz/ python gen_repository.py rm extra_options.h echo -n '"' >>extra_options.h echo -n "--force-module=blst " >>extra_options.h echo -n "--operations=" >>extra_options.h echo -n "BignumCalc," >>extra_options.h echo -n "BignumCalc_Fp2," >>extra_options.h echo -n "BignumCalc_Fp12," >>extra_options.h echo -n "BLS_BatchVerify," >>extra_options.h echo -n "BLS_FinalExp," >>extra_options.h echo -n "BLS_GenerateKeyPair," >>extra_options.h echo -n "BLS_HashToG1," >>extra_options.h echo -n "BLS_HashToG2," >>extra_options.h echo -n "BLS_IsG1OnCurve," >>extra_options.h echo -n "BLS_IsG2OnCurve," >>extra_options.h echo -n "BLS_Pairing," >>extra_options.h echo -n "BLS_PrivateToPublic," >>extra_options.h echo -n "BLS_PrivateToPublic_G2," >>extra_options.h echo -n "BLS_Sign," >>extra_options.h echo -n "BLS_Verify," >>extra_options.h echo -n "BLS_Compress_G1," >>extra_options.h echo -n "BLS_Compress_G2," >>extra_options.h echo -n "BLS_Decompress_G1," >>extra_options.h echo -n "BLS_Decompress_G2," >>extra_options.h echo -n "BLS_G1_Add," >>extra_options.h echo -n "BLS_G1_Mul," >>extra_options.h echo -n "BLS_G1_IsEq," >>extra_options.h echo -n "BLS_G1_Neg," >>extra_options.h echo -n "BLS_G2_Add," >>extra_options.h echo -n "BLS_G2_Mul," >>extra_options.h echo -n "BLS_G2_IsEq," >>extra_options.h echo -n "BLS_G2_Neg," >>extra_options.h echo -n "BLS_Aggregate_G1", >>extra_options.h echo -n "BLS_Aggregate_G2", >>extra_options.h echo -n "BLS_MapToG1", >>extra_options.h echo -n "BLS_MapToG2", >>extra_options.h echo -n "BignumCalc_Mod_BLS12_381_P," >>extra_options.h echo -n "BignumCalc_Mod_BLS12_381_R," >>extra_options.h echo -n "KDF_HKDF," >>extra_options.h echo -n "Misc " >>extra_options.h echo -n "--digests=SHA256 " >>extra_options.h echo -n "--curves=BLS12_381 " >>extra_options.h echo -n '"' >>extra_options.h # Build arkworks-algebra if [[ "$SANITIZER" != "memory" ]] then cd $SRC/cryptofuzz/modules/arkworks-algebra/ if [[ $CFLAGS != *-m32* ]] then make else rustup target add i686-unknown-linux-gnu make -f Makefile-i386 fi export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_ARKWORKS_ALGEBRA" fi # Build Constantine if [[ "$SANITIZER" != "memory" ]] then cd $SRC/ if [[ $CFLAGS != *-m32* ]] then tar Jxf nim-2.0.8-linux_x64.tar.xz else tar Jxf nim-2.0.8-linux_x32.tar.xz fi export NIM_PATH=$(realpath nim-2.0.8) export CONSTANTINE_PATH=$SRC/constantine/ cd $SRC/cryptofuzz/modules/constantine/ if [[ $CFLAGS != *-m32* ]] then make else make -f Makefile-i386 fi export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_CONSTANTINE" fi if [[ $CFLAGS = *-m32* ]] then # Build and install libgmp cd $SRC/ mkdir $SRC/libgmp-install tar xf gmp-6.2.1.tar.lz cd $SRC/gmp-6.2.1/ autoreconf -ivf if [[ $CFLAGS != *-m32* ]] then ./configure --prefix="$SRC/libgmp-install/" --enable-cxx else setarch i386 ./configure --prefix="$SRC/libgmp-install/" --enable-cxx fi make -j$(nproc) make install export CXXFLAGS="$CXXFLAGS -I $SRC/libgmp-install/include/" fi function build_blst() { if [[ "$SANITIZER" == "memory" ]] then CFLAGS="$CFLAGS -D__BLST_NO_ASM__ -D__BLST_PORTABLE__ -Dllimb_t=__uint128_t -D__builtin_assume(x)=(void)(x)" ./build.sh else ./build.sh fi export BLST_LIBBLST_A_PATH=$(realpath libblst.a) export BLST_INCLUDE_PATH=$(realpath bindings/) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BLST" } # Build blst (normal) cp -R $SRC/blst/ $SRC/blst_normal/ cd $SRC/blst_normal/ build_blst # Build mcl if [[ "$SANITIZER" != "memory" && $CFLAGS != *-m32* ]] then cd $SRC/mcl/ mkdir build/ cd build/ if [[ $CFLAGS != *-m32* ]] then cmake .. -DMCL_STATIC_LIB=on export LINK_FLAGS="$LINK_FLAGS -lgmp" else cmake .. -DMCL_STATIC_LIB=on \ -DGMP_INCLUDE_DIR="$SRC/libgmp-install/include/" \ -DGMP_LIBRARY="$SRC/libgmp-install/lib/libgmp.a" \ -DGMP_GMPXX_INCLUDE_DIR="$SRC/libgmp-install/include/" \ -DGMP_GMPXX_LIBRARY="$SRC/libgmp-install/lib/libgmpxx.a" \ -DMCL_USE_ASM=off export LINK_FLAGS="$LINK_FLAGS $SRC/libgmp-install/lib/libgmp.a" fi make export MCL_INCLUDE_PATH=$(realpath ../include/) export MCL_LIBMCL_A_PATH=$(realpath lib/libmcl.a) export MCL_LIBMCLBN384_A_PATH=$(realpath lib/libmclbn384.a) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_MCL" fi # Build Botan cd $SRC/botan/ if [[ $CFLAGS != *-m32* ]] then ./configure.py --cc-bin=$CXX \ --cc-abi-flags="$CXXFLAGS" \ --disable-shared \ --disable-modules=locking_allocator,x509 \ --build-targets=static \ --without-documentation else ./configure.py --cpu=x86_32 \ --cc-bin=$CXX \ --cc-abi-flags="$CXXFLAGS" \ --disable-shared \ --disable-modules=locking_allocator,x509 \ --build-targets=static \ --without-documentation fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE" export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a" export BOTAN_INCLUDE_PATH="$SRC/botan/build/include" # Build modules cd $SRC/cryptofuzz/modules/botan/ make -B cd $SRC/cryptofuzz/modules/blst/ make -B if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then cd $SRC/cryptofuzz/modules/mcl/ make -B fi # Build Cryptofuzz cd $SRC/cryptofuzz/ make -B -j cp cryptofuzz $OUT/cryptofuzz-bls-signatures # Build blst (optimized for size) cp -R $SRC/blst/ $SRC/blst_optimize_size/ cd $SRC/blst_optimize_size/ export CFLAGS="$CFLAGS -D__OPTIMIZE_SIZE__" build_blst cd $SRC/cryptofuzz/modules/blst/ make -B # Build Cryptofuzz cd $SRC/cryptofuzz/ rm entry.o; make cp cryptofuzz $OUT/cryptofuzz-bls-signatures_optimize_size ================================================ FILE: projects/bls-signatures/project.yaml ================================================ homepage: "https://github.com/supranational/blst" language: c++ primary_contact: "guidovranken@gmail.com" main_repo: "https://github.com/supranational/blst.git" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 auto_ccs: - "kelly@supranational.net" - "diederik.loerakker@ethereum.org" - "hoffmang@chia.net" - "bram@chia.net" - "mariano@chia.net" - "arvid@chia.net" - "bill@chia.net" - "pratyush795@gmail.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/bluez/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Install necessary packages RUN apt-get update && apt-get install -y \ make autoconf automake libtool pkg-config \ libdbus-1-dev libreadline8 libreadline-dev \ python-docutils libudev-dev udev libical-dev \ libdbus-1-dev systemd libbluetooth-dev RUN python3 -m pip install --upgrade pip && python3 -m pip install packaging RUN python3 -m pip install -U meson ninja # Clone necessary repositories RUN git clone git://git.kernel.org/pub/scm/libs/ell/ell.git RUN git clone --depth 1 https://github.com/bluez/bluez bluez RUN git clone https://github.com/GNOME/glib && \ cd glib && \ meson _build -Db_lundef=false -Ddefault_library=static -Dlibmount=disabled && \ ninja -C _build && \ ninja -C _build install WORKDIR bluez COPY *.sh $SRC/ COPY *.c $SRC/ ================================================ FILE: projects/bluez/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./bootstrap autoreconf -f ./configure --disable-systemd make -j$(nproc) INCLUDES="-I. -I./src -I./lib -I./gobex -I/usr/local/include/glib-2.0/ -I/src/glib/_build/glib/ -I/usr/include/bluetooth" STATIC_LIBS="./src/.libs/libshared-glib.a ./lib/.libs/libbluetooth-internal.a -l:libical.a -l:libicalss.a -l:libicalvcal.a -l:libdbus-1.a /src/glib/_build/glib/libglib-2.0.a" $CC $CFLAGS $INCLUDES $SRC/fuzz_xml.c -c $CC $CFLAGS $INCLUDES $SRC/fuzz_sdp.c -c $CC $CFLAGS $INCLUDES $SRC/fuzz_textfile.c -c $CC $CFLAGS $INCLUDES $SRC/fuzz_gobex.c -c $CC $CFLAGS $INCLUDES $SRC/fuzz_hci.c -c $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ ./src/bluetoothd-sdp-xml.o fuzz_xml.o -o $OUT/fuzz_xml \ $STATIC_LIBS -ldl -lpthread $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ fuzz_sdp.o -o $OUT/fuzz_sdp $STATIC_LIBS -ldl -lpthread $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_textfile.o -o $OUT/fuzz_textfile \ $STATIC_LIBS -ldl -lpthread src/textfile.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ fuzz_gobex.o ./gobex/gobex*.o -o $OUT/fuzz_gobex \ $STATIC_LIBS -ldl -lpthread $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ fuzz_hci.o ./gobex/gobex*.o -o $OUT/fuzz_hci \ $STATIC_LIBS -ldl -lpthread echo "[libfuzzer]" > $OUT/fuzz_gobex.options echo "detect_leaks=0" >> $OUT/fuzz_gobex.options ================================================ FILE: projects/bluez/fuzz_gobex.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "gobex/gobex.h" #include "gobex/gobex-packet.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { uint8_t buf[255]; GObexPacket *pkt; GError *err = NULL; pkt = g_obex_packet_decode(data, size, 0, G_OBEX_DATA_REF, &err); if (pkt != NULL) { /* Anything that decodes must encode */ g_obex_packet_encode(pkt, buf, sizeof(buf)); g_obex_packet_free(pkt); } return 0; } ================================================ FILE: projects/bluez/fuzz_hci.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "bluetooth.h" #include "sdp.h" #include "sdp_lib.h" #include "hci_lib.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int to_copy = size; uint8_t features[8]; if (size > 8) { to_copy = 8; } char *null_terminated = malloc(to_copy+1); memcpy(null_terminated, data, to_copy); null_terminated[to_copy] = '\0'; /* char *tmp = lmp_featurestostr(features, null_terminated, to_copy); if (tmp) { free(tmp); } */ char *tmp = NULL; size -= to_copy; data += to_copy; /* uint8_t cmds[64]; bzero(cmds, 64); for (int i = 0; i < 64 && i < size; i++) { cmds[i] = data[i]; } tmp = hci_commandstostr(cmds, NULL, 0); if (tmp) { free(tmp); } */ if (size > 4) { uint16_t id = *(uint16_t*)data; bt_compidtostr(id); } free(null_terminated); return 0; } ================================================ FILE: projects/bluez/fuzz_sdp.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "bluetooth.h" #include "sdp.h" #include "sdp_lib.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Target sdp_extract_pdu */ int scanned = 0; sdp_record_t *out = NULL; openlog("fuzz_sdp", LOG_PERROR, LOG_LOCAL0); out = sdp_extract_pdu(data, size, &scanned); if (out) { sdp_record_t *copy = sdp_copy_record(out); if (copy) { sdp_record_free(copy); } sdp_record_free(out); } closelog(); return 0; } ================================================ FILE: projects/bluez/fuzz_textfile.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include "src/textfile.h" char *get_null_terminated(const uint8_t **data, size_t *size) { #define STR_SIZE 75 if (*size < STR_SIZE || (int)*size < 0) { return NULL; } char *new_s = malloc(STR_SIZE + 1); memcpy(new_s, *data, STR_SIZE); new_s[STR_SIZE] = '\0'; *data = *data+STR_SIZE; *size -= STR_SIZE; return new_s; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { uint8_t *data_ptr = data; size_t size_val = size; char *key1 = get_null_terminated(&data_ptr, &size_val); char *val1 = get_null_terminated(&data_ptr, &size_val); char *key2 = get_null_terminated(&data_ptr, &size_val); if (!key1 || !val1 || !key2) { goto cleanup; } // Create a file with rest of content char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data_ptr, size_val, 1, fp); fclose(fp); textfile_put(filename, key1, val1); textfile_get(filename, key2); unlink(filename); cleanup: if (key1 != NULL) { free(key1); key1 = NULL; } if (val1 != NULL) { free(val1); val1 = NULL; } if (key2 != NULL) { free(key2); key2 = NULL; } return 0; } ================================================ FILE: projects/bluez/fuzz_xml.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "bluetooth.h" #include "sdp.h" #include "sdp_lib.h" #include "sdp-xml.h" void empty_func(void *d, const char *s) { return; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { sdp_record_t *rec; rec = sdp_xml_parse_record(data, size); if (rec != NULL) { convert_sdp_record_to_xml(rec, 0, empty_func); sdp_record_free(rec); } return 0; } ================================================ FILE: projects/bluez/project.yaml ================================================ homepage: "https://github.com/bluez/bluez" language: c primary_contact: "bluez.test.bot@gmail.com" main_repo: "https://github.com/bluez/bluez" auto_ccs: - "hj.tedd.an@gmail.com" - "david@adalogics.com" fuzzing_engines: - libfuzzer - honggfuzz - afl # - centipede disabled due to https://github.com/google/oss-fuzz/pull/10248#issuecomment-1579657163 ================================================ FILE: projects/bluez/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### # Remove tests that are not building with the fuzzing set up mv unit/test-mesh-crypto.c /tmp/ mv unit/test-midi.c /tmp/ for unit_test in $(ls unit/test-*.c); do unit_name=$(basename ${unit_test}) unit_name="${unit_name%.*}" echo ${unit_name} make unit/${unit_name} ./unit/${unit_name} done mv /tmp/test-mesh-crypto.c unit/test-mesh-crypto.c mv /tmp/test-midi.c unit/test-midi.c ================================================ FILE: projects/bmcweb/Dockerfile ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ pkg-config \ cmake \ python3-pip \ libpam0g-dev \ libsystemd-dev \ zlib1g-dev \ libzstd-dev RUN pip3 install -U meson ninja inflection pyyaml mako RUN git clone --depth 1 https://github.com/openbmc/bmcweb $SRC/bmcweb COPY build.sh $SRC/ COPY *_fuzzer.cpp $SRC/ WORKDIR $SRC/bmcweb ================================================ FILE: projects/bmcweb/build.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/bmcweb export CFLAGS="${CFLAGS} -fPIC" export CXXFLAGS="${CXXFLAGS} -fPIC" # Stub systemd.pc – bmcweb only uses it for unit-file install paths. mkdir -p $WORK/pkgconfig cat > $WORK/pkgconfig/systemd.pc <<'EOF' prefix=/usr systemd_system_unit_dir=${prefix}/lib/systemd/system Name: systemd Description: systemd (stub for fuzzing) Version: 245 EOF export PKG_CONFIG_PATH="$WORK/pkgconfig:${PKG_CONFIG_PATH:-}" # Configure with most features disabled – we only need parsing/utility code. meson setup build \ -Ddefault_library=static \ -Dprefer_static=true \ -Db_lto=false \ -Dwerror=false \ -Dtests=disabled \ -Dkvm=disabled \ -Dvm-websocket=disabled \ -Drest=disabled \ -Dhost-serial-socket=disabled \ -Dstatic-hosting=disabled \ -Dredfish-bmc-journal=disabled \ -Dredfish-cpu-log=disabled \ -Dredfish-dump-log=disabled \ -Dredfish-dbus-log=disabled \ -Dredfish-host-logger=disabled \ -Dinsecure-disable-ssl=enabled \ -Dinsecure-disable-auth=enabled \ -Dbmcweb-logging=disabled \ -Dcpp_args="${CXXFLAGS}" \ -Dcpp_link_args="${CXXFLAGS}" \ -Dc_args="${CFLAGS}" \ -Dc_link_args="${CFLAGS}" # Build as much as possible. The sdbusplus subproject fails to compile but # all bmcweb object files and other subproject libraries succeed. ninja -C build -k 0 || true # Extract compile flags from meson's compile_commands.json so the fuzzer # sources are compiled with exactly the same flags as bmcweb itself. COMPILE_FLAGS=$(python3 -c " import json, shlex, os builddir = os.path.abspath('build') with open('build/compile_commands.json') as f: for entry in json.load(f): if 'json_html_serializer.cpp' in entry['file']: args = shlex.split(entry['command']) out = [] i = 1 # skip compiler binary while i < len(args): a = args[i] if a in ('-MF', '-MQ', '-o'): i += 2; continue if a in ('-c', '-MD') or a.endswith('.cpp') or a.endswith('.o') or a.endswith('.d'): i += 1; continue # Convert relative include paths to absolute for prefix in ('-I', '-isystem'): if a.startswith(prefix) and not a.startswith(prefix + '/'): path = a[len(prefix):] a = prefix + os.path.normpath(os.path.join(builddir, path)) break out.append(a) i += 1 print(' '.join(out)) break ") # Find the bmcweb object files produced by ninja that our fuzzers need. BMCWEB_OBJS="" for name in boost_asio boost_beast json_html_serializer filter_expr_printer; do obj=$(find build -name "*${name}.cpp.o" -print -quit) if [ -z "$obj" ]; then echo "ERROR: object file for $name not found in build dir" exit 1 fi BMCWEB_OBJS="$BMCWEB_OBJS $obj" done # Collect all subproject static libraries for linking. LINK_LIBS=$(find build/subprojects -name "*.a" 2>/dev/null) # Build each fuzzer. for fuzzer_src in $SRC/*_fuzzer.cpp; do fuzzer_name=$(basename "$fuzzer_src" .cpp) $CXX $COMPILE_FLAGS \ -I$SRC/bmcweb \ -c "$fuzzer_src" -o "$WORK/${fuzzer_name}.o" $CXX $CXXFLAGS -std=c++23 \ "$WORK/${fuzzer_name}.o" $BMCWEB_OBJS \ $LIB_FUZZING_ENGINE $LINK_LIBS \ -lsystemd -lz -lzstd -lssl -lcrypto -latomic -lpam \ -o "$OUT/${fuzzer_name}" done ================================================ FILE: projects/bmcweb/content_type_fuzzer.cpp ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "http_utility.hpp" #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size == 0) { return 0; } std::string_view input(reinterpret_cast(data), size); // Test content type parser http_helpers::getContentType(input); // Test preferred content type parser with various preference orders constexpr std::array defaultPrefs = { http_helpers::ContentType::JSON, http_helpers::ContentType::HTML, http_helpers::ContentType::CBOR}; http_helpers::getPreferredContentType(input, defaultPrefs); // Test content type allowed check http_helpers::isContentTypeAllowed(input, http_helpers::ContentType::JSON, true); http_helpers::isContentTypeAllowed(input, http_helpers::ContentType::JSON, false); // Test encoding parser constexpr std::array defaultEncodings = { http_helpers::Encoding::ZSTD, http_helpers::Encoding::GZIP, http_helpers::Encoding::UnencodedBytes}; http_helpers::getPreferredEncoding(input, defaultEncodings); return 0; } ================================================ FILE: projects/bmcweb/filter_expr_fuzzer.cpp ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "filter_expr_printer.hpp" #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size == 0) { return 0; } std::string_view input(reinterpret_cast(data), size); // Use parseFilter which exercises phrase_parse (space-skipping) and // the FilterExpressionPrinter on successful parses std::optional result = redfish::parseFilter(input); if (result) { // Exercise the AST printer on successfully parsed expressions redfish::FilterExpressionPrinter printer; std::string printed = printer(*result); (void)printed; } return 0; } ================================================ FILE: projects/bmcweb/json_html_serializer_fuzzer.cpp ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "json_html_serializer.hpp" #include #include #include #include #include // Reuse bmcweb's own SAX parser to limit depth/width #include "http/parsing.hpp" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size == 0) { return 0; } std::string input(reinterpret_cast(data), size); // Parse JSON using bmcweb's own SAX parser (with depth/width limits) std::optional parsed = parseStringAsJson(input); if (parsed) { // Exercise the HTML serializer on successfully parsed JSON std::string html; json_html_util::dumpHtml(html, *parsed); (void)html; } return 0; } ================================================ FILE: projects/bmcweb/json_parser_fuzzer.cpp ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "http/parsing.hpp" #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string input(reinterpret_cast(data), size); // Exercise the main JSON parser with depth/width limits parseStringAsJson(input); // Also exercise content-type checking (cheap, reuses same input) std::string_view sv(reinterpret_cast(data), size); isJsonContentType(sv); return 0; } ================================================ FILE: projects/bmcweb/multipart_parser_fuzzer.cpp ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "multipart_parser.hpp" #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 4) { return 0; } // Use first byte to determine boundary length (1-64 chars) uint8_t boundaryLen = static_cast((data[0] % 64) + 1); // 1-64 chars size_t offset = 1; if (offset + boundaryLen > size) { return 0; } std::string boundary(reinterpret_cast(data + offset), boundaryLen); offset += boundaryLen; std::string_view body(reinterpret_cast(data + offset), size - offset); std::string contentType = "multipart/form-data; boundary="; contentType += boundary; MultipartParser parser; parser.parse(contentType, body); return 0; } ================================================ FILE: projects/bmcweb/project.yaml ================================================ homepage: "https://github.com/openbmc/bmcweb" language: c++ fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/openbmc/bmcweb.git' vendor_ccs: - david@adalogics.com ================================================ FILE: projects/boost/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y g++ python RUN git clone --recursive https://github.com/boostorg/boost.git WORKDIR boost # Preferably, move boost_regex_fuzzer.cc to the boost repository. COPY build.sh *.zip *.cc $SRC/ ================================================ FILE: projects/boost/boost_datetime_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include using namespace boost::gregorian; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); try { std::string s(fdp.ConsumeRandomLengthString(15)); date d(from_simple_string(s)); to_simple_string(d); date d1(from_undelimited_string(s)); to_iso_extended_string(d1); date::ymd_type ymd = d1.year_month_day(); greg_weekday wd = d1.day_of_week(); wd.as_long_string(); ymd.month.as_long_string(); } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_filesystem_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); try { boost::filesystem::path p(fdp.ConsumeRandomLengthString(5)); p.replace_filename(fdp.ConsumeRandomLengthString(5)); p.has_extension(); p.extension(); p.replace_extension(fdp.ConsumeRandomLengthString(3)); boost::filesystem::path p1(fdp.ConsumeRandomLengthString(5)); p.concat(p1); p.append(p1); p.remove_filename_and_trailing_separators(); p /= (p1); p += (p1); p.lexically_relative(p1); p.filename_is_dot(); p.remove_filename(); p.swap(p1); p.root_directory(); p.relative_path(); p.parent_path(); p.has_stem(); } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_graph_graphml_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include #ifdef DEBUG #include #endif #include #include #include typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, boost::property, boost::property > Graph; using namespace boost; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); try { Graph g; boost::dynamic_properties dp(boost::ignore_other_properties); std::stringstream input(fdp.ConsumeRemainingBytesAsString()); read_graphml(input, g, dp); auto viter = make_iterator_range(vertices(g)); #ifdef DEBUG for (auto v : viter) { std::cout << v << " "; } #endif } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_graph_graphviz_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include #include #include #ifdef DEBUG #include #endif #include #include struct DotVertex { std::string name; std::string label; int peripheries; }; struct DotEdge { std::string label; }; typedef boost::adjacency_list graph_t; using namespace boost; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); try { graph_t graphviz; boost::dynamic_properties dp(boost::ignore_other_properties); dp.property("node_id", boost::get(&DotVertex::name, graphviz)); read_graphviz(fdp.ConsumeRemainingBytesAsString(), graphviz, dp); auto viter = make_iterator_range(vertices(graphviz)); #ifdef DEBUG for (auto v : viter) { std::cout << v << " "; } #endif } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_programoptions_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include namespace po = boost::program_options; #include #include using namespace std; po::options_description set_options() { po::options_description opts; opts.add_options() ("global_string", po::value()) ("strings.word", po::value()) ("strings.phrase", po::value()) ("strings.quoted", po::value()) ("ints.positive", po::value()) ("ints.negative", po::value()) ("ints.hex", po::value()) ("ints.oct", po::value()) ("ints.bin", po::value()) ("floats.positive", po::value()) ("floats.negative", po::value()) ("floats.double", po::value()) ("floats.int", po::value()) ("floats.int_dot", po::value()) ("floats.dot", po::value()) ("floats.exp_lower", po::value()) ("floats.exp_upper", po::value()) ("floats.exp_decimal", po::value()) ("floats.exp_negative", po::value()) ("floats.exp_negative_val", po::value()) ("floats.exp_negative_negative_val", po::value()) ("booleans.number_true", po::bool_switch()) ("booleans.number_false", po::bool_switch()) ("booleans.yn_true", po::bool_switch()) ("booleans.yn_false", po::bool_switch()) ("booleans.tf_true", po::bool_switch()) ("booleans.tf_false", po::bool_switch()) ("booleans.onoff_true", po::bool_switch()) ("booleans.onoff_false", po::bool_switch()) ("booleans.present_equal_true", po::bool_switch()) ("booleans.present_no_equal_true", po::bool_switch()) ; return opts; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { try { FuzzedDataProvider fdp(data, size); auto opts = set_options(); po::variables_map vars; stringstream st(fdp.ConsumeRemainingBytesAsString()); const bool ALLOW_UNREGISTERED = true; po::parsed_options parsed = parse_config_file(st, opts, ALLOW_UNREGISTERED); store(parsed, vars); vector unregistered = po::collect_unrecognized(parsed.options, po::exclude_positional); notify(vars); } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_ptree_inforead_fuzzer.cc ================================================ /* * Fuzzing of boost property tree parsers. * by Paul Dreik 20180818 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include int readInfo(const char* Data, size_t Size) { namespace pt = boost::property_tree; std::stringstream ss; ss.write(Data, Size); pt::ptree tree; try { pt::read_info(ss, tree); return tree.size() ? 1 : 0; } catch (...) { return 0; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { readInfo(reinterpret_cast(Data), Size); return 0; } ================================================ FILE: projects/boost/boost_ptree_iniread_fuzzer.cc ================================================ /* * Fuzzing of boost property tree parsers. * by Paul Dreik 20180818 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include int readIni(const char* Data, size_t Size) { namespace pt = boost::property_tree; std::stringstream ss; ss.write(Data, Size); pt::ptree tree; try { pt::read_ini(ss, tree); return tree.size() ? 1 : 0; } catch (...) { return 0; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { readIni(reinterpret_cast(Data), Size); return 0; } ================================================ FILE: projects/boost/boost_ptree_jsonread_fuzzer.cc ================================================ /* * Fuzzing of boost property tree parsers. * by Paul Dreik 20180818 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include int readJson(const char* Data, size_t Size) { namespace pt = boost::property_tree; std::stringstream ss; ss.write(Data, Size); pt::ptree tree; try { pt::read_json(ss, tree); return tree.size() ? 1 : 0; } catch (...) { return 0; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { readJson(reinterpret_cast(Data), Size); return 0; } ================================================ FILE: projects/boost/boost_ptree_xmlread_fuzzer.cc ================================================ /* * Fuzzing of boost property tree parsers. * by Paul Dreik 20180818 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include int readXml(const char* Data, size_t Size) { namespace pt = boost::property_tree; if (Size < 1) { // no data to use for flags - skip. return 0; } std::stringstream ss; const auto firstbyte = Data[0]; ss.write(Data + 1, Size - 1); pt::ptree tree; try { // set the parse flags based on the first byte int flags = 0; if (firstbyte & 0x1) { flags |= pt::xml_parser::no_concat_text; } if (firstbyte & 0x2) { flags |= pt::xml_parser::no_comments; } if (firstbyte & 0x4) { flags |= pt::xml_parser::trim_whitespace; } pt::read_xml(ss, tree, flags); return tree.size() ? 1 : 0; } catch (...) { return 0; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { readXml(reinterpret_cast(Data), Size); return 0; } ================================================ FILE: projects/boost/boost_regex_fuzzer.cc ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // From https://svn.boost.org/trac10/ticket/12818 // This fuzz target can likely be enhanced to exercise more code. // The ideal place for this fuzz target is the boost repository. #ifdef DEBUG #include #endif #include #include namespace { void assertPostConditions(boost::match_results const& match, boost::regex const& e) { // See https://www.boost.org/doc/libs/1_71_0/libs/regex/doc/html/boost_regex/ref/regex_match.html assert(match.size() == e.mark_count() + 1); assert(!match.empty()); assert(!match.prefix().matched); assert(!match.suffix().matched); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { FuzzedDataProvider fuzzed_data(Data, Size); // First value is length of the regex string size_t regex_length = fuzzed_data.ConsumeIntegral(); // Second value is regexp string whose length is `regex_length` std::string regex_string = fuzzed_data.ConsumeBytesAsString(regex_length); try { boost::regex e(regex_string); // Last value is the text to be matched std::string text = fuzzed_data.ConsumeRemainingBytesAsString(); #ifdef DEBUG std::cout << "Regexp string: " << regex_string << "Size: " << regex_string.size() << std::endl; std::cout << "Text: " << text << "Size: " << text.size() << std::endl; #endif boost::match_results what; bool match = boost::regex_match(text, what, e, boost::match_default | boost::match_partial); if (match) assertPostConditions(what, e); } catch (const std::runtime_error &) { } return 0; } ================================================ FILE: projects/boost/boost_regex_pattern_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #ifdef DEBUG #include #endif #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { FuzzedDataProvider fdp(Data, Size); // Currently, we just consume all the fuzzed corpus into the regex pattern std::string regex_string = fdp.ConsumeRemainingBytesAsString(); const uint8_t where_array[] = {0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48}; std::string random(where_array, where_array + sizeof(where_array)); std::string empty(""); std::string spaces(" "); try { std::vector wheres; wheres.push_back(random); wheres.push_back(empty); wheres.push_back(spaces); boost::regex e(regex_string); // We're using multiple texts to be matched. #ifdef DEBUG std::cout << "Regexp string: " << regex_string << "Size: " << regex_string.size() << std::endl; #endif for (const auto& where : wheres) { try { boost::match_results what; bool match = boost::regex_match(where, what, e, boost::match_default | boost::match_partial | boost::match_posix | boost::match_any); } catch(...) { } try { boost::match_results what; bool match = boost::regex_match(where, what, e, boost::match_default | boost::match_partial | boost::match_perl | boost::match_any); } catch(...) { } } } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_regex_replace_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #ifdef DEBUG #include #endif #include #include #include #include // purpose of the fuzzer: // fuzz the format string syntax used in match-replace // // the mutator comes from a boost example that: // takes the contents of a file and transform to // syntax highlighted code in html format boost::regex e1, e2; extern const char* expression_text; extern const char* pre_expression; extern const char* pre_format; extern const char* match_against; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { FuzzedDataProvider fdp(Data, Size); std::string format_string = fdp.ConsumeRemainingBytesAsString(); try{ e1.assign(expression_text); e2.assign(pre_expression); std::string in; in.assign(match_against); std::ostringstream t(std::ios::out | std::ios::binary); std::ostream_iterator oi(t); boost::regex_replace(oi, in.begin(), in.end(), e2, format_string, boost::match_default | boost::format_all); std::string s(t.str()); #ifdef DEBUG std::cout << s << std::endl; #endif } catch(...) { } return 0; } const char* pre_expression = "(<)|(>)|(&)|\\r"; const char* pre_format = "(?1<)(?2>)(?3&)"; const char* expression_text = // preprocessor directives: index 1 "(^[[:blank:]]*#(?:[^\\\\\\n]|\\\\[^\\n[:punct:][:word:]]*[\\n[:punct:][:word:]])*)|" // comment: index 2 "(//[^\\n]*|/\\*.*?\\*/)|" // literals: index 3 "\\<([+-]?(?:(?:0x[[:xdigit:]]+)|(?:(?:[[:digit:]]*\\.)?[[:digit:]]+" "(?:[eE][+-]?[[:digit:]]+)?))u?(?:(?:int(?:8|16|32|64))|L)?)\\>|" // string literals: index 4 "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|" // keywords: index 5 "\\<(__asm|__cdecl|__declspec|__export|__far16|__fastcall|__fortran|__import" "|__pascal|__rtti|__stdcall|_asm|_cdecl|__except|_export|_far16|_fastcall" "|__finally|_fortran|_import|_pascal|_stdcall|__thread|__try|asm|auto|bool" "|break|case|catch|cdecl|char|class|const|const_cast|continue|default|delete" "|do|double|dynamic_cast|else|enum|explicit|extern|false|float|for|friend|goto" "|if|inline|int|long|mutable|namespace|new|operator|pascal|private|protected" "|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_cast" "|struct|switch|template|this|throw|true|try|typedef|typeid|typename|union|unsigned" "|using|virtual|void|volatile|wchar_t|while)\\>" ; const char* match_against = "#include " "#include " "#include " "#include " "" "" "extern \"C\" int main(int argc, char** argv) {" " std::string regex_string;" " std::getline(std::cin, regex_string);" " std::string where(\"AAAA\");" " try {" " boost::regex e(regex_string);" " std::cout << \"Regexp string: \" << regex_string << \"Size: \" << regex_string.size() << std::endl;" " boost::match_results what;" " bool match = boost::regex_match(where, what, e, boost::match_default | boost::match_partial | boost::match_perl | boost::match_posix | boost::match_any);" " if (match)" " std::cout << match << std::endl;" " }" " catch (const std::runtime_error &err) {" " std::cerr << \"Caught exception: \" << err.what() << std::endl;" " }" " return 0;" "}"; ================================================ FILE: projects/boost/boost_stralg_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { try{ FuzzedDataProvider fdp(Data, Size); std::string x = fdp.ConsumeRemainingBytesAsString(); boost::algorithm::to_upper_copy(x); boost::algorithm::trim_copy(x); boost::algorithm::replace_all_copy(x, "A", "LHVBSLDFVSDJHKG"); typedef boost::algorithm::find_iterator string_find_iterator; for(string_find_iterator It=boost::algorithm::make_find_iterator(x, boost::algorithm::first_finder("A", boost::algorithm::is_iequal())); It!=string_find_iterator(); ++It ){ boost::copy_range(*It); } typedef boost::algorithm::split_iterator string_split_iterator; for(string_split_iterator It=boost::algorithm::make_split_iterator(x, boost::algorithm::first_finder(" ", boost::algorithm::is_iequal())); It!=string_split_iterator(); ++It ){ boost::copy_range(*It); } boost::algorithm::erase_all_copy(x, "A"); boost::algorithm::erase_head_copy(x, 2147483647); boost::algorithm::erase_head_copy(x, -2147483648); boost::algorithm::erase_tail_copy(x, 2147483647); boost::algorithm::erase_tail_copy(x, -2147483648); } catch(...) { } return 0; } ================================================ FILE: projects/boost/boost_uuid_fuzzer.cc ================================================ /* Copyright 2024 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // The ideal place for this fuzz target is the boost repository. #include #include #include #include #include #include #include using namespace std; using namespace boost::uuids; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size){ try{ FuzzedDataProvider fdp(Data, Size); std::string s = fdp.ConsumeRemainingBytesAsString(); string_generator gen_string; name_generator_sha1 gen_name(ns::url()); hash hasher; uuid u_string, u_name; u_string = gen_string(s); u_name = gen_name(s); size_t string_hash = hasher(u_string); size_t name_hash = hash_value(u_name); size_t uuid_hash_value = hasher(boost::uuids::uuid()); string out_string = to_string(u_string); wstring out_wstring = to_wstring(u_string); swap(u_string, u_name); } catch(...) { } return 0; } ================================================ FILE: projects/boost/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Work around build issue cp "/usr/local/include/x86_64-unknown-linux-gnu/c++/v1/__config_site" "/usr/local/include/c++/v1/" # Build boost CXXFLAGS="$CXXFLAGS -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" \ ./bootstrap.sh --with-toolset=clang --prefix=/usr; echo "using clang : ossfuzz : $CXX : \"$CXXFLAGS\" \"$CXXFLAGS\" \"${LIB_FUZZING_ENGINE}\" ;" >user-config.jam ./b2 --user-config=user-config.jam --toolset=clang-ossfuzz link=static --with-headers --with-graph --with-filesystem --with-program_options headers stage; # Very simple build rule, but sufficient here. #boost regexp $CXX $CXXFLAGS -I . ../boost_regex_fuzzer.cc libs/regex/src/*.cpp $LIB_FUZZING_ENGINE -o boost_regex_fuzzer $CXX $CXXFLAGS -I . ../boost_regex_pattern_fuzzer.cc libs/regex/src/*.cpp $LIB_FUZZING_ENGINE -o boost_regex_pattern_fuzzer $CXX $CXXFLAGS -I . ../boost_regex_replace_fuzzer.cc libs/regex/src/*.cpp $LIB_FUZZING_ENGINE -o boost_regex_replace_fuzzer #boost property tree parsers $CXX $CXXFLAGS -I . ../boost_ptree_xmlread_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_ptree_xmlread_fuzzer $CXX $CXXFLAGS -I . ../boost_ptree_jsonread_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_ptree_jsonread_fuzzer $CXX $CXXFLAGS -I . ../boost_ptree_iniread_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_ptree_iniread_fuzzer $CXX $CXXFLAGS -I . ../boost_ptree_inforead_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_ptree_inforead_fuzzer #boost graph graphviz $CXX $CXXFLAGS -I . ../boost_graph_graphviz_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_graph_graphviz_fuzzer stage/lib/libboost_graph.a $CXX $CXXFLAGS -I . ../boost_graph_graphml_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_graph_graphml_fuzzer stage/lib/libboost_graph.a #boost datetime $CXX $CXXFLAGS -I . ../boost_datetime_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_datetime_fuzzer #boost filesystem $CXX $CXXFLAGS -I . ../boost_filesystem_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_filesystem_fuzzer stage/lib/libboost_filesystem.a #boost algorithm/strings $CXX $CXXFLAGS -I . ../boost_stralg_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_stralg_fuzzer #boost uuid $CXX $CXXFLAGS -I . ../boost_uuid_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_uuid_fuzzer #boost programoptions $CXX $CXXFLAGS -I . ../boost_programoptions_fuzzer.cc $LIB_FUZZING_ENGINE -o boost_programoptions_fuzzer stage/lib/libboost_program_options.a # Copy the fuzzer executables, zip-ed corpora, option and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' # find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' # If you have dictionaries. # find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' # If you have custom options. find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' # If you have seed corpora (you better have them!) ================================================ FILE: projects/boost/project.yaml ================================================ homepage: "http://www.boost.org/" language: c++ primary_contact: "mclow@boost.org" auto_ccs: - "jz.maddock@googlemail.com" - "bshas3@gmail.com" - "jking@apache.org" - "jeremy.william.murphy@gmail.com" - "christian.mazakas@gmail.com" - "research@shielder.it" main_repo: 'https://github.com/boostorg/boost.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/boost-beast/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder:v1 RUN git clone --depth 1 --single-branch --branch master https://github.com/boostorg/boost.git WORKDIR boost RUN git submodule update --init libs/beast RUN git -C libs/beast checkout develop RUN git submodule update --init tools/boostdep RUN python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" beast COPY build.sh $SRC/ ================================================ FILE: projects/boost-beast/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ./bootstrap.sh echo "using clang : ossfuzz : $CXX : \"$CXXFLAGS\" \"$CXXFLAGS\" \"${LIB_FUZZING_ENGINE}\" ;" >user-config.jam ./b2 --user-config=user-config.jam --toolset=clang-ossfuzz --prefix=$WORK/stage --with-headers link=static install tar -xvf libs/beast/test/fuzz/seeds.tar -C libs/beast/test/fuzz for i in libs/beast/test/fuzz/*.cpp; do fuzzer=$(basename $i .cpp) $CXX $CXXFLAGS -pthread -I $WORK/stage/include libs/beast/test/fuzz/$fuzzer.cpp $LIB_FUZZING_ENGINE -o $OUT/$fuzzer if [ -d "libs/beast/test/fuzz/seeds/$fuzzer" ]; then zip -q -r -j $OUT/"$fuzzer"_seed_corpus.zip libs/beast/test/fuzz/seeds/$fuzzer fi done ================================================ FILE: projects/boost-beast/project.yaml ================================================ homepage: "https://www.boost.org/" language: c++ primary_contact: "vinnie.falco@gmail.com" auto_ccs: - "ashtumashtum@gmail.com" main_repo: 'https://github.com/boostorg/beast.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/boost-json/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 --single-branch --branch master https://github.com/boostorg/boost.git RUN pwd RUN ls RUN git -C boost submodule update --init libs/json RUN git -C boost/libs/json checkout develop RUN git -C boost submodule update --init --depth 1 \ libs/assert \ libs/config/ \ libs/compat \ libs/container \ libs/container_hash/ \ libs/core \ libs/describe \ libs/endian \ libs/headers/ \ libs/intrusive/ \ libs/move/ \ libs/mp11/ \ libs/predef/ \ libs/system/ \ libs/throw_exception/ \ libs/winapi/ \ libs/variant2/ \ tools/boost_install \ tools/build WORKDIR boost COPY build.sh $SRC/ ================================================ FILE: projects/boost-json/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./bootstrap.sh --with-toolset=clang echo "using clang : ossfuzz : $CXX : \"$CXXFLAGS\" \"$CXXFLAGS\" \"${LIB_FUZZING_ENGINE}\" ;" >user-config.jam ./b2 --user-config=user-config.jam \ --toolset=clang-ossfuzz \ --prefix=$WORK/stage \ --with-json \ include=/usr/local/include/x86_64-unknown-linux-gnu/c++/v1 \ link=static \ install for i in libs/json/fuzzing/*.cpp; do fuzzer=$(basename $i .cpp) $CXX $CXXFLAGS -pthread libs/json/fuzzing/$fuzzer.cpp -I $WORK/stage/include/ $WORK/stage/lib/*.a $LIB_FUZZING_ENGINE -o $OUT/$fuzzer zip -q -r -j $OUT/${fuzzer}_seed_corpus.zip libs/json/fuzzing/old_crashes done ================================================ FILE: projects/boost-json/project.yaml ================================================ homepage: "http://www.boost.org/" language: c++ primary_contact: "pauldreikossfuzz@gmail.com" auto_ccs: - "vinnie.falco@gmail.com" - "grisumbras@gmail.com" - "pdimov@gmail.com" main_repo: 'https://github.com/boostorg/json.git' ================================================ FILE: projects/boringssl/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y wget \ binutils cmake ninja-build liblzma-dev libz-dev \ pkg-config autoconf libtool RUN git clone --depth 1 https://boringssl.googlesource.com/boringssl # Use ASN.1 pdu protobuf and converter from the google/fuzzing repo. RUN git clone --depth 1 https://github.com/google/fuzzing.git RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git RUN (mkdir LPM && cd LPM && cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release && ninja) COPY *.cc build.sh $SRC/ ================================================ FILE: projects/boringssl/build.sh ================================================ #!/bin/bash -eux # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir -p $WORK/boringssl cd $WORK/boringssl CFLAGS="$CFLAGS -DBORINGSSL_UNSAFE_FUZZER_MODE" CXXFLAGS="$CXXFLAGS -DBORINGSSL_UNSAFE_FUZZER_MODE" CMAKE_DEFINES="-DBORINGSSL_ALLOW_CXX_RUNTIME=1" if [[ $CFLAGS = *sanitize=memory* ]] then CMAKE_DEFINES+=" -DOPENSSL_NO_ASM=1" fi cmake -GNinja -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX \ -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ $CMAKE_DEFINES $SRC/boringssl/ ninja fuzzerFiles=$(find $SRC/boringssl/fuzz/ -name "*.cc") find . -name "*.a" for F in $fuzzerFiles; do fuzzerName=$(basename $F .cc) echo "Building fuzzer $fuzzerName" $CXX $CXXFLAGS \ -D_BORINGSSL_LIBPKI_ -std=c++1z \ -o $OUT/${fuzzerName} $LIB_FUZZING_ENGINE $F \ -I $SRC/boringssl/include ./libpki.a ./libssl.a ./libcrypto.a if [ -d "$SRC/boringssl/fuzz/${fuzzerName}_corpus" ]; then zip -j $OUT/${fuzzerName}_seed_corpus.zip $SRC/boringssl/fuzz/${fuzzerName}_corpus/* fi done if [[ $CFLAGS != *sanitize=memory* ]]; then fuzzerLPMFiles=$(find $SRC/ -maxdepth 1 -name "*.cc") cp $SRC/fuzzing/proto/asn1-pdu/* $SRC/ rm -rf genfiles && mkdir genfiles && $SRC/LPM/external.protobuf/bin/protoc asn1_pdu.proto --cpp_out=genfiles --proto_path=$SRC/ for F in $fuzzerLPMFiles do fuzzerName=$(echo ${F#*_}) fuzzerName=$(basename $fuzzerName .cc) echo "Building fuzzer $fuzzerName" $CXX $CXXFLAGS -I genfiles -I . -I $SRC/libprotobuf-mutator/ -I $SRC/LPM/external.protobuf/include -I include $LIB_FUZZING_ENGINE \ -DNDEBUG \ -I $SRC/boringssl/include \ $F genfiles/asn1_pdu.pb.cc $SRC/asn1_pdu_to_der.cc $SRC/common.cc \ ./libssl.a ./libcrypto.a \ $SRC/LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ $SRC/LPM/src/libprotobuf-mutator.a \ -Wl,--start-group $SRC/LPM/external.protobuf/lib/lib*.a -Wl,--end-group \ -o $OUT/"${fuzzerName}_lpm" done fi ================================================ FILE: projects/boringssl/fuzz_certs.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // This fuzz target fuzzes the same API as // https://github.com/google/boringssl/blob/master/fuzz/cert.cc, but it employs // libprotobuf-mutator for structure-aware fuzzing. #include #include #include #include "asn1_pdu.pb.h" #include "asn1_pdu_to_der.h" #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { asn1_pdu::ASN1PDUToDER converter; std::vector encoded = converter.PDUToDER(asn1); const uint8_t* buf = encoded.data(); size_t len = encoded.size(); X509* x509 = d2i_X509(NULL, &buf, len); if (x509 != NULL) { // Extract the public key. EVP_PKEY_free(X509_get_pubkey(x509)); // Reserialize the structure. uint8_t* der = NULL; i2d_X509(x509, &der); OPENSSL_free(der); } X509_free(x509); ERR_clear_error(); } ================================================ FILE: projects/boringssl/fuzz_pkcs12.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // This fuzz target fuzzes the same API as // https://github.com/google/boringssl/blob/master/fuzz/pkcs12.cc, but it // employs libprotobuf-mutator for structure-aware fuzzing. #include #include #include #include #include "asn1_pdu.pb.h" #include "asn1_pdu_to_der.h" #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { asn1_pdu::ASN1PDUToDER converter; std::vector encoded = converter.PDUToDER(asn1); const uint8_t* buf = encoded.data(); size_t len = encoded.size(); bssl::UniquePtr certs(sk_X509_new_null()); EVP_PKEY* key = nullptr; CBS cbs; CBS_init(&cbs, buf, len); PKCS12_get_key_and_certs(&key, certs.get(), &cbs, "foo"); EVP_PKEY_free(key); } ================================================ FILE: projects/boringssl/fuzz_pkcs8.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // This fuzz target fuzzes the same API as // https://github.com/google/boringssl/blob/master/fuzz/pkcs8.cc, but it employs // libprotobuf-mutator for structure-aware fuzzing. #include #include #include #include #include "asn1_pdu.pb.h" #include "asn1_pdu_to_der.h" #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" DEFINE_PROTO_FUZZER(const asn1_pdu::PDU& asn1) { asn1_pdu::ASN1PDUToDER converter; std::vector encoded = converter.PDUToDER(asn1); const uint8_t* buf = encoded.data(); size_t len = encoded.size(); CBS cbs; CBS_init(&cbs, buf, len); bssl::UniquePtr pkey(EVP_parse_private_key(&cbs)); if (pkey == NULL) { return; } uint8_t* der; size_t der_len; bssl::ScopedCBB cbb; if (CBB_init(cbb.get(), 0) && EVP_marshal_private_key(cbb.get(), pkey.get()) && CBB_finish(cbb.get(), &der, &der_len)) { OPENSSL_free(der); } ERR_clear_error(); } ================================================ FILE: projects/boringssl/project.yaml ================================================ homepage: "https://boringssl.googlesource.com/boringssl/" language: c++ primary_contact: "agl@google.com" auto_ccs: - "bbe@google.com" - "davidben@google.com" - "svaldez@google.com" sanitizers: - address - undefined - memory main_repo: 'https://boringssl.googlesource.com/boringssl' ================================================ FILE: projects/botan/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make python RUN git clone --depth 1 https://github.com/randombit/botan.git botan RUN git clone --depth 1 https://github.com/randombit/crypto-corpus.git fuzzer_corpus WORKDIR botan COPY *.sh $SRC/ ================================================ FILE: projects/botan/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/botan ln -s $SRC/fuzzer_corpus . ./src/scripts/config_for_oss_fuzz.py $CXX "$CXXFLAGS" make -j$(nproc) libs fuzzers make fuzzer_corpus_zip # the seed corpus zips will also be in this directory cp build/fuzzer/* $OUT ================================================ FILE: projects/botan/project.yaml ================================================ homepage: "https://botan.randombit.net" language: c++ primary_contact: "jack.lloyd@gmail.com" auto_ccs: - "re.korthaus@googlemail.com" - "droelf@googlemail.com" - "norritt@bytefortress.de" sanitizers: - address - memory - undefined main_repo: 'https://github.com/randombit/botan.git' fuzzing_engines: - afl - centipede - honggfuzz - libfuzzer ================================================ FILE: projects/botan/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## make -j$(nproc) check ================================================ FILE: projects/botocore/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone --depth=1 https://github.com/boto/botocore botocore COPY *.sh *py $SRC/ WORKDIR $SRC/botocore ================================================ FILE: projects/botocore/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/botocore/fuzz_serialization.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import io import botocore from botocore import serialize from botocore.model import ServiceModel def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) protocols = [ 'rest-xml', 'json', 'query' ] protocol_str = protocols[fdp.ConsumeIntInRange(0, len(protocols)-1)] # Simple model with a single shape of type blob model = { 'metadata': {'protocol': protocol_str, 'apiVersion': '2022-01-01'}, 'documentation': '', 'operations': { 'FuzzOperation': { 'name': 'FuzzOperation', 'http': { 'method': 'POST', 'requestUri': '/', }, 'input': {'shape': 'FuzzInputShape'}, } }, 'shapes': { 'FuzzInputShape': { 'type': 'structure', 'members': { 'Blob': {'shape': 'BlobType'}, }, }, 'BlobType': { 'type': 'blob', }, }, } service_model = ServiceModel(model) request_serializer = serialize.create_serializer( service_model.metadata['protocol'] ) body = io.BytesIO(data) try: request_serializer.serialize_to_request( body, service_model.operation_model('FuzzOperation') ) except botocore.exceptions.ParamValidationError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/botocore/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/boto/botocore language: python main_repo: https://github.com/boto/botocore sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/bottleneck/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN pip3 install --upgrade pip && pip3 install cython numpy RUN git clone --depth 1 https://github.com/pydata/bottleneck WORKDIR bottleneck COPY build.sh *.py $SRC/ ================================================ FILE: projects/bottleneck/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/bottleneck pip3 install . python3 setup.py install # Build fuzzers and put them in $OUT/ for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/bottleneck/fuzz_bn.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Scalar equivalene checker""" import os import sys import atheris import numpy as np from numpy.testing import assert_array_almost_equal import bottleneck as bn def gen_random_array(data, fdp = None): if fdp is None: fdp = atheris.FuzzedDataProvider(data) l1 = list() for i in range(fdp.ConsumeIntInRange(5, 3000)): l1.append(fdp.ConsumeIntInRange(1,10000)) a = np.array(l1) return a def TestOneInput(data): """Tests scalar equivalence and also move operations""" fdp = atheris.FuzzedDataProvider(data) a = gen_random_array(data, fdp) func_pairs = [ (bn.nansum, bn.slow.nansum), (bn.nanmean, bn.slow.nanmean), (bn.nanstd, bn.slow.nanstd), (bn.nanvar, bn.slow.nanvar), (bn.nanmin, bn.slow.nanmin), (bn.median, bn.slow.median), (bn.nanmedian, bn.slow.nanmedian), (bn.ss, bn.slow.ss), (bn.nanargmin, bn.slow.nanargmin), (bn.nanargmax, bn.slow.nanargmax), (bn.anynan, bn.slow.anynan), (bn.allnan, bn.slow.allnan), ] idx = 0 for func0, func1 in func_pairs: idx = idx + 1 actual = func0(a) desired = func1(a) assert_array_almost_equal( actual, desired, err_msg="Failed scalar equivalence" ) # Test move operations window = fdp.ConsumeIntInRange(2, 50) min_count = fdp.ConsumeIntInRange(1, window) try: actual = bn.move_median( a, window=window, min_count = fdp.ConsumeIntInRange(1,100) ) except ValueError: return try: desired = bn.slow.move_median( a, window=window, min_count=fdp.ConsumeIntInRange(1, 100) ) except ValueError: return assert_array_almost_equal( actual, desired, err_msg="Failed move operation" ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/bottleneck/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pydata/bottleneck language: python main_repo: https://github.com/pydata/bottleneck sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/brotli/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake libtool make RUN git clone --depth 1 https://github.com/google/brotli.git WORKDIR brotli COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/brotli/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cmake . -DBUILD_TESTING=ON -DBUILD_SHARED_LIBS=OFF make clean make -j$(nproc) $CC $CFLAGS -c -std=c99 -I. -I./c/include c/fuzz/decode_fuzzer.c $CXX $CXXFLAGS ./decode_fuzzer.o -o $OUT/decode_fuzzer \ $LIB_FUZZING_ENGINE ./libbrotlidec.a ./libbrotlicommon.a cp java/org/brotli/integration/fuzz_data.zip $OUT/decode_fuzzer_seed_corpus.zip chmod a-x $OUT/decode_fuzzer_seed_corpus.zip # we will try to run it otherwise ================================================ FILE: projects/brotli/project.yaml ================================================ homepage: "https://github.com/google/brotli" language: c++ primary_contact: "eustas@chromium.org" vendor_ccs: - "jkew@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/google/brotli.git' file_github_issue: True ================================================ FILE: projects/brotli/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/brotli make test ================================================ FILE: projects/brotli-java/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/brotli brotli-java WORKDIR brotli-java COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/brotli-java/FuzzDecode.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.*; import org.brotli.dec.BrotliInputStream; public class FuzzDecode { public static void fuzzerTestOneInput(FuzzedDataProvider data) { byte[] buffer = new byte[65536]; byte[] inputBytes = data.consumeBytes(65536); // Brotli allows 0-bit prefix codes - thus even small input could produce large output. long totalOutputCap = Math.min(4096L * inputBytes.length, 3L << 24); totalOutputCap = Math.max(totalOutputCap, 1L << 20); long totalOutput = 0; ByteArrayInputStream input = new ByteArrayInputStream(inputBytes); try { BrotliInputStream brotliInput = new BrotliInputStream(input); while (true) { int len = brotliInput.read(buffer, 0, buffer.length); if (len <= 0) { break; } totalOutput += len; if (totalOutput >= totalOutputCap) break; } } catch (IOException expected) {} } } ================================================ FILE: projects/brotli-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd java/org/brotli sed -i 's/1.6 $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/brotli-java/project.yaml ================================================ homepage: "https://github.com/google/brotli/tree/master/java" language: jvm primary_contact: "eustas@chromium.org" main_repo: "https://github.com/google/brotli" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address file_github_issue: True ================================================ FILE: projects/brpc/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev libgtest-dev libgoogle-perftools-dev libsnappy-dev RUN git clone --depth 1 https://github.com/apache/brpc.git RUN cp $SRC/brpc/test/fuzzing/oss-fuzz.sh $SRC/build.sh WORKDIR $SRC/brpc/ COPY run_tests.sh $SRC/ ================================================ FILE: projects/brpc/project.yaml ================================================ homepage: "https://brpc.apache.org" language: c++ primary_contact: "security@apache.org" vendor_ccs: - "zhujiashun2010@gmail.com" - "wangweibing@baidu.com" - "serverglen@gmail.com" - "jerrytan@apache.org" auto_ccs: - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined main_repo: "https://github.com/apache/incubator-brpc" base_os_version: ubuntu-24-04 ================================================ FILE: projects/brpc/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable leak sanitizer export ASAN_OPTIONS="detect_leaks=0" # Disable failing testing and tests requires network connection and run the remaining unit testings make -C $SRC/brpc/build/test -j$(nproc) && ctest --test-dir $SRC/brpc/build --output-on-failure -j$(nproc) -E \ "test_butil|bthread_timer_thread_unittest|brpc_alpn_protocol_unittest|brpc_channel_unittest|brpc_interceptor_unittest|brpc_ssl_unittest|bthread_mutex_unittest|bthread_cond_unittest|bthread_butex_unittest|bthread_dispatcher_unittest|bthread_fd_unittest|bthread_setconcurrency_unittest|brpc_http_rpc_protocol_unittest|brpc_naming_service_unittest|brpc_event_dispatcher_unittest|brpc_server_unittest|brpc_streaming_rpc_unittest|brpc_socket_unittest" ================================================ FILE: projects/brunsli/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake libtool make RUN git clone --depth 1 https://github.com/google/brunsli.git && \ cd brunsli && \ git submodule update --init --depth 1 WORKDIR brunsli COPY *.sh $SRC/ ================================================ FILE: projects/brunsli/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Bump gtest to work with llvm21: https://github.com/google/oss-fuzz/pull/13915 sed -i 's/e2239ee6043f73722e7aa812a459f54a28552929/6910c9d9165801d8827d628cb72eb7ea9dd538c5/g' CMakeLists.txt cmake . -DBUILD_TESTING=ON make clean make -j$(nproc) all # TODO(eustas): add seed corpus $CXX $CXXFLAGS -std=c++11 -I./c/include c/tests/fuzz_decode.cc \ ./CMakeFiles/build_huffman_table_test.dir/c/tests/test_utils.cc.o \ -o $OUT/fuzz_decode $LIB_FUZZING_ENGINE \ ./artifacts/libbrunslidec-static.a ./artifacts/libbrunslicommon-static.a \ ./_deps/brotli-build/libbrotlidec-static.a \ ./_deps/brotli-build/libbrotlicommon-static.a $CXX $CXXFLAGS -std=c++11 -I./c/include c/tests/fuzz_decode_streaming.cc \ ./CMakeFiles/build_huffman_table_test.dir/c/tests/test_utils.cc.o \ -o $OUT/fuzz_decode_streaming $LIB_FUZZING_ENGINE \ ./artifacts/libbrunslidec-static.a ./artifacts/libbrunslicommon-static.a \ ./_deps/brotli-build/libbrotlidec-static.a \ ./_deps/brotli-build/libbrotlicommon-static.a ================================================ FILE: projects/brunsli/project.yaml ================================================ homepage: "https://github.com/google/brunsli" language: c++ primary_contact: "eustas@chromium.org" vendor_ccs: - "jkew@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/google/brunsli.git' file_github_issue: True base_os_version: ubuntu-24-04 ================================================ FILE: projects/brunsli/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### make test ================================================ FILE: projects/bs4/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Held back because of github.com/google/oss-fuzz/pull/13407 # Please fix the build failure + upgrade. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y bzr git libxslt-dev libxml2-dev zlib1g-dev RUN python3 -m pip install --upgrade pip RUN python3 -m pip install soupsieve html5lib lxml RUN python3 -m pip install git+https://git.launchpad.net/beautifulsoup COPY build.sh bs4_fuzzer.py $SRC/ ================================================ FILE: projects/bs4/bs4_fuzzer.py ================================================ #!/usr/bin/python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import logging import warnings from bs4 import BeautifulSoup, ParserRejectedMarkup import soupsieve from soupsieve.util import SelectorSyntaxError try: import HTMLParser HTMLParseError = HTMLParser.HTMLParseError except ImportError: # HTMLParseError is removed in Python 3.5. Since it can never be # thrown in 3.5, we can just define our own class as a placeholder. class HTMLParseError(Exception): pass @atheris.instrument_func def TestOneInput(data): """TestOneInput gets random data from the fuzzer, and throws it at bs4.""" if len(data) < 12: return parsers = ['lxml-xml', 'html5lib', 'html.parser', 'lxml'] try: idx = int(data[0]) % len(parsers) except ValueError: return css_selector, data = data[1:10], data[10:] try: soup = BeautifulSoup(data[1:], features=parsers[idx]) except HTMLParseError: return except ValueError: return except ParserRejectedMarkup: return list(soup.find_all(True)) if soup.css: try: soup.css.select(css_selector.decode('utf-8', 'replace')) except SelectorSyntaxError: return except NotImplementedError: return soup.prettify() def main(): logging.disable(logging.CRITICAL) warnings.filterwarnings('ignore') atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/bs4/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/bs4/project.yaml ================================================ homepage: "https://www.crummy.com/software/BeautifulSoup/" main_repo: "https://code.launchpad.net/~leonardr/beautifulsoup/bs4" language: python primary_contact: "leonard.richardson@gmail.com" auto_ccs: - "julien.voisin@dustri.org" - "ipudney@google.com" - "security@tidelift.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined base_os_version: ubuntu-24-04 ================================================ FILE: projects/bson-rust/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/mongodb/bson-rust bson-rust WORKDIR bson-rust COPY build.sh $SRC/ ================================================ FILE: projects/bson-rust/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -eox pipefail target_out_dir=fuzz/target/x86_64-unknown-linux-gnu/release cargo fuzz build -O cargo fuzz list | while read i; do [[ "$i" == "generate_corpus" ]] && continue cp $target_out_dir/$i $OUT/ done ================================================ FILE: projects/bson-rust/project.yaml ================================================ homepage: "https://github.com/mongodb/bson-rust" language: rust main_repo: "https://github.com/mongodb/bson-rust" sanitizers: - address fuzzing_engines: - libfuzzer vendor_ccs: - maxnair.dev@gmail.com ================================================ FILE: projects/burntsushi-toml/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/BurntSushi/toml toml COPY build.sh $SRC/ WORKDIR $SRC/toml ================================================ FILE: projects/burntsushi-toml/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/BurntSushi/toml/ossfuzz FuzzToml fuzz_toml gofuzz ================================================ FILE: projects/burntsushi-toml/project.yaml ================================================ homepage: "https://github.com/BurntSushi/toml" language: go main_repo: "https://github.com/BurntSushi/toml" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - maxnair.dev@gmail.com ================================================ FILE: projects/bz2file/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/nvawda/bz2file bz2file COPY *.sh *py $SRC/ WORKDIR $SRC/bz2file ================================================ FILE: projects/bz2file/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/bz2file/fuzz_bz2file.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import bz2file def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) bzfile_path = '/tmp/random_file.txt' with open(bzfile_path, 'wb') as f: f.write(fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 2048))) try: with bz2file.open(bzfile_path) as target_file: target_file.seek(fdp.ConsumeIntInRange(-1, 100)) target_file.read(size=fdp.ConsumeIntInRange(-1, 100)) except (ValueError,EOFError,OSError): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/bz2file/project.yaml ================================================ homepage: https://github.com/nvawda/bz2file main_repo: https://github.com/nvawda/bz2file language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/bzip2/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone git://sourceware.org/git/bzip2.git RUN git clone git://sourceware.org/git/bzip2-tests.git COPY run_tests.sh build.sh *.c $SRC/ WORKDIR $SRC ================================================ FILE: projects/bzip2/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd bzip2 SRCL=(blocksort.o huffman.o crctable.o randtable.o compress.o decompress.o bzlib.o) for source in ${SRCL[@]}; do name=$(basename $source .o) $CC $CFLAGS -c ${name}.c done rm -f libbz2.a ar cq libbz2.a ${SRCL[@]} && ranlib libbz2.a # build fuzzers for file in $SRC/*.c; do name=$(basename $file .c) $CC $CFLAGS -c -I . $SRC/${name}.c -o $OUT/${name}.o $CXX $CXXFLAGS -o $OUT/${name} $OUT/${name}.o $LIB_FUZZING_ENGINE \ libbz2.a rm -f $OUT/${name}.o done # build decompress seed corpus from ".bz2" samples # 1) look for all ".bz2" files in ./bzip2 and ./bzip2-test that are <100k # 2) remove base file name collisions # 3) add to (bzip2_decompress_target_seed_corpus.zip) archive find $SRC/bzip2* -type f -name "*.bz2" -size -100k \ | awk -F/ '{a[$NF]=$0}END{for(i in a)print a[i]}' \ | zip -j0r bzip2_decompress_target_seed_corpus.zip -@ ================================================ FILE: projects/bzip2/bzip2_compress_target.c ================================================ /* # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### */ #include "bzlib.h" #include #include #include #include extern int BZ2_bzBuffToBuffCompress(char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int blockSize100k, int verbosity, int workFactor); extern int BZ2_bzBuffToBuffDecompress(char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int small, int verbosity); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int r, blockSize100k, workFactor, small; unsigned int nZ, nOut; /* Copying @julian-seward1's comment from * https://github.com/google/oss-fuzz/pull/1887#discussion_r226852388 * * They just reflect the fact that the worst case output size is 101% * of the input size + 600 bytes (I assume -- this is now nearly 20 * years old). Since the buffer is in mallocville, presumably asan * will complain if it gets overrun. I doubt that will happen though. */ nZ = size + 600 + (size / 100); char *zbuf = malloc(nZ); blockSize100k = (size % 11) + 1; if (blockSize100k > 9) { blockSize100k = 9; } workFactor = size % 251; // Choose highest compression (blockSize100k=9) r = BZ2_bzBuffToBuffCompress(zbuf, &nZ, (char *)data, size, blockSize100k, /*verbosity=*/0, workFactor); if (r != BZ_OK) { #ifdef __DEBUG__ fprintf(stdout, "Compression error: %d\n", r); #endif free(zbuf); return 0; } nOut = size*2; char *outbuf = malloc(nOut); small = size % 2; r = BZ2_bzBuffToBuffDecompress(outbuf, &nOut, zbuf, nZ, small, /*verbosity=*/0); if (r != BZ_OK) { #ifdef __DEBUG__ fprintf(stdout, "Decompression error: %d\n", r); #endif free(zbuf); free(outbuf); return 0; } assert(nOut == size); assert(memcmp(data, outbuf, size) == 0); free(zbuf); free(outbuf); return 0; } ================================================ FILE: projects/bzip2/bzip2_decompress_target.c ================================================ /* # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### */ #include "bzlib.h" #include #include #include #include extern int BZ2_bzBuffToBuffDecompress(char* dest, unsigned int* destLen, char* source, unsigned int sourceLen, int small, int verbosity); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int r, small; unsigned int nZ, nOut; // See: https://github.com/google/bzip2-rpc/blob/master/unzcrash.c#L39 nOut = size*2; char *outbuf = malloc(nOut); small = size % 2; r = BZ2_bzBuffToBuffDecompress(outbuf, &nOut, (char *)data, size, small, /*verbosity=*/0); if (r != BZ_OK) { #ifdef __DEBUG__ fprintf(stdout, "Decompression error: %d\n", r); #endif } free(outbuf); return 0; } ================================================ FILE: projects/bzip2/bzip2_fd.c ================================================ /* # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### */ #include "bzlib.h" #include #include #include #include #include #include static void fuzzer_write_data(FILE *file, const uint8_t *data, size_t size) { int bzerr = 0; int blockSize100k = 9; int verbosity = 0; int workFactor = 30; unsigned int nbytes_in_lo32, nbytes_in_hi32; unsigned int nbytes_out_lo32, nbytes_out_hi32; BZFILE* bzf = BZ2_bzWriteOpen(&bzerr, file, blockSize100k, verbosity, workFactor); if (bzerr != BZ_OK) return; /* Use low-level BZ2_bzWrite (was incorrectly using high-level BZ2_bzwrite) */ BZ2_bzWrite(&bzerr, bzf, (void*)data, size); BZ2_bzWriteClose64(&bzerr, bzf, 0, &nbytes_in_lo32, &nbytes_in_hi32, &nbytes_out_lo32, &nbytes_out_hi32); } static void fuzzer_read_data(const int file_descriptor) { int bzerr = 0; char obuf[BZ_MAX_UNUSED]; BZFILE* bzf2 = BZ2_bzdopen(file_descriptor, "rb"); if (!bzf2) return; while (bzerr == BZ_OK) { int nread = BZ2_bzRead(&bzerr, bzf2, obuf, BZ_MAX_UNUSED); if (nread == 0 && bzerr == BZ_OK) break; } BZ2_bzclose(bzf2); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char* filename = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename) { return 0; } const int file_descriptor = mkstemp(filename); if (file_descriptor < 0) { free(filename); return 0; } FILE* file = fdopen(file_descriptor, "wb"); if (!file) { close(file_descriptor); free(filename); return 0; } fuzzer_write_data(file, data, size); fflush(file); int read_fd = open(filename, O_RDONLY); if (read_fd >= 0) { fuzzer_read_data(read_fd); } /* Removed BZ2_bzflush(file) - it expects BZFILE*, not FILE* */ fclose(file); unlink(filename); free(filename); return 0; } ================================================ FILE: projects/bzip2/bzip2_filename.c ================================================ /* # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### */ #include "bzlib.h" #include #include #include #include #include #include #include #include static void fuzzer_write_data(FILE *file, const uint8_t *data, size_t size) { int bzerr = 0; int blockSize100k = 9; int verbosity = 0; int workFactor = 30; uint nbytes_in_lo32, nbytes_in_hi32; uint nbytes_out_lo32, nbytes_out_hi32; BZFILE* bzf = BZ2_bzWriteOpen ( &bzerr, file, blockSize100k, verbosity, workFactor ); BZ2_bzWrite (&bzerr, bzf, (void*)data, size); BZ2_bzWriteClose64 ( &bzerr, bzf, 0, &nbytes_in_lo32, &nbytes_in_hi32, &nbytes_out_lo32, &nbytes_out_hi32 ); return; } static void fuzzer_read_data(char *filename) { int bzerr = 0; char obuf[BZ_MAX_UNUSED]; BZFILE* bzf2 = BZ2_bzopen(filename,"rb"); while (bzerr == BZ_OK) { BZ2_bzRead ( &bzerr, bzf2, obuf, BZ_MAX_UNUSED); } BZ2_bzReadClose ( &bzerr, bzf2); return; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char* filename = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename) { perror("Failed to allocate file name buffer."); abort(); } const int file_descriptor = mkstemp(filename); if (file_descriptor < 0) { perror("Failed to make temporary file."); abort(); } FILE* file = fdopen(file_descriptor, "wb"); if (!file) { perror("Failed to open file descriptor."); close(file_descriptor); abort(); } fuzzer_write_data(file, data, size); fuzzer_read_data(filename); BZ2_bzlibVersion(); BZ2_bzflush(file); fclose(file); if (unlink(filename) != 0) { perror("WARNING: Failed to delete temporary file."); } free(filename); return 0; } ================================================ FILE: projects/bzip2/project.yaml ================================================ homepage: "https://sourceware.org/bzip2/" language: c++ primary_contact: "bzip2fuzzer@gmail.com" auto_ccs: - "bshas3@gmail.com" vendor_ccs: - "twsmith@mozilla.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined architectures: - x86_64 - i386 ================================================ FILE: projects/bzip2/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/bzip2-tests/run-tests.sh --tests-dir=bzip2-tests/ ================================================ FILE: projects/c-ares/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config RUN git clone --depth 1 https://github.com/c-ares/c-ares.git RUN git clone --depth 1 https://github.com/google/googletest WORKDIR c-ares COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/c-ares/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/googletest mkdir build cd build cmake .. make -j$(nproc) make install cd $SRC/c-ares # Build the project. ./buildconf ./configure --enable-debug --enable-tests make clean make -j$(nproc) V=1 all # Build the fuzzers. $CC $CFLAGS -Iinclude -Isrc/lib -c $SRC/c-ares/test/ares-test-fuzz.c -o $WORK/ares-test-fuzz.o $CXX $CXXFLAGS -std=c++11 $WORK/ares-test-fuzz.o \ -o $OUT/ares_parse_reply_fuzzer \ $LIB_FUZZING_ENGINE $SRC/c-ares/src/lib/.libs/libcares.a $CC $CFLAGS -Iinclude -Isrc/lib -c $SRC/c-ares/test/ares-test-fuzz-name.c \ -o $WORK/ares-test-fuzz-name.o $CXX $CXXFLAGS -std=c++11 $WORK/ares-test-fuzz-name.o \ -o $OUT/ares_create_query_fuzzer \ $LIB_FUZZING_ENGINE $SRC/c-ares/src/lib/.libs/libcares.a # Archive and copy to $OUT seed corpus if the build succeeded. zip -j $OUT/ares_parse_reply_fuzzer_seed_corpus.zip $SRC/c-ares/test/fuzzinput/* zip -j $OUT/ares_create_query_fuzzer_seed_corpus.zip \ $SRC/c-ares/test/fuzznames/* ================================================ FILE: projects/c-ares/project.yaml ================================================ homepage: "https://c-ares.haxx.se/" language: c++ primary_contact: "drysdale@google.com" auto_ccs: - "daniel.haxx@gmail.com" - "brad@brad-house.com" fuzzing_engines: - afl - libfuzzer - honggfuzz sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/c-ares/c-ares.git' ================================================ FILE: projects/c-ares/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/c-ares/test make test ================================================ FILE: projects/c-blosc/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/Blosc/c-blosc.git c-blosc WORKDIR c-blosc COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/c-blosc/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build with fuzzer and unit test (Turn on shared build for unit testing only) # Shared library of local zstd requires x64 architecture, thus disable it # in i386 architecture if [ "$ARCHITECTURE" = "i386" ]; then cmake . -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_FUZZERS=ON -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=OFF \ -DBUILD_STATIC=ON -DBUILD_SHARED=ON -DDEACTIVATE_ZSTD=ON else cmake . -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_FUZZERS=ON -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=OFF \ -DBUILD_STATIC=ON -DBUILD_SHARED=ON fi make clean make -j$(nproc) # Package seed corpus zip -j $OUT/decompress_fuzzer_seed_corpus.zip compat/*.cdata # Copy the fuzzer executables, zip-ed corpora, and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' ================================================ FILE: projects/c-blosc/project.yaml ================================================ homepage: "https://github.com/Blosc/c-blosc" language: c++ primary_contact: "blosc.oss.fuzz@gmail.com" auto_ccs: - "nathan.moinvaziri@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/Blosc/c-blosc.git' ================================================ FILE: projects/c-blosc/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### # Disable leak sanitizer and run unit testing export ASAN_OPTIONS="detect_leaks=0" ctest --test-dir . ================================================ FILE: projects/c-blosc2/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/Blosc/c-blosc2.git c-blosc2 WORKDIR c-blosc2 COPY *.sh $SRC/ ================================================ FILE: projects/c-blosc2/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build project export LDSHARED=lld # Build with fuzzer and unit test cmake . -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_FUZZERS=ON -DBUILD_TESTS=ON -DBUILD_BENCHMARKS=OFF \ -DBUILD_EXAMPLES=OFF -DBUILD_STATIC=ON -DBUILD_SHARED=OFF make clean make -j$(nproc) # Package seed corpus zip -j $OUT/decompress_chunk_fuzzer_seed_corpus.zip compat/*.cdata zip -j $OUT/decompress_frame_fuzzer_seed_corpus.zip tests/fuzz/corpus/* # Copy the fuzzer executables, zip-ed corpora, and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' ================================================ FILE: projects/c-blosc2/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/Blosc/c-blosc2" language: c++ primary_contact: "blosc.oss.fuzz@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/Blosc/c-blosc2.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/c-blosc2/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### # Disable leak sanitizer and run unit testing export ASAN_OPTIONS="detect_leaks=0" ctest --test-dir . ================================================ FILE: projects/cachetools/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/tkem/cachetools/ COPY build.sh *.py $SRC/ WORKDIR cachetools ================================================ FILE: projects/cachetools/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/cachetools/fuzz_cached.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import cachetools import random import datetime from threading import Lock def get_ttu(_key, value, now): # assume value.ttl contains the item's time-to-live in hours return datetime.datetime.now() + random.random() * datetime.timedelta(days=200000) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) cache_size = fdp.ConsumeIntInRange(1,32) cache_ttl = fdp.ConsumeProbability() cache_lock = None if fdp.ConsumeBool(): cache_lock = Lock() # Random caching types CACHE_TYPES = [ {}, cachetools.FIFOCache(maxsize=cache_size), cachetools.LFUCache(maxsize=cache_size), cachetools.LRUCache(maxsize=cache_size), # cachetools.MRUCache(maxsize=cache_size), cachetools.RRCache(maxsize=cache_size, choice=random.choice), cachetools.TTLCache(maxsize=cache_size, ttl=cache_ttl), cachetools.TLRUCache(maxsize=cache_size, ttu=get_ttu, timer=datetime.datetime.now) ] # Generate a random cached function @cachetools.cached(cache=fdp.PickValueInList(CACHE_TYPES), lock=cache_lock, info=fdp.ConsumeBool()) def fib(n): return n if n < 2 else fib(n - 1) + fib(n - 2) for i in range(20): fib(fdp.ConsumeIntInRange(1, 20)) # Try and get coverage of different properties try: fib.maxsize() fib.currsize() except AttributeError: pass def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": atheris.instrument_all() main() ================================================ FILE: projects/cachetools/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/tkem/cachetools/ language: python main_repo: https://github.com/tkem/cachetools/ sanitizers: - address - undefined vendor_ccs: - sean@compactcloud.co.uk ================================================ FILE: projects/caddy/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/caddyserver/caddy caddy COPY build.sh $SRC/ ================================================ FILE: projects/caddy/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # We move the caddy folder in here rather than the Dockerfile to make CI work. # See here for the failure that triggered this: https://github.com/caddyserver/caddy/pull/4449 mkdir -p $GOPATH/src/github.com/caddyserver/caddy/ mv $SRC/caddy $GOPATH/src/github.com/caddyserver/caddy/v2 cd "$GOPATH"/src/github.com/caddyserver/caddy/v2 find . -name '*_fuzz.go' | while read -r target do # Arguments are : # path of the package with the fuzz target # name of the fuzz function # name of the fuzzer to be built # optional tag to be used by go build and such fuzzed_func=$(grep -o "Fuzz[a-zA-Z]\+" "$target") fuzzer_name=$(echo "$fuzzed_func" | sed -E 's/([A-Z])/-\L\1/g' | sed 's/^-//') # find the relative directory and remove the first `.` (`./` is removed for root) target_dir=$(dirname "$target"); target_dir="${target_dir//.}"; target_corpus_name="${fuzzer_name}_seed_corpus.zip" curl -s -f -O "https://raw.githubusercontent.com/caddyserver/caddy/fuzz-seed-corpus/${target_corpus_name}" || true compile_go_fuzzer github.com/caddyserver/caddy/v2"$target_dir" "$fuzzed_func" "$fuzzer_name" gofuzz done ================================================ FILE: projects/caddy/project.yaml ================================================ homepage: "https://caddyserver.com/" language: go primary_contact: "msaa1990@gmail.com" auto_ccs: - "Adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/caddyserver/caddy.git" ================================================ FILE: projects/caffeine/CaffeineSpecFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.github.benmanes.caffeine.cache.CaffeineSpec; import java.lang.IllegalArgumentException; public class CaffeineSpecFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { CaffeineSpec spec = CaffeineSpec.parse(data.consumeRemainingAsString()); if (spec == null) { throw new FuzzerSecurityIssueLow("null specification"); } } catch (IllegalArgumentException e) { /* documented to be thrown, ignore */ } catch (Exception e) { e.printStackTrace(System.out); throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/caffeine/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/ben-manes/caffeine RUN apt update && apt install -y openjdk-11-jdk-headless openjdk-21-jdk-headless ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk-amd64 COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/caffeine ================================================ FILE: projects/caffeine/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ALL_JARS="" pushd "${SRC}/caffeine" ./gradlew --no-daemon caffeine:jar install -v ./caffeine/build/libs/caffeine-*-SNAPSHOT.jar "$OUT/caffeine.jar" ALL_JARS="${ALL_JARS} caffeine.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac --release 11 -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java cp $SRC/*.class $OUT/ for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/caffeine/project.yaml ================================================ homepage: "https://github.com/ben-manes/caffeine" language: jvm main_repo: "https://github.com/ben-manes/caffeine.git" primary_contact: "ben.manes@gmail.com" auto_ccs: - "cpovirk@google.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/cairo/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y python3-pip gtk-doc-tools libffi-dev autotools-dev libtool gperf RUN pip3 install -U meson==1.4.0 ninja packaging RUN git clone --depth 1 git://git.sv.nongnu.org/freetype/freetype2.git RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib RUN git clone --depth 1 https://gitlab.freedesktop.org/cairo/cairo.git && \ zip -q $SRC/cairo_seed_corpus.zip $SRC/cairo/test/reference/* && \ zip -q $SRC/svg-render-fuzzer_seed_corpus.zip $SRC/cairo/test/svg/*.svg ADD https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/png.dict $SRC/cairo.dict ADD https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/svg.dict $SRC/svg-render-fuzzer.dict WORKDIR $SRC/cairo COPY targets $SRC/fuzz COPY build.sh $SRC/ ================================================ FILE: projects/cairo/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PREFIX=$WORK/prefix mkdir -p $PREFIX export PKG_CONFIG="`which pkg-config` --static" export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig export PATH=$PREFIX/bin:$PATH BUILD=$WORK/build rm -rf $WORK/* rm -rf $BUILD mkdir -p $BUILD # Build glib pushd $SRC/glib/ meson \ setup \ --prefix=$PREFIX \ --libdir=lib \ --default-library=static \ -Db_lundef=false \ -Doss_fuzz=enabled \ -Dlibmount=disabled \ _builddir ninja -C _builddir ninja -C _builddir install popd pushd $SRC/freetype2 ./autogen.sh ./configure --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH" make -j$(nproc) make install # Build cairo pushd $SRC/cairo CFLAGS="-DDEBUG_SVG_RENDER $CFLAGS" meson \ setup \ --prefix=$PREFIX \ --libdir=lib \ --default-library=static \ _builddir ninja -C _builddir ninja -C _builddir install popd mv $SRC/{*.zip,*.dict} $OUT if [ ! -f "${OUT}/cairo_seed_corpus.zip" ]; then echo "missing seed corpus" exit 1 fi if [ ! -f "${OUT}/cairo.dict" ]; then echo "missing dictionary" exit 1 fi PREDEPS_LDFLAGS="-Wl,-Bdynamic -ldl -lm -lc -pthread -lrt -lpthread" DEPS="gmodule-2.0 glib-2.0 gio-2.0 gobject-2.0 freetype2 cairo cairo-gobject" BUILD_CFLAGS="$CFLAGS `pkg-config --static --cflags $DEPS`" BUILD_LDFLAGS="-Wl,-static `pkg-config --static --libs $DEPS`" fuzzers=$(find $SRC/fuzz/ -name "*_fuzzer.c") for f in $fuzzers ; do fuzzer_name=$(basename $f .c) $CC $CFLAGS $BUILD_CFLAGS \ -c $f -o $WORK/${fuzzer_name}.o $CXX $CXXFLAGS \ $WORK/${fuzzer_name}.o -o $OUT/${fuzzer_name} \ $PREDEPS_LDFLAGS \ $BUILD_LDFLAGS \ $LIB_FUZZING_ENGINE \ -Wl,-Bdynamic cd $OUT; ln -sf cairo_seed_corpus.zip ${fuzzer_name}_seed_corpus.zip cd $OUT; ln -sf cairo.dict ${fuzzer_name}.dict done # Fuzzers with non-PNG dict/seed corpus. for f in $SRC/cairo/test/svg/fuzzer/svg-render-fuzzer.c ; do fuzzer_name=$(basename $f .c) $CC $CFLAGS $BUILD_CFLAGS \ -c $f -o $WORK/${fuzzer_name}.o $CXX $CXXFLAGS \ $WORK/${fuzzer_name}.o -o $OUT/${fuzzer_name} \ $PREDEPS_LDFLAGS \ $BUILD_LDFLAGS \ $LIB_FUZZING_ENGINE \ -Wl,-Bdynamic done ================================================ FILE: projects/cairo/project.yaml ================================================ homepage: https://gitlab.freedesktop.org/cairo/cairo language: c primary_contact: security-tps@google.com auto_ccs: - "psychon@znc.in" sanitizers: - address - undefined vendor_ccs: - "jkew@mozilla.com" - "jmuizelaar@mozilla.com" - "twsmith@mozilla.com" view_restrictions: none main_repo: 'https://gitlab.freedesktop.org/cairo/cairo.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/cairo/targets/fuzzer_temp_file.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that // require a file instead of an input buffer. #ifndef FUZZER_TEMP_FILE_H_ #define FUZZER_TEMP_FILE_H_ #include #include #include #include #include // Pure-C interface for creating and cleaning up temporary files. static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) { char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename_buffer) { perror("Failed to allocate file name buffer."); abort(); } const int file_descriptor = mkstemp(filename_buffer); if (file_descriptor < 0) { perror("Failed to make temporary file."); abort(); } FILE* file = fdopen(file_descriptor, "wb"); if (!file) { perror("Failed to open file descriptor."); close(file_descriptor); abort(); } const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file); if (bytes_written < size) { close(file_descriptor); fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size); abort(); } fclose(file); return filename_buffer; } static void fuzzer_release_tmpfile(char* filename) { if (unlink(filename) != 0) { perror("WARNING: Failed to delete temporary file."); } free(filename); } // C++ RAII object for creating temporary files. #ifdef __cplusplus class FuzzerTemporaryFile { public: FuzzerTemporaryFile(const uint8_t* data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) {} ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); } const char* filename() const { return filename_; } private: char* filename_; }; #endif #endif // FUZZER_TEMP_FILE_H_ ================================================ FILE: projects/cairo/targets/pdf_surface_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" const double width_in_inches = 3; const double height_in_inches = 3; const double width_in_points = width_in_inches * 72.0; const double height_in_points = height_in_inches * 72.0; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { cairo_t *cr; cairo_surface_t *surface; cairo_status_t status; if (size == 0) { return 0; } char *tmpfile = fuzzer_get_tmpfile(data, size); surface = cairo_pdf_surface_create(tmpfile, width_in_points, height_in_points); status = cairo_surface_status(surface); if (status != CAIRO_STATUS_SUCCESS) { fuzzer_release_tmpfile(tmpfile); return 0; } char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_TITLE, buf); cr = cairo_create(surface); cairo_tag_begin(cr, buf, NULL); cairo_tag_end(cr, buf); cairo_destroy(cr); cairo_surface_destroy(surface); free(buf); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/cairo/targets/raster_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" static cairo_surface_t * acquire (cairo_pattern_t *pattern, void *closure, cairo_surface_t *target, const cairo_rectangle_int_t *extents) { return cairo_image_surface_create_from_png(closure); } static void release (cairo_pattern_t *pattern, void *closure, cairo_surface_t *surface) { cairo_surface_destroy(surface); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { cairo_t *cr; cairo_surface_t *surface; cairo_pattern_t *pattern; cairo_content_t content; cairo_status_t status; int w, h; char *tmpfile = fuzzer_get_tmpfile(data, size); surface = cairo_image_surface_create_from_png(tmpfile); status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { fuzzer_release_tmpfile(tmpfile); return 0; } cr = cairo_create(surface); content = cairo_surface_get_content(surface); w = cairo_image_surface_get_width(surface); h = cairo_image_surface_get_height(surface); char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; pattern = cairo_pattern_create_raster_source(buf, content, w, h); cairo_raster_source_pattern_set_acquire (pattern, acquire, release); cairo_set_source(cr, pattern); cairo_pdf_surface_set_page_label(surface, buf); cairo_pdf_surface_set_metadata(surface, CAIRO_PDF_METADATA_KEYWORDS, buf); cairo_paint(cr); cairo_destroy(cr); cairo_pattern_destroy(pattern); cairo_surface_destroy(surface); free(buf); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/cairo/targets/surface_write_png_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "fuzzer_temp_file.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { cairo_surface_t *image; cairo_surface_t *surface; cairo_status_t status; cairo_format_t format; char *tmpfile = fuzzer_get_tmpfile(data, size); image = cairo_image_surface_create_from_png(tmpfile); status = cairo_surface_status (image); if (status != CAIRO_STATUS_SUCCESS) { fuzzer_release_tmpfile(tmpfile); return 0; } format = cairo_image_surface_get_format(image); surface = cairo_image_surface_create_for_data((unsigned char*)data, format, 1, 1, size); status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy(image); fuzzer_release_tmpfile(tmpfile); return 0; } cairo_surface_write_to_png(surface, tmpfile); cairo_surface_destroy(surface); cairo_surface_destroy(image); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/cairo/targets/text_glyphs_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "fuzzer_temp_file.h" const int glyph_range = 9; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < glyph_range) { return 0; } cairo_t *cr; cairo_surface_t *surface; cairo_status_t status; cairo_text_extents_t extents; cairo_text_cluster_t cluster; char *tmpfile = fuzzer_get_tmpfile(data, size); surface = cairo_image_surface_create_from_png(tmpfile); status = cairo_surface_status(surface); if (status != CAIRO_STATUS_SUCCESS) { fuzzer_release_tmpfile(tmpfile); return 0; } char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; cr = cairo_create(surface); cairo_text_extents(cr, buf, &extents); cluster.num_bytes = size; cluster.num_glyphs = 1; for (int i = 0; i < glyph_range; i++) { // Taken from test/text-glyph-range.c cairo_glyph_t glyph = { (long int)data[i], 10 * i, 25 }; cairo_show_text_glyphs(cr, buf, size, &glyph, 1, &cluster, 1, 0); } cairo_destroy(cr); cairo_surface_destroy(surface); free(buf); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/calcite/.gitignore ================================================ project-parent/calcite project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/calcite/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/sql.dict $SRC/SqlParserFuzzer.dict && \ cp fuzzing/dictionaries/sql.dict $SRC/CalciteFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/SqlParserFuzzer_seed_corpus.zip go-fuzz-corpus/sqlparser/corpus/* && \ zip -j $SRC/CalciteFuzzer_seed_corpus.zip go-fuzz-corpus/sqlparser/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/calcite RUN git clone --depth 1 https://github.com/apache/calcite/ $SRC/project-parent/calcite COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/calcite/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=calcite PROJECT_GROUP_ID=org.apache.calcite PROJECT_ARTIFACT_ID=calcite MAIN_REPOSITORY=https://github.com/apache/calcite/ GRADLE_ARGS="-x test -x javadoc" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT # set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && ./gradlew publishToMavenLocal $GRADLE_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT pushd $PROJECT export CALCITE_VERSION=$(./gradlew properties --no-daemon --console=plain | sed -nr "s/^version:\ (.*)/\1/p") popd #install (cd $PROJECT && ./gradlew publishToMavenLocal $GRADLE_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent/fuzz-targets -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/calcite/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 15 15 15 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.calcite calcite-core ${env.CALCITE_VERSION} org.hsqldb hsqldb 2.7.2 test maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/calcite/project-parent/fuzz-targets/src/test/java/com/example/CalciteFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.calcite.adapter.jdbc.JdbcSchema; import org.apache.calcite.jdbc.CalciteConnection; import org.apache.calcite.plan.Contexts; import org.apache.calcite.rel.RelNode; import org.apache.calcite.runtime.CalciteException; import org.apache.calcite.schema.SchemaPlus; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.pretty.SqlPrettyWriter; import org.apache.calcite.tools.*; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import java.sql.*; import javax.sql.DataSource; import java.util.concurrent.atomic.AtomicInteger; class CalciteFuzzer { static String jdbcUrl; static Connection connection; static CalciteConnection calciteConnection; static DataSource mockDataSource; static SqlParser.Config parserConfig; static SchemaPlus rootSchema; @BeforeAll static void setUp() throws SQLException, ClassNotFoundException { Class.forName("org.hsqldb.jdbcDriver"); jdbcUrl = MockDb.INSTANCE.getUrl(); connection = DriverManager.getConnection(jdbcUrl, "", ""); try (Statement s = connection.createStatement()) { s.execute("create table testtable(" + "key integer," + "value varchar(25))"); s.execute("insert into testtable values(1, 'test1')"); s.execute("insert into testtable values(2, 'test2')"); } mockDataSource = JdbcSchema.dataSource(jdbcUrl, "org.hsqldb.jdbcDriver", "", ""); } @AfterAll static void cleanUp() { try { connection.close(); calciteConnection.close(); } catch (Exception e) { } } @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { connection = DriverManager.getConnection("jdbc:calcite:"); calciteConnection = connection.unwrap(CalciteConnection.class); } catch (SQLException e) { return; } try { int key = data.consumeInt(); PreparedStatement preparedStatement = calciteConnection.prepareStatement("UPDATE testtable SET value=? WHERE key=" + key); preparedStatement.setString(key, data.consumeString(5000)); preparedStatement.executeUpdate(); } catch (SQLException e) { } parserConfig = SqlParser.config(); rootSchema = calciteConnection.getRootSchema(); rootSchema.add("exampleSchema", JdbcSchema.create(rootSchema, "exampleSchema", mockDataSource, null, null)); try { Frameworks.ConfigBuilder configBuilder = Frameworks.newConfigBuilder() .defaultSchema(rootSchema) .parserConfig(parserConfig) .context(Contexts.of(calciteConnection.config())); Planner planner = Frameworks.getPlanner(configBuilder.build()); SqlNode node = planner.parse(data.consumeString(5000)); SqlNode validateNode = planner.validate(node); SqlWriter writer = new SqlPrettyWriter(); validateNode.unparse(writer, 0,0); } catch (SqlParseException | ValidationException e) { } catch (AssertionError e) { // Need to catch in order to find more interesting findings. } try { FrameworkConfig config = Frameworks.newConfigBuilder() .defaultSchema(rootSchema) .build(); RelBuilder r = RelBuilder.create(config); RelNode node = r .scan("exampleSchema", "TESTTABLE") .filter(r.equals(r.field(data.consumeString(1000)), r.literal(data.consumeInt()))) .project(r.field(data.consumeString(1000)), r.field(data.consumeRemainingAsString())) .build(); RelRunner runner = connection.unwrap(RelRunner.class); PreparedStatement ps = runner.prepareStatement(node); ps.execute(); ps.getResultSet(); } catch (SQLException e) { } catch (CalciteException | IllegalArgumentException e) { // Need to catch in order to find more interesting findings. } } static class MockDb { MockDb() {} static final MockDb INSTANCE = new MockDb(); private final AtomicInteger id = new AtomicInteger(1); public String getUrl() { return "jdbc:hsqldb:mem:db" + id.getAndIncrement(); } } } ================================================ FILE: projects/calcite/project-parent/fuzz-targets/src/test/java/com/example/SqlParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.impl.SqlParserImpl; class SqlParserFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { SqlParser.Config sqlParserConfig = SqlParser .configBuilder() .setParserFactory(SqlParserImpl.FACTORY) .build(); String input = data.consumeRemainingAsString(); SqlParser parser = SqlParser.create(input, sqlParserConfig); parser.parseQuery(); parser.parseStmt(); parser.parseStmtList(); parser.parseExpression(); } catch (SqlParseException e) { } } } ================================================ FILE: projects/calcite/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom fuzz-targets ================================================ FILE: projects/calcite/project.yaml ================================================ homepage: "https://calcite.apache.org/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/calcite/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" base_os_version: ubuntu-24-04 ================================================ FILE: projects/calcite-avatica/Base64Fuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.IOException; import org.apache.calcite.avatica.util.Base64; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [org.apache.calcite.avatica.util.Base64] public static java.lang.String encodeBytes(byte[],int) throws java.io.IOException public class Base64Fuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { if (data.consumeBoolean()) { Base64.encodeBytes(data.consumeRemainingAsBytes()); } else { Base64.decode(data.consumeRemainingAsBytes()); } } catch (IOException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/calcite-avatica/ConnectStringParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.sql.SQLException; import java.util.Properties; import org.apache.calcite.avatica.ConnectStringParser; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [org.apache.calcite.avatica.ConnectStringParser] public static java.util.Properties parse(java.lang.String) throws java.sql.SQLException public class ConnectStringParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { ConnectStringParser.parse(data.consumeRemainingAsString()); } catch (SQLException e) { // Known exception } } } ================================================ FILE: projects/calcite-avatica/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/apache/calcite-avatica calcite-avatica COPY *.sh *.java $SRC/ WORKDIR $SRC/calcite-avatica ================================================ FILE: projects/calcite-avatica/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## # Gradle build with gradle wrapper rm -rf $HOME/.gradle/caches/ ./gradlew clean build shadowJar -x test ./gradlew --stop CURRENT_VERSION=$(./gradlew properties | grep ^version: | cut -d" " -f2) cp "./shaded/core/build/libs/avatica-$CURRENT_VERSION-shadow.jar" $OUT/avatica.jar ALL_JARS="avatica.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/calcite-avatica/project.yaml ================================================ homepage: https://github.com/apache/calcite-avatica main_repo: https://github.com/apache/calcite-avatica language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/canvg/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/canvg/canvg COPY fuzz.js $SRC/canvg COPY babel.config.json $SRC/canvg COPY package.patch $SRC/canvg WORKDIR $SRC/canvg ================================================ FILE: projects/canvg/babel.config.json ================================================ { "presets": ["@babel/preset-typescript"], "plugins": [ "@babel/plugin-transform-modules-commonjs", "@babel/plugin-transform-typescript" ], "ignore": ["**/@jazzer.js", "**/@babel", "**/istanbul-reports", "**/test/**", "**/tests/**", "**/__tests__/**"] } ================================================ FILE: projects/canvg/build.sh ================================================ #!/bin/bash # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # We sadly need some updated dependencies to build canvg patch package.json package.json } transform_dir_into_commonjs "$SRC/canvg/src" transform_dir_into_commonjs "$SRC/canvg/dist" change_type_to_commonjs "$SRC/canvg" # Build Fuzzers. compile_javascript_fuzzer canvg fuzz.js -i canvg ================================================ FILE: projects/canvg/fuzz.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const canvg = require('./dist/index.js'); const canvas = require('canvas'); const fetch = require("node-fetch-commonjs"); const { DOMParser } = require('xmldom'); const preset = canvg.presets.node({ DOMParser, canvas, fetch }); module.exports.fuzz = async function(data) { try { const provider = new FuzzedDataProvider(data); const func = provider.consumeIntegralInRange(0, 3); const canvasWidth = provider.consumeIntegralInRange(0, 9999); const canvasHeight = provider.consumeIntegralInRange(0, 9999); const svgStr = provider.consumeRemainingAsString(); switch (func) { case 0: const canvas = preset.createCanvas(canvasWidth, canvasHeight); const ctx = canvas.getContext('2d'); const svg = canvg.Canvg.fromString(ctx, svgStr, preset); await svg.render(); canvas.toBuffer(); break; case 1: const parser = new canvg.Parser({ DOMParser: DOMParser }); parser.parse(svgStr); break; case 2: const canvgInstance = new canvg.Canvg('', svgStr, preset); canvgInstance.start(); canvgInstance.stop(); break; case 3: const canvgInstance2 = new canvg.Canvg('', svgStr, preset); canvgInstance2.start(); await new Promise(resolve => setTimeout(resolve, 1000)); canvgInstance2.stop(); break; } } catch (error) { if (!ignoredError(error)) throw error; } }; function ignoredError(error) { return !!ignored.find((message) => error.message.indexOf(message) !== -1); } const ignored = [ "Cannot read properties", "Cannot set properties", "Attribute class redefined", "Expected positive number", "Unterminated command", "Unexpected character", "Attribute height redefined", "Attribute", "Invalid number ending", "Expected a flag", "end tag name", ]; ================================================ FILE: projects/canvg/package.patch ================================================ diff --git a/package.json b/package.json index fe964f2..1fe1188 100644 --- a/package.json +++ b/package.json @@ -92,8 +92,8 @@ "@rollup/plugin-node-resolve": "^13.0.5", "@rollup/plugin-replace": "^4.0.0", "@size-limit/preset-small-lib": "^7.0.8", - "@swc/core": "^1.2.136", - "@swc/helpers": "^0.3.2", + "@swc/core": "^1.3.66", + "@swc/helpers": "^0.5.0", "@swc/jest": "^0.2.17", "@trigen/babel-preset": "^8.0.0-alpha.5", "@trigen/browserslist-config": "^8.0.0-alpha.2", ================================================ FILE: projects/canvg/project.yaml ================================================ homepage: https://canvg.js.org/ language: javascript main_repo: https://github.com/canvg/canvg fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/capnproto/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf automake libtool zlib1g-dev RUN git clone --depth 1 https://github.com/capnproto/capnproto WORKDIR $SRC/capnproto COPY build.sh $SRC/ ================================================ FILE: projects/capnproto/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project cd c++ autoreconf -i ./configure --disable-shared make -j$(nproc) make -j$(nproc) capnp-llvm-fuzzer-testcase cp *fuzzer* $OUT/ ================================================ FILE: projects/capnproto/project.yaml ================================================ homepage: "https://capnproto.org" language: c++ primary_contact: "security@sandstorm.io" auto_ccs: - "p.antoine@catenacyber.fr" - "kenton@cloudflare.com" sanitizers: - address - undefined main_repo: 'https://github.com/capnproto/capnproto' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/capstone/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make cmake RUN pip3 install --upgrade setuptools build wheel pip RUN git clone --depth 1 --branch v5 https://github.com/capstone-engine/capstone.git capstonev5 RUN git clone --depth 1 --branch next https://github.com/capstone-engine/capstone.git capstonenext WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/capstone/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #add next branch for branch in v5 next do cd $SRC/capstone$branch # build project mkdir build # does not seem to work in source directory # + make.sh overwrites CFLAGS cd build cmake -DCAPSTONE_BUILD_SHARED=0 .. make cd $SRC/capstone$branch/bindings/python #better debug info sed -i -e 's/#print/print/' capstone/__init__.py ( export CFLAGS="" export AFL_NOOPT=1 python3 -m pip install . ) cd $SRC/capstone$branch/suite mkdir fuzz/corpus find MC/ -name *.cs | ./test_corpus3.py cd fuzz zip -r fuzz_disasm"$branch"_seed_corpus.zip corpus/ cp fuzz_disasm"$branch"_seed_corpus.zip $OUT/ # export other associated stuff cp fuzz_disasm.options $OUT/fuzz_disasm$branch.options cd ../../build # build fuzz target FUZZO=CMakeFiles/fuzz_disasm.dir/suite/fuzz/fuzz_disasm.c.o if [ -f CMakeFiles/fuzz_disasm.dir/suite/fuzz/platform.c.o ]; then FUZZO="$FUZZO CMakeFiles/fuzz_disasm.dir/suite/fuzz/platform.c.o" fi $CXX $CXXFLAGS $FUZZO -o $OUT/fuzz_disasm$branch libcapstone.a $LIB_FUZZING_ENGINE python3 -m pip uninstall -y capstone done ================================================ FILE: projects/capstone/project.yaml ================================================ homepage: "https://www.capstone-engine.org" language: c++ primary_contact: "capstone.engine@gmail.com" auto_ccs: - "p.antoine@catenacyber.fr" - "stalkr@stalkr.net" - "kabeor00@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/capstone-engine/capstone.git' ================================================ FILE: projects/cascadia/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/andybalholm/cascadia COPY build.sh $SRC/ WORKDIR $SRC/cascadia ================================================ FILE: projects/cascadia/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/andybalholm/cascadia/fuzz Fuzz fuzz ================================================ FILE: projects/cascadia/project.yaml ================================================ homepage: "https://github.com/andybalholm/cascadia" primary_contact: "cascadia@balholm.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/andybalholm/cascadia' ================================================ FILE: projects/casync/Dockerfile ================================================ # Copyright 2018 Red Hat Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y \ python3-pip pkg-config wget \ liblzma-dev \ libzstd-dev \ libcurl4-openssl-dev \ libssl-dev \ libudev-dev \ zlib1g-dev \ libacl1-dev \ libfuse-dev \ rsync \ udev \ && \ pip3 install meson ninja RUN git clone --depth 1 https://github.com/systemd/casync casync WORKDIR casync COPY build.sh $SRC/ ================================================ FILE: projects/casync/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Red Hat Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ tools/oss-fuzz.sh ================================================ FILE: projects/casync/project.yaml ================================================ homepage: "https://github.com/casync/casync" language: c++ primary_contact: "lennart@poettering.net" sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory auto_ccs: - zbyszek@in.waw.pl - poettering@gmail.com - fsumsal@redhat.com main_repo: 'https://github.com/systemd/casync' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/catapult/project.yaml ================================================ homepage: "https://github.com/nemtech/catapult-server" main_repo: "https://github.com/nemtech/catapult-server" primary_contact: "wayonb@gmail.com" auto_ccs: - "gimer.outer.space@gmail.com" - "jaguar5pow4@gmail.com" sanitizers: - address - memory - undefined ================================================ FILE: projects/cbor-java/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool wget RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://android.googlesource.com/platform/external/cbor-java cbor-java WORKDIR cbor-java COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/cbor-java/FuzzDec.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.*; import co.nstant.in.cbor.CborDecoder; import co.nstant.in.cbor.CborException; public class FuzzDec { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); CborDecoder decoder = new CborDecoder(bais); try { decoder.decode(); } catch (CborException e) {} } } ================================================ FILE: projects/cbor-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=11 -Djavac.target.version=11 -X" $MVN package $MAVEN_ARGS find . -name "cbor-0.8.jar" -exec cp {} $OUT/cbor.jar \; ALL_JARS="cbor.jar" BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -name 'Fuzz*.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/cbor-java/project.yaml ================================================ homepage: "https://android.googlesource.com/platform/external/cbor-java/+/refs/heads/master" language: jvm primary_contact: "constantin.rack@gmail.com" main_repo: "https://android.googlesource.com/platform/external/cbor-java/+/refs/heads/master" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: ubuntu-24-04 ================================================ FILE: projects/cbor2/Dockerfile ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone --depth 1 https://github.com/agronholm/cbor2.git WORKDIR cbor2 COPY build.sh $SRC/ ================================================ FILE: projects/cbor2/build.sh ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Ensure C extension gets built export CBOR2_BUILD_C_EXTENSION=1 # Build and install project (using current CFLAGS, CXXFLAGS). This is required # for projects with C extensions so that they're built with the proper flags. pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/cbor2/project.yaml ================================================ homepage: "https://github.com/agronholm/cbor2" main_repo: "https://github.com/agronholm/cbor2" language: python primary_contact: "alex.gronholm@nextday.fi" fuzzing_engines: - libfuzzer sanitizers: - address - undefined ================================================ FILE: projects/cctz/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf libgtest-dev libgmock-dev RUN git clone --depth 1 https://github.com/google/cctz COPY run_tests.sh build.sh $SRC/ COPY fuzz_* $SRC/ RUN mkdir -p gtest-build && cd gtest-build && \ cmake /usr/src/googletest && \ make install && rm -rf gtest-build WORKDIR $SRC/cctz ================================================ FILE: projects/cctz/build.sh ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Set BUILD_TESTING=ON for unit testing in run_tests.sh mkdir build && cd build cmake -DBUILD_TESTING=ON -DBUILD_BENCHMARK=OFF ../ make # Compile fuzzers cp $SRC/fuzz_* . $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./fuzz_cctz.cc ./libcctz.a -I../include/ -o $OUT/fuzz_cctz ================================================ FILE: projects/cctz/fuzz_cctz.cc ================================================ /* Copyright 2020 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "cctz/civil_time.h" #include "cctz/time_zone.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fuzzed_data(data, size); cctz::time_zone lax; std::string tz = fuzzed_data.ConsumeRandomLengthString(); if (load_time_zone(tz, &lax)) { std::chrono::system_clock::time_point tp; std::string date_format = fuzzed_data.ConsumeRandomLengthString(); std::string parse_format = fuzzed_data.ConsumeRandomLengthString(); cctz::parse(parse_format, date_format, lax, &tp); const auto t1 = cctz::convert(cctz::civil_second( fuzzed_data.ConsumeIntegral(), fuzzed_data.ConsumeIntegral(), fuzzed_data.ConsumeIntegral(), fuzzed_data.ConsumeIntegral(), fuzzed_data.ConsumeIntegral(), fuzzed_data.ConsumeIntegral()), lax); std::string format = fuzzed_data.ConsumeRandomLengthString(); cctz::format(format, t1, lax); } return 0; } ================================================ FILE: projects/cctz/project.yaml ================================================ homepage: https://github.com/google/cctz main_repo: https://github.com/google/cctz language: c++ vendor_ccs: - david@adalogics.com fuzzing_engines: - afl - honggfuzz - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/cctz/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build ================================================ FILE: projects/cel-cpp/.bazelrc ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Force the use of Clang for C++ builds. build --action_env=CC=clang build --action_env=CXX=clang++ build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:oss_fuzz build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none build:oss-fuzz --cxxopt=-stdlib=libc++ build:oss-fuzz --linkopt=-lc++ build:oss-fuzz --verbose_failures build:oss-fuzz --spawn_strategy=standalone ================================================ FILE: projects/cel-cpp/BUILD ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") cc_fuzz_test( name = "fuzz_parse", deps = ["//parser"], srcs = ["fuzz_parse.cc"], ) ================================================ FILE: projects/cel-cpp/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install python3 openjdk-11-jdk -y RUN git clone --depth 1 https://github.com/google/cel-cpp/ COPY build.sh $SRC/ RUN mkdir $SRC/cel-cpp/fuzz/ COPY build.sh $SRC/cel-cpp COPY BUILD fuzz*.cc $SRC/cel-cpp/fuzz/ COPY MODULE.bazel .bazelrc $SRC/ RUN cat MODULE.bazel >> $SRC/cel-cpp/MODULE.bazel RUN cat .bazelrc >> $SRC/cel-cpp/.bazelrc WORKDIR $SRC/cel-cpp # This is to fix Fuzz Introspector build by using LLVM old pass manager # re https://github.com/ossf/fuzz-introspector/issues/305 ENV OLD_LLVMPASS=1 ================================================ FILE: projects/cel-cpp/MODULE.bazel ================================================ bazel_dep(name = "rules_fuzzing", version = "0.6.0") ================================================ FILE: projects/cel-cpp/WORKSPACE ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "fuzzing_rules_python", urls = ["https://github.com/bazelbuild/rules_python/archive/refs/tags/0.11.0.tar.gz"], sha256 = "c03246c11efd49266e8e41e12931090b613e12a59e6f55ba2efd29a7cb8b4258", strip_prefix = "rules_python-0.11.0", ) http_archive( name = "rules_fuzzing", sha256 = "23bb074064c6f488d12044934ab1b0631e8e6898d5cf2f6bde087adb01111573", strip_prefix = "rules_fuzzing-0.3.1", urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/v0.3.1.zip"], repo_mapping = { "@rules_python": "@fuzzing_rules_python", }, ) load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies") rules_fuzzing_dependencies() load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init") rules_fuzzing_init() ================================================ FILE: projects/cel-cpp/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export USE_BAZEL_VERSION="7.3.2" export CC=${CC:-clang} export CXX=${CXX:-clang++} # modified version of bazel_build_fuzz_tests to work around issues with # bzlmod dependency on rules_fuzzing bazel build -c opt --config=oss-fuzz //fuzz:fuzz_parse_oss_fuzz for oss_fuzz_archive in $(find bazel-bin/ -name "*oss_fuzz.tar"); do tar --no-same-owner -xvf "${oss_fuzz_archive}" -C "${OUT}" done if [ "$SANITIZER" = "coverage" ]; then echo "Collecting the repository source files for coverage tracking." declare -r COVERAGE_SOURCES="${OUT}/proc/self/cwd" mkdir -p "${COVERAGE_SOURCES}" declare -r RSYNC_FILTER_ARGS=( "--include" "*.h" "--include" "*.cc" "--include" "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*.inc" "--include" "*/" "--exclude" "*" ) rsync -avLk "${RSYNC_FILTER_ARGS[@]}" \ "$(bazel info execution_root)/" \ "${COVERAGE_SOURCES}/" fi ================================================ FILE: projects/cel-cpp/fuzz_parse.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include "parser/options.h" #include "parser/parser.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string str (reinterpret_cast(data), size); google::api::expr::parser::ParserOptions options; options.max_recursion_depth = 128; options.expression_size_codepoint_limit = 1 << 20; try { auto parse_status = google::api::expr::parser::Parse(str, "fuzzinput", options); if (!parse_status.ok()) { static_cast(parse_status.status().message()); } } catch (const std::exception& e) { return 0; } return 0; } ================================================ FILE: projects/cel-cpp/project.yaml ================================================ homepage: "https://cel.dev" language: c++ primary_contact: "tswadell@google.com" auto_ccs : - "jdtatum@google.com" - "kyessenov@google.com" - "p.antoine@catenacyber.fr" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory main_repo: 'https://github.com/google/cel-cpp' file_github_issue: True fuzzing_engines: - honggfuzz - libfuzzer ================================================ FILE: projects/cel-go/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/cel-go RUN apt-get update && apt-get install -y protobuf-compiler libprotobuf-dev binutils cmake \ ninja-build liblzma-dev libz-dev pkg-config autoconf libtool RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git RUN mkdir LPM; \ cd LPM; \ cmake $SRC/libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release; \ ninja; RUN git clone --depth 1 https://github.com/mdempsky/go114-fuzz-build.git RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@latest COPY go-lpm.cc $SRC/ COPY fuzz*.go $SRC/cel-go/cel/ COPY build.sh $SRC/ COPY *.proto $SRC/ WORKDIR $SRC/cel-go ================================================ FILE: projects/cel-go/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir fuzzlpm $SRC/LPM/external.protobuf/bin/protoc --cpp_out=fuzzlpm/ -I$SRC/ $SRC/cel-go-lpm.proto $CXX $CXXFLAGS -DNDEBUG -c -I fuzzlpm/ -I $SRC/LPM/external.protobuf/include fuzzlpm/cel-go-lpm.pb.cc $CXX $CXXFLAGS -DNDEBUG -c -I. -I ../libprotobuf-mutator/ -I $SRC/LPM/external.protobuf/include $SRC/go-lpm.cc ( cd $SRC/go114-fuzz-build sed -i -e 's/LLVMFuzzerTestOneInput/LPMFuzzerTestOneInput/' main.go go build ) $SRC/LPM/external.protobuf/bin/protoc --go_out=fuzzlpm/ -I$SRC/ $SRC/cel-go-lpm.proto cp fuzzlpm/github.com/google/cel-go/cel/*.pb.go cel/ $SRC/go114-fuzz-build/go114-fuzz-build -func FuzzEval -o fuzz_lpm.a github.com/google/cel-go/cel $CXX $CXXFLAGS $LIB_FUZZING_ENGINE cel-go-lpm.pb.o go-lpm.o \ fuzz_lpm.a \ $SRC/LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ $SRC/LPM/src/libprotobuf-mutator.a \ -Wl,--start-group $SRC/LPM/external.protobuf/lib/lib*.a -Wl,--end-group \ -o $OUT/fuzz_lpm compile_go_fuzzer github.com/google/cel-go/cel FuzzCompile fuzz_compile ================================================ FILE: projects/cel-go/cel-go-lpm.proto ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// syntax = "proto3"; package celgolpm; option go_package = "github.com/google/cel-go/cel"; message FuzzVariables { string expr = 1; map inputs = 2; } ================================================ FILE: projects/cel-go/fuzz_compile.go ================================================ package cel func FuzzCompile(data []byte) int { env, err := getCELFuzzEnv() if err != nil { panic("impossible to create env") } ast, issues := env.Compile(string(data)) if issues != nil && issues.Err() != nil { return 0 } _, err = env.Program(ast) if err != nil { return 0 } return 1 } ================================================ FILE: projects/cel-go/fuzz_env.go ================================================ package cel // Create environment for running under Address sanitizer without timing out. func getCELFuzzEnv() (*Env, error) { // Very dense expressions (balanced trees) can cause address sanitizer to // timeout even though they typically fail in under a second uninstrumented. return NewEnv(ParserRecursionLimit(60)) } ================================================ FILE: projects/cel-go/fuzz_eval.go ================================================ package cel import ( "google.golang.org/protobuf/proto" "github.com/google/cel-go/checker/decls" exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) func FuzzEval(data []byte) int { gen := &FuzzVariables{} err := proto.Unmarshal(data, gen) if err != nil { panic("Failed to unmarshal LPM generated variables") } declares := make([]*exprpb.Decl, 0, len(gen.Inputs)) for k, _ := range gen.Inputs { declares = append(declares, decls.NewVar(k, decls.String)) } env, err := getCELFuzzEnv() if err != nil { panic("impossible to create env") } env, err = env.Extend(Declarations(declares...)) if err != nil { panic("impossible to create env") } ast, issues := env.Compile(gen.Expr) if issues != nil && issues.Err() != nil { return 0 } prg, err := env.Program(ast) if err != nil { return 0 } //fmt.Printf("loltry %#+v\n", gen) _, _, err = prg.Eval(gen.Inputs) return 1 } ================================================ FILE: projects/cel-go/go-lpm.cc ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "fuzzlpm/cel-go-lpm.pb.h" #include "src/libfuzzer/libfuzzer_macro.h" extern "C" void LPMFuzzerTestOneInput(const uint8_t *buffer, size_t size); DEFINE_PROTO_FUZZER(const celgolpm::FuzzVariables& input) { size_t size = input.ByteSizeLong(); if (size > 0) { uint8_t *buffer = (uint8_t *) malloc(size); //printf("debugs %d: %s\n", size, input.DebugString().c_str()); input.SerializeToArray((uint8_t *) buffer, size); LPMFuzzerTestOneInput(buffer, size); free(buffer); } } ================================================ FILE: projects/cel-go/project.yaml ================================================ homepage: "https://opensource.google/projects/cel" primary_contact: "tswadell@google.com" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/google/cel-go' file_github_issue: True ================================================ FILE: projects/cert-manager/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/cert-manager/cert-manager --depth=1 COPY build.sh pki_fuzzer.go $SRC/ WORKDIR $SRC/cert-manager ================================================ FILE: projects/cert-manager/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/pki_fuzzer.go $SRC/cert-manager/pkg/util/pki/ # These test files break the build, so removing; the fuzz tests don't need them rm $SRC/cert-manager/pkg/controller/certificates/trigger/trigger_controller_test.go rm $SRC/cert-manager/pkg/controller/certificates/revisionmanager/revisionmanager_controller_test.go cd $SRC/cert-manager go mod tidy compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/internal/webhook/admission/certificaterequest/approval FuzzValidate FuzzValidate_approval compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/trigger FuzzProcessItem FuzzProcessItem_trigger compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/revisionmanager FuzzProcessItem FuzzProcessItem_revisionmanager compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/issuing FuzzProcessItem FuzzProcessItem_issuing compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/readiness FuzzProcessItem FuzzProcessItem_readiness compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/keymanager FuzzProcessItem FuzzProcessItem_keymanager compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificates/requestmanager FuzzProcessItem FuzzProcessItem_requestmanager compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificaterequests/vault FuzzVaultCRController FuzzVaultCRController compile_native_go_fuzzer_v2 github.com/cert-manager/cert-manager/pkg/controller/certificaterequests/venafi FuzzVenafiCRController FuzzVenafiCRController compile_go_fuzzer github.com/cert-manager/cert-manager/pkg/util/pki FuzzUnmarshalSubjectStringToRDNSequence FuzzUnmarshalSubjectStringToRDNSequence compile_go_fuzzer github.com/cert-manager/cert-manager/pkg/util/pki FuzzDecodePrivateKeyBytes FuzzDecodePrivateKeyBytes ================================================ FILE: projects/cert-manager/pki_fuzzer.go ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package pki func FuzzUnmarshalSubjectStringToRDNSequence(data []byte) int { UnmarshalSubjectStringToRDNSequence(string(data)) return 1 } func FuzzDecodePrivateKeyBytes(data []byte) int { DecodePrivateKeyBytes(data) return 1 } ================================================ FILE: projects/cert-manager/project.yaml ================================================ homepage: "https://cert-manager.io" # Send reports to the cert-manager-security distribution list. # - https://cert-manager.io/docs/contributing/security/ # - https://github.com/cert-manager/community/blob/main/SECURITY.md#reporting-process primary_contact: "cert-manager-security@googlegroups.com" # Allow people listed in maintainers.csv file to sign in to https://oss-fuzz.com/ # - https://github.com/cert-manager/community/blob/main/maintainers.csv auto_ccs: - "ashley.davis@venafi.com" # Ashley Davis,sgtcodfish,Venafi - "i@am.so-aweso.me" # Jake Sanders,jakexks,G-Research - "irbekrm@gmail.com" # Irbe Krumina,irbekrm,Tailscale - "jmunnelly@apple.com" # James Munnelly,munnerz,Apple - "mael.valais@gmail.com" # Maël Valais,maelvls,Venafi - "me@joshvanl.dev" # Josh van Leeuwen,joshvanl,Diagrid - "richard.wall@venafi.com" # Richard Wall,wallrj,Venafi - "tim.ramlot@venafi.com" # Tim Ramlot,inteon,Venafi vendor_ccs : - "adam@adalogics.com" # Adam Korczynski,AdamKorcz,ADALogics language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/cert-manager/cert-manager' ================================================ FILE: projects/cfengine/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ build-essential libpcre2-dev libtool autoconf automake bison flex libssl-dev \ libbison-dev libacl1 libacl1-dev lmdb-utils liblmdb-dev libpam0g-dev libtool \ libyaml-dev libxml2-dev RUN git clone --branch pcre2-10.39 https://github.com/PhilipHazel/pcre2 pcre2 && \ cd pcre2 && \ ./autogen.sh && \ ./configure && \ make all && \ make install && \ sed -i "s/\$libS\$libR \(-lpcre2-8$\)/\$libS\$libR -Wl,-Bstatic \1 -Wl,-Bdynamic/" /usr/local/bin/pcre2-config RUN git clone --depth=1 https://github.com/librsync/librsync RUN git clone --depth 1 https://github.com/cfengine/core --recursive WORKDIR core COPY build.sh string_fuzzer.c $SRC/ ================================================ FILE: projects/cfengine/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/librsync cmake . -DBUILD_SHARED_LIBS=OFF make install cd $SRC/core ./autogen.sh ./configure --enable-static --disable-shared make V=1 -j$(nproc) cd libpromises mv $SRC/string_fuzzer.c . find . -name "*.o" -exec ar rcs fuzz_lib.a {} \; $CC $CFLAGS -I./ -c string_fuzzer.c -o string_fuzzer.o $CC $CXXFLAGS $LIB_FUZZING_ENGINE string_fuzzer.o \ -o $OUT/string_fuzzer fuzz_lib.a \ ../libntech/libutils/.libs/libutils.a ================================================ FILE: projects/cfengine/project.yaml ================================================ homepage: "https://github.com/cfengine/core" main_repo: "https://github.com/cfengine/core" language: c++ primary_contact: "vratislav.podzimek@northern.tech" auto_ccs: - "Adam@adalogics.com" fuzzing_engines: - afl - honggfuzz - libfuzzer sanitizers: - address - undefined - memory ================================================ FILE: projects/cfengine/string_fuzzer.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){ if(size<4) { return 0; } for (int i=0; i $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/cglib/pom.xml ================================================ 4.0.0 ossfuzz cglib-fuzzer ${cglibVersion} jar 15 15 ossfuzz.ASTFuzzer UTF-8 com.code-intelligence jazzer-api 0.12.0 cglib cglib ${cglibVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/cglib/project.yaml ================================================ homepage: "https://github.com/cglib/cglib/wiki" language: jvm main_repo: "https://github.com/cglib/cglib" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/cglib/src/main/java/ossfuzz/EnhancerFuzzer.java ================================================ /* * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.FixedValue; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; class SampleClass { String test() { return "Hello World"; } String test(String string) { return string; } }; class FixedValueCallback implements FixedValue { FixedValueCallback(String string) { m_string = string; } @Override public Object loadObject() throws Exception { return m_string; } public String getString() { return m_string; } protected String m_string; } class MethodInterceptorCallback implements MethodInterceptor { MethodInterceptorCallback(String string) { m_string = string; } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if (method.getDeclaringClass() == SampleClass.class) { if (method.getParameterCount() == 0) { return m_string; } } return proxy.invokeSuper(obj, args); } public String getString() { return m_string; } protected String m_string; } public class EnhancerFuzzer { public static void fixedValueCallback(FuzzedDataProvider fuzzedDataProvider) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); FixedValueCallback fixedValueCallback = new FixedValueCallback(fuzzedDataProvider.consumeRemainingAsString()); enhancer.setCallback(fixedValueCallback); SampleClass proxy = (SampleClass) enhancer.create(); if (!proxy.test().equals(fixedValueCallback.getString())) { throw new FuzzerSecurityIssueLow("FixedValue defect"); } if (!proxy.test("someString").equals(fixedValueCallback.getString())) { throw new FuzzerSecurityIssueLow("FixedValue defect"); } } public static void methodInterceptorCallback(FuzzedDataProvider fuzzedDataProvider) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(SampleClass.class); MethodInterceptorCallback methodInterceptorCallback = new MethodInterceptorCallback(fuzzedDataProvider.consumeString(5)); enhancer.setCallback(methodInterceptorCallback); SampleClass proxy = (SampleClass) enhancer.create(); if (!proxy.test().equals(methodInterceptorCallback.getString())) { throw new FuzzerSecurityIssueLow("MethodInterceptor defect"); } String argument = fuzzedDataProvider.consumeRemainingAsString(); if (!proxy.test(argument).equals(argument)) { throw new FuzzerSecurityIssueLow("MethodInterceptor defect"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { fixedValueCallback(fuzzedDataProvider); methodInterceptorCallback(fuzzedDataProvider); } } ================================================ FILE: projects/chardet/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/erikrose/chardet chardet COPY *.sh *py $SRC/ WORKDIR $SRC/chardet ================================================ FILE: projects/chardet/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/chardet/fuzz_detector.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import chardet def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) # General detection. chardet.detect(data) # Incremental feeding> detector = chardet.universaldetector.UniversalDetector() for b in data: detector.feed(b) if detector.done: break detector.close() res = detector.result def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/chardet/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/erikrose/chardet language: python main_repo: https://github.com/erikrose/chardet sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/charset_normalizer/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/jawah/charset_normalizer charset_normalizer WORKDIR charset_normalizer COPY build.sh *.py $SRC/ ================================================ FILE: projects/charset_normalizer/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Enable pysecsan export ENABLE_PYSECSAN="1" pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/charset_normalizer/fuzz_normalize.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from charset_normalizer import from_bytes def TestOneInput(data): """Simply pass fuzz data directly into charset_normaliser""" # No exceptions thrown from_bytes(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/charset_normalizer/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/jawah/charset_normalizer language: python main_repo: https://github.com/jawah/charset_normalizer primary_contact: tahri.ahmed@proton.me sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/checker-framework/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt update && apt install -y openjdk-17-jdk RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/typetools/checker-framework WORKDIR checker-framework COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ ================================================ FILE: projects/checker-framework/UtilCheckerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.checkerframework.checker.formatter.util.FormatUtil; import org.checkerframework.checker.i18nformatter.qual.I18nConversionCategory; import org.checkerframework.checker.i18nformatter.util.I18nFormatUtil; import java.lang.IllegalArgumentException; import org.checkerframework.checker.regex.util.RegexUtil; public class UtilCheckerFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { fuzzChecker(data); } catch (IllegalArgumentException ignored) {} } private static void fuzzChecker(FuzzedDataProvider data) { int choice = data.consumeInt(0, 2); String content; switch (choice) { case 0: content = data.consumeRemainingAsString(); FormatUtil.formatParameterCategories(content); FormatUtil.tryFormatSatisfiability(content); break; case 1: I18nConversionCategory[] categories = { I18nConversionCategory.NUMBER, I18nConversionCategory.DATE, I18nConversionCategory.NUMBER, I18nConversionCategory.UNUSED, I18nConversionCategory.stringToI18nConversionCategory(data.consumeString(100)) }; I18nConversionCategory category = data.pickValue(categories); I18nFormatUtil.hasFormat(data.consumeRemainingAsString(), category); break; case 2: content = data.consumeRemainingAsString(); if (RegexUtil.isRegex(content)) { RegexUtil.asRegex(content); } break; } } } ================================================ FILE: projects/checker-framework/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #mv $SRC/{*.zip,*.dict} $OUT ln -s $MVN /bin/mvn export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" CURRENT_VERSION=$(./gradlew properties --console=plain | sed -nr "s/^version:\ (.*)/\1/p") ./gradlew build -x test -x :checker:javadoc -x :framework-test:spotlessJavaCheck cp "./checker/build/libs/checker-$CURRENT_VERSION-all.jar" "$OUT/checker.jar" cp "./framework/build/libs/framework-$CURRENT_VERSION.jar" "$OUT/checker-framework.jar" ALL_JARS="checker.jar checker-framework.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer --release 15 cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --instrumentation_excludes=com.fasterxml.jackson.core.** \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --disabled_hooks=\"com.code_intelligence.jazzer.sanitizers.RegexInjection\" --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/checker-framework/project.yaml ================================================ homepage: "https://github.com/typetools/checker-framework" language: jvm main_repo: "git@github.com:typetools/checker-framework.git" primary_contact: "michael.ernst@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" run_tests: False ================================================ FILE: projects/checkstyle/CheckstyleFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.puppycrawl.tools.checkstyle.JavaParser; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.FileText; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; // jvm-autofuzz-heuristics-1 public class CheckstyleFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Heuristic name: jvm-autofuzz-heuristics-1 Path path = null; try { path = Files.createTempFile("oss-fuzz.", ".oss-fuzz"); Files.write(path, data.consumeRemainingAsBytes()); FileContents content = new FileContents(new FileText(path.toFile(), "UTF-8")); JavaParser.parse(content); } catch (IOException | CheckstyleException | NoClassDefFoundError e) { // Known exception } finally { if (path != null) { try { Files.deleteIfExists(path); } catch (IOException e) { // Known Exception } } } } } ================================================ FILE: projects/checkstyle/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/checkstyle/checkstyle checkstyle COPY *.sh *Fuzzer.java $SRC/ WORKDIR $SRC/checkstyle ================================================ FILE: projects/checkstyle/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## export TARGET_PACKAGE_PREFIX="com.puppycrawl.tools.checkstyle." MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 --update-snapshots" $MVN clean package $MAVEN_ARGS BUILD_CLASSPATH= RUNTIME_CLASSPATH= for JARFILE in $(find ./ -name *.jar) do cp $JARFILE $OUT/ BUILD_CLASSPATH=$BUILD_CLASSPATH$OUT/$(basename $JARFILE): RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH\$this_dir/$(basename $JARFILE): done # Build corpus with valid java files mkdir $SRC/tmp-corpus find $SRC -name "*.java" -exec cp {} $SRC/tmp-corpus/ \; zip -j $OUT/CheckstyleFuzzer_seed_corpus.zip $SRC/tmp-corpus/* # Retrieve apache-common-lang3 library # This library provides method to translate primitive type arrays to # their respective class object arrays to avoid compilation error. wget -P $OUT/ https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar wget -P $OUT/ https://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.11.1/antlr4-runtime-4.11.1.jar BUILD_CLASSPATH=$BUILD_CLASSPATH:$JAZZER_API_PATH:$OUT/commons-lang3-3.12.0.jar:$OUT/antlr4-runtime-4.11.1.jar RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH:\$this_dir/commons-lang3-3.12.0.jar:\$this_dir/antlr4-runtime-4.11.1.jar:\$this_dir for fuzzer in $(ls $SRC/*Fuzzer.java) do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/checkstyle/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/checkstyle/checkstyle language: jvm main_repo: https://github.com/checkstyle/checkstyle sanitizers: - address - undefined vendor_ccs: - arthur.chan@adalogics.com - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/chrono/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/chronotope/chrono chrono WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/chrono/build.sh ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Note: This project creates Rust fuzz targets exclusively cd $SRC/chrono cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_reader $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_format $OUT/ ================================================ FILE: projects/chrono/project.yaml ================================================ homepage: "https://github.com/chronotope/chrono" main_repo: "https://github.com/chronotope/chrono.git" language: rust primary_contact: "dirkjan@ochtman.nl" sanitizers: - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/cifuzz-example/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN git clone https://github.com/jonathanmetzman/cifuzz-example.git --depth 1 WORKDIR cifuzz-example COPY build.sh $SRC/ ================================================ FILE: projects/cifuzz-example/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make clean # Not strictly necessary, since we are building in a fresh dir. make -j$(nproc) all # Build the fuzz targets. # make -j$(nproc) check # Sanity check, not strictly required, but nice to have. # Copy the fuzzer executables, zip-ed corpora, option and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' # If you have dictionaries. find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' # If you have custom options. find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' # If you have seed corpora (you better have them!) ================================================ FILE: projects/cifuzz-example/project.yaml ================================================ base_os_version: ubuntu-24-04 language: c++ sanitizers: - address disabled: true primary_contact: fake@example.com main_repo: 'https://github.com/jonathanmetzman/cifuzz-example.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/cilium/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y wget RUN wget https://raw.githubusercontent.com/google/AFL/master/dictionaries/json.dict -O $OUT/fuzz.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus RUN git clone --depth 1 https://github.com/cilium/cilium RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN git clone --depth 1 https://github.com/cilium/proxy COPY build.sh $SRC/ WORKDIR $SRC/cilium ================================================ FILE: projects/cilium/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cilium/test/fuzzing/oss-fuzz-build.sh $SRC/cncf-fuzzing/projects/cilium/build.sh zip "$OUT/fuzz_seed_corpus.zip" "$SRC"/go-fuzz-corpus/json/corpus/* ================================================ FILE: projects/cilium/project.yaml ================================================ homepage: "https://cilium.io" language: go primary_contact: "security@cilium.io" auto_ccs: - "andre@isovalent.com" - "joe@isovalent.com" - "natalia@isovalent.com" - "robin@isovalent.com" - "adam@adalogics.com" - "david@adalogics.com" - "liz@isovalent.com" - "chris@isovalent.com" main_repo: "https://github.com/cilium/cilium.git" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/circl/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y make autoconf automake libtool wget python RUN git clone --depth 1 https://github.com/MozillaSecurity/cryptofuzz RUN git clone --depth 1 --branch 3.9.0 --single-branch https://github.com/randombit/botan.git RUN git clone --depth 1 https://github.com/supranational/blst.git RUN wget -nv https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 COPY build.sh $SRC/ ================================================ FILE: projects/circl/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_CIRCL" export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" export LINK_FLAGS="" # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ # Configure Cryptofuzz cd $SRC/cryptofuzz/ python gen_repository.py echo -n '"' >>extra_options.h echo -n "--force-module=circl " >>extra_options.h echo -n "--curves=secp384r1,bls12_381 " >>extra_options.h echo -n "--operations=" >>extra_options.h echo -n "ECC_PrivateToPublic," >>extra_options.h echo -n "ECC_Point_Add," >>extra_options.h echo -n "ECC_Point_Mul," >>extra_options.h echo -n "ECC_Point_Dbl," >>extra_options.h echo -n "BLS_PrivateToPublic," >>extra_options.h echo -n "BLS_G1_Add," >>extra_options.h echo -n "BLS_G1_Mul," >>extra_options.h echo -n "BLS_G1_Neg," >>extra_options.h echo -n "BLS_G1_IsEq," >>extra_options.h echo -n "BLS_IsG1OnCurve," >>extra_options.h echo -n "BLS_HashToG1," >>extra_options.h echo -n "BLS_PrivateToPublic_G2," >>extra_options.h echo -n "BLS_G2_Add," >>extra_options.h echo -n "BLS_G2_Mul," >>extra_options.h echo -n "BLS_G2_Neg," >>extra_options.h echo -n "BLS_G2_IsEq," >>extra_options.h echo -n "BLS_IsG2OnCurve," >>extra_options.h echo -n "BLS_HashToG2," >>extra_options.h echo -n "BLS_Compress_G1," >>extra_options.h echo -n "BLS_Decompress_G1," >>extra_options.h echo -n "BLS_Pairing," >>extra_options.h echo -n "BignumCalc_Mod_BLS12_381_P," >>extra_options.h echo -n "BignumCalc_Mod_BLS12_381_R" >>extra_options.h echo -n '"' >>extra_options.h # Build Botan cd $SRC/botan if [[ $CFLAGS != *-m32* ]] then ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation else ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE" export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a" export BOTAN_INCLUDE_PATH="$SRC/botan/build/include" cd $SRC/cryptofuzz/modules/botan/ make -f Makefile-oracle -j $(nproc) # Build blst cd $SRC/blst/ ./build.sh export BLST_LIBBLST_A_PATH=$(realpath libblst.a) export BLST_INCLUDE_PATH=$(realpath bindings/) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BLST" cd $SRC/cryptofuzz/modules/blst/ make -j $(nproc) cd $SRC/cryptofuzz/modules/circl/ go mod init cryptofuzz/circl go mod tidy make -j $(nproc) cd $SRC/cryptofuzz/ make -j $(nproc) cp cryptofuzz $OUT/ ================================================ FILE: projects/circl/project.yaml ================================================ homepage: "https://github.com/cloudflare/circl" language: c++ primary_contact: "guidovranken@gmail.com" main_repo: "https://github.com/cloudflare/circl.git" auto_ccs: - "armfazh@cloudflare.com" - "bas@cloudflare.com" sanitizers: - address architectures: - x86_64 ================================================ FILE: projects/cirq/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone \ --depth 1 \ --branch main \ https://github.com/quantumlib/Cirq.git WORKDIR $SRC/Cirq # Install pip dependencies. RUN --mount=type=cache,target=/root/.cache/pip \ export PIP_ROOT_USER_ACTION=ignore && \ pip3 install --upgrade pip && \ pip3 install -r dev_tools/requirements/dev.env.txt # Install Cirq-related modules. RUN export PIP_ROOT_USER_ACTION=ignore && \ pip3 install --no-cache-dir \ ./cirq-core \ ./cirq-aqt \ ./cirq-web \ ./cirq-ionq \ ./cirq-google \ ./cirq-pasqal COPY build.sh fuzz_circuit.py $SRC/ ================================================ FILE: projects/cirq/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do fuzzer_basename=$(basename -s .py $fuzzer) fuzzer_package=${fuzzer_basename}.pkg pyinstaller --distpath $OUT --onefile --name $fuzzer_package --hidden-import "scipy._cyutility" --hidden-import "numpy._core._exceptions" $fuzzer echo "#!/bin/sh # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") LD_PRELOAD=\$this_dir/sanitizer_with_fuzzer.so \ ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \ \$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/cirq/fuzz_circuit.py ================================================ #!/usr/bin/python3 # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ import atheris import sys import cirq @atheris.instrument_func def TestOneInput(data): """Fuzzing target for Cirq circuit operations.""" fdp = atheris.FuzzedDataProvider(data) # Test basic circuit creation circuit = cirq.Circuit() # Generate random number of qubits num_qubits = fdp.ConsumeIntInRange(1, 3) qubits = cirq.LineQubit.range(num_qubits) # Generate random number of operations num_ops = fdp.ConsumeIntInRange(1, 5) for _ in range(num_ops): if not fdp.remaining_bytes(): break # Choose random gate type gate_type = fdp.ConsumeIntInRange(0, 5) if gate_type == 0 and len(qubits) >= 1: # Single qubit X gate qubit_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) circuit.append(cirq.X(qubits[qubit_idx])) elif gate_type == 1 and len(qubits) >= 1: # Single qubit Y gate qubit_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) circuit.append(cirq.Y(qubits[qubit_idx])) elif gate_type == 2 and len(qubits) >= 1: # Single qubit Z gate qubit_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) circuit.append(cirq.Z(qubits[qubit_idx])) elif gate_type == 3 and len(qubits) >= 1: # Hadamard gate qubit_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) circuit.append(cirq.H(qubits[qubit_idx])) elif gate_type == 4 and len(qubits) >= 2: # CNOT gate control_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) target_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) if control_idx != target_idx: circuit.append(cirq.CNOT(qubits[control_idx], qubits[target_idx])) elif gate_type == 5 and len(qubits) >= 2: # CZ gate control_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) target_idx = fdp.ConsumeIntInRange(0, len(qubits) - 1) if control_idx != target_idx: circuit.append(cirq.CZ(qubits[control_idx], qubits[target_idx])) simulator = cirq.Simulator() simulator.simulate(circuit) def main(): """Main entry point for the fuzzer.""" atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cirq/project.yaml ================================================ homepage: "https://github.com/quantumlib/Cirq" language: python primary_contact: "quantum-oss-maintainers@google.com" auto_ccs: - "mhucka@google.com" - "mrtoastcheng@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/quantumlib/Cirq.git" ================================================ FILE: projects/civetweb/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y zlib1g-dev RUN git clone https://github.com/civetweb/civetweb WORKDIR $SRC/civetweb COPY build.sh $SRC/ ================================================ FILE: projects/civetweb/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed -i 's/CFLAGS += -g -fsanitize=address,fuzzer,undefined/#CFLAGS += -g -fsanitize=address,fuzzer,undefined/' ./Makefile export LDFLAGS="${LIB_FUZZING_ENGINE} ${CFLAGS}" chmod +x ./fuzztest/build.sh ./fuzztest/build.sh mv civetweb_fuzz* $OUT/ ================================================ FILE: projects/civetweb/project.yaml ================================================ homepage: "https://github.com/civetweb/civetweb" primary_contact: "bel2125@gmail.com" language: c fuzzing_engines: - libfuzzer - honggfuzz auto_ccs: - "xt4ubq@gmail.com" - "david@adalogics.com" main_repo: 'https://github.com/civetweb/civetweb' ================================================ FILE: projects/cjson/Dockerfile ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake RUN git clone --depth 1 https://github.com/DaveGamble/cJSON.git cjson WORKDIR cjson COPY build.sh $SRC/ ================================================ FILE: projects/cjson/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project $SRC/cjson/fuzzing/ossfuzz.sh ================================================ FILE: projects/cjson/project.yaml ================================================ homepage: "https://github.com/DaveGamble/cJSON" language: c++ primary_contact: "max@maxbruckner.de" auto_ccs: - "randy440088@gmail.com" - "wp_scut@163.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/DaveGamble/cJSON.git' ================================================ FILE: projects/clamav/Dockerfile ================================================ # Copyright (C) 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y \ flex bison \ python3-dev \ pkg-config # # We need the latest toolchain to reliably build clamav. # oss-fuzz requires nightly for the -Z option, so we use that as well. # RUN rustup update nightly ENV RUSTUP_TOOLCHAIN=nightly-x86_64-unknown-linux-gnu # # Build static libs for dependencies # RUN python3 -m pip install --upgrade pip RUN python3 -m pip install mussels RUN git clone --depth 1 https://github.com/Cisco-Talos/clamav-mussels-cookbook.git RUN mkdir /mussels RUN cd ${SRC}/clamav-mussels-cookbook && \ msl build libclamav_deps -t host-static -w /mussels/work -i /mussels/install # Collect clamav source & fuzz corpus RUN git clone --depth 1 https://github.com/Cisco-Talos/clamav.git WORKDIR clamav COPY build.sh replay_build.sh $SRC/ ================================================ FILE: projects/clamav/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -ex export GIT_DISCOVERY_ACROSS_FILESYSTEM=1 # # Build the library. # rm -rf ${SRC}/build mkdir -p ${SRC}/build cd ${SRC}/build # # Run ./configure # export CLAMAV_DEPENDENCIES=/mussels/install cmake ${SRC}/clamav \ -DENABLE_FUZZ=ON \ -DHAVE_MMAP=OFF \ -DJSONC_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include/json-c" \ -DJSONC_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libjson-c.a" \ -DENABLE_JSON_SHARED=OFF \ -DBZIP2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include" \ -DBZIP2_LIBRARY_RELEASE="$CLAMAV_DEPENDENCIES/lib/libbz2.a" \ -DOPENSSL_ROOT_DIR="$CLAMAV_DEPENDENCIES" \ -DOPENSSL_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include" \ -DOPENSSL_CRYPTO_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libcrypto.a" \ -DOPENSSL_SSL_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libssl.a" \ -DZLIB_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libssl.a" \ -DLIBXML2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include/libxml2" \ -DLIBXML2_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libxml2.a" \ -DPCRE2_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include" \ -DPCRE2_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libpcre2-8.a" \ -DZLIB_INCLUDE_DIR="$CLAMAV_DEPENDENCIES/include" \ -DZLIB_LIBRARY="$CLAMAV_DEPENDENCIES/lib/libz.a" \ -DCMAKE_INSTALL_PREFIX="install" # Build libclamav and the fuzz targets make -j$(nproc) cp ./fuzz/clamav_* ${OUT}/. # # Collect the fuzz corpora. # # `scanfile` & `scanmap` # ---------- mkdir ${SRC}/all-scantype-seeds git clone --depth 1 https://github.com/Cisco-Talos/clamav-fuzz-corpus.git $SRC/clamav-fuzz-corpus for type in ARCHIVE MAIL OLE2 PDF HTML PE ELF SWF XMLDOCS HWP3; do # Prepare seed corpus for the type-specific fuzz targets. zip ${OUT}/clamav_scanfile_${type}_fuzzer_seed_corpus.zip ${SRC}/clamav-fuzz-corpus/scantype/${type}/* zip ${OUT}/clamav_scanmap_${type}_fuzzer_seed_corpus.zip ${SRC}/clamav-fuzz-corpus/scantype/${type}/* # Prepare dictionary for the type-specific fuzz targets (may not exist for all types). cp ${SRC}/clamav-fuzz-corpus/scantype/${type}.dict ${OUT}/clamav_scanfile_${type}_fuzzer.dict 2>/dev/null || : cp ${SRC}/clamav-fuzz-corpus/scantype/${type}.dict ${OUT}/clamav_scanmap_${type}_fuzzer.dict 2>/dev/null || : # Copy seeds for the generic fuzz target. cp ${SRC}/clamav-fuzz-corpus/scantype/${type}/* ${SRC}/all-scantype-seeds/ done # Add weird files git clone --depth=1 https://github.com/corkami/pocs find ./pocs/ -type f -print0 | xargs -0 -I % mv -f % ${SRC}/all-scantype-seeds/ # Prepare seed corpus for the generic fuzz target. cp ${SRC}/clamav-fuzz-corpus/scantype/other/* ${SRC}/all-scantype-seeds/ zip ${OUT}/clamav_scanfile_fuzzer_seed_corpus.zip ${SRC}/all-scantype-seeds/* zip ${OUT}/clamav_scanmap_fuzzer_seed_corpus.zip ${SRC}/all-scantype-seeds/* rm -r ${SRC}/all-scantype-seeds # `dbload` # -------- for type in CDB CFG CRB FP FTM HDB HSB IDB IGN IGN2 LDB MDB MSB NDB PDB WDB YARA; do # Prepare seed corpus for the type-specific fuzz targets. zip ${OUT}/clamav_dbload_${type}_fuzzer_seed_corpus.zip ${SRC}/clamav-fuzz-corpus/database/${type}/* # Prepare dictionary for the type-specific fuzz targets (may not exist for all types). cp ${SRC}/clamav-fuzz-corpus/database/${type}.dict ${OUT}/clamav_dbload_${type}_fuzzer.dict 2>/dev/null || : done ================================================ FILE: projects/clamav/clamav-scanfile-fuzzer.options ================================================ [libfuzzer] ================================================ FILE: projects/clamav/project.yaml ================================================ homepage: "https://www.clamav.net/" language: c++ primary_contact: "clamav.fuzz@gmail.com" auto_ccs: - clamav-bugs@external.cisco.com sanitizers: - address - undefined fuzzing_engines: - libfuzzer - afl main_repo: 'https://github.com/Cisco-Talos/clamav-devel.git' ================================================ FILE: projects/clamav/replay_build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This script is useful for OSS-Fuzz infrastructure which is used to rebuild # code from cached images. This is to support various ongoing efforts in # OSS-Fuzz. cd ${SRC}/build make -j$(nproc) cp ./fuzz/clamav_* ${OUT}/. ================================================ FILE: projects/clib/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake libcurl4-gnutls-dev -qq RUN git clone --depth 1 https://github.com/clibs/clib WORKDIR $SRC/ COPY build.sh $SRC/ ================================================ FILE: projects/clib/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd clib make -j$(nproc) sed 's/int main(int argc/int main2(int argc/g' -i ./src/clib-search.c sed 's/int main(int argc/int main2(int argc/g' -i ./src/clib-configure.c find . -name "*.o" -exec ar rcs fuzz_lib.a {} \; $CC $CFLAGS -Wno-unused-function -U__STRICT_ANSI__ \ -DHAVE_PTHREADS=1 -pthread \ -c src/common/clib-cache.c src/clib-configure.c \ src/common/clib-settings.c src/common/clib-package.c \ test/fuzzing/fuzz_manifest.c -I./asprintf -I./deps/ \ -I./deps/asprintf $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_manifest.o \ -o $OUT/fuzz_manifest clib-cache.o clib-configure.o clib-settings.o clib-package.o \ -I./deps/asprintf -I./deps -I./asprintf \ fuzz_lib.a -L/usr/lib/x86_64-linux-gnu -lcurl echo "[libfuzzer]" > $OUT/fuzz_manifest.options echo "detect_leaks=0" >> $OUT/fuzz_manifest.options ================================================ FILE: projects/clib/project.yaml ================================================ homepage: "https://github.com/clibs/clib" language: c primary_contact: "joseph.werle@gmail.com" auto_ccs: - "Adam@adalogics.com" - "isty001@gmail.com" main_repo: 'https://github.com/clibs/clib' ================================================ FILE: projects/click/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/pallets/click click COPY *.sh *py $SRC/ WORKDIR $SRC/click ================================================ FILE: projects/click/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/click/fuzz_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import click from click.parser import OptionParser from click import exceptions def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) # Create a parser we can fuzz. # This can be extended further by creating logic that will create arbitrary # parser. ctx = click.Context(click.Command("fuzz")) parser = OptionParser(ctx) click.Option("+z", is_flag=True).add_to_parser(parser, ctx) click.Option("-b", is_flag=False).add_to_parser(parser, ctx) click.Option("+c", multiple=fdp.ConsumeBool()).add_to_parser(parser, ctx) click.Option("-d", default="abc").add_to_parser(parser, ctx) click.Option("+e", type=int).add_to_parser(parser, ctx) click.Option("-f", type=click.Choice(["option1", "option2"])).add_to_parser(parser, ctx) click.Option("!g", type=click.Choice(["option1", "option2"])).add_to_parser(parser, ctx) click.Option("!h", default="abcd").add_to_parser(parser, ctx) args = [] for idx in range(fdp.ConsumeIntInRange(1, 15)): args.append(fdp.ConsumeUnicodeNoSurrogates(64)) try: parser.parse_args(args) except exceptions.ClickException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/click/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pallets/click language: python main_repo: https://github.com/pallets/click sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/clickhouse/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update -y \ && env DEBIAN_FRONTEND=noninteractive \ apt-get install --yes --no-install-recommends \ bash \ wget \ curl \ ccache \ expect \ ninja-build \ perl \ pkg-config \ python3 \ python3-lxml \ python3-requests \ python3-termcolor \ protobuf-compiler \ libprotoc-dev \ libgrpc++-dev \ protobuf-compiler-grpc \ libprotobuf-dev \ sudo \ tzdata \ nasm RUN git clone -j 8 --recursive https://github.com/ClickHouse/ClickHouse $SRC/ClickHouse WORKDIR $SRC/ClickHouse COPY build.sh $SRC/ ================================================ FILE: projects/clickhouse/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir -p $SRC/ClickHouse/build && cd $SRC/ClickHouse/build [ -e CMakeLists ] && rm -rf CMakeFiles [ -e CMakeCache.txt ] && rm -rf CMakeCache.txt sed -i -e '/warnings.cmake)/d' $SRC/ClickHouse/CMakeLists.txt # It will be hard to maintain any compilation fails (if any) in two repositories. # Also ClickHouse won't compile without this. # It is very strange, because we have as many warnings as you could imagine. sed -i -e 's/add_warning(/no_warning(/g' $SRC/ClickHouse/CMakeLists.txt # ClickHouse uses libcxx from contrib. # Enabling libstdc++ manually will cause duplicate symbols at linker stage. # Plus we want to fuzz the same binary as we have in our CI # https://github.com/ClickHouse/ClickHouse/blob/2e2ef087129ed072404bdc084e8028a5c5869dc0/PreLoad.cmake#L23 unset CFLAGS unset CXXFLAGS unset LDFLAGS # ClickHouse builds `protoc` from sources to be dependent only on compiler # but if we build ClickHouse with any kind of sanitizer, then `protoc` # will be built with sanitizer too... # Protoc will be used during ClickHouse builds to generate .cpp sources from .proto files # and everything works in our CI, but not here... # We use libprotobuf-mutator and self-written script to generate SQL-based AST from mutated .proto # Maybe some of proto files are too complex and this is the cause of `protoc` failures # So, this flag only helps to supress error from `protoc` built with any kind of sanitizer export MSAN_OPTIONS=exit_code=0 printenv NUM_JOBS=$(nproc || grep -c ^processor /proc/cpuinfo) if (( $NUM_JOBS > 10 )); then NUM_JOBS=$(expr $NUM_JOBS / 4) fi CLICKHOUSE_CMAKE_FLAGS=( "-DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache" "-DCMAKE_C_COMPILER=$CC" "-DCMAKE_CXX_COMPILER=$CXX" "-DCMAKE_BUILD_TYPE=RelWithDebInfo" "-DLIB_FUZZING_ENGINE:STRING=$LIB_FUZZING_ENGINE" "-DENABLE_FUZZING=1" "-DENABLE_PROTOBUF=1" "-DPARALLEL_COMPILE_JOBS=$NUM_JOBS" ) if [ "$SANITIZER" = "coverage" ]; then cmake -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DWITH_COVERAGE=1 else cmake -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DSANITIZE=$SANITIZER fi TARGETS=$(find $SRC/ClickHouse/src $SRC/ClickHouse/programs -name '*_fuzzer.cpp' -\! -name '*gtest_*' -prune -execdir basename {} .cpp ';' | tr '\n' ' ') if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space TARGETS=( ${TARGETS[@]:0:2} ) fi for FUZZER_TARGET in $TARGETS do # Skip this fuzzer because of linker errors (the size of the binary is too big) if [ "$FUZZER_TARGET" = "execute_query_fuzzer" ]; then continue fi ninja -j $NUM_JOBS $FUZZER_TARGET # Find this binary in build directory and strip it TEMP=$(find $SRC/ClickHouse/build -name $FUZZER_TARGET) # We have to preserve certain symbols e.g. LLVMFuzzerTestOneInput and some sanitizer-related once to not fail build checks: # https://github.com/google/oss-fuzz/blob/860447a7121e344cc1627f492f67f3a23e86e6c5/infra/base-images/base-runner/bad_build_check#L173 # https://github.com/google/oss-fuzz/blob/860447a7121e344cc1627f492f67f3a23e86e6c5/infra/base-images/base-runner/test_all.py#L92-L96 # because of that we strip only debug symbols strip --strip-debug $TEMP done # copy out fuzzer binaries find $SRC/ClickHouse/build -name '*_fuzzer' -exec cp -v '{}' $OUT ';' # copy out fuzzer options and dictionaries cp $SRC/ClickHouse/tests/fuzz/*.dict $OUT/ cp $SRC/ClickHouse/tests/fuzz/*.options $OUT/ # prepare corpus dirs mkdir -p $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/ mkdir -p $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/ mkdir -p $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/ mkdir -p $SRC/ClickHouse/tests/fuzz/execute_query_fuzzer.in/ # prepare corpus cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/0_stateless/*.sql $SRC/ClickHouse/tests/fuzz/execute_query_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/create_parser_fuzzer.in/ cp $SRC/ClickHouse/tests/queries/1_stateful/*.sql $SRC/ClickHouse/tests/fuzz/execute_query_fuzzer.in/ # copy out corpus cd $SRC/ClickHouse/tests/fuzz for dir in *_fuzzer.in; do fuzzer=$(basename $dir .in) zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/" done # copy sources for code coverage if required if [ "$SANITIZER" = "coverage" ]; then mkdir -p $OUT/src/ClickHouse/ cp -rL --parents $SRC/ClickHouse/src $OUT cp -rL --parents $SRC/ClickHouse/base $OUT fi # Just check binaries size BINARIES_SIZE=$(find $SRC/ClickHouse/build -name '*_fuzzer' -exec du -sh '{}' ';') ================================================ FILE: projects/clickhouse/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://clickhouse.com/" language: c++ primary_contact: "security@clickhouse.com" auto_ccs: - "jakalletti@gmail.com" - "man2gm@gmail.com" - "kochetovnicolai@gmail.com" - "hq.zero.iq@gmail.com" - "milovidov@clickhouse.com" - "ivan@clickhouse.com" - "avogar@clickhouse.com" - "Nikita.Taranov@clickhouse.com" - "Antonio@clickhouse.com" - "Nikolay.Degterinskii@clickhouse.com" - "sergei@clickhouse.com" - "tavplubix@clickhouse.com" - "felixoid@clickhouse.com" - "n0vik@clickhouse.com" - "yakov@clickhouse.com" - "maksim@clickhouse.com" - "nk@clickhouse.com" - "nikitamikhaylov@clickhouse.com" - "alesapin@clickhouse.com" - "vdimir@clickhouse.com" - "qoega@clickhouse.com" - "kssenii@clickhouse.com" - "anton@clickhouse.com" - "oleksandr@clickhouse.com" - "vitlibar@clickhouse.com" - "igor@clickhouse.com" - "robert@clickhouse.com" - "sema.checherinda@clickhouse.com" - "Jianfei.Hu@clickhouse.com" - "san.tran@clickhouse.com" sanitizers: - address - memory - undefined fuzzing_engines: - libfuzzer main_repo: 'https://github.com/ClickHouse/ClickHouse.git' ================================================ FILE: projects/clock/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/benbjohnson/clock WORKDIR clock COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/clock/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/fuzz_test.go $SRC/clock/ go mod tidy go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer github.com/benbjohnson/clock FuzzClock FuzzClock ================================================ FILE: projects/clock/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package clock import ( "testing" "time" ) func FuzzClock(f *testing.F) { f.Fuzz(func(t *testing.T, addString, setString, timerString string) { addTime, err := time.ParseDuration(addString) if err != nil { return } setTime, err := time.Parse(time.RFC3339, setString) if err != nil { return } timerTime, err := time.ParseDuration(timerString) if err != nil { return } m := NewMock() m.Add(addTime) m.Set(setTime) m.Timer(timerTime) }) } ================================================ FILE: projects/clock/project.yaml ================================================ homepage: "https://github.com/benbjohnson/clock" language: go main_repo: "https://github.com/benbjohnson/clock" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/closure-compiler/.gitignore ================================================ project-parent/closure-compiler project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/closure-compiler/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/closure-compiler RUN wget -O "./bazelisk" "https://github.com/bazelbuild/bazelisk/releases/download/v1.16.0/bazelisk-linux-amd64" RUN chmod +x bazelisk RUN mv bazelisk /usr/local/bin/bazelisk RUN git clone --depth 1 https://github.com/google/closure-compiler/ $SRC/project-parent/closure-compiler COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/closure-compiler/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=closure-compiler PROJECT_GROUP_ID=com.google.javascript PROJECT_ARTIFACT_ID=closure-compiler MAIN_REPOSITORY=https://github.com/google/closure-compiler/ function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install mvn -pl $PROJECT install -DskipTests mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT #install (cd $PROJECT && bazelisk build //:all) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 cp $SRC/project-parent/closure-compiler/bazel-bin/compiler_uberjar_deploy.jar $OUT/ ALL_JARS="compiler_uberjar_deploy.jar" # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes:$(echo $ALL_JARS | xargs printf -- "$OUT/%s:")." RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent/fuzz-targets -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/closure-compiler/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.junit.platform junit-platform-launcher 1.9.2 com.google.javascript closure-compiler 1.0 system ${basedir}/../closure-compiler/bazel-bin/compiler_uberjar_deploy.jar maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/closure-compiler/project-parent/fuzz-targets/src/test/java/com/example/ParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.util.ArrayList; import java.util.Collections; import com.google.javascript.jscomp.parsing.Config; import com.google.javascript.jscomp.parsing.Config.JsDocParsing; import com.google.javascript.jscomp.parsing.Config.LanguageMode; import com.google.javascript.jscomp.parsing.ParserRunner; import com.google.javascript.jscomp.parsing.ParserRunner.ParseResult; import com.google.javascript.rhino.*; import com.google.javascript.rhino.StaticSourceFile.SourceKind; class ParserFuzzer { static SourceKind [] sourceKinds = {SourceKind.STRONG, SourceKind.WEAK, SourceKind.EXTERN, SourceKind.NON_CODE}; static LanguageMode [] languageModes = {LanguageMode.ECMASCRIPT3, LanguageMode.ECMASCRIPT5, LanguageMode.ECMASCRIPT_2015, LanguageMode.ECMASCRIPT_2016, LanguageMode.ECMASCRIPT_2017, LanguageMode.ECMASCRIPT_2018, LanguageMode.ECMASCRIPT_2019, LanguageMode.ECMASCRIPT_2020, LanguageMode.ECMASCRIPT_2021, LanguageMode.ES_NEXT, LanguageMode.UNSTABLE, LanguageMode.UNSUPPORTED}; static JsDocParsing [] jsDocParsings = {JsDocParsing.INCLUDE_ALL_COMMENTS, JsDocParsing.TYPES_ONLY, JsDocParsing.INCLUDE_DESCRIPTIONS_WITH_WHITESPACE, JsDocParsing.INCLUDE_DESCRIPTIONS_NO_WHITESPACE}; static Config.RunMode [] runModes = {Config.RunMode.KEEP_GOING, Config.RunMode.STOP_AFTER_ERROR}; static Config.StrictMode [] strictModes = {Config.StrictMode.STRICT, Config.StrictMode.SLOPPY}; static TestErrorReporter [] testErrorReporters = {new TestErrorReporter().expectAllWarnings(), new TestErrorReporter().expectAllErrors()}; @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { String name = data.consumeString(200); StaticSourceFile file = new SimpleSourceFile(name, data.pickValue(sourceKinds)); Config config = ParserRunner.createConfig(data.pickValue(languageModes), data.pickValue(jsDocParsings), data.pickValue(runModes), null, data.consumeBoolean(), data.pickValue(strictModes)); TestErrorReporter testErrorReporter = data.pickValue(testErrorReporters); String sourceString = data.consumeRemainingAsString(); ParseResult result = ParserRunner.parse(file, sourceString, config, testErrorReporter); } catch (RuntimeException e) { // Need to catch RuntimeException to pass fuzzing blocker. } } static class TestErrorReporter implements ErrorReporter { private final ArrayList expectedErrors = new ArrayList<>(); private final ArrayList expectedWarnings = new ArrayList<>(); private final ArrayList seenErrors = new ArrayList<>(); private final ArrayList seenWarnings = new ArrayList<>(); @Override public void error(String message, String sourceName, int line, int lineOffset) { this.seenErrors.add(message); } @Override public void warning(String message, String sourceName, int line, int lineOffset) { this.seenWarnings.add(message); } public TestErrorReporter expectAllErrors(String... errors) { Collections.addAll(this.expectedErrors, errors); return this; } public TestErrorReporter expectAllWarnings(String... warnings) { Collections.addAll(this.expectedWarnings, warnings); return this; } } } ================================================ FILE: projects/closure-compiler/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom fuzz-targets ================================================ FILE: projects/closure-compiler/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://developers.google.com/closure/compiler/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/google/closure-compiler/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/closure-library/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/google/closure-library.git COPY fuzz.js $SRC/closure-library WORKDIR $SRC/closure-library ================================================ FILE: projects/closure-library/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies. npm install npm install --save-dev @jazzer.js/core # Build Fuzzers. compile_javascript_fuzzer closure-library fuzz.js -i closure-library --sync ================================================ FILE: projects/closure-library/fuzz.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); require("google-closure-library"); const SafeHtml = goog.require('goog.html.SafeHtml'); const googString = goog.require('goog.string.Const'); const TrustedResourceUrl = goog.require('goog.html.TrustedResourceUrl'); const UncheckedResourceUrl = goog.require('goog.html.UncheckedResourceUrl'); module.exports.fuzz = function(data) { const provider = new FuzzedDataProvider(data); const html = provider.consumeString(300); const shouldWrap = provider.consumeBoolean(); const tagName = shouldWrap ? provider.consumeString(10) : ''; let safeHtml; try { const method = provider.consumeIntegralInRange(1, 6); switch (method) { case 1: safeHtml = SafeHtml.create(tagName, { innerHtml: html }); break; case 2: safeHtml = SafeHtml.fromConstant(googString.from(html)); break; case 3: safeHtml = SafeHtml.fromTrustedResourceUrl(TrustedResourceUrl.fromConstant(googString.from(html))); break; case 4: safeHtml = SafeHtml.fromUntrustedResourceUrl(UncheckedResourceUrl.fromConstant(googString.from(html))); break; case 5: safeHtml = SafeHtml.unwrap(SafeHtml.create(tagName, { innerHtml: html })); break; case 6: safeHtml = SafeHtml.concat(SafeHtml.create(tagName, { innerHtml: html }), SafeHtml.EMPTY); break; } const htmlString = SafeHtml.unwrap(safeHtml); const isEmpty = provider.consumeBoolean(); const emptySafeHtml = isEmpty ? SafeHtml.EMPTY : safeHtml; const concatenatedSafeHtml = SafeHtml.concat(safeHtml, emptySafeHtml); const isTrusted = provider.consumeBoolean(); const trustedSafeHtml = isTrusted ? SafeHtml.htmlEscape(htmlString) : concatenatedSafeHtml; SafeHtml.unwrap(trustedSafeHtml); } catch (error) { if (!ignoredError(error)) throw error; } }; function ignoredError(error) { return !!ignored.find((message) => error.message.indexOf(message) !== -1); } const ignored = [ "Cannot read properties of" ]; ================================================ FILE: projects/closure-library/project.yaml ================================================ homepage: https://developers.google.com/closure/library/ language: javascript main_repo: https://github.com/google/closure-library fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/cloud-custodian/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN git clone https://github.com/cloud-custodian/cloud-custodian RUN apt-get install build-essential libssl-dev libffi-dev pkg-config python3-dev cargo -y RUN pip3 install --upgrade pip RUN curl https://sh.rustup.rs -sSf | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" RUN rustup install nightly RUN rustup default stable COPY *.sh *.py $SRC/ WORKDIR $SRC/cloud-custodian ================================================ FILE: projects/cloud-custodian/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install . python3 -m pip install tools/c7n_gcp for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/cloud-custodian/fuzz_actions_parser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' fdp = atheris.FuzzedDataProvider(data) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: action_registry.parse(data, resource_manager) except (exceptions.PolicyValidationError, ProfileNotFound): pass except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_actions_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.actions import autotag, network, notify from c7n.actions import invoke, webhook, autoscaling from c7n.actions import metric, policy from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 6) object = None option = FuzzOption(fdp) data = _generate_random_dict(fdp) event = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = autotag.AutoTagUser(data, resource_manager) object.validate() elif choice == 2: object = notify.Notify(data, resource_manager) object.validate() elif choice == 3: object = invoke.LambdaInvoke(data, resource_manager) elif choice == 4: resource_manager.config = FuzzConfig(fdp) object = webhook.Webhook(data, resource_manager) elif choice == 5: object = autoscaling.AutoscalingBase(data, resource_manager) elif choice == 6: object = metric.PutMetric(data, resource_manager) if object: object.process(resources, event) except (exceptions.PolicyValidationError, ProfileNotFound): pass except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_actions_validate.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.actions import autotag, network, notify from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 3) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = autotag.AutoTagUser(data, resource_manager) elif choice == 2: object = network.ModifyVpcSecurityGroupsAction(data, resource_manager) object.type = fdp.ConsumeUnicodeNoSurrogates(1024) elif choice == 3: object = notify.Notify(data, resource_manager) if object: object.validate() except (exceptions.PolicyValidationError, ProfileNotFound): pass except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_filters_parser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.filters import offhours from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' fdp = atheris.FuzzedDataProvider(data) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if fdp.ConsumeBool(): filter_registry.parse(data, resource_manager) else: schedule_tag = fdp.ConsumeUnicodeNoSurrogates(1024) offhours.OffHour(data, resource_manager).parser.parse(schedule_tag) offhours.OnHour(data, resource_manager).parser.parse(schedule_tag) except (exceptions.PolicyValidationError, ProfileNotFound): pass except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_filters_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.filters import multiattr, missing, metrics from c7n.filters import offhours, vpc, revisions from c7n.filters import backup, health, iamaccess from c7n.filters import policystatement, iamanalyzer from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 12) option = FuzzOption(fdp) data = _generate_random_dict(fdp) event = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = multiattr.MultiAttrFilter(data, resource_manager) object.validate() elif choice == 2: data['policy'] = resource_manager.ctx.policy object = missing.Missing(data, resource_manager) object.validate() elif choice == 3: object = offhours.OnHour(data, resource_manager) object.validate() elif choice == 4: object = offhours.OffHour(data, resource_manager) object.validate() elif choice == 5: object = vpc.SubnetFilter(data, resource_manager) object.validate() elif choice == 6: object = vpc.NetworkLocation(data, resource_manager) object.validate() elif choice == 7: object = revisions.Diff(data, resource_manager) object.validate() elif choice == 8: object = backup.ConsecutiveAwsBackupsFilter(data, resource_manager) elif choice == 9: object = health.HealthEventFilter(data, resource_manager) elif choice == 10: object = policystatement.HasStatementFilter(data, resource_manager) elif choice == 11: resource_manager.config = FuzzConfig(fdp) object = iamaccess.CrossAccountAccessFilter(data, resource_manager) elif choice == 12: object = iamanalyzer.AccessAnalyzer(data, resource_manager) if object: object.process(resources, event) except (exceptions.PolicyValidationError, ProfileNotFound): pass except ValueError as e: if "Filter requires resource expression" not in str(e): raise e except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_filters_validate.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.filters import multiattr, missing, metrics from c7n.filters import offhours, vpc, revisions from c7n.resources import aws, rdsparamgroup, elasticache, ec2 from c7n.resources import emr, account, apigw, elb, s3, glue from c7n.resources import appelb def TestOneInput(data): """Fuzz encode and decode""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 10) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext(provider, option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = multiattr.MultiAttrFilter(data, resource_manager) elif choice == 2: data['policy'] = resource_manager.ctx.policy object = missing.Missing(data, resource_manager) elif choice == 3: object = metrics.MetricsFilter(data, resource_manager) elif choice == 4: object = offhours.OnHour(data, resource_manager) elif choice == 5: object = offhours.OffHour(data, resource_manager) elif choice == 6: object = vpc.SecurityGroupFilter(data, resource_manager) elif choice == 7: object = vpc.SubnetFilter(data, resource_manager) elif choice == 8: object = vpc.VpcFilter(data, resource_manager) elif choice == 9: object = vpc.NetworkLocation(data, resource_manager) elif choice == 10: object = revisions.Diff(data, resource_manager) if object: object.validate() except (exceptions.PolicyValidationError, ProfileNotFound): pass except ValueError as e: if "Filter requires resource expression" not in str(e): raise e except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): aws.AWS() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_gcp_actions_validate_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from google.auth.exceptions import DefaultCredentialsError with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry, FilterValidationError from c7n.actions import ActionRegistry from c7n_gcp import provider from c7n_gcp.actions import labels, cscc, notify from c7n_gcp.resources import iam, dns, armor, build, secret from c7n_gcp.resources import pubsub, logging, network, mlengine from c7n_gcp.resources import bigquery, cloudrun, appengine from c7n_gcp.resources import loadbalancer, sql, service, gke from c7n_gcp.resources import bigtable, memstore, kms, datafusion from c7n_gcp.resources import cloudbilling, function, spanner from c7n_gcp.resources import resourcemanager, source, osconfig from c7n_gcp.resources import dataproc, notebook, artifactregistry from c7n_gcp.resources import compute, storage, deploymentmanager from c7n_gcp.resources import dataflow def TestOneInput(data): """Fuzz tools/c7n_gcp""" object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 4) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.ConsumeUnicodeNoSurrogates(1024) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext("gcp", option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = labels.SetLabelsAction(data, resource_manager) object.validate() elif choice == 2: object = labels.LabelDelayedAction(data, resource_manager) object.validate() elif choice == 3: event = _generate_random_dict(fdp) object = cscc.PostFinding(data, resource_manager) object.validate() object.process(resources, event) elif choice == 4: object = notify.Notify(data, resource_manager) object.process(resources) except ( exceptions.PolicyValidationError, DefaultCredentialsError, FilterValidationError): pass except ValueError as e: if "Filter requires resource expression" not in str(e) and "No GCP Project ID" not in str(e): raise e except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): provider.GoogleCloud() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_gcp_filters_validate_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from google.auth.exceptions import DefaultCredentialsError with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry, FilterValidationError from c7n.actions import ActionRegistry from c7n_gcp import provider from c7n_gcp.filters import labels, recommender, metrics, alerts from c7n_gcp.filters import sccfindings, timerange, iampolicy from c7n_gcp.resources import iam, dns, armor, build, secret from c7n_gcp.resources import pubsub, logging, network, mlengine from c7n_gcp.resources import bigquery, cloudrun, appengine from c7n_gcp.resources import loadbalancer, sql, service, gke from c7n_gcp.resources import bigtable, memstore, kms, datafusion from c7n_gcp.resources import cloudbilling, function, spanner from c7n_gcp.resources import resourcemanager, source, osconfig from c7n_gcp.resources import dataproc, notebook, artifactregistry from c7n_gcp.resources import compute, storage, deploymentmanager from c7n_gcp.resources import dataflow def TestOneInput(data): """Fuzz tools/c7n_gcp""" object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 7) option = FuzzOption(fdp) data = _generate_random_dict(fdp) event = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.ConsumeUnicodeNoSurrogates(1024) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = resourcemanager.Organization(FuzzContext("gcp", option), manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources try: if choice == 1: object = labels.LabelActionFilter(data, resource_manager) object.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) object.validate() elif choice == 2: object = recommender.RecommenderFilter(data, resource_manager) object.validate() elif choice == 3: object = metrics.GCPMetricsFilter(data, resource_manager) object.validate() elif choice == 4: object = sccfindings.SecurityComandCenterFindingsFilter(data, resource_manager) elif choice == 5: object = timerange.TimeRangeFilter(data, resource_manager) elif choice == 6: object = iampolicy.IamPolicyFilter(data, resource_manager) elif choice == 7: object = alerts.AlertsFilter(data, resource_manager) if object: object.process(resources, event) except ( exceptions.PolicyValidationError, DefaultCredentialsError, FilterValidationError): pass except ValueError as e: if "Filter requires resource expression" not in str(e) and "not enough values to unpack" not in str(e): raise e except OSError as e: if "Network is unreachable" not in str(e): raise e except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): provider.GoogleCloud() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_gcp_resources_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from google.auth.exceptions import DefaultCredentialsError with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, manager, data from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n_gcp import provider from c7n_gcp.resources import iam, dns, armor, build, secret from c7n_gcp.resources import pubsub, logging, network, mlengine from c7n_gcp.resources import bigquery, cloudrun, appengine from c7n_gcp.resources import loadbalancer, sql, service, gke from c7n_gcp.resources import bigtable, memstore, kms, datafusion from c7n_gcp.resources import cloudbilling, function, spanner from c7n_gcp.resources import resourcemanager, source, osconfig from c7n_gcp.resources import dataproc, notebook, artifactregistry from c7n_gcp.resources import compute, storage, deploymentmanager from c7n_gcp.resources import dataflow def TestOneInput(data): """Fuzz tools/c7n_gcp""" object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 14) option = FuzzOption(fdp) data = _generate_random_dict(fdp) event = None manager_data = _generate_random_dict(fdp) type = fdp.ConsumeUnicodeNoSurrogates(1024) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) resource_manager = manager.ResourceManager(FuzzContext("gcp", option), manager_data) try: if choice == 1: object = gke.ServerConfig(data, resource_manager) event = _generate_random_dict(fdp) elif choice == 2: resource_manager = sql.SqlInstance(FuzzContext(provider, option), manager_data) object = sql.SqlInstanceDelete(data, resource_manager) elif choice == 3: object = kms.KmsLocationKmsKeyringFilter(data, resource_manager) event = _generate_random_dict(fdp) elif choice == 4: resource_manager = compute.Instance(FuzzContext(provider, option), manager_data) object = compute.EffectiveFirewall(data, resource_manager) event = _generate_random_dict(fdp) elif choice == 5: object = resourcemanager.HierarchyAction(data, resource_manager) elif choice == 6: object = resourcemanager.AccessApprovalFilter(data, resource_manager) elif choice == 7: object = resourcemanager.AccessApprovalFilter(data, resource_manager) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resources = manager.resources if object: if event: object.process(resources, event) else: object.process(resources) except (exceptions.PolicyValidationError, DefaultCredentialsError): pass except ValueError as e: if "Filter requires resource expression" not in str(e): raise e except (KeyError, TypeError): pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): provider.GoogleCloud() def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_query_parser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from c7n import exceptions, utils def TestOneInput(data): """Fuzz encode and decode""" fdp = atheris.FuzzedDataProvider(data) try: qp = utils.QueryParser.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) except exceptions.PolicyValidationError: pass c7njme = utils.C7NJMESPathParser() try: c7njme.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) except: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_resources_parser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from c7n import exceptions from c7n.resources import ec2, aws, health, sagemaker, emr def TestOneInput(data): """Fuzz encode and decode""" fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 5) try: if choice == 1: ec2.QueryFilter.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) elif choice == 2: aws.Arn.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) elif choice == 3: health.QueryFilter.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) elif choice == 4: sagemaker.QueryFilter.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) elif choice == 5: emr.QueryFilter.parse(fdp.ConsumeUnicodeNoSurrogates(1024)) except (exceptions.PolicyValidationError, ValueError, TypeError): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_resources_process.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from botocore.exceptions import ClientError, ProfileNotFound with atheris.instrument_imports(): from c7n import policy as c7n_policy from c7n import exceptions, data, query, manager from c7n.filters import FilterRegistry from c7n.actions import ActionRegistry from c7n.resources.aws import AWS from c7n.resources import ml, sar, s3control, ec2, ebs from c7n.resources import batch, mq, route53, securityhub from c7n.resources import vpc, shield, iam, sfn, cloudtrail from c7n.resources import code, appflow, awslambda, emr, ami from c7n.resources import secretsmanager, airflow, account from c7n.resources import cloudfront, elasticsearch def TestOneInput(data): """Fuzz validate functions in resources package""" registry_type = [ 'c7n.data', 'rds-param-group', 'elasticache', 'ec2', 'emr', 'aws.account', 'rest-account', 'elb', 's3', 'iac', 'rds', 'glue-catalog', 'app-elb-target-group' ] provider = 'aws' object = None event = None resources_object = None fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 58) option = FuzzOption(fdp) data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) type = fdp.PickValueInList(registry_type) action_registry = ActionRegistry("%s.actions" % type) filter_registry = FilterRegistry("%s.filters" % type) context = FuzzContext(provider, option) resource_manager = query.QueryResourceManager(context, manager_data) resource_manager.action_registry = action_registry resource_manager.filter_registry = filter_registry resource_manager.type = type resource_manager.config = FuzzConfig(fdp) resources = manager.resources initializeResources(context, manager_data) try: if choice == 1: object = ml.DeleteMLModel(data = data, manager = resource_manager) elif choice == 2: object = sar.Delete(data = data, manager = resource_manager) elif choice == 3: object = sar.CrossAccount(data = data, manager = resource_manager) elif choice == 4: object = s3control.AccessPointCrossAccount(data = data, manager = resource_manager) elif choice == 5: object = s3control.Delete(data = data, manager = resource_manager) elif choice == 6: object = ec2.MonitorInstances(data = data, manager = resource_manager) elif choice == 7: resources_object = batch.UpdateComputeEnvironment(data = data, manager = resource_manager) elif choice == 8: resources_object = batch.DeleteComputeEnvironment(data = data, manager = resource_manager) elif choice == 9: resources_object = batch.DefinitionDeregister(data = data, manager = resource_manager) elif choice == 10: resources_object = mq.Delete(data = data, manager = resource_manager) elif choice == 11: resources_object = route53.SetQueryLogging(data = data, manager = resource_manager) resources_object.validate() elif choice == 12: resources_object = route53.IsQueryLoggingEnabled(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 13: resources_object = route53.ResolverQueryLogConfigAssociate(data = data, manager = resource_manager) elif choice == 14: resources_object = route53.ReadinessCheckCrossAccount(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 15: resources_object = securityhub.SecurityHubFindingFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) resources_object.validate() elif choice == 16: resources_object = securityhub.PostFinding(data = data, manager = resource_manager) event = _generate_random_dict(fdp) resources_object.validate() elif choice == 17: resources_object = cloudfront.IsWafEnabled(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 18: resources_object = vpc.ModifyVpc(data = data, manager = resource_manager) elif choice == 19: resources_object = vpc.DeleteVpc(data = data, manager = resource_manager) elif choice == 20: resources_object = shield.SetShieldProtection(data = data, manager = resource_manager) elif choice == 21: resources_object = iam.SetBoundary(data = data, manager = resource_manager) resources_object.validate() elif choice == 22: resources_object = iam.CertificateDelete(data = data, manager = resource_manager) elif choice == 23: resources_object = iam.SetPolicy(data = data, manager = resource_manager) resources_object.validate() elif choice == 24: resources_object = iam.RoleDelete(data = data, manager = resource_manager) elif choice == 25: resources_object = sfn.InvokeStepFunction(data = data, manager = resource_manager) elif choice == 26: resources_object = cloudtrail.Status(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 27: resources_object = cloudtrail.EventSelectors(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 28: resources_object = cloudtrail.UpdateTrail(data = data, manager = resource_manager) resources_object.validate() elif choice == 29: resources_object = cloudtrail.DeleteTrail(data = data, manager = resource_manager) elif choice == 30: resources_object = code.DeleteApplication(data = data, manager = resource_manager) elif choice == 31: resources_object = code.DeleteDeploymentGroup(data = data, manager = resource_manager) elif choice == 32: resources_object = appflow.DeleteAppFlowResource(data = data, manager = resource_manager) elif choice == 33: resources_object = awslambda.LambdaEnableXrayTracing(data = data, manager = resource_manager) elif choice == 34: resources_object = awslambda.LambdaEventSource(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 35: resources_object = awslambda.LambdaCrossAccountAccessFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 36: resources_object = awslambda.VersionTrim(data = data, manager = resource_manager) elif choice == 37: resources_object = awslambda.RemovePolicyStatement(data = data, manager = resource_manager) elif choice == 38: resources_object = awslambda.LayerCrossAccount(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 39: resources_object = awslambda.LayerRemovePermissions(data = data, manager = resource_manager) elif choice == 40: resources_object = awslambda.DeleteLayerVersion(data = data, manager = resource_manager) elif choice == 41: resources_object = emr.EMRSecurityConfigurationFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 42: resources_object = emr.DeleteEMRSecurityConfiguration(data = data, manager = resource_manager) elif choice == 43: resources_object = emr.EMRServerlessDelete(data = data, manager = resource_manager) elif choice == 44: resources_object = ami.AmiCrossAccountFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 45: resources_object = secretsmanager.CrossAccountAccessFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 46: resources_object = secretsmanager.HasStatementFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 47: resources_object = airflow.UpdateApacheAirflowEnvironment(data = data, manager = resource_manager) elif choice == 48: resources_object = airflow.DeleteApacheAirflowEnvironment(data = data, manager = resource_manager) elif choice == 49: resources_object = account.AccountCredentialReport(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 50: resources_object = account.AccountOrganization(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 51: resources_object = account.MacieEnabled(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 52: resources_object = account.CloudTrailEnabled(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 53: resources_object = account.ConfigEnabled(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 54: resources_object = account.IAMSummary(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 55: resources_object = account.AccessAnalyzer(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 56: resources_object = account.AccountPasswordPolicy(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 57: resources_object = elasticsearch.ElasticSearchCrossAccountAccessFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) elif choice == 58: resources_object = elasticsearch.ElasticSearchCrossClusterFilter(data = data, manager = resource_manager) event = _generate_random_dict(fdp) if object: object.process(data) if resources_object: if event: resources_object.process(resources, event) else: resources_object.process(resources) except ( ValueError, ClientError, ProfileNotFound, KeyError, TypeError, exceptions.PolicyValidationError): pass except AttributeError as e: if "object has no attribute" not in str(e): raise e def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) map["name"] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def initializeProviders(): AWS() def initializeResources(ctx, data): ebs.EBS(ctx, data) ebs.Snapshot(ctx, data) ami.AMI(ctx, data) route53.ResolverQueryLogConfig(ctx, data) emr.EMRSecurityConfiguration(ctx, data) def main(): initializeProviders() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, name, option): self.options = None self.session_factory = c7n_policy.get_session_factory(name, option) self.policy = FuzzPolicy(name) self.tracer = FuzzTracer() self.execution_id = "id" self.start_time = "1234567890" class FuzzPolicy: def __init__(self, provider_name): self.provider_name = provider_name self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True class FuzzOption: def __init__(self, fdp): self.region = fdp.ConsumeUnicodeNoSurrogates(1024) self.profile = fdp.ConsumeUnicodeNoSurrogates(1024) self.assume_role = fdp.ConsumeUnicodeNoSurrogates(1024) self.external_id = fdp.ConsumeUnicodeNoSurrogates(1024) class FuzzConfig: def __init__(self, fdp): self.account_id = fdp.ConsumeUnicodeNoSurrogates(1024) self.region = fdp.ConsumeUnicodeNoSurrogates(1024) if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/fuzz_resources_validate.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris # with atheris.instrument_imports(): # For local testing from c7n import exceptions, manager from c7n.resources import health, kafka, sagemaker, ebs, emr, route53 from c7n.resources import awslambda, cw, ec2, ecr, servicecatalog, asg from c7n.resources import secretsmanager, account, redshift, eks, glue from c7n.resources import securityhub, cloudtrail, ssm, rds, efs, vpc from c7n.resources import rdscluster, iam, ami, appelb, s3, cloudfront def TestOneInput(data): """Fuzz validate functions in resources package""" fdp = atheris.FuzzedDataProvider(data) choice = fdp.ConsumeIntInRange(1, 56) object = None data = _generate_random_dict(fdp) manager_data = _generate_random_dict(fdp) resource_manager = manager.ResourceManager(FuzzContext(FuzzPolicy), manager_data) try: if choice == 1: object = health.QueryFilter(data) elif choice == 2: object = kafka.SetMonitoring(data = data, manager = resource_manager) elif choice == 3: object = sagemaker.QueryFilter(data) elif choice == 4: object = ebs.CopySnapshot(data = data, manager = resource_manager) elif choice == 5: object = emr.QueryFilter(data) elif choice == 6: object = awslambda.SetConcurrency(data = data, manager = resource_manager) elif choice == 7: object = cw.EncryptLogGroup(data = data, manager = resource_manager) elif choice == 8: object = ec2.DisableApiStop(data = data, manager = resource_manager) elif choice == 9: object = ec2.Snapshot(data = data, manager = resource_manager) elif choice == 10: object = ec2.QueryFilter(data) elif choice == 11: object = ecr.SetLifecycle(data = data, manager = resource_manager) elif choice == 12: object = route53.SetQueryLogging(data = data, manager = resource_manager) elif choice == 13: object = servicecatalog.RemoveSharedAccounts(data = data, manager = resource_manager) elif choice == 14: object = account.SetAccountPasswordPolicy(data = data, manager = resource_manager) elif choice == 15: object = account.ServiceLimit(data = data, manager = resource_manager) elif choice == 16: object = account.EnableDataEvents(data = data, manager = resource_manager) elif choice == 17: object = account.SetS3PublicBlock(data = data, manager = resource_manager) elif choice == 18: object = account.GlueCatalogEncryptionEnabled(data) elif choice == 19: object = ebs.CopySnapshot(data = data, manager = resource_manager) elif choice == 20: object = ebs.EncryptInstanceVolumes(data = data, manager = resource_manager) elif choice == 21: object = ebs.CreateSnapshot(data = data, manager = resource_manager) elif choice == 22: object = ebs.ModifyVolume(data = data, manager = resource_manager) elif choice == 23: object = eks.UpdateConfig(data = data, manager = resource_manager) elif choice == 24: object = redshift.SetRedshiftLogging(data = data, manager = resource_manager) elif choice == 25: object = redshift.RedshiftSetAttributes(data = data, manager = resource_manager) elif choice == 26: object = glue.SecurityConfigFilter(data) elif choice == 27: object = asg.PropagateTags(data = data, manager = resource_manager) elif choice == 28: object = asg.Update(data = data, manager = resource_manager) elif choice == 29: object = securityhub.SecurityHubFindingFilter(data) elif choice == 30: object = securityhub.PostFinding(data = data, manager = resource_manager) elif choice == 31: object = cloudtrail.UpdateTrail(data = data, manager = resource_manager) elif choice == 32: object = ssm.SendCommand(data = data, manager = resource_manager) elif choice == 33: object = rds.Delete(data = data, manager = resource_manager) elif choice == 34: object = rds.SetPermissions(data = data, manager = resource_manager) elif choice == 35: object = rds.RegionCopySnapshot(data = data, manager = resource_manager) elif choice == 36: object = rds.ModifyDb(data = data, manager = resource_manager) elif choice == 37: object = efs.ConfigureLifecycle(data = data, manager = resource_manager) elif choice == 38: object = rdscluster.ModifyDbCluster(data = data, manager = resource_manager) elif choice == 39: object = vpc.FlowLogv2Filter(data) elif choice == 40: object = vpc.DhcpOptionsFilter(data) elif choice == 41: object = vpc.SGPermission(data) elif choice == 42: object = vpc.SetPermissions(data = data, manager = resource_manager) elif choice == 43: object = iam.SetBoundary(data = data, manager = resource_manager) elif choice == 44: object = iam.SetGroups(data = data, manager = resource_manager) elif choice == 45: object = iam.SetPolicy(data = data, manager = resource_manager) elif choice == 46: object = ami.SetDeprecation(data = data, manager = resource_manager) elif choice == 47: object = ami.SetPermissions(data = data, manager = resource_manager) elif choice == 48: object = appelb.SetS3Logging(data = data, manager = resource_manager) elif choice == 49: object = appelb.SetS3Logging(data = data, manager = resource_manager) elif choice == 50: object = s3.ToggleLogging(data = data, manager = resource_manager) elif choice == 51: object = s3.BucketEncryption(data = data, manager = resource_manager) elif choice == 52: object = s3.BucketEncryption(data = data, manager = resource_manager) elif choice == 53: object = cloudfront.DistributionUpdateAction(data = data, manager = resource_manager) elif choice == 54: object = cloudfront.BaseUpdateAction(data = data, manager = resource_manager) elif choice == 55: object = cloudfront.StreamingDistributionUpdateAction(data = data, manager = resource_manager) elif choice == 56: object = cloudfront.StreamingDistributionUpdateAction(data = data, manager = resource_manager) if object: object.validate() except (exceptions.PolicyValidationError, ValueError): pass # except (KeyError, TypeError): # pass def _generate_random_dict(fdp): map = dict() for count in range(fdp.ConsumeIntInRange(1, 100)): map[fdp.ConsumeUnicodeNoSurrogates(1024)] = fdp.ConsumeUnicodeNoSurrogates(1024) return map def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() class FuzzContext: def __init__(self, policy): self.session_factory = None self.options = None self.policy = policy self.tracer = FuzzTracer() class FuzzPolicy: def __init__(self): self.provider_name = "FuzzProviderName" self.name = "FuzzName" class FuzzTracer: def subsegment(type): return True if __name__ == "__main__": main() ================================================ FILE: projects/cloud-custodian/project.yaml ================================================ base_os_version: ubuntu-24-04 fuzzing_engines: - libfuzzer homepage: https://github.com/cloud-custodian/cloud-custodian language: python main_repo: https://github.com/cloud-custodian/cloud-custodian sanitizers: - address - undefined primary_contact: "kapil@stacklet.io" vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/cloud-hypervisor/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust as builder ## Install build dependencies. RUN apt-get update RUN git clone --depth 1 https://github.com/cloud-hypervisor/cloud-hypervisor.git # Always use the latest nightly toolchain since that's the version being # validated with Cloud Hypervisor CI ENV RUSTUP_TOOLCHAIN nightly COPY build.sh $SRC/ ================================================ FILE: projects/cloud-hypervisor/build.sh ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/cloud-hypervisor cargo fuzz build -O FUZZ_TARGET_OUTPUT_DIR=target/x86_64-unknown-linux-gnu/release for f in fuzz/fuzz_targets/*.rs do FUZZ_TARGET_NAME=$(basename ${f%.*}) cp fuzz/$FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT/ done ================================================ FILE: projects/cloud-hypervisor/project.yaml ================================================ homepage: "https://github.com/cloud-hypervisor/cloud-hypervisor" language: rust primary_contact: "bo.arvin.chen@gmail.com" auto_ccs: - "michael2012zhao@hotmail.com" - "Henry.Wang@arm.com" - "rbradford@rivosinc.com" - "samuel.e.ortiz@protonmail.com" - "liuwe@microsoft.com" - "seb@rivosinc.com" - "nistephe@microsoft.com" - "fabduchene@microsoft.com" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: 'https://github.com/cloud-hypervisor/cloud-hypervisor' ================================================ FILE: projects/cmake/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Install minimal build dependencies # Note: We don't install libssl-dev because it would break MSan # (all code must be instrumented for MSan to work properly) RUN apt-get update && apt-get install -y \ make \ autoconf \ automake \ libtool \ pkg-config # Clone official CMake repository (fuzzing support merged in fad74f77) RUN git clone --depth 1 https://gitlab.kitware.com/cmake/cmake CMake RUN git clone --depth 1 https://github.com/strongcourage/fuzzing-corpus WORKDIR CMake COPY build.sh $SRC/ ================================================ FILE: projects/cmake/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build CMake with all bundled dependencies for proper sanitizer support. # MSan requires all code to be instrumented, so we use bundled libraries # and disable OpenSSL (which would require building from source). mkdir build-dir && cd build-dir # Configure CMake # - Enable fuzzing targets # - Use bundled libraries (required for MSan - all code must be instrumented) # - Disable OpenSSL (not needed for fuzzing, avoids uninstrumented code) # - Disable server mode (deprecated) # - Disable tests (not needed for fuzzing) cmake .. \ -DCMAKE_C_COMPILER="${CC}" \ -DCMAKE_CXX_COMPILER="${CXX}" \ -DCMAKE_C_FLAGS="${CFLAGS}" \ -DCMAKE_CXX_FLAGS="${CXXFLAGS}" \ -DCMake_BUILD_FUZZING=ON \ -DCMAKE_USE_SYSTEM_LIBRARIES=OFF \ -DCMAKE_USE_OPENSSL=OFF \ -DBUILD_TESTING=OFF \ -DCMAKE_BUILD_TYPE=Release # Build CMakeLib (contains all the code we want to fuzz) make -j$(nproc) CMakeLib # Store paths for fuzzer linking CMAKE_SOURCE="${SRC}/CMake" CMAKE_BUILD="${CMAKE_SOURCE}/build-dir" CMAKE_LIB_DIR="${CMAKE_BUILD}/Source" UTILITIES_DIR="${CMAKE_BUILD}/Utilities" # Common include paths INCLUDE_FLAGS="-I${CMAKE_SOURCE}/Source" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_BUILD}/Source" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_BUILD}/Utilities" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Utilities/std" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Utilities/cmlibuv/include" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Utilities/cmlibrhash" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Utilities/cm3p" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Utilities" INCLUDE_FLAGS="${INCLUDE_FLAGS} -I${CMAKE_SOURCE}/Source/LexerParser" # Common libraries to link (order matters for static linking!) # NOTE: This list may need updating if CMake adds/removes bundled dependencies COMMON_LIBS="${CMAKE_LIB_DIR}/libCMakeLib.a" COMMON_LIBS="${COMMON_LIBS} ${CMAKE_LIB_DIR}/kwsys/libcmsys.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/std/libcmstd.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmcppdap/libcmcppdap.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmexpat/libcmexpat.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmlibarchive/libarchive/libcmlibarchive.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmliblzma/libcmliblzma.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmzstd/libcmzstd.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmzlib/libcmzlib.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmbzip2/libcmbzip2.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmcurl/lib/libcmcurl.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmnghttp2/libcmnghttp2.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmjsoncpp/libcmjsoncpp.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmlibrhash/libcmlibrhash.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmlibuv/libcmlibuv.a" COMMON_LIBS="${COMMON_LIBS} ${UTILITIES_DIR}/cmllpkgc/libcmllpkgc.a" # System libs needed SYS_LIBS="-lpthread -ldl -lrt" # Function to build a fuzzer build_fuzzer() { local name=$1 local source=$2 echo "Building ${name}..." $CXX $CXXFLAGS ${INCLUDE_FLAGS} -c "${source}" -o "${name}.o" $CXX $CXXFLAGS $LIB_FUZZING_ENGINE "${name}.o" ${COMMON_LIBS} ${SYS_LIBS} -o "$OUT/${name}" } # Build fuzzers cd ../Tests/Fuzzing # 1. XML Parser Fuzzer (existing) build_fuzzer "xml_parser_fuzzer" "xml_parser_fuzzer.cc" # 2. ListFile Lexer Fuzzer build_fuzzer "cmListFileLexerFuzzer" "cmListFileLexerFuzzer.cxx" # 3. Generator Expression Fuzzer build_fuzzer "cmGeneratorExpressionFuzzer" "cmGeneratorExpressionFuzzer.cxx" # 4. ELF Fuzzer build_fuzzer "cmELFFuzzer" "cmELFFuzzer.cxx" # 5. Archive Extract Fuzzer build_fuzzer "cmArchiveExtractFuzzer" "cmArchiveExtractFuzzer.cxx" # 6. File Lock Fuzzer build_fuzzer "cmFileLockFuzzer" "cmFileLockFuzzer.cxx" # 7. Expression Parser Fuzzer build_fuzzer "cmExprParserFuzzer" "cmExprParserFuzzer.cxx" # 8. PkgConfig Parser Fuzzer build_fuzzer "cmPkgConfigParserFuzzer" "cmPkgConfigParserFuzzer.cxx" # 9. JSON Parser Fuzzer build_fuzzer "cmJSONParserFuzzer" "cmJSONParserFuzzer.cxx" # 10. Script Fuzzer (highest coverage - executes CMake scripts) build_fuzzer "cmScriptFuzzer" "cmScriptFuzzer.cxx" # 11. String Algorithms Fuzzer build_fuzzer "cmStringAlgorithmsFuzzer" "cmStringAlgorithmsFuzzer.cxx" # 12. Version Fuzzer build_fuzzer "cmVersionFuzzer" "cmVersionFuzzer.cxx" # 13. CMake Path Fuzzer build_fuzzer "cmCMakePathFuzzer" "cmCMakePathFuzzer.cxx" # 14. GCC Depfile Fuzzer build_fuzzer "cmGccDepfileFuzzer" "cmGccDepfileFuzzer.cxx" # 15. Glob Fuzzer build_fuzzer "cmGlobFuzzer" "cmGlobFuzzer.cxx" # Build seed corpora echo "Building seed corpora..." # Helper function for corpus build_corpus() { local name=$1 local dir=$2 if [ -d "${dir}" ]; then zip -j "$OUT/${name}_seed_corpus.zip" "${dir}"/* 2>/dev/null || true fi } # XML corpus (existing) zip -j $OUT/xml_parser_fuzzer_seed_corpus.zip \ $SRC/fuzzing-corpus/xml/*.xml 2>/dev/null || true # New corpora build_corpus "cmListFileLexerFuzzer" "corpus/listfile" build_corpus "cmGeneratorExpressionFuzzer" "corpus/genex" build_corpus "cmELFFuzzer" "corpus/elf" build_corpus "cmArchiveExtractFuzzer" "corpus/archive" build_corpus "cmFileLockFuzzer" "corpus/filelock" build_corpus "cmExprParserFuzzer" "corpus/expr" build_corpus "cmPkgConfigParserFuzzer" "corpus/pkgconfig" build_corpus "cmJSONParserFuzzer" "corpus/json" build_corpus "cmScriptFuzzer" "corpus/script" build_corpus "cmStringAlgorithmsFuzzer" "corpus/string" build_corpus "cmVersionFuzzer" "corpus/version" build_corpus "cmCMakePathFuzzer" "corpus/path" build_corpus "cmGccDepfileFuzzer" "corpus/depfile" # Note: No corpus/glob directory in upstream - glob patterns are simple strings # Copy dictionaries (cmFoo.dict -> cmFooFuzzer.dict) echo "Copying dictionaries..." for dict in *.dict; do if [ -f "$dict" ]; then base="${dict%.dict}" if [ "$base" = "xml_parser" ]; then cp "$dict" "$OUT/xml_parser_fuzzer.dict" else cp "$dict" "$OUT/${base}Fuzzer.dict" fi fi done # Copy options files (for timeout/memory limits) echo "Copying options files..." for opts in *.options; do if [ -f "$opts" ]; then cp "$opts" "$OUT/" fi done echo "Build complete! Built 15 fuzzers with corpora, dictionaries, and options." ================================================ FILE: projects/cmake/project.yaml ================================================ homepage: "https://gitlab.kitware.com/cmake/cmake" main_repo: "https://gitlab.kitware.com/cmake/cmake" language: c++ primary_contact: "brad.king@kitware.com" auto_ccs: - "Adam@adalogics.com" - "tyler.yankee@kitware.com" sanitizers: - address - undefined - memory fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/cmark/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake python3 RUN git clone --depth 1 https://github.com/commonmark/cmark.git cmark WORKDIR cmark COPY run_tests.sh build.sh *.dict *.options $SRC/ ================================================ FILE: projects/cmark/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake -DBUILD_TESTING=ON ../ make -j$(nproc) cd .. $CC $CFLAGS -Isrc -Ibuild/src -c fuzz/cmark-fuzz.c -o cmark_fuzzer.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE cmark_fuzzer.o build/src/libcmark.a -o $OUT/cmark_fuzzer cp $SRC/*.options $OUT/ cp fuzz/dictionary $OUT/cmark.dict mkdir -p corpus python3 test/spec_tests.py --fuzz-corpus corpus --spec test/spec.txt python3 test/spec_tests.py --fuzz-corpus corpus --spec test/regression.txt python3 test/spec_tests.py --fuzz-corpus corpus --spec test/smart_punct.txt zip -j $OUT/cmark_fuzzer_seed_corpus.zip corpus/* ================================================ FILE: projects/cmark/cmark_fuzzer.options ================================================ [libfuzzer] dict = cmark.dict ================================================ FILE: projects/cmark/project.yaml ================================================ homepage: "http://commonmark.org" language: c++ primary_contact: "jgm@berkeley.edu" auto_ccs: - "wellnhofer@aevum.de" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/commonmark/cmark.git' ================================================ FILE: projects/cmark/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd build make test ================================================ FILE: projects/cockroachdb/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/cockroachdb/cockroach.git cockroach RUN wget https://go.dev/dl/go1.22.9.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.22.9.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ WORKDIR cockroach COPY build.sh $SRC/ ================================================ FILE: projects/cockroachdb/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cockroach/build/oss-fuzz/build.sh ================================================ FILE: projects/cockroachdb/project.yaml ================================================ homepage: "https://www.cockroachlabs.com/" language: go primary_contact: "stan@cockroachlabs.com" auto_ccs: - "renato@cockroachlabs.com" - "herko@cockroachlabs.com" - "darryl@cockroachlabs.com" main_repo: "https://github.com/cockroachdb/cockroach.git" file_github_issue: true fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/compress/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/klauspost/compress RUN git clone --depth 1 https://github.com/klauspost/compress-fuzz WORKDIR compress COPY build.sh $SRC/ ================================================ FILE: projects/compress/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project $SRC/compress/ossfuzz/ossfuzz.sh ================================================ FILE: projects/compress/project.yaml ================================================ homepage: "https://github.com/klauspost/compress" language: go primary_contact: "klauspost@gmail.com" main_repo: "https://github.com/klauspost/compress" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/config-validator/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go # Clone the actual repo with the fuzz target. RUN git clone --depth 1 https://github.com/GoogleCloudPlatform/config-validator $GOPATH/src/github.com/GoogleCloudPlatform/config-validator COPY build.sh $SRC/ # Required to avoid 'working directory is not part of a module' error. WORKDIR $GOPATH/src/github.com/GoogleCloudPlatform/config-validator ================================================ FILE: projects/config-validator/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Copy the library files needed to initialize the validator. mkdir -p $OUT/validatorfiles cp -a 'test/cf/constraints' $OUT/validatorfiles cp -a 'test/cf/library' $OUT/validatorfiles cp -a 'test/cf/templates' $OUT/validatorfiles # Copy the corpus. zip -jr $OUT/fuzz_config_validator_seed_corpus.zip internal/fuzz/corpus # Compile the fuzzer. compile_go_fuzzer github.com/GoogleCloudPlatform/config-validator/internal/fuzz Fuzz fuzz_config_validator ================================================ FILE: projects/config-validator/project.yaml ================================================ homepage: "https://github.com/GoogleCloudPlatform/config-validator/" main_repo: "https://github.com/GoogleCloudPlatform/config-validator/" primary_contact: "mpetkov@google.com" auto_ccs: - morgantep@google.com - martin.p.petkov@gmail.com language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/configparser/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN python -m pip install 'setuptools~=69.0' RUN git clone https://github.com/jaraco/configparser/ configparser COPY *.sh *py $SRC/ WORKDIR $SRC/configparser ================================================ FILE: projects/configparser/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/configparser/fuzz_dict.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import json from backports import configparser def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: json_dict = json.loads(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except: return if not isinstance(json_dict, dict): return config_parser = configparser.ConfigParser() try: config_parser.read_dict(json_dict) except (configparser.Error): pass except ValueError: # Thrown at: https://github.com/jaraco/configparser/blob/8b5181b4f270be88f3e4572300406587fdbd4a6e/src/backports/configparser/__init__.py#L422 pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/configparser/fuzz_read.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from backports import configparser def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) config_parser = configparser.ConfigParser() try: config_parser.read_string(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except (configparser.Error): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/configparser/project.yaml ================================================ homepage: https://github.com/jaraco/configparser/ main_repo: https://github.com/jaraco/configparser/ language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/connectedhomeip/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 # Install prerequisite packages # See connectedhomeip/docs/guides/BUILDING.md#prerequisites RUN apt-get update && \ apt-get install -y --no-install-recommends pkg-config libssl-dev libdbus-1-dev libglib2.0-dev libglib2.0-0\ libavahi-client-dev ninja-build libmount-dev libblkid-dev \ unzip libgirepository1.0-dev libcairo2-dev libreadline-dev patchelf file libevent-dev # Install Rust for building `cryptography` python package when bootstraping pigweed RUN curl https://sh.rustup.rs -sSf | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" RUN rustup install nightly RUN rustup default nightly RUN git clone --depth=1 https://github.com/project-chip/connectedhomeip.git connectedhomeip # PW_PROJECT_ROOT is used in requirements.build.txt ENV PW_PROJECT_ROOT=$SRC/connectedhomeip # Ensure global python has access to build requirements RUN pip3 install -r connectedhomeip/scripts/setup/requirements.build.txt # checkout submodules required for linux RUN cd $SRC/connectedhomeip && scripts/checkout_submodules.py --shallow --platform linux # Bootstrap pigweed environment SHELL ["/bin/bash", "-c"] RUN cd $SRC/connectedhomeip && . scripts/bootstrap.sh COPY build.sh $SRC/ ================================================ FILE: projects/connectedhomeip/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # workaround to get Fuzz Introspector to build; making it link with lld instead of the environment's gold linker which gives an error if [ "$SANITIZER" == "introspector" ]; then export CFLAGS=$(echo "$CFLAGS" | sed 's/gold/lld/g') export CXXFLAGS=$(echo "$CXXFLAGS" | sed 's/gold/lld/g') fi cd $SRC/connectedhomeip # Activate Pigweed environment set +u PW_ENVSETUP_QUIET=1 source scripts/activate.sh set -u #This adds zap-cli to PATH, needed for fuzzing all-clusters-app export PATH="/src/connectedhomeip/.environment/cipd/packages/zap/:$PATH" # Create a build directory with the following options: # - `oss_fuzz` enables OSS-Fuzz build # - `is_clang` selects clang toolchains (does not support AFL fuzzing engine) # - `enable_rrti` enables RTTI to support UBSan build # - `chip_enable_thread_safety_checks` disabled since OSS-Fuzz clang does not # seem to currently support or need this analysis # - `chip_enable_openthread` disabled since OSS-Fuzz clang issues a compile # error on GenericConnectivityManagerImpl_Thread.ipp and current fuzzing # does not differentiate between thread/Wifi/TCP/UDP/BLE connectivity # implementations. # - `target_ldflags` forces compiler to use LLVM's linker gn gen out/fuzz_targets \ --args=" oss_fuzz=true \ is_clang=true \ enable_rtti=true \ chip_enable_thread_safety_checks=false \ chip_enable_thread=false \ target_ldflags=[\"-fuse-ld=lld\"]" # Deactivate Pigweed environment to use OSS-Fuzz toolchains deactivate # Compile fuzz targets ninja -C out/fuzz_targets fuzz_tests cp out/fuzz_targets/tests/* $OUT/ # Copy some GLib and GIO runtime libraries into $OUT so fuzzed all-clusters app can run under OSS-Fuzz base-runner, which does not provide these libraries. mkdir -p $OUT/lib cp /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0 $OUT/lib/ cp /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 $OUT/lib/ cp /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 $OUT/lib/ cp /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 $OUT/lib/ for f in $OUT/fuzz-*; do file "$f" | grep -q "ELF" && patchelf --set-rpath '$ORIGIN/lib' "$f" done patchelf --set-rpath '$ORIGIN' $OUT/lib/*.so* 2>/dev/null ================================================ FILE: projects/connectedhomeip/project.yaml ================================================ homepage: "https://buildwithmatter.com/" language: c++ primary_contact: "andreilitvin@google.com" base_os_version: ubuntu-24-04 auto_ccs: - "asad_haque@comcast.com" - "lalabdulkarim@csa-iot.org" - "mboyington@google.com" - "szewczyk@google.com" - "tennessee@google.com" - "aalami@csa-iot.org" sanitizers: - address - undefined # MemorySanitizer is deactivated due to false positives related to Glib # For MSan; Glib and all others libs should be compiled with MSan # - memory fuzzing_engines: - libfuzzer - honggfuzz - centipede main_repo: 'https://github.com/project-chip/connectedhomeip.git' ================================================ FILE: projects/connexion/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip asgiref flask RUN git clone --depth=1 https://github.com/python-jsonschema/jsonschema-specifications jsonschema_specifications RUN git clone https://github.com/spec-first/connexion connexion COPY *.sh *py $SRC/ WORKDIR $SRC/connexion ================================================ FILE: projects/connexion/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do # Add relevant data and two hidden modules compile_python_fuzzer $fuzzer \ --add-data ./connexion/resources/schemas/:connexion/resources/schemas/ \ --add-data $SRC/jsonschema_specifications/jsonschema_specifications/schemas:jsonschema_specifications/schemas \ --hidden-import=asgiref \ --hidden-import=flask done ================================================ FILE: projects/connexion/fuzz_query_resolving.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import connexion from werkzeug.datastructures import MultiDict def fixed_params(data): """Create a given URI parser and pass in fixed params for the URI object and a random query.""" fdp = atheris.FuzzedDataProvider(data) collection_formats = ['csv', 'pipes', 'multi'] parameters = [{ "name": "letters", "in": "query", "type": "string", "items": { "type": "string" }, "collectionFormat": fdp.PickValueInList(collection_formats), }] parser_classes = [ connexion.uri_parsing.OpenAPIURIParser, connexion.uri_parsing.Swagger2URIParser, connexion.uri_parsing.AlwaysMultiURIParser, connexion.uri_parsing.FirstValueURIParser, ] parser_class = fdp.PickValueInList(parser_classes) parser = parser_class(parameters, {}) param_dict = MultiDict([ (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)) ]) parser.resolve_query(param_dict.to_dict(flat=False)) def arbitrary(data): """Create a given URI parser and pass in random params as well as random query params.""" fdp = atheris.FuzzedDataProvider(data) collection_formats = ['csv', 'pipes', 'multi'] parameters = [{ fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): { fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24) }, "collectionFormat": fdp.PickValueInList(collection_formats), }] parser_classes = [ connexion.uri_parsing.OpenAPIURIParser, connexion.uri_parsing.Swagger2URIParser, connexion.uri_parsing.AlwaysMultiURIParser, connexion.uri_parsing.FirstValueURIParser, ] parser_class = fdp.PickValueInList(parser_classes) try: parser = parser_class(parameters, {}) except KeyError: return param_dict = MultiDict([ (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)), (fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24)) ]) parser.resolve_query(param_dict.to_dict(flat=False)) def TestOneInput(data): fixed_params(data) arbitrary(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/connexion/project.yaml ================================================ homepage: https://github.com/spec-first/connexion main_repo: https://github.com/spec-first/connexion language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/containerd/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN apt-get update && apt-get install -y btrfs-progs libc-dev pkg-config libseccomp-dev gcc wget libbtrfs-dev RUN git clone --depth 1 https://github.com/containerd/containerd RUN git clone --depth=1 https://github.com/AdamKorcz/instrumentation COPY build.sh $SRC/ WORKDIR $SRC/containerd ================================================ FILE: projects/containerd/build.sh ================================================ #/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/containerd/contrib/fuzz/oss_fuzz_build.sh ================================================ FILE: projects/containerd/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/containerd/containerd" main_repo: "https://github.com/containerd/containerd" primary_contact: "security@containerd.io" auto_ccs : - "adam@adalogics.com" - "samuelkarp@google.com" - "derek@mcgstyle.net" - "estesp@gmail.com" - "mikebrow@gmail.com" - "cjingram@google.com" - "kato.kazuyoshi@gmail.com" - "vinaygo@google.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/coreutils/project.yaml ================================================ homepage: "http://www.gnu.org/software/coreutils/" main_repo: "https://github.com/coreutils/coreutils" primary_contact: "P@draigBrady.com" ================================================ FILE: projects/cosign/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/sigstore/cosign # For json corpus RUN git clone --depth=1 https://github.com/dvyukov/go-fuzz-corpus # For json dictionary RUN git clone --depth=1 https://github.com/rc0r/afl-fuzz COPY build.sh $SRC/ WORKDIR $SRC/cosign ================================================ FILE: projects/cosign/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./test/fuzz/oss_fuzz_build.sh ================================================ FILE: projects/cosign/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://sigstore.dev" main_repo: "https://github.com/sigstore/cosign" primary_contact: "security@sigstore.dev" auto_ccs: - lhinds@sigstore.dev - hblauzvern@sigstore.dev - codysoyland@sigstore.dev - bcallaway@sigstore.dev vendor_ccs: - adam@adalogics.com language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/cosmos-sdk/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/cosmos/cosmos-sdk COPY build.sh $SRC WORKDIR $SRC/cosmos-sdk ================================================ FILE: projects/cosmos-sdk/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ bash -x ./fuzz/oss-fuzz-build.sh ================================================ FILE: projects/cosmos-sdk/project.yaml ================================================ homepage: "https://github.com/cosmos/cosmos-sdk" primary_contact: "fuzzing@orijtech.com" auto_ccs: - emmanuel@orijtech.com - cuong@orijtech.com - elias@orijtech.com language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/cosmos/cosmos-sdk" ================================================ FILE: projects/coturn/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake libssl-dev libevent-dev RUN git clone https://github.com/coturn/coturn COPY build.sh $SRC/ WORKDIR $SRC/coturn/ ================================================ FILE: projects/coturn/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir my_build pushd my_build/ cmake -DFUZZER=ON -DLIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" \ -DCMAKE_EXE_LINKER_FLAGS="-Wl,-rpath,'\$ORIGIN/lib'" -DWITH_MYSQL=OFF -Wno-dev ../. make -j$(nproc) popd pushd my_build/fuzzing/ cp FuzzStun $OUT/FuzzStun cp FuzzStunClient $OUT/FuzzStunClient popd pushd fuzzing/input/ cp FuzzStun_seed_corpus.zip $OUT/FuzzStun_seed_corpus.zip cp FuzzStunClient_seed_corpus.zip $OUT/FuzzStunClient_seed_corpus.zip popd pushd /lib/x86_64-linux-gnu/ mkdir $OUT/lib/ cp libevent* $OUT/lib/. popd ================================================ FILE: projects/coturn/project.yaml ================================================ homepage: "https://github.com/coturn/coturn" language: c base_os_version: ubuntu-24-04 primary_contact: "eakraly@gmail.com" auto_ccs: - "eakraly@gmail.com" - "gustavogb@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/coturn/coturn' ================================================ FILE: projects/coveragepy/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/nedbat/coveragepy WORKDIR coveragepy COPY build.sh *.py $SRC/ ================================================ FILE: projects/coveragepy/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/coveragepy/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from coverage.exceptions import NotPython from coverage.parser import PythonParser def TestOneInput(data): """Fuzzer for PythonParser""" fdp = atheris.FuzzedDataProvider(data) t = fdp.ConsumeUnicodeNoSurrogates(1024) if not t: return try: p = PythonParser(text = t) p.parse_source() except (NotPython, MemoryError) as e2: # Catch Memory error for stack overflows # Catch NotPython issues raised by coveragepy pass except ValueError as e: if "source code string cannot contain null bytes" in str(e): # Not interesting pass else: raise e def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/coveragepy/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/nedbat/coveragepy/ language: python main_repo: https://github.com/nedbat/coveragepy primary_contact: nedbat@gmail.com sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com # Bug reports are public by default: view_restrictions: none ================================================ FILE: projects/cpp-httplib/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool # Install brotli. RUN apt-get install -y libbrotli-dev # Install zlib. RUN apt-get update && apt-get install -y zlib1g-dev RUN git clone --depth 1 https://github.com/yhirose/cpp-httplib.git cpp-httplib WORKDIR cpp-httplib COPY build.sh $SRC/ ================================================ FILE: projects/cpp-httplib/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzz targets specified in test/Makefile. cd test/fuzzing && make -j$(nproc) server_fuzzer # Copy the fuzzer executables, zip-ed corpora, option and dictionary files to $OUT. find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' # Copy fuzz-target. find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' # Copy dictionaries. find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' # Copy seed corpora. ================================================ FILE: projects/cpp-httplib/project.yaml ================================================ homepage: "https://github.com/yhirose/cpp-httplib" language: c++ primary_contact: "yuji.hirose.bug@gmail.com" auto_ccs : - "cpp-httplib-oss-fuzz@googlegroups.com" - "omkarjadhav@google.com" - "hlivingstone@google.com" - "kalaskar@google.com" - "ankitlohia@google.com" sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory main_repo: 'https://github.com/yhirose/cpp-httplib.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/cppcheck/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth=1 https://github.com/danmar/cppcheck.git WORKDIR cppcheck COPY build.sh $SRC/ ================================================ FILE: projects/cppcheck/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build fuzzer cd $SRC/cppcheck/oss-fuzz make -j$(nproc) oss-fuzz-client cp oss-fuzz-client $OUT/ ================================================ FILE: projects/cppcheck/project.yaml ================================================ homepage: "https://cppcheck.sourceforge.net" language: c++ primary_contact: "daniel.marjamaki@gmail.com" auto_ccs: - "daniel.marjamaki@gmail.com" - "ettl.martin78@gmail.com" - "firewave0000@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/danmar/cppcheck.git' ================================================ FILE: projects/cppitertools/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/ryanhaining/cppitertools cppitertools WORKDIR cppitertools COPY build.sh *.cpp $SRC/ ================================================ FILE: projects/cppitertools/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_* . $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -I./ -I./cppitertools fuzz_cppitertools.cpp -std=c++17 -o $OUT/fuzz_cppitertools ================================================ FILE: projects/cppitertools/fuzz_cppitertools.cpp ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include using iter::chain; using iter::combinations; using iter::compress; using iter::cycle; using iter::groupby; void FuzzChained(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::vector v; for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 1024); i++) { v.push_back((char)fdp.ConsumeIntegral()); } const auto ch = chain(v, v, v); std::vector v2(std::begin(ch), std::end(ch)); } int length(const std::string &s) { return s.size(); } void FuzzGroupby(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::vector v; for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 1024); i++) { v.push_back(fdp.ConsumeRandomLengthString()); } for (auto &&gb : groupby(v, length)) { } } void FuzzCycle(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::vector v; for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 1024); i++) { v.push_back(fdp.ConsumeIntegral()); } auto ch = cycle(v); std::vector o; size_t count = 0; for (auto val : ch) { o.push_back(val); count++; if (count > 1500) { break; } } } void FuzzCombinations(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::string s = fdp.ConsumeRandomLengthString(); std::vector> sc; size_t count = 0; for (auto &&v : combinations(s, fdp.ConsumeIntegralInRange(1, 16))) { sc.emplace_back(std::begin(v), std::end(v)); count++; if (count > 1500) { break; } } } void FuzzCompress(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::vector ivec; std::vector bvec; for (int i = 0; i < 100; i++) { ivec.push_back(fdp.ConsumeIntegralInRange(1, 1000000)); bvec.push_back(fdp.ConsumeBool()); } auto c = compress(ivec, bvec); std::vector v(std::begin(c), std::end(c)); const auto &c2 = c; (void)(std::begin(c) == std::end(c2)); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzChained(data, size); FuzzGroupby(data, size); FuzzCycle(data, size); FuzzCombinations(data, size); FuzzCompress(data, size); return 0; } ================================================ FILE: projects/cppitertools/project.yaml ================================================ homepage: "https://github.com/ryanhaining/cppitertools" main_repo: "https://github.com/ryanhaining/cppitertools" language: c++ vendor_ccs: - david@adalogics.com ================================================ FILE: projects/cpuinfo/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/pytorch/cpuinfo WORKDIR cpuinfo COPY build.sh *.c $SRC/ ================================================ FILE: projects/cpuinfo/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Use fuzzer-file paths instead of kernel paths sed -i 's/"\/proc\/cpuinfo"/"\/tmp\/libfuzzer.config"/g' src/x86/linux/cpuinfo.c sed -i 's/"\/sys\/devices\/system\/cpu\/kernel_max"/"\/tmp\/libfuzzer.config"/g' src/linux/processors.c mkdir build cd build cmake \ -DCPUINFO_BUILD_UNIT_TESTS=OFF \ -DCPUINFO_BUILD_MOCK_TESTS=OFF \ -DCPUINFO_BUILD_BENCHMARKS=OFF \ .. make $CC $CFLAGS -c $SRC/fuzz_cpuinfo.c -o fuzz_cpuinfo.o \ -I/src/cpuinfo/src -I/src/cpuinfo/include $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_cpuinfo.o -o $OUT/fuzz_cpuinfo \ ./libcpuinfo.a ================================================ FILE: projects/cpuinfo/fuzz_cpuinfo.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[256]; sprintf(filename, "/tmp/libfuzzer.config"); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); struct cpuinfo_x86_linux_processor processors[256]; cpuinfo_x86_linux_parse_proc_cpuinfo(256, processors); cpuinfo_linux_get_max_processors_count(); unlink(filename); return 0; } ================================================ FILE: projects/cpuinfo/project.yaml ================================================ homepage: "https://github.com/pytorch/cpuinfo" main_repo: "https://github.com/pytorch/cpuinfo" language: c vendor_ccs: - david@adalogics.com ================================================ FILE: projects/cpython3/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y build-essential libncursesw5-dev \ libreadline-dev libssl-dev libgdbm-dev \ libc6-dev libsqlite3-dev tk-dev libbz2-dev \ zlib1g-dev libffi-dev RUN git clone https://github.com/python/cpython.git cpython3 WORKDIR cpython3 COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/cpython3/build.sh ================================================ #!/bin/bash # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Ignore memory leaks from python scripts invoked in the build export ASAN_OPTIONS="detect_leaks=0" export MSAN_OPTIONS="halt_on_error=0:exitcode=0:report_umrs=0" # Remove -pthread from CFLAGS, this trips up ./configure # which thinks pthreads are available without any CLI flags CFLAGS=${CFLAGS//"-pthread"/} # Ensure assert statements are enabled. It may help identify problems # earlier if those fire. CFLAGS="${CFLAGS} -UNDEBUG" # We use some internal CPython API. CFLAGS="${CFLAGS} -IInclude/internal/" FLAGS=() case $SANITIZER in address) FLAGS+=("--with-address-sanitizer") ;; memory) FLAGS+=("--with-memory-sanitizer") # installing ensurepip takes a while with MSAN instrumentation, so # we disable it here FLAGS+=("--without-ensurepip") # -msan-keep-going is needed to allow MSAN's halt_on_error to function FLAGS+=("CFLAGS=-mllvm -msan-keep-going=1") ;; undefined) FLAGS+=("--with-undefined-behavior-sanitizer") ;; esac ./configure "${FLAGS[@]:-}" --prefix $OUT # We use altinstall to avoid having the Makefile create symlinks make -j$(nproc) altinstall FUZZ_DIR=Modules/_xxtestfuzz for fuzz_test in $(cat $FUZZ_DIR/fuzz_tests.txt) do # Build (but don't link) the fuzzing stub with a C compiler $CC $CFLAGS $($OUT/bin/python*-config --cflags) $FUZZ_DIR/fuzzer.c \ -D _Py_FUZZ_ONE -D _Py_FUZZ_$fuzz_test -c -Wno-unused-function \ -o $WORK/$fuzz_test.o # Link with C++ compiler to appease libfuzzer $CXX $CXXFLAGS -rdynamic $WORK/$fuzz_test.o -o $OUT/$fuzz_test \ $LIB_FUZZING_ENGINE $($OUT/bin/python*-config --ldflags --embed) # Zip up and copy any seed corpus if [ -d "${FUZZ_DIR}/${fuzz_test}_corpus" ]; then zip -j "${OUT}/${fuzz_test}_seed_corpus.zip" ${FUZZ_DIR}/${fuzz_test}_corpus/* fi # Copy over the dictionary for this test if [ -e "${FUZZ_DIR}/dictionaries/${fuzz_test}.dict" ]; then cp "${FUZZ_DIR}/dictionaries/${fuzz_test}.dict" "$OUT/${fuzz_test}.dict" fi done # A little bit hacky but we have to copy $OUT/include to # $OUT/$OUT/include as the coverage build needs all source # files used in execution and expects it to be there. # See projects/tensorflow/build.sh for prior art if [ "$SANITIZER" = "coverage" ] then mkdir -p $OUT/$OUT cp -r $OUT/include $OUT/$OUT/ fi ================================================ FILE: projects/cpython3/project.yaml ================================================ homepage: "https://python.org/" language: c++ primary_contact: "seth@python.org" main_repo: "https://github.com/python/cpython" auto_ccs: - "alex.gaynor@gmail.com" - "ammar@ammaraskar.com" - "greg@krypto.org" - "pablogsal@python.org" - "stanulbrych@gmail.com" fuzzing_engines: - afl - honggfuzz - libfuzzer sanitizers: - address - memory - undefined ================================================ FILE: projects/cpython3/run_tests.sh ================================================ #!/bin/bash # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Ignore memory leaks from python scripts invoked in the build export ASAN_OPTIONS="detect_leaks=0" # Skip network related unit test case make test TESTOPTS="-u all,-network,-urlfetch" ================================================ FILE: projects/cras/Dockerfile ================================================ # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Defines a docker image that can build cras fuzzers. # FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get -y update && \ apt-get install -y \ automake \ build-essential \ cmake \ g++ \ git \ libasound-dev \ libdbus-1-dev \ libgtest-dev \ libncurses5-dev \ libsbc-dev \ libspeexdsp-dev \ libsystemd-dev \ libclang1 \ libtool \ libudev-dev \ wget \ zip RUN apt-get clean RUN cd /tmp && git clone https://github.com/google/googletest.git -b v1.8.x && \ cd googletest && \ mkdir build && cd build && \ cmake .. -DBUILD_SHARED_LIBS=ON \ -DINSTALL_GTEST=ON \ -DCMAKE_INSTALL_PREFIX:PATH=/usr && \ make && make install # Need to build and install alsa so there is a static lib. RUN mkdir -p /tmp/alsa-build && cd /tmp/alsa-build && \ wget https://alsa-project.org/files/pub/lib/alsa-lib-1.1.4.1.tar.bz2 && \ echo 91bb870c14d1c7c269213285eeed874fa3d28112077db061a3af8010d0885b76 alsa-lib-1.1.4.1.tar.bz2 | sha256sum -c && \ tar xjf alsa-lib-* && \ cd alsa-lib-* && \ ./configure --enable-static --disable-shared && \ make clean && \ make -j$(nproc) all && \ make install RUN cd $SRC && git clone https://chromium.googlesource.com/chromiumos/third_party/adhd WORKDIR adhd COPY build.sh $SRC/ ================================================ FILE: projects/cras/build.sh ================================================ #!/bin/bash -eux # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd ${SRC}/adhd devtools/oss-fuzz-build.sh ================================================ FILE: projects/cras/project.yaml ================================================ homepage: "https://www.chromium.org" language: rust primary_contact: "cujomalainey@chromium.org" auto_ccs: - "hychao@chromium.org" - "cychiang@chromium.org" - "yuhsuan@chromium.org" - "enshuo@chromium.org" - "judyhsiao@chromium.org" - "johnylin@chromium.org" - "aaronyu@google.com" - "hunghsienchen@chromium.org" - "htcheong@chromium.org" - "jrwu@chromium.org" - "cranelw@google.com" - "eddyhsu@google.com" - "andyross@google.com" - "bailideng@google.com" - "normanbt@google.com" - "pteerapong@google.com" - "whalechang@google.com" sanitizers: - address - undefined fuzzing_engines: - afl - honggfuzz - libfuzzer builds_per_day: 4 main_repo: 'https://chromium.googlesource.com/chromiumos/third_party/adhd' ================================================ FILE: projects/cri-o/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y libaio-dev autoconf gettext texinfo \ libbtrfs-dev git libassuan-dev libdevmapper-dev libglib2.0-dev libc6-dev \ libgpgme-dev libgpg-error-dev libseccomp-dev libsystemd-dev libselinux1-dev \ pkg-config go-md2man libudev-dev software-properties-common systemd RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ RUN git clone --depth 1 https://github.com/cri-o/cri-o RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing COPY build.sh $SRC/ RUN wget https://sourceware.org/ftp/lvm2/LVM2.2.03.15.tgz \ && tar -xvzf ./LVM2.2.03.15.tgz \ && cd LVM2.2.03.15 \ && ./configure --disable-selinux \ && make WORKDIR $SRC/cri-o ================================================ FILE: projects/cri-o/build.sh ================================================ #/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/cri-o/build.sh ================================================ FILE: projects/cri-o/project.yaml ================================================ homepage: "https://cri-o.io/" main_repo: "https://github.com/cri-o/cri-o" primary_contact: "cncf-crio-security@lists.cncf.io" auto_ccs : - "adam@adalogics.com" - "david@adalogics.com" - "pehunt@redhat.com" - "sgrunert@redhat.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/croaring/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make RUN git clone --depth 1 https://github.com/RoaringBitmap/CRoaring croaring RUN mv croaring/fuzz/* $SRC/ RUN sed -i 's/DENABLE_ROARING_TESTS=OFF/DENABLE_ROARING_TESTS=ON/g' $SRC/build.sh COPY run_tests.sh $SRC/ WORKDIR $SRC/croaring ================================================ FILE: projects/croaring/project.yaml ================================================ homepage: "https://roaringbitmap.org" language: c primary_contact: "lemire@gmail.com" auto_ccs: - "k2@ktwo.ca" - "lemire@gmail.com" sanitizers: - address - undefined - memory: experimental: True main_repo: "https://github.com/RoaringBitmap/CRoaring" fuzzing_engines: - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/croaring/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### # Skipping realdata_unit as it is failing ctest --test-dir build-dir -E realdata_unit ================================================ FILE: projects/cron-utils/CronParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.cronutils.parser.CronParser; import com.cronutils.model.definition.CronDefinition; import com.cronutils.model.definition.CronDefinitionBuilder; import com.cronutils.model.CronType; public class CronParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { CronType[] cronTypes = { CronType.CRON4J, CronType.QUARTZ, CronType.UNIX, CronType.SPRING, CronType.SPRING53 }; CronType cronType = data.pickValue(cronTypes); CronDefinition cronDef = CronDefinitionBuilder.instanceDefinitionFor(cronType); CronParser parser = new CronParser(cronDef); try{ parser.parse(data.consumeRemainingAsString()); } catch(IllegalArgumentException | ArrayIndexOutOfBoundsException e){ return; } } } ================================================ FILE: projects/cron-utils/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/jmrozanec/cron-utils.git cron-utils COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/cron-utils ================================================ FILE: projects/cron-utils/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15 -Dmaven.javadoc.skip=true" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/cron-utils-$CURRENT_VERSION.jar" $OUT/cron-utils.jar ALL_JARS="cron-utils.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/cron-utils/project.yaml ================================================ homepage: "https://github.com/jmrozanec/cron-utils" language: jvm primary_contact: "" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/jmrozanec/cron-utils.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/croniter/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/kiorky/croniter COPY build.sh *.py $SRC/ WORKDIR croniter ================================================ FILE: projects/croniter/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Workaround for oss-fuzz not being able to recognise which croniter modules are used # See https://github.com/ossf/fuzz-introspector/issues/1010 export PYFUZZPACKAGE=$SRC/croniter/src/croniter # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/croniter/fuzz_iter.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys from datetime import datetime from croniter import croniter from croniter.croniter import CroniterError, CroniterBadTypeRangeError def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) base = datetime(2012, 4, 6, 13, 26, 10) try: cron_str = fdp.ConsumeString(50) hash_id = fdp.ConsumeBytes(2) croniter.is_valid(cron_str, hash_id=hash_id) itr = croniter(cron_str, base, hash_id=hash_id) idx = 0 for v in itr.all_next(): idx += 1 if idx > 10: break itr.get_next() itr.get_prev() except (CroniterError, CroniterBadTypeRangeError) as e: pass except NameError as e: # Catch https://github.com/kiorky/croniter/blob/bb5a45196e5f8f15fd0890f4ee5e9697671a3fe2/src/croniter/croniter.py#L781 if not "'exc' is not defined" in str(e): raise e def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/croniter/fuzz_match.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import datetime from croniter import croniter from croniter.croniter import CroniterError, CroniterBadTypeRangeError def RandomDateTime(fdp): return datetime.datetime.now() + fdp.ConsumeProbability() * datetime.timedelta(days=200000) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) cron_str = fdp.ConsumeString(50) testdate = RandomDateTime(fdp) try: croniter.match(cron_str, testdate) except (CroniterError, CroniterBadTypeRangeError) as e: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/croniter/fuzz_range.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import datetime from croniter import croniter_range from croniter.croniter import CroniterError, CroniterBadTypeRangeError def RandomDateTime(fdp): return datetime.datetime.now() + fdp.ConsumeProbability() * datetime.timedelta(days=200000) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) cron_str = fdp.ConsumeString(50) start = RandomDateTime(fdp) stop = RandomDateTime(fdp) try: idx = 0 for dt in croniter_range(start, stop, cron_str): idx += 1 if idx > 10: break except (CroniterError, CroniterBadTypeRangeError) as e: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/croniter/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/kiorky/croniter language: python main_repo: https://github.com/kiorky/croniter sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - sean@compactcloud.co.uk ================================================ FILE: projects/crossplane/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/crossplane/crossplane-runtime $SRC/crossplane-runtime RUN git clone --depth 1 https://github.com/crossplane/crossplane $SRC/crossplane COPY build.sh $SRC/ WORKDIR $SRC ================================================ FILE: projects/crossplane/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/crossplane $SRC/crossplane/test/fuzz/oss_fuzz_build.sh cd $SRC/crossplane-runtime $SRC/crossplane-runtime/test/fuzz/oss_fuzz_build.sh ================================================ FILE: projects/crossplane/project.yaml ================================================ homepage: "https://github.com/crossplane/crossplane" main_repo: "https://github.com/crossplane/crossplane" primary_contact: "jbw976@gmail.com" auto_ccs : - "me@muvaf.com" - "nicc@rk0n.org" - "alper.oss.fuzz@gmail.com" - "p.scorsolini@gmail.com" vendor_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/crosvm/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth=1 --recursive https://chromium.googlesource.com/crosvm/crosvm $SRC/crosvm RUN apt-get update && apt-get install --yes --no-install-recommends \ libclang-dev \ pkg-config \ libcap-dev COPY build.sh $SRC ================================================ FILE: projects/crosvm/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd crosvm # Build crosvm fuzzers # Unset the SRC variable as it will interfere with minijail's common.mk framework. env -u SRC cargo fuzz build -O # Copy fuzzer binaries to $OUT FUZZ_TARGET_OUTPUT_DIR="target/x86_64-unknown-linux-gnu/release" for f in fuzz/fuzz_targets/*.rs; do FUZZ_TARGET_NAME=$(basename ${f%.*}) cp "${FUZZ_TARGET_OUTPUT_DIR}/${FUZZ_TARGET_NAME}" "$OUT/" done ================================================ FILE: projects/crosvm/project.yaml ================================================ homepage: "http://crosvm.dev" language: rust primary_contact: "denniskempin@google.com" auto_ccs: - "crosvm-core@google.com" - "dverkamp@google.com" - "fmayle@google.com" - "keiichiw@google.com" - "takayas@google.com" - "zihanchen@google.com" main_repo: "https://chromium.googlesource.com/crosvm/crosvm" sanitizers: - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/crow/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake make libasio-dev RUN git clone --depth 1 https://github.com/CrowCpp/Crow.git crow RUN cp $SRC/crow/tests/fuzz/build.sh $SRC/ COPY run_tests.sh $SRC/run_tests.sh WORKDIR crow ================================================ FILE: projects/crow/project.yaml ================================================ homepage: "https://crowcpp.org/master/" language: c++ primary_contact: "capuanobailey@gmail.com" main_repo: "https://github.com/CrowCpp/Crow" ================================================ FILE: projects/crow/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/crow/build ASAN_OPTIONS=detect_leaks=0 ctest --output-on-failure -j$(nproc) ================================================ FILE: projects/cryptofuzz/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust@sha256:c5216a9896a598dced7ce6708bb3226e443473f567045b4f282595776cc641f1 # ! Project pinned after a clang update and an afl link error. Log: https://oss-fuzz-gcb-logs.storage.googleapis.com/log-8bc8a5ea-9bfb-421d-bfe9-911828e88741.txt RUN apt-get update && \ apt-get install -y software-properties-common wget make autoconf automake libtool build-essential cmake mercurial gyp ninja-build zlib1g-dev libsqlite3-dev bison flex texinfo lzip bsdmainutils # mbedtls needs jsonschema which needs rpds-py which needs pip>=20 # or a Rust toolchain. RUN pip3 install 'pip>=20' RUN wget https://go.dev/dl/go1.22.7.linux-amd64.tar.gz RUN wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz RUN git clone --depth 1 https://github.com/golang/go go-dev RUN git clone --depth 1 https://github.com/golang/crypto go-crypto RUN git clone --depth 1 https://github.com/golang/sys.git go-sys RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora RUN git clone --depth 1 https://github.com/openssl/openssl RUN git clone --depth 1 https://boringssl.googlesource.com/boringssl RUN git clone --depth 1 git://git.gnupg.org/libgcrypt.git RUN git clone --depth 1 https://github.com/weidai11/cryptopp/ RUN wget https://gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.49.tar.bz2 RUN git clone --depth 1 -b oss-fuzz https://github.com/project-everest/hacl-star evercrypt RUN git clone --depth 1 https://github.com/google/cityhash.git RUN git clone --depth 1 https://github.com/randombit/botan.git RUN git clone --depth 1 https://github.com/wolfSSL/wolfssl.git RUN git clone --depth 1 https://github.com/wolfSSL/wolfsm RUN git clone --depth 1 --recurse-submodules -b mbedtls-3.6 https://github.com/Mbed-TLS/mbedtls.git RUN hg clone https://hg.mozilla.org/projects/nspr RUN hg clone https://hg.mozilla.org/projects/nss RUN git clone --depth 1 https://github.com/jedisct1/libsodium.git RUN git clone --depth 1 https://github.com/libtom/libtomcrypt.git RUN git clone --depth 1 https://github.com/microsoft/SymCrypt.git RUN hg clone https://gmplib.org/repo/gmp/ libgmp/ || \ (wget 'https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.lz' && tar xf gmp-6.2.1.tar.lz && mv $SRC/gmp-6.2.1/ $SRC/libgmp/) RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-4.0.0.tar.gz RUN git clone --depth 1 https://github.com/indutny/bn.js.git RUN git clone --depth 1 https://github.com/MikeMcl/bignumber.js.git RUN git clone --depth 1 https://github.com/guidovranken/libfuzzer-js.git RUN git clone --depth 1 https://github.com/brix/crypto-js.git RUN git clone --depth 1 https://github.com/trezor/trezor-firmware.git RUN git clone --depth 1 https://github.com/Cyan4973/xxHash.git RUN git clone --depth 1 https://github.com/paulmillr/noble-ed25519.git RUN git clone --depth 1 https://github.com/paulmillr/noble-bls12-381.git RUN git clone --depth 1 https://github.com/paulmillr/noble-secp256k1.git RUN git clone --depth 1 https://github.com/supranational/blst.git RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git RUN apt-get remove -y libunwind8 RUN apt-get update && apt-get install -y libssl-dev RUN wget https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 RUN wget https://nodejs.org/dist/v14.17.1/node-v14.17.1-linux-x64.tar.xz RUN pip3 install -r $SRC/mbedtls/scripts/basic.requirements.txt RUN bash -c "wget $(curl https://ziglang.org/download/index.json | jq -r '.master."x86_64-linux".tarball') -O zig-latest.tar.xz" COPY build.sh xxd.c $SRC/ ================================================ FILE: projects/cryptofuzz/README.md ================================================ This OSS-Fuzz project is a composite of multiple cryptographic libraries. It invokes a large amount of implementations for cryptographic primitives across multiple popular libraries, coordinated from a single fuzzing harness. Its objectives are: 1. To assert programmatic soundness: find memory bugs, crashes and time-outs with the help of sanitizers. 2. To assert semantic soundness: detect invalid output occurring under legal use of the library's API. One method to detect invalid results (point 2) is to assert equivalence between two or more outputs generated by a single library with the same input (but where each output allowed to be computed differently), aka "self-differential" testing. See [here](https://github.com/openssl/openssl/issues/8675) for a bug found with self-differential testing. Another method is to compare a result against the result of different library, where both results are expected to be the same. If they are not the same, this indicates a bug in at least one library. This second method is what merits the composite setup of the project; adherence to the normative specification of a cryptographic primitive is implicitly asserted under the assumption that at least one implementation gets it right. Because determining which one of libraries gets it wrong cannot be reliably automated, all library maintainers are notified in this event, so that the cause of discrepancy can be resolved collaboratively. Library builds embedding optimized assembly language code and those using pure C implementations have been assigned separate fuzzer targets (binaries), because either implementation can have distinct bugs that will not transpire if only the other one is tested. OpenSSL, BoringSSL and LibreSSL are assigned separate fuzzing targets because their exported symbols largely overlap and can therefore not be bundled into a single binary. At this time of writing, no differential testing is performed, because support for additional libraries is not ready yet, but I intend to support mbed TLS and libsodium shortly, and support for popular or built-in cryptography implementations for Go, Rust, Java and Javascript is planned. To further clear things up, at some point in the future, the matrix of support libraries versus fuzzing binaries could look like this: A binary embedding OpenSSL, mbed TLS, libsodium, Go, Rust, Java, Javascript, ..., ... A binary embedding BoringSSL, mbed TLS, libsodium, Go, Rust, Java, Javascript, ..., ... A binary embedding LibreSSL, mbed TLS, libsodium, Go, Rust, Java, Javascript, ..., ... and another 3 binaries for all of the pure C versions (no assembly language optimizations) of these libraries. As more libraries are added, I will add a throttle mechanism to Cryptofuzz to ensure that no more than, say, 4 libraries will be called during a single iteration, so that no amount of supported libraries will impact the overall speed of the fuzzing process. More information can be found at [Cryptofuzz](https://github.com/guidovranken/cryptofuzz). ================================================ FILE: projects/cryptofuzz/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # TODO(metzman): Switch this to LIB_FUZZING_ENGINE when it works. # https://github.com/google/oss-fuzz/issues/2336 export CXXFLAGS="$CXXFLAGS -D_LIBCPP_DEBUG=1" export GO111MODULE=off # Install Go stable binaries mkdir $SRC/go-bootstrap cd $SRC/go-bootstrap tar zxf $SRC/go1.23.1.linux-amd64.tar.gz mv go/ go-123 export GOROOT_123=$SRC/go-bootstrap/go-123/ export GOPATH_123=$GOROOT_123/packages/ mkdir $GOPATH_123 mkdir -p $GOPATH_123/src/golang.org/x/crypto/ cp -R $SRC/go-crypto/* $GOPATH_123/src/golang.org/x/crypto/ mkdir -p $GOPATH_123/src/golang.org/x/sys/ cp -R $SRC/go-sys/* $GOPATH_123/src/golang.org/x/sys/ export PATH_GO_123=$GOROOT_123/bin:$GOROOT_123/packages/bin:$PATH tar zxf $SRC/go1.22.7.linux-amd64.tar.gz mv go/ go-122 export GOROOT_122=$SRC/go-bootstrap/go-122/ export GOPATH_122=$GOROOT_122/packages/ mkdir $GOPATH_122 mkdir -p $GOPATH_122/src/golang.org/x/crypto/ cp -R $SRC/go-crypto/* $GOPATH_122/src/golang.org/x/crypto/ mkdir -p $GOPATH_122/src/golang.org/x/sys/ cp -R $SRC/go-sys/* $GOPATH_122/src/golang.org/x/sys/ export PATH_GO_122=$GOROOT_122/bin:$GOROOT_122/packages/bin:$PATH # Compile Go development version cd $SRC/go-dev/src/ export OLD_PATH=$PATH PATH="$PATH_GO_123" ./make.bash export GOROOT_DEV=$(realpath ../) export GOPATH_DEV=$GOROOT_DEV/packages mkdir $GOPATH_DEV mkdir -p $GOPATH_DEV/src/golang.org/x/crypto/ cp -R $SRC/go-crypto/* $GOPATH_DEV/src/golang.org/x/crypto/ mkdir -p $GOPATH_DEV/src/golang.org/x/sys/ cp -R $SRC/go-sys/* $GOPATH_DEV/src/golang.org/x/sys/ export PATH_GO_DEV=$GOROOT_DEV/bin:$GOROOT_DEV/packages/bin:$PATH if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_GOLANG" fi if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then # Install nodejs/npm # It is required for building noble-bls12-381 cd $SRC/ tar Jxf node-v14.17.1-linux-x64.tar.xz export PATH="$PATH:$SRC/node-v14.17.1-linux-x64/bin/" fi # Compile xxd $CC $SRC/xxd.c -o /usr/bin/xxd # Copy the upstream checkout of xxHash over the old version rm -rf $SRC/cryptofuzz/modules/reference/xxHash/ cp -R $SRC/xxHash/ $SRC/cryptofuzz/modules/reference/ # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ export LINK_FLAGS="" if [[ $CFLAGS = *-m32* ]] then export LINK_FLAGS="$LINK_FLAGS -latomic" fi export INCLUDE_PATH_FLAGS="" # Generate lookup tables. This only needs to be done once. cd $SRC/cryptofuzz python gen_repository.py # This enables runtime checks for C++-specific undefined behaviour. export CXXFLAGS="$CXXFLAGS -D_GLIBCXX_DEBUG" # wolfCrypt uses a slightly different ECDH algorithm than Trezor and libsecp256k1. # This disables running ECDH in Trezor and libsecp256k1 to prevent mismatches. export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_DISABLE_SPECIAL_ECDH" export CXXFLAGS="$CXXFLAGS -I $SRC/cryptofuzz/fuzzing-headers/include" if [[ $CFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then # Compile libfuzzer-js (required for all JavaScript libraries) export LIBFUZZER_A_PATH="$LIB_FUZZING_ENGINE" cd $SRC/libfuzzer-js/ make export LIBFUZZER_JS_PATH=$(realpath .) export LINK_FLAGS="$LINK_FLAGS $LIBFUZZER_JS_PATH/js.o $LIBFUZZER_JS_PATH/quickjs/libquickjs.a" # Compile bn.js module export BN_JS_PATH="$SRC/bn.js/lib/bn.js" export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BN_JS" cd $SRC/cryptofuzz/modules/bn.js/ make # Compile bignumber.js module export BIGNUMBER_JS_PATH="$SRC/bignumber.js/bignumber.js" export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BIGNUMBER_JS" cd $SRC/cryptofuzz/modules/bignumber.js/ make export CRYPTO_JS_PATH="$SRC/crypto-js/" export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_CRYPTO_JS" cd $SRC/cryptofuzz/modules/crypto-js/ make fi if [[ $CFLAGS != *-m32* && "$SANITIZER" != "coverage" ]] then cd $SRC/ tar Jxf zig-latest.tar.xz export ZIG_BIN=$(realpath zig-linux-x86_64*/zig) cd $SRC/cryptofuzz/modules/zig/ make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_ZIG" fi # Compile NSS if [[ $CFLAGS != *-m32* ]] then mkdir $SRC/nss-nspr mv $SRC/nss $SRC/nss-nspr/ mv $SRC/nspr $SRC/nss-nspr/ cd $SRC/nss-nspr/ # Prevent compilation error with Clang export CFLAGS="$CFLAGS -Wno-unused-but-set-variable" CXX="$CXX -stdlib=libc++" LDFLAGS="$CFLAGS" nss/build.sh --enable-fips --static --disable-tests --fuzz=oss export NSS_NSPR_PATH=$(realpath $SRC/nss-nspr/) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NSS" export LINK_FLAGS="$LINK_FLAGS -lsqlite3" # Compile Cryptofuzz NSS module cd $SRC/cryptofuzz/modules/nss make -B fi # Rename blake2b_* functions to avoid symbol collisions with other libraries cd $SRC/trezor-firmware/crypto sed -i "s/\>new_no_asm.h #echo "typedef unsigned long long llimb_t;" >>new_no_asm.h #echo "#else" >>new_no_asm.h #echo "typedef __uint128_t llimb_t;" >>new_no_asm.h #echo "#endif" >>new_no_asm.h #cat src/no_asm.h >>new_no_asm.h #mv new_no_asm.h src/no_asm.h #CFLAGS="$CFLAGS -D__BLST_NO_ASM__ -D__BLST_PORTABLE__" ./build.sh #export BLST_LIBBLST_A_PATH=$(realpath libblst.a) #export BLST_INCLUDE_PATH=$(realpath bindings/) #export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BLST" # ## Compile Cryptofuzz blst module #cd $SRC/cryptofuzz/modules/blst/ #make -B -j$(nproc) # Build libsecp256k1 cd $SRC/secp256k1/ autoreconf -ivf export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SECP256K1" if [[ $CFLAGS = *sanitize=memory* ]] then ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental --enable-module-schnorrsig --enable-module-ecdh --with-asm=no else ./configure --enable-static --disable-tests --disable-benchmark --disable-exhaustive-tests --enable-module-recovery --enable-experimental --enable-module-schnorrsig --enable-module-ecdh fi make export SECP256K1_INCLUDE_PATH=$(realpath .) export LIBSECP256K1_A_PATH=$(realpath .libs/libsecp256k1.a) # Compile Cryptofuzz libsecp256k1 module cd $SRC/cryptofuzz/modules/secp256k1/ make -B -j$(nproc) #if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] #then # noble-secp256k1 # cd $SRC/noble-secp256k1/ # npm install && npm run build # export NOBLE_SECP256K1_PATH=$(realpath lib/index.js) # # cd $SRC/cryptofuzz/modules/noble-secp256k1/ # export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_SECP256K1" # make -B # noble-bls12-381 # cd $SRC/noble-bls12-381/ # cp math.ts new_index.ts # $(awk '/^export/ {print "tail -n +"FNR+1" index.ts"; exit}' index.ts) >>new_index.ts # mv new_index.ts index.ts # npm install && npm run build # export NOBLE_BLS12_381_PATH=$(realpath index.js) # export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_BLS12_381" # cd $SRC/cryptofuzz/modules/noble-bls12-381/ # make -B # noble-ed25519 # cd $SRC/cryptofuzz/modules/noble-ed25519/ # export NOBLE_ED25519_PATH="$SRC/noble-ed25519/index.js" # export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_ED25519" # make -B #fi ## Compile SymCrypt if [[ $CFLAGS != *-m32* ]] then cd $SRC/SymCrypt/ # Disable speculative load hardening because # this results in MSAN false positives sed -i '/.*x86-speculative-load-hardening.*/d' lib/CMakeLists.txt # Unittests don't build with clang and are not needed anyway sed -i "s/^add_subdirectory(unittest)$//g" CMakeLists.txt mkdir b/ cd b/ if [[ $CFLAGS = *sanitize=memory* ]] then cmake -DSYMCRYPT_USE_ASM=off ../ else cmake ../ fi make symcrypt_common symcrypt_generic -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SYMCRYPT" export SYMCRYPT_INCLUDE_PATH=$(realpath ../inc/) export LIBSYMCRYPT_COMMON_A_PATH=$(realpath lib/libsymcrypt_common.a) export SYMCRYPT_GENERIC_A_PATH=$(realpath lib/symcrypt_generic.a) # Compile Cryptofuzz SymCrypt module cd $SRC/cryptofuzz/modules/symcrypt make -B fi # Compile libgmp cd $SRC/libgmp/ autoreconf -ivf if [[ $CFLAGS = *-m32* ]] then setarch i386 ./configure --enable-maintainer-mode --enable-assert elif [[ $CFLAGS = *sanitize=memory* ]] then ./configure --enable-maintainer-mode --enable-assert --disable-assembly else ./configure --enable-maintainer-mode --enable-assert fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBGMP" export LIBGMP_INCLUDE_PATH=$(realpath .) export LIBGMP_A_PATH=$(realpath .libs/libgmp.a) # Compile Cryptofuzz libgmp module cd $SRC/cryptofuzz/modules/libgmp make -B # Compile mpdecimal cd $SRC/ tar zxf mpdecimal-4.0.0.tar.gz cd mpdecimal-4.0.0/ ./configure cd libmpdec/ make libmpdec.a -j$(nproc) cd ../ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_MPDECIMAL" export LIBMPDEC_A_PATH=$(realpath libmpdec/libmpdec.a) export LIBMPDEC_INCLUDE_PATH=$(realpath libmpdec/) # Compile Cryptofuzz mpdecimal module cd $SRC/cryptofuzz/modules/mpdecimal make -B # Compile Cityhash cd $SRC/cityhash if [[ $CFLAGS != *-m32* ]] then CXXFLAGS="$CXXFLAGS -msse4.2" ./configure --disable-shared else ./configure --disable-shared fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -I$SRC/cityhash/src" export CRYPTOFUZZ_REFERENCE_CITY_O_PATH="$SRC/cityhash/src/city.o" ############################################################################## # Compile cryptopp cd $SRC/cryptopp if [[ $CFLAGS != *sanitize=memory* ]] then make libcryptopp.a -j$(nproc) else export CXXFLAGS="$CXXFLAGS -DCRYPTOPP_DISABLE_ASM=1" make libcryptopp.a -j$(nproc) fi export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_CRYPTOPP" export LIBCRYPTOPP_A_PATH="$SRC/cryptopp/libcryptopp.a" export CRYPTOPP_INCLUDE_PATH="$SRC/cryptopp" # Compile Cryptofuzz cryptopp module cd $SRC/cryptofuzz/modules/cryptopp make -B ############################################################################## # Compile Mbed TLS cd $SRC/mbedtls/ scripts/config.py set MBEDTLS_PLATFORM_MEMORY scripts/config.py set MBEDTLS_CMAC_C scripts/config.py set MBEDTLS_NIST_KW_C scripts/config.py set MBEDTLS_ARIA_C if [[ $CFLAGS == *sanitize=memory* ]] then scripts/config.py unset MBEDTLS_HAVE_ASM scripts/config.py unset MBEDTLS_PADLOCK_C scripts/config.py unset MBEDTLS_AESNI_C scripts/config.py unset MBEDTLS_AESCE_C fi mkdir build/ cd build/ cmake .. -DENABLE_PROGRAMS=0 -DENABLE_TESTING=0 make -j$(nproc) export MBEDTLS_LIBMBEDCRYPTO_A_PATH="$SRC/mbedtls/build/library/libmbedcrypto.a" export MBEDTLS_INCLUDE_PATH="$SRC/mbedtls/include" export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_MBEDTLS -DCRYPTOFUZZ_TF_PSA_CRYPTO" # Compile Cryptofuzz module for Mbed TLS with the legacy crypto API cd $SRC/cryptofuzz/modules/mbedtls make -B # Compile Cryptofuzz module for Mbed TLS with the PSA crypto API cd $SRC/cryptofuzz/modules/tf-psa-crypto make -B ############################################################################## # Compile Botan cd $SRC/botan if [[ $CFLAGS != *-m32* ]] then if [[ $CFLAGS != *sanitize=memory* ]] then ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation else ./configure.py --disable-asm --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation fi else ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator --build-targets=static --without-documentation fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN" export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a" export BOTAN_INCLUDE_PATH="$SRC/botan/build/include" # Compile Cryptofuzz Botan module cd $SRC/cryptofuzz/modules/botan make -B ############################################################################## if [[ $CFLAGS != *sanitize=memory* ]] then # Compile libgpg-error (dependency of libgcrypt) cd $SRC/ tar jxvf libgpg-error-1.49.tar.bz2 cd libgpg-error-1.49/ if [[ $CFLAGS != *-m32* ]] then ./configure --enable-static else ./configure --enable-static --host=i386 fi ASAN_OPTIONS=detect_leaks=0 make -j$(nproc) make install export LINK_FLAGS="$LINK_FLAGS $SRC/libgpg-error-1.49/src/.libs/libgpg-error.a" # Compile libgcrypt cd $SRC/libgcrypt autoreconf -ivf if [[ $CFLAGS = *-m32* ]] then ./configure --enable-static --disable-doc --disable-jent-support --host=i386 else ./configure --enable-static --disable-doc --disable-jent-support fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBGCRYPT" export LIBGCRYPT_A_PATH="$SRC/libgcrypt/src/.libs/libgcrypt.a" export LIBGCRYPT_INCLUDE_PATH="$SRC/libgcrypt/src" # Compile Cryptofuzz libgcrypt module cd $SRC/cryptofuzz/modules/libgcrypt make -B fi # Compile libsodium cd $SRC/libsodium autoreconf -ivf if [[ $CFLAGS != *sanitize=memory* ]] then ./configure else ./configure --disable-asm fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBSODIUM" export LIBSODIUM_A_PATH="$SRC/libsodium/src/libsodium/.libs/libsodium.a" export LIBSODIUM_INCLUDE_PATH="$SRC/libsodium/src/libsodium/include" # Compile Cryptofuzz libsodium module cd $SRC/cryptofuzz/modules/libsodium make -B # Disabled because NSS now also embeds evercrypt, leading to symbol collisions #if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] #then # # Compile EverCrypt (with assembly) # cd $SRC/evercrypt/dist # make -C portable -j$(nproc) libevercrypt.a # make -C kremlin/kremlib/dist/minimal -j$(nproc) # # export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_EVERCRYPT" # export EVERCRYPT_A_PATH="$SRC/evercrypt/dist/portable/libevercrypt.a" # export KREMLIN_A_PATH="$SRC/evercrypt/dist/kremlin/kremlib/dist/minimal/*.o" # export EVERCRYPT_INCLUDE_PATH="$SRC/evercrypt/dist" # export KREMLIN_INCLUDE_PATH="$SRC/evercrypt/dist/kremlin/include" # export INCLUDE_PATH_FLAGS="$INCLUDE_PATH_FLAGS -I $EVERCRYPT_INCLUDE_PATH -I $KREMLIN_INCLUDE_PATH" # # # Compile Cryptofuzz EverCrypt (with assembly) module # cd $SRC/cryptofuzz/modules/evercrypt # make -B #fi ############################################################################## # Compile Cryptofuzz reference (without assembly) module export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_REFERENCE" cd $SRC/cryptofuzz/modules/reference make -B ############################################################################## # Compile Cryptofuzz Veracrypt (without assembly) module export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_VERACRYPT" cd $SRC/cryptofuzz/modules/veracrypt make -B ############################################################################## # Compile Cryptofuzz Monero (without assembly) module export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_MONERO" cd $SRC/cryptofuzz/modules/monero make -B ############################################################################## # Compile Cryptofuzz Golang (123) module if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then cd $SRC/cryptofuzz/modules/golang GOROOT="$GOROOT_123" GOPATH="$GOPATH_123" PATH="$PATH_GO_123" make -B fi if [[ $CFLAGS != *-m32* ]] then # Compile Cryptofuzz (NSS-based) cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL $INCLUDE_PATH_FLAGS" make -B -j$(nproc) # Generate dictionary ./generate_dict # Patch fuzzer if [ "$SANITIZER" = undefined ]; then patchelf --set-rpath '$ORIGIN/lib/jdk-18.0.1/lib/server/' $SRC/cryptofuzz/cryptofuzz fi # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-nss # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-nss.dict # Copy seed corpus cp $SRC/cryptofuzz-corpora/libressl_latest.zip $OUT/cryptofuzz-nss_seed_corpus.zip rm $SRC/cryptofuzz/modules/nss/module.a CXXFLAGS=${CXXFLAGS//"-DCRYPTOFUZZ_NSS"/} LINK_FLAGS=${LINK_FLAGS//"-lsqlite3"/} fi rm -f $SRC/cryptofuzz/modules/golang/module.a if [[ $CFLAGS != *sanitize=memory* ]] then # libtomcrypt can only be compiled with NSS, because OpenSSL, LibreSSL and # BoringSSL have symbol collisions with libtomcrypt. # # So, now that NSS-based Cryptofuzz has been compiled, remove libtomcrypt export CXXFLAGS=${CXXFLAGS/-DCRYPTOFUZZ_LIBTOMCRYPT/} rm -rf "$LIBTOMCRYPT_A_PATH" fi ############################################################################## # Compile wolfCrypt cd $SRC/wolfsm/ ./install.sh cd $SRC/wolfssl # Enable additional wolfCrypt features which cannot be activated through arguments to ./configure export CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP" autoreconf -ivf export WOLFCRYPT_CONFIGURE_PARAMS="--enable-static --enable-md2 --enable-md4 --enable-ripemd --enable-blake2 --enable-blake2s --enable-pwdbased --enable-scrypt --enable-hkdf --enable-cmac --enable-arc4 --enable-camellia --enable-aesccm --enable-aesctr --enable-xts --enable-des3 --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --enable-aessiv --enable-shake256 --enable-curve25519 --enable-curve448 --disable-crypttests --disable-examples --enable-keygen --enable-compkey --enable-ed448 --enable-ed25519 --enable-ecccustcurves --enable-xchacha --enable-cryptocb --enable-eccencrypt --enable-aesgcm-stream --enable-shake128 --enable-siphash --enable-eccsi --with-eccminsz=0 --enable-aeseax --enable-ed25519-stream --enable-ed448-stream --enable-sm2 --enable-sm3 --enable-sm4-cbc --enable-sm4-ccm --enable-sm4-ctr --enable-sm4-ecb --enable-sm4-gcm --enable-smallstack" if [[ $CFLAGS = *sanitize=memory* ]] then export WOLFCRYPT_CONFIGURE_PARAMS="$WOLFCRYPT_CONFIGURE_PARAMS -disable-asm" fi if [[ $CFLAGS = *-m32* ]] then export WOLFCRYPT_CONFIGURE_PARAMS="$WOLFCRYPT_CONFIGURE_PARAMS -disable-fastmath" fi ./configure $WOLFCRYPT_CONFIGURE_PARAMS make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_WOLFCRYPT" export WOLFCRYPT_LIBWOLFSSL_A_PATH="$SRC/wolfssl/src/.libs/libwolfssl.a" export WOLFCRYPT_INCLUDE_PATH="$SRC/wolfssl" # Compile Cryptofuzz wolfcrypt (without assembly) module cd $SRC/cryptofuzz/modules/wolfcrypt make -B ############################################################################## # Compile Cryptofuzz Golang (122) module if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then cd $SRC/cryptofuzz/modules/golang GOROOT="$GOROOT_122" GOPATH="$GOPATH_122" PATH="$PATH_GO_122" make -B fi # OpenSSL can currently not be used together with wolfCrypt due to symbol collisions export SAVE_CXXFLAGS="$CXXFLAGS" export CXXFLAGS=${CXXFLAGS/-DCRYPTOFUZZ_WOLFCRYPT/} ############################################################################## if [[ $CFLAGS != *sanitize=memory* ]] then # Compile Openssl (with assembly) cd $SRC/openssl if [[ $CFLAGS != *-m32* ]] then ./config --debug enable-md2 enable-rc5 else setarch i386 ./config --debug enable-md2 enable-rc5 fi make -j$(nproc) # Compile Cryptofuzz OpenSSL (with assembly) module cd $SRC/cryptofuzz/modules/openssl OPENSSL_INCLUDE_PATH="$SRC/openssl/include" OPENSSL_LIBCRYPTO_A_PATH="$SRC/openssl/libcrypto.a" make -B # Compile Cryptofuzz cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -I $SRC/openssl/include $INCLUDE_PATH_FLAGS" make -B -j$(nproc) # Generate dictionary ./generate_dict # Patch fuzzer if [ "$SANITIZER" = undefined ]; then patchelf --set-rpath '$ORIGIN/lib/jdk-18.0.1/lib/server/' $SRC/cryptofuzz/cryptofuzz fi # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-openssl # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-openssl.dict # Copy seed corpus cp $SRC/cryptofuzz-corpora/openssl_latest.zip $OUT/cryptofuzz-openssl_seed_corpus.zip fi ############################################################################## # Compile Openssl (without assembly) cd $SRC/openssl if [[ $CFLAGS != *-m32* ]] then ./config --debug no-asm enable-md2 enable-rc5 else setarch i386 ./config --debug no-asm enable-md2 enable-rc5 fi make clean make -j$(nproc) # Compile Cryptofuzz OpenSSL (without assembly) module cd $SRC/cryptofuzz/modules/openssl OPENSSL_INCLUDE_PATH="$SRC/openssl/include" OPENSSL_LIBCRYPTO_A_PATH="$SRC/openssl/libcrypto.a" make -B # Compile Cryptofuzz cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -I $SRC/openssl/include $INCLUDE_PATH_FLAGS" make -B -j$(nproc) # Generate dictionary ./generate_dict # Patch fuzzer if [ "$SANITIZER" = undefined ]; then patchelf --set-rpath '$ORIGIN/lib/jdk-18.0.1/lib/server/' $SRC/cryptofuzz/cryptofuzz fi # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-openssl-noasm # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-openssl-noasm.dict # Copy seed corpus cp $SRC/cryptofuzz-corpora/openssl_latest.zip $OUT/cryptofuzz-openssl-noasm_seed_corpus.zip rm -f $SRC/cryptofuzz/modules/golang/module.a export CXXFLAGS="$SAVE_CXXFLAGS" ############################################################################## # Compile Cryptofuzz Golang (dev branch) module if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]] then cd $SRC/cryptofuzz/modules/golang GOROOT="$GOROOT_DEV" GOPATH="$GOPATH_DEV" PATH="$PATH_GO_DEV" make -B fi ############################################################################## if [[ $CFLAGS != *sanitize=memory* ]] then # Compile BoringSSL (with assembly) cd $SRC/boringssl rm -rf build ; mkdir build cd build if [[ $CFLAGS = *-m32* ]] then GOROOT="$GOROOT_DEV" GOPATH="$GOPATH_DEV" PATH="$PATH_GO_DEV" setarch i386 cmake -DCMAKE_CXX_FLAGS="$CXXFLAGS -fno-sanitize=vptr" -DCMAKE_C_FLAGS="$CFLAGS -fno-sanitize=vptr" -DBORINGSSL_ALLOW_CXX_RUNTIME=1 -DCMAKE_ASM_FLAGS="-m32" .. else GOROOT="$GOROOT_DEV" GOPATH="$GOPATH_DEV" PATH="$PATH_GO_DEV" cmake -DCMAKE_CXX_FLAGS="$CXXFLAGS -fno-sanitize=vptr" -DCMAKE_C_FLAGS="$CFLAGS -fno-sanitize=vptr" -DBORINGSSL_ALLOW_CXX_RUNTIME=1 .. fi make -j$(nproc) crypto # Compile Cryptofuzz BoringSSL (with assembly) module cd $SRC/cryptofuzz/modules/openssl OPENSSL_INCLUDE_PATH="$SRC/boringssl/include" OPENSSL_LIBCRYPTO_A_PATH="$SRC/boringssl/build/crypto/libcrypto.a" CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BORINGSSL" make -B # Compile Cryptofuzz cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -I $SRC/openssl/include $INCLUDE_PATH_FLAGS" make -B -j$(nproc) # Generate dictionary ./generate_dict # Patch fuzzer if [ "$SANITIZER" = undefined ]; then patchelf --set-rpath '$ORIGIN/lib/jdk-18.0.1/lib/server/' $SRC/cryptofuzz/cryptofuzz fi # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-boringssl # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-boringssl.dict # Copy seed corpus cp $SRC/cryptofuzz-corpora/boringssl_latest.zip $OUT/cryptofuzz-boringssl_seed_corpus.zip fi # Compile Cryptofuzz libgmp mini-gmp module cd $SRC/cryptofuzz/modules/libgmp make -B -f Makefile-mini-gmp ############################################################################## # Compile BoringSSL (without assembly) cd $SRC/boringssl rm -rf build ; mkdir build cd build GOROOT="$GOROOT_DEV" GOPATH="$GOPATH_DEV" PATH="$PATH_GO_DEV" cmake -DCMAKE_CXX_FLAGS="$CXXFLAGS -fno-sanitize=vptr" -DCMAKE_C_FLAGS="$CFLAGS -fno-sanitize=vptr" -DBORINGSSL_ALLOW_CXX_RUNTIME=1 -DOPENSSL_NO_ASM=1 .. make -j$(nproc) crypto # Compile Cryptofuzz BoringSSL (without assembly) module cd $SRC/cryptofuzz/modules/openssl OPENSSL_INCLUDE_PATH="$SRC/boringssl/include" OPENSSL_LIBCRYPTO_A_PATH="$SRC/boringssl/build/crypto/libcrypto.a" CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BORINGSSL" make -B # Compile Cryptofuzz cd $SRC/cryptofuzz LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" CXXFLAGS="$CXXFLAGS -I $SRC/openssl/include $INCLUDE_PATH_FLAGS" make -B -j$(nproc) # Generate dictionary ./generate_dict # Patch fuzzer if [ "$SANITIZER" = undefined ]; then patchelf --set-rpath '$ORIGIN/lib/jdk-18.0.1/lib/server/' $SRC/cryptofuzz/cryptofuzz fi # Copy fuzzer cp $SRC/cryptofuzz/cryptofuzz $OUT/cryptofuzz-boringssl-noasm # Copy dictionary cp $SRC/cryptofuzz/cryptofuzz-dict.txt $OUT/cryptofuzz-boringssl-noasm.dict # Copy seed corpus cp $SRC/cryptofuzz-corpora/boringssl_latest.zip $OUT/cryptofuzz-boringssl-noasm_seed_corpus.zip ================================================ FILE: projects/cryptofuzz/project.yaml ================================================ homepage: "https://github.com/guidovranken/cryptofuzz" language: c++ primary_contact: "guidovranken@gmail.com" auto_ccs: - kurt@roeckx.be - agl@google.com - davidben@google.com - svaldez@google.com - beck@obtuse.com - joel.sing@gmail.com - kinichiro.inoguchi@gmail.com - github@pureftpd.org - jussi.kivilinna@gmail.com - szanella@gmail.com - karthik.bhargavan@gmail.com - jonathan.protzenko@gmail.com - richard@levitte.org - ppzgs1@gmail.com - jack.lloyd@gmail.com - shane.lontis@hotmail.com - david@wolfssl.com - kaleb@wolfssl.com - jacob@wolfssl.com - sledru@mozilla.com - bbeurdouche@mozilla.com - matthias.st.pierre@gmail.com - kaleb.himes@gmail.com - polubelovam@gmail.com - mbed-tls-security@lists.trustedfirmware.org - choller@mozilla.com - djackson@mozilla.com - dkeeler@mozilla.com - jkratzer@mozilla.com - jschanck@mozilla.com - jschwartzentruber@mozilla.com - nkulatova@mozilla.com - twsmith@mozilla.com - mdauer@mozilla.com vendor_ccs: - oss-fuzz@mozilla-fuzzing.iam.gserviceaccount.com sanitizers: - address - undefined - memory architectures: - x86_64 main_repo: 'https://github.com/guidovranken/cryptofuzz' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/cryptofuzz/xxd.c ================================================ /* xxd: my hexdump facility. jw * * 2.10.90 changed to word output * 3.03.93 new indent style, dumb bug inserted and fixed. * -c option, mls * 26.04.94 better option parser, -ps, -l, -s added. * 1.07.94 -r badly needs - as input file. Per default autoskip over * consecutive lines of zeroes, as unix od does. * -a shows them too. * -i dump as c-style #include "file.h" * 1.11.95 if "xxd -i" knows the filename, an 'unsigned char filename_bits[]' * array is written in correct c-syntax. * -s improved, now defaults to absolute seek, relative requires a '+'. * -r improved, now -r -s -0x... is supported. * change/suppress leading '\0' bytes. * -l n improved: stops exactly after n bytes. * -r improved, better handling of partial lines with trailing garbage. * -r improved, now -r -p works again! * -r improved, less flushing, much faster now! (that was silly) * 3.04.96 Per repeated request of a single person: autoskip defaults to off. * 15.05.96 -v added. They want to know the version. * -a fixed, to show last line inf file ends in all zeros. * -u added: Print upper case hex-letters, as preferred by unix bc. * -h added to usage message. Usage message extended. * Now using outfile if specified even in normal mode, aehem. * No longer mixing of ints and longs. May help doze people. * Added binify ioctl for same reason. (Enough Doze stress for 1996!) * 16.05.96 -p improved, removed occasional superfluous linefeed. * 20.05.96 -l 0 fixed. tried to read anyway. * 21.05.96 -i fixed. now honours -u, and prepends __ to numeric filenames. * compile -DWIN32 for NT or W95. George V. Reilly, * -v improved :-) * support --gnuish-longhorn-options * 25.05.96 MAC support added: CodeWarrior already uses ``outline'' in Types.h * which is included by MacHeaders (Axel Kielhorn). Renamed to * xxdline(). * 7.06.96 -i printed 'int' instead of 'char'. *blush* * added Bram's OS2 ifdefs... * 18.07.96 gcc -Wall @ SunOS4 is now slient. * Added osver for MSDOS/DJGPP/WIN32. * 29.08.96 Added size_t to strncmp() for Amiga. * 24.03.97 Windows NT support (Phil Hanna). Clean exit for Amiga WB (Bram) * 02.04.97 Added -E option, to have EBCDIC translation instead of ASCII * (azc10@yahoo.com) * 22.05.97 added -g (group octets) option (jcook@namerica.kla.com). * 23.09.98 nasty -p -r misfeature fixed: slightly wrong output, when -c was * missing or wrong. * 26.09.98 Fixed: 'xxd -i infile outfile' did not truncate outfile. * 27.10.98 Fixed: -g option parser required blank. * option -b added: 01000101 binary output in normal format. * 16.05.00 Added VAXC changes by Stephen P. Wall * 16.05.00 Improved MMS file and merge for VMS by Zoltan Arpadffy * 2011 March Better error handling by Florian Zumbiehl. * 2011 April Formatting by Bram Moolenaar * 08.06.2013 Little-endian hexdump (-e) and offset (-o) by Vadim Vygonets. * * (c) 1990-1998 by Juergen Weigert (jnweiger@informatik.uni-erlangen.de) * * I hereby grant permission to distribute and use xxd * under X11-MIT or GPL-2.0 (at the user's choice). * * Small changes made afterwards by Bram Moolenaar et al. * * Distribute freely and credit me, * make money and share with me, * lose money and don't ask me. */ /* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */ #if _MSC_VER >= 1400 # define _CRT_SECURE_NO_DEPRECATE # define _CRT_NONSTDC_NO_DEPRECATE #endif #if !defined(CYGWIN) && (defined(CYGWIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)) # define CYGWIN #endif #include #ifdef VAXC # include #else # include #endif #if defined(WIN32) || defined(__BORLANDC__) || defined(CYGWIN) # include /* for setmode() */ #else # ifdef UNIX # include # endif #endif #include #include /* for strncmp() */ #include /* for isalnum() */ #if __MWERKS__ && !defined(BEBOX) # include /* for fdopen() on MAC */ #endif #if defined(__BORLANDC__) && __BORLANDC__ <= 0x0410 && !defined(fileno) /* Missing define and prototype grabbed from the BC 4.0 */ # define fileno(f) ((f)->fd) FILE _FAR *_Cdecl _FARFUNC fdopen(int __handle, char _FAR *__type); #endif /* This corrects the problem of missing prototypes for certain functions * in some GNU installations (e.g. SunOS 4.1.x). * Darren Hiebert (sparc-sun-sunos4.1.3_U1/2.7.2.2) */ #if defined(__GNUC__) && defined(__STDC__) # ifndef __USE_FIXED_PROTOTYPES__ # define __USE_FIXED_PROTOTYPES__ # endif #endif #ifndef __USE_FIXED_PROTOTYPES__ /* * This is historic and works only if the compiler really has no prototypes: * * Include prototypes for Sun OS 4.x, when using an ANSI compiler. * FILE is defined on OS 4.x, not on 5.x (Solaris). * if __SVR4 is defined (some Solaris versions), don't include this. */ #if defined(sun) && defined(FILE) && !defined(__SVR4) && defined(__STDC__) # define __P(a) a /* excerpt from my sun_stdlib.h */ extern int fprintf __P((FILE *, char *, ...)); extern int fputs __P((char *, FILE *)); extern int _flsbuf __P((unsigned char, FILE *)); extern int _filbuf __P((FILE *)); extern int fflush __P((FILE *)); extern int fclose __P((FILE *)); extern int fseek __P((FILE *, long, int)); extern int rewind __P((FILE *)); extern void perror __P((char *)); # endif #endif extern long int strtol(); extern long int ftell(); char version[] = "xxd V1.10 27oct98 by Juergen Weigert"; #ifdef WIN32 char osver[] = " (Win32)"; #else char osver[] = ""; #endif #if defined(WIN32) # define BIN_READ(yes) ((yes) ? "rb" : "rt") # define BIN_WRITE(yes) ((yes) ? "wb" : "wt") # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT) # define BIN_ASSIGN(fp, yes) setmode(fileno(fp), (yes) ? O_BINARY : O_TEXT) # define PATH_SEP '\\' #elif defined(CYGWIN) # define BIN_READ(yes) ((yes) ? "rb" : "rt") # define BIN_WRITE(yes) ((yes) ? "wb" : "w") # define BIN_CREAT(yes) ((yes) ? (O_CREAT|O_BINARY) : O_CREAT) # define BIN_ASSIGN(fp, yes) ((yes) ? (void) setmode(fileno(fp), O_BINARY) : (void) (fp)) # define PATH_SEP '/' #else # ifdef VMS # define BIN_READ(dummy) "r" # define BIN_WRITE(dummy) "w" # define BIN_CREAT(dummy) O_CREAT # define BIN_ASSIGN(fp, dummy) fp # define PATH_SEP ']' # define FILE_SEP '.' # else # define BIN_READ(dummy) "r" # define BIN_WRITE(dummy) "w" # define BIN_CREAT(dummy) O_CREAT # define BIN_ASSIGN(fp, dummy) fp # define PATH_SEP '/' # endif #endif /* open has only to arguments on the Mac */ #if __MWERKS__ # define OPEN(name, mode, umask) open(name, mode) #else # define OPEN(name, mode, umask) open(name, mode, umask) #endif #ifdef AMIGA # define STRNCMP(s1, s2, l) strncmp(s1, s2, (size_t)l) #else # define STRNCMP(s1, s2, l) strncmp(s1, s2, l) #endif #ifndef __P # if defined(__STDC__) || defined(WIN32) || defined(__BORLANDC__) # define __P(a) a # else # define __P(a) () # endif #endif /* Let's collect some prototypes */ /* CodeWarrior is really picky about missing prototypes */ static void exit_with_usage __P((void)); static void die __P((int)); static int huntype __P((FILE *, FILE *, FILE *, int, int, long)); static void xxdline __P((FILE *, char *, int)); #define TRY_SEEK /* attempt to use lseek, or skip forward by reading */ #define COLS 256 /* change here, if you ever need more columns */ #define LLEN (12 + (9*COLS-1) + COLS + 2) char hexxa[] = "0123456789abcdef0123456789ABCDEF", *hexx = hexxa; /* the different hextypes known by this program: */ #define HEX_NORMAL 0 #define HEX_POSTSCRIPT 1 #define HEX_CINCLUDE 2 #define HEX_BITS 3 /* not hex a dump, but bits: 01111001 */ #define HEX_LITTLEENDIAN 4 static char *pname; static void exit_with_usage(void) { fprintf(stderr, "Usage:\n %s [options] [infile [outfile]]\n", pname); fprintf(stderr, " or\n %s -r [-s [-]offset] [-c cols] [-ps] [infile [outfile]]\n", pname); fprintf(stderr, "Options:\n"); fprintf(stderr, " -a toggle autoskip: A single '*' replaces nul-lines. Default off.\n"); fprintf(stderr, " -b binary digit dump (incompatible with -ps,-i,-r). Default hex.\n"); fprintf(stderr, " -c cols format octets per line. Default 16 (-i: 12, -ps: 30).\n"); fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n"); fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n"); fprintf(stderr, " -g number of octets per group in normal output. Default 2 (-e: 4).\n"); fprintf(stderr, " -h print this summary.\n"); fprintf(stderr, " -i output in C include file style.\n"); fprintf(stderr, " -l len stop after octets.\n"); fprintf(stderr, " -o off add to the displayed file position.\n"); fprintf(stderr, " -ps output in postscript plain hexdump style.\n"); fprintf(stderr, " -r reverse operation: convert (or patch) hexdump into binary.\n"); fprintf(stderr, " -r -s off revert with added to file positions found in hexdump.\n"); fprintf(stderr, " -s %sseek start at bytes abs. %sinfile offset.\n", #ifdef TRY_SEEK "[+][-]", "(or +: rel.) "); #else "", ""); #endif fprintf(stderr, " -u use upper case hex letters.\n"); fprintf(stderr, " -v show version: \"%s%s\".\n", version, osver); exit(1); } static void die(int ret) { fprintf(stderr, "%s: ", pname); perror(NULL); exit(ret); } /* * Max. cols binary characters are decoded from the input stream per line. * Two adjacent garbage characters after evaluated data delimit valid data. * Everything up to the next newline is discarded. * * The name is historic and came from 'undo type opt h'. */ static int huntype( FILE *fpi, FILE *fpo, FILE *fperr, int cols, int hextype, long base_off) { int c, ign_garb = 1, n1 = -1, n2 = 0, n3, p = cols; long have_off = 0, want_off = 0; rewind(fpi); while ((c = getc(fpi)) != EOF) { if (c == '\r') /* Doze style input file? */ continue; /* Allow multiple spaces. This doesn't work when there is normal text * after the hex codes in the last line that looks like hex, thus only * use it for PostScript format. */ if (hextype == HEX_POSTSCRIPT && (c == ' ' || c == '\n' || c == '\t')) continue; n3 = n2; n2 = n1; if (c >= '0' && c <= '9') n1 = c - '0'; else if (c >= 'a' && c <= 'f') n1 = c - 'a' + 10; else if (c >= 'A' && c <= 'F') n1 = c - 'A' + 10; else { n1 = -1; if (ign_garb) continue; } ign_garb = 0; if (p >= cols) { if (!hextype) { if (n1 < 0) { p = 0; continue; } want_off = (want_off << 4) | n1; continue; } else p = 0; } if (base_off + want_off != have_off) { if (fflush(fpo) != 0) die(3); #ifdef TRY_SEEK c = fseek(fpo, base_off + want_off - have_off, 1); if (c >= 0) have_off = base_off + want_off; #endif if (base_off + want_off < have_off) { fprintf(fperr, "%s: sorry, cannot seek backwards.\n", pname); return 5; } for (; have_off < base_off + want_off; have_off++) if (putc(0, fpo) == EOF) die(3); } if (n2 >= 0 && n1 >= 0) { if (putc((n2 << 4) | n1, fpo) == EOF) die(3); have_off++; want_off++; n1 = -1; if ((++p >= cols) && !hextype) { /* skip rest of line as garbage */ want_off = 0; while ((c = getc(fpi)) != '\n' && c != EOF) ; if (c == EOF && ferror(fpi)) die(2); ign_garb = 1; } } else if (n1 < 0 && n2 < 0 && n3 < 0) { /* already stumbled into garbage, skip line, wait and see */ if (!hextype) want_off = 0; while ((c = getc(fpi)) != '\n' && c != EOF) ; if (c == EOF && ferror(fpi)) die(2); ign_garb = 1; } } if (fflush(fpo) != 0) die(3); #ifdef TRY_SEEK fseek(fpo, 0L, 2); #endif if (fclose(fpo) != 0) die(3); if (fclose(fpi) != 0) die(2); return 0; } /* * Print line l. If nz is false, xxdline regards the line a line of * zeroes. If there are three or more consecutive lines of zeroes, * they are replaced by a single '*' character. * * If the output ends with more than two lines of zeroes, you * should call xxdline again with l being the last line and nz * negative. This ensures that the last line is shown even when * it is all zeroes. * * If nz is always positive, lines are never suppressed. */ static void xxdline(FILE *fp, char *l, int nz) { static char z[LLEN+1]; static int zero_seen = 0; if (!nz && zero_seen == 1) strcpy(z, l); if (nz || !zero_seen++) { if (nz) { if (nz < 0) zero_seen--; if (zero_seen == 2) if (fputs(z, fp) == EOF) die(3); if (zero_seen > 2) if (fputs("*\n", fp) == EOF) die(3); } if (nz >= 0 || zero_seen > 0) if (fputs(l, fp) == EOF) die(3); if (nz) zero_seen = 0; } } /* This is an EBCDIC to ASCII conversion table */ /* from a proposed BTL standard April 16, 1979 */ static unsigned char etoa64[] = { 0040,0240,0241,0242,0243,0244,0245,0246, 0247,0250,0325,0056,0074,0050,0053,0174, 0046,0251,0252,0253,0254,0255,0256,0257, 0260,0261,0041,0044,0052,0051,0073,0176, 0055,0057,0262,0263,0264,0265,0266,0267, 0270,0271,0313,0054,0045,0137,0076,0077, 0272,0273,0274,0275,0276,0277,0300,0301, 0302,0140,0072,0043,0100,0047,0075,0042, 0303,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0304,0305,0306,0307,0310,0311, 0312,0152,0153,0154,0155,0156,0157,0160, 0161,0162,0136,0314,0315,0316,0317,0320, 0321,0345,0163,0164,0165,0166,0167,0170, 0171,0172,0322,0323,0324,0133,0326,0327, 0330,0331,0332,0333,0334,0335,0336,0337, 0340,0341,0342,0343,0344,0135,0346,0347, 0173,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0350,0351,0352,0353,0354,0355, 0175,0112,0113,0114,0115,0116,0117,0120, 0121,0122,0356,0357,0360,0361,0362,0363, 0134,0237,0123,0124,0125,0126,0127,0130, 0131,0132,0364,0365,0366,0367,0370,0371, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0372,0373,0374,0375,0376,0377 }; int main(int argc, char *argv[]) { FILE *fp, *fpo; int c, e, p = 0, relseek = 1, negseek = 0, revert = 0; int cols = 0, nonzero = 0, autoskip = 0, hextype = HEX_NORMAL; int ebcdic = 0; int octspergrp = -1; /* number of octets grouped in output */ int grplen; /* total chars per octet group */ long length = -1, n = 0, seekoff = 0, displayoff = 0; static char l[LLEN+1]; /* static because it may be too big for stack */ char *pp; #ifdef AMIGA /* This program doesn't work when started from the Workbench */ if (argc == 0) exit(1); #endif pname = argv[0]; for (pp = pname; *pp; ) if (*pp++ == PATH_SEP) pname = pp; #ifdef FILE_SEP for (pp = pname; *pp; pp++) if (*pp == FILE_SEP) { *pp = '\0'; break; } #endif while (argc >= 2) { pp = argv[1] + (!STRNCMP(argv[1], "--", 2) && argv[1][2]); if (!STRNCMP(pp, "-a", 2)) autoskip = 1 - autoskip; else if (!STRNCMP(pp, "-b", 2)) hextype = HEX_BITS; else if (!STRNCMP(pp, "-e", 2)) hextype = HEX_LITTLEENDIAN; else if (!STRNCMP(pp, "-u", 2)) hexx = hexxa + 16; else if (!STRNCMP(pp, "-p", 2)) hextype = HEX_POSTSCRIPT; else if (!STRNCMP(pp, "-i", 2)) hextype = HEX_CINCLUDE; else if (!STRNCMP(pp, "-r", 2)) revert++; else if (!STRNCMP(pp, "-E", 2)) ebcdic++; else if (!STRNCMP(pp, "-v", 2)) { fprintf(stderr, "%s%s\n", version, osver); exit(0); } else if (!STRNCMP(pp, "-c", 2)) { if (pp[2] && STRNCMP("ols", pp + 2, 3)) cols = (int)strtol(pp + 2, NULL, 0); else { if (!argv[2]) exit_with_usage(); cols = (int)strtol(argv[2], NULL, 0); argv++; argc--; } } else if (!STRNCMP(pp, "-g", 2)) { if (pp[2] && STRNCMP("group", pp + 2, 5)) octspergrp = (int)strtol(pp + 2, NULL, 0); else { if (!argv[2]) exit_with_usage(); octspergrp = (int)strtol(argv[2], NULL, 0); argv++; argc--; } } else if (!STRNCMP(pp, "-o", 2)) { if (pp[2] && STRNCMP("ffset", pp + 2, 5)) displayoff = (int)strtol(pp + 2, NULL, 0); else { if (!argv[2]) exit_with_usage(); displayoff = (int)strtol(argv[2], NULL, 0); argv++; argc--; } } else if (!STRNCMP(pp, "-s", 2)) { relseek = 0; negseek = 0; if (pp[2] && STRNCMP("kip", pp+2, 3) && STRNCMP("eek", pp+2, 3)) { #ifdef TRY_SEEK if (pp[2] == '+') relseek++; if (pp[2+relseek] == '-') negseek++; #endif seekoff = strtol(pp + 2+relseek+negseek, (char **)NULL, 0); } else { if (!argv[2]) exit_with_usage(); #ifdef TRY_SEEK if (argv[2][0] == '+') relseek++; if (argv[2][relseek] == '-') negseek++; #endif seekoff = strtol(argv[2] + relseek+negseek, (char **)NULL, 0); argv++; argc--; } } else if (!STRNCMP(pp, "-l", 2)) { if (pp[2] && STRNCMP("en", pp + 2, 2)) length = strtol(pp + 2, (char **)NULL, 0); else { if (!argv[2]) exit_with_usage(); length = strtol(argv[2], (char **)NULL, 0); argv++; argc--; } } else if (!strcmp(pp, "--")) /* end of options */ { argv++; argc--; break; } else if (pp[0] == '-' && pp[1]) /* unknown option */ exit_with_usage(); else break; /* not an option */ argv++; /* advance to next argument */ argc--; } if (!cols) switch (hextype) { case HEX_POSTSCRIPT: cols = 30; break; case HEX_CINCLUDE: cols = 12; break; case HEX_BITS: cols = 6; break; case HEX_NORMAL: case HEX_LITTLEENDIAN: default: cols = 16; break; } if (octspergrp < 0) switch (hextype) { case HEX_BITS: octspergrp = 1; break; case HEX_NORMAL: octspergrp = 2; break; case HEX_LITTLEENDIAN: octspergrp = 4; break; case HEX_POSTSCRIPT: case HEX_CINCLUDE: default: octspergrp = 0; break; } if (cols < 1 || ((hextype == HEX_NORMAL || hextype == HEX_BITS || hextype == HEX_LITTLEENDIAN) && (cols > COLS))) { fprintf(stderr, "%s: invalid number of columns (max. %d).\n", pname, COLS); exit(1); } if (octspergrp < 1 || octspergrp > cols) octspergrp = cols; else if (hextype == HEX_LITTLEENDIAN && (octspergrp & (octspergrp-1))) { fprintf(stderr, "%s: number of octets per group must be a power of 2 with -e.\n", pname); exit(1); } if (argc > 3) exit_with_usage(); if (argc == 1 || (argv[1][0] == '-' && !argv[1][1])) BIN_ASSIGN(fp = stdin, !revert); else { if ((fp = fopen(argv[1], BIN_READ(!revert))) == NULL) { fprintf(stderr,"%s: ", pname); perror(argv[1]); return 2; } } if (argc < 3 || (argv[2][0] == '-' && !argv[2][1])) BIN_ASSIGN(fpo = stdout, revert); else { int fd; int mode = revert ? O_WRONLY : (O_TRUNC|O_WRONLY); if (((fd = OPEN(argv[2], mode | BIN_CREAT(revert), 0666)) < 0) || (fpo = fdopen(fd, BIN_WRITE(revert))) == NULL) { fprintf(stderr, "%s: ", pname); perror(argv[2]); return 3; } rewind(fpo); } if (revert) { if (hextype && (hextype != HEX_POSTSCRIPT)) { fprintf(stderr, "%s: sorry, cannot revert this type of hexdump\n", pname); return -1; } return huntype(fp, fpo, stderr, cols, hextype, negseek ? -seekoff : seekoff); } if (seekoff || negseek || !relseek) { #ifdef TRY_SEEK if (relseek) e = fseek(fp, negseek ? -seekoff : seekoff, 1); else e = fseek(fp, negseek ? -seekoff : seekoff, negseek ? 2 : 0); if (e < 0 && negseek) { fprintf(stderr, "%s: sorry cannot seek.\n", pname); return 4; } if (e >= 0) seekoff = ftell(fp); else #endif { long s = seekoff; while (s--) if (getc(fp) == EOF) { if (ferror(fp)) { die(2); } else { fprintf(stderr, "%s: sorry cannot seek.\n", pname); return 4; } } } } if (hextype == HEX_CINCLUDE) { if (fp != stdin) { if (fprintf(fpo, "unsigned char %s", isdigit((int)argv[1][0]) ? "__" : "") < 0) die(3); for (e = 0; (c = argv[1][e]) != 0; e++) if (putc(isalnum(c) ? c : '_', fpo) == EOF) die(3); if (fputs("[] = {\n", fpo) == EOF) die(3); } p = 0; c = 0; while ((length < 0 || p < length) && (c = getc(fp)) != EOF) { if (fprintf(fpo, (hexx == hexxa) ? "%s0x%02x" : "%s0X%02X", (p % cols) ? ", " : &",\n "[2*!p], c) < 0) die(3); p++; } if (c == EOF && ferror(fp)) die(2); if (p && fputs("\n", fpo) == EOF) die(3); if (fputs(&"};\n"[3 * (fp == stdin)], fpo) == EOF) die(3); if (fp != stdin) { if (fprintf(fpo, "unsigned int %s", isdigit((int)argv[1][0]) ? "__" : "") < 0) die(3); for (e = 0; (c = argv[1][e]) != 0; e++) if (putc(isalnum(c) ? c : '_', fpo) == EOF) die(3); if (fprintf(fpo, "_len = %d;\n", p) < 0) die(3); } if (fclose(fp)) die(2); if (fclose(fpo)) die(3); return 0; } if (hextype == HEX_POSTSCRIPT) { p = cols; e = 0; while ((length < 0 || n < length) && (e = getc(fp)) != EOF) { if (putc(hexx[(e >> 4) & 0xf], fpo) == EOF || putc(hexx[e & 0xf], fpo) == EOF) die(3); n++; if (!--p) { if (putc('\n', fpo) == EOF) die(3); p = cols; } } if (e == EOF && ferror(fp)) die(2); if (p < cols) if (putc('\n', fpo) == EOF) die(3); if (fclose(fp)) die(2); if (fclose(fpo)) die(3); return 0; } /* hextype: HEX_NORMAL or HEX_BITS or HEX_LITTLEENDIAN */ if (hextype != HEX_BITS) grplen = octspergrp + octspergrp + 1; /* chars per octet group */ else /* hextype == HEX_BITS */ grplen = 8 * octspergrp + 1; e = 0; while ((length < 0 || n < length) && (e = getc(fp)) != EOF) { if (p == 0) { sprintf(l, "%08lx:", ((unsigned long)(n + seekoff + displayoff)) & 0xffffffff); for (c = 9; c < LLEN; l[c++] = ' '); } if (hextype == HEX_NORMAL) { l[c = (10 + (grplen * p) / octspergrp)] = hexx[(e >> 4) & 0xf]; l[++c] = hexx[ e & 0xf]; } else if (hextype == HEX_LITTLEENDIAN) { int x = p ^ (octspergrp-1); l[c = (10 + (grplen * x) / octspergrp)] = hexx[(e >> 4) & 0xf]; l[++c] = hexx[ e & 0xf]; } else /* hextype == HEX_BITS */ { int i; c = (10 + (grplen * p) / octspergrp) - 1; for (i = 7; i >= 0; i--) l[++c] = (e & (1 << i)) ? '1' : '0'; } if (ebcdic) e = (e < 64) ? '.' : etoa64[e-64]; /* When changing this update definition of LLEN above. */ l[12 + (grplen * cols - 1)/octspergrp + p] = #ifdef __MVS__ (e >= 64) #else (e > 31 && e < 127) #endif ? e : '.'; if (e) nonzero++; n++; if (++p == cols) { l[c = (12 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0'; xxdline(fpo, l, autoskip ? nonzero : 1); nonzero = 0; p = 0; } } if (e == EOF && ferror(fp)) die(2); if (p) { l[c = (12 + (grplen * cols - 1)/octspergrp + p)] = '\n'; l[++c] = '\0'; xxdline(fpo, l, 1); } else if (autoskip) xxdline(fpo, l, -1); /* last chance to flush out suppressed lines */ if (fclose(fp)) die(2); if (fclose(fpo)) die(3); return 0; } /* vi:set ts=8 sw=4 sts=2 cino+={2 cino+=n-2 : */ ================================================ FILE: projects/cryptography/Dockerfile ================================================ # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN git clone https://github.com/pyca/cryptography RUN apt-get update && apt-get install build-essential libssl-dev libffi-dev pkg-config python3-dev cargo -y RUN pip3 install --upgrade pip RUN curl https://sh.rustup.rs -sSf | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" RUN rustup install nightly RUN rustup default nightly WORKDIR cryptography COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/cryptography/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzzers in $OUT. python3 -m pip cache purge # Compiling with sancov is causing some issues at the moment. This is likely # due to some missing flags propagated throughout. unset RUSTFLAGS unset CXXFLAGS unset CFLAGS python3 -m pip install . cd $SRC for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/cryptography/fuzz_aead.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import cryptography.hazmat.primitives.ciphers.aead as aead def TestInput(input_bytes): if len(input_bytes) < 12: return fdp = atheris.FuzzedDataProvider(input_bytes) choice = fdp.ConsumeIntInRange(1,4) if choice == 1: cipher = aead.ChaCha20Poly1305(aead.ChaCha20Poly1305.generate_key()) if choice == 2: cipher = aead.AESGCM(aead.AESGCM.generate_key(bit_length=128)) if choice == 3: cipher = aead.AESOCB3(aead.AESOCB3.generate_key(bit_length=128)) if choice == 4: cipher = aead.AESCCM(aead.AESCCM.generate_key(bit_length=128)) msg = fdp.ConsumeBytes(32) authentext = fdp.ConsumeBytes(32) nonce = fdp.ConsumeBytes(12) if len(nonce) < 12: return ciphertext = cipher.encrypt(nonce, msg, authentext) plaintext = cipher.decrypt(nonce, ciphertext, authentext) assert (plaintext == msg), "Encryption/Decrption error!" def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=False) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cryptography/fuzz_dh.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import dh from cryptography.hazmat.primitives.kdf.hkdf import HKDF def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) try: parameters = dh.generate_parameters( generator=(2 if fdp.ConsumeBool() else 5), key_size=fdp.ConsumeInt(4) ) except ValueError as e: # This can only happen if the key_size isn't valid return server_private_key = parameters.generate_private_key() peer_private_key = parameters.generate_private_key() server_derived_shared_key = server_private_key.exchange(peer_private_key.public_key()) peer_derived_shared_key = peer_private_key.exchange(server_private_key.public_key()) infobytes = fdp.ConsumeBytes(10) server_derived_key = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=infobytes, ).derive(server_derived_shared_key) peer_derived_key = HKDF( algorithm=hashes.SHA256(), length=32, salt=None, info=infobytes, ).derive(peer_derived_shared_key) assert (server_derived_key == peer_derived_key), "Key Derivation Error!!" def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=False) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cryptography/fuzz_dsa.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import dsa, utils def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) private_key = dsa.generate_private_key(key_size=1024) public_key = private_key.public_key() data = fdp.ConsumeBytes(20) more_data = fdp.ConsumeBytes(20) hasher = hashes.Hash(hashes.SHA256()) hasher.update(data) hasher.update(more_data) digest = hasher.finalize() sig1 = private_key.sign(data,hashes.SHA256()) sig2 = private_key.sign(digest,utils.Prehashed(hashes.SHA256())) public_key.verify(sig1,data,hashes.SHA256()) public_key.verify(sig2,digest,utils.Prehashed(hashes.SHA256())) def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=False) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cryptography/fuzz_rsa.py ================================================ #!/usr/bin/python3 # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import rsa, utils, padding def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) private_key = rsa.generate_private_key(key_size=1024, public_exponent=65537) public_key = private_key.public_key() data = fdp.ConsumeBytes(20) more_data = fdp.ConsumeBytes(20) hasher = hashes.Hash(hashes.SHA256()) hasher.update(data) hasher.update(more_data) digest = hasher.finalize() sig1 = private_key.sign(data, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256()) sig2 = private_key.sign(digest, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), utils.Prehashed(hashes.SHA256())) public_key.verify(sig1, data, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), hashes.SHA256()) public_key.verify(sig2, digest, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH), utils.Prehashed(hashes.SHA256())) def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=False) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cryptography/fuzz_sym.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import base64 import atheris with atheris.instrument_imports(): from cryptography.fernet import Fernet from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC def TestInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) plaintext = fdp.ConsumeBytes(32) key = Fernet(Fernet.generate_key()) token = key.encrypt(plaintext) text = key.decrypt(token) assert (plaintext == text), "Encryption/Decrption error!" password = fdp.ConsumeBytes(8) salt = fdp.ConsumeBytes(16) kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=salt, iterations=1, ) key = Fernet(base64.urlsafe_b64encode(kdf.derive(password))) token = key.encrypt(plaintext) text = key.decrypt(token) assert (plaintext == text), "Encryption/Decrption error!" def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=False) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cryptography/project.yaml ================================================ base_os_version: ubuntu-24-04 auto_ccs: - paul.l.kehrer@gmail.com fuzzing_engines: - libfuzzer homepage: https://github.com/pyca/cryptography language: python main_repo: https://github.com/pyca/cryptography primary_contact: alex.gaynor@gmail.com sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/cryptsetup/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://gitlab.com/cryptsetup/cryptsetup.git COPY build.sh $SRC/ ================================================ FILE: projects/cryptsetup/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./cryptsetup/tests/fuzz/oss-fuzz-build.sh ================================================ FILE: projects/cryptsetup/project.yaml ================================================ homepage: "https://gitlab.com/cryptsetup/cryptsetup" language: c builds_per_day: 2 primary_contact: "gmazyland@gmail.com" auto_ccs: - okozina@redhat.com - vtrefny@redhat.com - daniel.zatovic@gmail.com sanitizers: - address - memory - undefined architectures: - x86_64 main_repo: "https://gitlab.com/cryptsetup/cryptsetup.git" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/cssselect/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/scrapy/cssselect cssselect COPY *.sh *py $SRC/ WORKDIR $SRC/cssselect ================================================ FILE: projects/cssselect/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/cssselect/fuzz_parse.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import cssselect def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) css = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) try: cssselect.parser.parse(css) except (cssselect.parser.SelectorError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cssselect/fuzz_xpath.py ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1 # Imports by the generated code import cssselect def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) css = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) # Class target. try: translator = cssselect.xpath.GenericTranslator() translator.css_to_xpath(css) except(cssselect.parser.SelectorError,TypeError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/cssselect/project.yaml ================================================ homepage: https://github.com/scrapy/cssselect main_repo: https://github.com/scrapy/cssselect language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/cubefs/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/cubefs/cubefs RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing.git COPY build.sh $SRC/ RUN cd /src/cubefs && make cli WORKDIR $SRC/cubefs ================================================ FILE: projects/cubefs/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed 's/go 1.17/go 1.21/g' -i ./go.mod $SRC/cncf-fuzzing/projects/cubefs/build.sh ================================================ FILE: projects/cubefs/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/cubefs/cubefs" main_repo: "https://github.com/cubefs/cubefs" primary_contact: "626148589@qq.com" auto_ccs: - "changliang@oppo.com" - "baijiaruo@126.com" - "tangjingyu@oppo.com" - "david@adalogics.com" - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/cups/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y zlib1g-dev libavahi-client-dev libsystemd-dev RUN git clone --depth 1 https://github.com/OpenPrinting/cups RUN git clone --depth 1 https://github.com/OpenPrinting/fuzzing.git RUN cp $SRC/fuzzing/projects/cups/oss_fuzz_build.sh $SRC/build.sh COPY run_tests.sh *.diff $SRC/ RUN cd $SRC/fuzzing && git apply $SRC/test_patch.diff WORKDIR $SRC/cups ================================================ FILE: projects/cups/project.yaml ================================================ homepage: "https://openprinting.github.io/cups/" main_repo: 'https://github.com/OpenPrinting/cups' # help_url: language: c primary_contact: "jiongchiyu@gmail.com" auto_ccs: - "till.kamppeter@gmail.com" - "ossfuzz@iosifache.me" - "msweet@msweet.org" - "pushinliu@gmail.com" # vendor_ccs: architectures: - x86_64 # - i386 sanitizers: - address - memory # - undefined fuzzing_engines: - libfuzzer - afl - honggfuzz # builds_per_day: 2 ================================================ FILE: projects/cups/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build the unit tests export ASAN_OPTIONS=detect_leaks=0 cd $SRC/cups # these locales fail: rm locale/cups_hu.po rm locale/cups_pt.po # Below we run two test suites. # cups has another test suite which is part # of `make test`: `cd test; ./run-stp-tests.sh`, # however, this requires a non-root user and # network interfaces that OSS-Fuzz doesn't support. pushd cups make test popd pushd scheduler make test popd ================================================ FILE: projects/cups/test_patch.diff ================================================ diff --git a/projects/cups/oss_fuzz_build.sh b/projects/cups/oss_fuzz_build.sh index 01ebaf3..f72b756 100755 --- a/projects/cups/oss_fuzz_build.sh +++ b/projects/cups/oss_fuzz_build.sh @@ -34,7 +34,7 @@ popd pushd $SRC/cups # Show build version echo "CUPS version: $(git rev-parse HEAD)" -./configure --enable-static --disable-shared +./configure --enable-unit-tests --enable-static --disable-shared make # -j$(nproc) popd ================================================ FILE: projects/cups-filters/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool build-essential ### for cups-filters-2.x # RUN sed --in-place 's/focal/noble/g' /etc/apt/sources.list # RUN apt update && apt-get install -y chrpath gnutls-dev libppd-dev libavahi-common-dev libavahi-client-dev autopoint gettext libcups2-dev ghostscript mupdf-tools # RUN git clone --depth 1 https://github.com/OpenPrinting/cups-filters.git ### for cups-filters-1.x RUN apt update && apt-get install -y libexif-dev libglib2.0-dev libavahi-glib-dev liblcms2-dev libfreetype6-dev libfontconfig1-dev libqpdf-dev libpoppler-cpp-dev poppler-utils \ libunistring-dev libsystemd-dev libcap-dev gettext autopoint libcups2-dev libavahi-client-dev ghostscript mupdf-tools # ubuntu 20.04 only supports cups-filters 1.x RUN git clone --depth 1 -b "1.x" https://github.com/OpenPrinting/cups-filters.git RUN git clone --depth 1 https://github.com/OpenPrinting/fuzzing.git RUN cp $SRC/fuzzing/projects/cups-filters/oss_fuzz_build.sh $SRC/build.sh WORKDIR $SRC/cups-filters COPY run_tests.sh $SRC/ ================================================ FILE: projects/cups-filters/project.yaml ================================================ homepage: "https://github.com/OpenPrinting/cups-filters" main_repo: "https://github.com/OpenPrinting/cups-filters.git" # help_url: language: c++ primary_contact: "jiongchiyu@gmail.com" auto_ccs: - "till.kamppeter@gmail.com" - "ossfuzz@iosifache.me" - "msweet@msweet.org" # - "jsmeix@suse.de" # - "debian@alteholz.de" # - "zdohnal@redhat.com" # - "basu.aveek@gmail.com" # vendor_ccs: architectures: - x86_64 # - i386 sanitizers: - address - memory # - undefined fuzzing_engines: - libfuzzer # - afl # - honggfuzz # builds_per_day: 2 ================================================ FILE: projects/cups-filters/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/cura-engine/project.yaml ================================================ homepage: "https://github.com/Ultimaker/CuraEngine" language: c++ primary_contact: "j.vankessel@ultimaker.com" auto_ccs: - "artem.smotrakov@gmail.com" sanitizers: - address - undefined main_repo: "https://github.com/Ultimaker/CuraEngine.git" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/curl/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN git clone --depth 1 https://github.com/curl/curl.git /src/curl RUN git clone --depth 1 https://github.com/curl/curl-fuzzer.git /src/curl_fuzzer # Use curl-fuzzer's scripts to get latest dependencies. RUN $SRC/curl_fuzzer/scripts/ossfuzzdeps.sh WORKDIR $SRC/curl_fuzzer COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/curl/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the curl-fuzzer project. if [[ ! -z "${REPLAY_ENABLED-}" ]]; then # If we don't do this, the curl library won't rebuild. rm -f $SRC/curl_fuzzer/build/curl-install/lib/libcurl.a pushd $SRC/curl make install popd fi ./ossfuzz.sh ================================================ FILE: projects/curl/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://curl.haxx.se/" language: c++ primary_contact: "daniel@haxx.se" auto_ccs: - "daniel.haxx@gmail.com" - "cmeister2@gmail.com" - "stefan.eissing@gmail.com" sanitizers: - address - undefined - memory fuzzing_engines: - afl - honggfuzz - libfuzzer architectures: - x86_64 - i386 main_repo: 'https://github.com/curl/curl.git' ================================================ FILE: projects/curl/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/curl make test ================================================ FILE: projects/curvesapi/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/virtuald/curvesapi curvesapi COPY *.sh *.java $SRC/ WORKDIR $SRC/curvesapi ================================================ FILE: projects/curvesapi/ParseFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.graphbuilder.math.ExpressionTree; import com.graphbuilder.math.Expression; import com.graphbuilder.math.ExpressionParseException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [com.graphbuilder.math.ExpressionTree] public static com.graphbuilder.math.Expression parse(java.lang.String) public class ParseFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { com.graphbuilder.math.ExpressionTree.parse(data.consumeRemainingAsString()); } catch (ExpressionParseException e1) {} } } ================================================ FILE: projects/curvesapi/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## find ./ -name pom.xml -exec sed -i 's/source>1.51.81.51.8 $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/curvesapi/project.yaml ================================================ homepage: https://github.com/virtuald/curvesapi main_repo: https://github.com/virtuald/curvesapi language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/cxxopts/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y python3 RUN git clone --depth 1 https://github.com/jarro2783/cxxopts.git cxxopts WORKDIR cxxopts COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/cxxopts/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable ccache for chronos check since ccache is not compatible with bazel export PATH=$(echo $PATH | tr ':' '\n' | grep -v ccache | tr '\n' ':' | sed 's/:$//') export CXXFLAGS="${CXXFLAGS} -std=c++17" export USE_BAZEL_VERSION=7.4.0 bazel_build_fuzz_tests # Build unit test $CXX $CXXFLAGS -o unittest -Iinclude -Itest test/main.cpp test/options.cpp ================================================ FILE: projects/cxxopts/project.yaml ================================================ homepage: "https://github.com/jarro2783/cxxopts" language: c++ primary_contact: "jarro.2783@gmail.com" main_repo: "https://github.com/jarro2783/cxxopts" auto_ccs: - nathaniel@rough.run fuzzing_engines: - afl - honggfuzz - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/cxxopts/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./unittest ================================================ FILE: projects/cyclonedds/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt install -y \ autoconf \ automake \ libssl-dev \ libcunit1 \ libcunit1-dev \ bison \ libbison-dev RUN git clone --depth 1 https://github.com/eclipse-cyclonedds/cyclonedds COPY build.sh $SRC WORKDIR $SRC/cyclonedds # This is to fix Fuzz Introspector build by using LLVM old pass manager # re https://github.com/ossf/fuzz-introspector/issues/305 ENV OLD_LLVMPASS 1 ================================================ FILE: projects/cyclonedds/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ source fuzz/oss-fuzz-build.sh ================================================ FILE: projects/cyclonedds/project.yaml ================================================ homepage: "https://projects.eclipse.org/projects/iot.cyclonedds" language: c auto_ccs: - "federico.maggi@gmail.com" primary_contact: "eb@ilities.com" fuzzing_engines: - afl - honggfuzz - libfuzzer sanitizers: - address - undefined main_repo: 'https://github.com/eclipse-cyclonedds/cyclonedds.git' ================================================ FILE: projects/d3/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/d3/d3.git RUN #mkdir -p $SRC/d3/fuzz_tests COPY fuzz_tests $SRC/d3/fuzz_tests COPY babel.config.json $SRC/d3 WORKDIR $SRC/d3 ================================================ FILE: projects/d3/babel.config.json ================================================ { "plugins": ["@babel/plugin-transform-modules-commonjs"], "ignore": ["**/@jazzer.js", "**/@babel", "**/istanbul-reports"] } ================================================ FILE: projects/d3/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ function change_type_to_commonjs() { # Find all package.json files inside the node_modules directory find "$1" -name "package.json" -type f | while read -r package_file; do # Check if the file contains the "type" field if grep -q '"type": "module"' "$package_file"; then # Replace "type": "module" with "type": "commonjs" sed -i 's/"type": "module"/"type": "commonjs"/' "$package_file" echo "Updated $package_file" fi done } function transform_dir_into_commonjs() { babel "$1" --keep-file-extension -D -d "$1"_commonjs rm -r "$1" mv "$1"_commonjs "$1" } function remove_dev_dependencies() { package_json=$(cat package.json) # Remove the "devDependencies" item from package.json new_package_json=$(echo "$package_json" | jq 'del(.devDependencies)') # Overwrite the package.json file with the updated content echo "$new_package_json" > package.json } # Install dependencies. remove_dev_dependencies npm install --global yarn yarn install npm install -g @babel/cli yarn add --dev @babel/core @babel/plugin-transform-modules-commonjs yarn add --dev @jazzer.js/core transform_dir_into_commonjs $SRC/d3/src transform_dir_into_commonjs $SRC/d3/node_modules change_type_to_commonjs $SRC/d3 # Build Fuzzers. compile_javascript_fuzzer d3 fuzz_tests/fuzz_csv_parse -i d3- --sync ================================================ FILE: projects/d3/fuzz_tests/fuzz_csv_parse.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const d3 = require("../src/index.js"); module.exports.fuzz = function (data) { d3.csvParse(data.toString()) }; ================================================ FILE: projects/d3/project.yaml ================================================ homepage: https://d3js.org/ language: javascript main_repo: https://github.com/d3/d3.git fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - yakdan@code-intelligence.com - norbert.schneider@code-intelligence.com - peter.samarin@code-intelligence.com ================================================ FILE: projects/dapr/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/dapr/dapr RUN git clone --depth 1 https://github.com/dapr/kit RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing WORKDIR $SRC/dapr COPY build.sh $SRC/ ================================================ FILE: projects/dapr/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="${CXXFLAGS} -lresolv" $SRC/cncf-fuzzing/projects/dapr/build.sh ================================================ FILE: projects/dapr/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://dapr.io/" language: go primary_contact: "schneideryaron@gmail.com" main_repo: "https://github.com/dapr" auto_ccs: - "artur04@gmail.com" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/dart/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y g++-multilib git python3 curl RUN git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git ENV PATH="${SRC}/depot_tools:${PATH}" RUN mkdir dart-sdk && cd dart-sdk && fetch dart COPY build.sh $SRC COPY patch.diff $SRC WORKDIR $SRC/dart-sdk/sdk # This is to fix Fuzz Introspector build by using LLVM old pass manager # re https://github.com/ossf/fuzz-introspector/issues/305 ENV OLD_LLVMPASS=1 ================================================ FILE: projects/dart/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project # Apply patch to fix libfuzzer compatibility with MSan stubs git apply ../../patch.diff ./tools/build.py -j$(nproc) -m debug -a x64 --sanitizer=asan dart_libfuzzer cp out/DebugASANX64/*fuzzer $OUT/ ================================================ FILE: projects/dart/patch.diff ================================================ diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -5280,10 +5280,12 @@ extern "C" void dart_msan_write16(void* addr) { __msan_unpoison(addr, 16); } #else +// These stubs are needed because libFuzzer may call these functions. +// They should be no-ops instead of UNREACHABLE() to avoid crashes. extern "C" void __msan_unpoison(const volatile void*, size_t) { - UNREACHABLE(); + // No-op when MSan is not enabled. } extern "C" void __msan_unpoison_param(size_t) { - UNREACHABLE(); + // No-op when MSan is not enabled. } #endif ================================================ FILE: projects/dart/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://dart.dev" language: c++ primary_contact: "scheglov@google.com" auto_ccs : - "p.antoine@catenacyber.fr" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: 'https://github.com/dart-lang/sdk.git' ================================================ FILE: projects/dask/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y pkg-config RUN git clone https://github.com/dask/dask COPY build.sh fuzz_fuse.py $SRC/ WORKDIR $SRC/dask ================================================ FILE: projects/dask/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/dask/fuzz_fuse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import dask from dask.optimization import ( fuse, fuse_linear, ) from dask.utils_test import dec, inc, add def get_fuse_dict(data): fdp = atheris.FuzzedDataProvider(data) fuse_dict = dict() number_of_entries = fdp.ConsumeIntInRange(1, 50) operations = [dec, inc, add] previous_keys = list() key="a" fuse_dict[key] = 1 previous_keys.append(key) for i in range(number_of_entries): newk=key+str(i) val_op = operations[fdp.ConsumeIntInRange(0, 2)] val_id = previous_keys[fdp.ConsumeIntInRange(0, len(previous_keys)-1)] fuse_dict[newk] = (val_op, val_id) previous_keys.append(newk) return fuse_dict @atheris.instrument_func def TestOneInput(data): if len(data) < 10: return fdp = atheris.FuzzedDataProvider(data) fuzzed_dict = get_fuse_dict(data) if len(fuzzed_dict) == 0: return if fdp.ConsumeBool(): fuse( fuzzed_dict, rename_keys=fdp.ConsumeBool() ) else: fuse_linear( fuzzed_dict, rename_keys=fdp.ConsumeBool() ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/dask/fuzz_serialize.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import json from dask.config import ( deserialize, serialize ) @atheris.instrument_func def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: fuzzed_dict = json.loads(fdp.ConsumeString(sys.maxsize)) except json.JSONDecodeError: return if type(fuzzed_dict) is not dict: return serialized = serialize(fuzzed_dict) config = deserialize(serialized) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/dask/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/dask/dask language: python main_repo: https://github.com/dask/dask sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/data-encoding/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && \ apt-get install -y make autoconf automake libtool curl cmake python RUN git clone https://github.com/ia0/data-encoding WORKDIR $SRC/data-encoding # The default toolchain used by OSS-Fuzz is too old for our fuzzing crate. ENV RUSTUP_TOOLCHAIN nightly-2025-07-16 COPY build.sh $SRC/ ================================================ FILE: projects/data-encoding/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd lib cargo fuzz build find $SRC/data-encoding/target/x86_64-unknown-linux-gnu/release -maxdepth 1 \ -type f -perm -u=x -exec cp {} $OUT \; ================================================ FILE: projects/data-encoding/project.yaml ================================================ homepage: "https://github.com/ia0/data-encoding" main_repo: "https://github.com/ia0/data-encoding.git" sanitizers: - address fuzzing_engines: - libfuzzer language: rust primary_contact: "github@ia0.eu" auto_ccs: - "cretin@google.com" - "fuzzing@fuchsia.dev" vendor_ccs: - "arthur.chan@adalogics.com" - "david@adalogics.com" ================================================ FILE: projects/date/project.yaml ================================================ homepage: "https://howardhinnant.github.io/date/date.html" language: c++ primary_contact: "capuanobailey@gmail.com" main_repo: "https://github.com/HowardHinnant/date" ================================================ FILE: projects/dateparser/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone --depth 1 https://github.com/scrapinghub/dateparser.git dateparser \ && cp dateparser/fuzzing/build.sh $SRC/ \ && mv dateparser/fuzzing/corpus $SRC/ WORKDIR $SRC/dateparser ================================================ FILE: projects/dateparser/project.yaml ================================================ homepage: "https://dateparser.readthedocs.io/en/latest/" language: python primary_contact: "opensource@zyte.com" auto_ccs: - "ennamarie19@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/scrapinghub/dateparser.git" ================================================ FILE: projects/dav1d/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel nasm && \ pip3 install meson ninja RUN curl --silent -O https://storage.googleapis.com/aom-test-data/fuzzer/dec_fuzzer_seed_corpus.zip RUN curl --silent -O https://download.videolan.org/contrib/dav1d/dav1d_fuzzer_seed_corpus.zip RUN git clone --depth 1 https://code.videolan.org/videolan/dav1d.git dav1d RUN cd dav1d && git clone https://code.videolan.org/videolan/dav1d-test-data.git tests/dav1d-test-data WORKDIR dav1d COPY build.sh run_tests.sh $SRC/ COPY linux32.meson $SRC/ ================================================ FILE: projects/dav1d/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # setup build=${WORK}/build # cleanup rm -rf ${build} mkdir -p ${build} # prepare cross file for i386 compiliation if [ "$ARCHITECTURE" = "i386" ]; then MESON_CFLAGS="'$(echo $CFLAGS | sed -e 's/ /;, ;/g' | tr \; \')'" MESON_CXXFLAGS="'$(echo $CXXFLAGS | sed -e 's/ /;, ;/g' | tr \; \')'" sed -e "s/CC$/'$CC'/; s/CXX$/'$CXX'/; s/CFLAGS$/[$MESON_CFLAGS]/; s/CXXFLAGS$/[$MESON_CXXFLAGS]/" < ${SRC}/linux32.meson > ${WORK}/linux32.meson CROSS="--cross-file ${WORK}/linux32.meson" fi # build library meson -Denable_tools=false -Dfuzzing_engine=oss-fuzz \ -Db_lundef=false -Ddefault_library=static -Dbuildtype=debugoptimized \ -Dlogging=false -Dfuzzer_ldflags=$LIB_FUZZING_ENGINE \ -Dtestdata_tests=true \ ${CROSS:-} \ ${build} ninja -j $(nproc) -C ${build} # prepare seed corpus rm -rf ${WORK}/tmp mkdir -p ${WORK}/tmp/testdata unzip -q $SRC/dav1d_fuzzer_seed_corpus.zip -d ${WORK}/tmp/testdata cp $SRC/dec_fuzzer_seed_corpus.zip ${WORK}/tmp/seed_corpus.zip (cd ${WORK}/tmp && zip -q -m -r -0 ${WORK}/tmp/seed_corpus.zip testdata) # copy fuzzers and link testdata for fuzzer in $(find ${build}/tests/libfuzzer -maxdepth 1 -type f -executable -name 'dav1d_fuzzer*'); do cp "${fuzzer}" $OUT/ cp ${WORK}/tmp/seed_corpus.zip $OUT/$(basename "$fuzzer")_seed_corpus.zip done ================================================ FILE: projects/dav1d/linux32.meson ================================================ [binaries] c = CC cpp = CXX ar = 'ar' strip = 'strip' [properties] c_args = CFLAGS c_link_args = CFLAGS cpp_args = CXXFLAGS cpp_link_args = CXXFLAGS [host_machine] system = 'linux' cpu_family = 'x86' cpu = 'i686' endian = 'little' ================================================ FILE: projects/dav1d/project.yaml ================================================ homepage: "https://code.videolan.org/videolan/dav1d" language: c++ primary_contact: "janne.grunau@gmail.com" auto_ccs: - "rsbultje@gmail.com" - "kempfjb@gmail.com" - "b@rr-dav.id.au" - "dav1d-fuzz@videolan.org" - "psilokos@twoorioles.com" - "gramner@twoorioles.com" vendor_ccs: - "media-alerts@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - memory - undefined coverage_extra_args: -ignore-filename-regex=.*dump.h architectures: - i386 - x86_64 main_repo: 'https://code.videolan.org/videolan/dav1d.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dav1d/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd /work/build meson test ================================================ FILE: projects/dbus-broker/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust:ubuntu-24-04 RUN git clone --depth 1 https://github.com/bus1/dbus-broker # RUSTUP_TOOLCHAIN is set explicitly to match the latest images # to get around https://github.com/google/oss-fuzz/issues/14220. # It should be removed once that issue is resolved. ENV RUSTUP_TOOLCHAIN nightly-2025-09-05 RUN cargo install bindgen-cli WORKDIR dbus-broker COPY *.c build.sh $SRC/ ================================================ FILE: projects/dbus-broker/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # The MESON_* variables are passed to meson to build dbus-broker itself and the original # variables are used to build the fuzz target without meson to make the script compatible # with fuzz-introspector. Once the fuzz target is built with meson as well the MESON_* # variables can be safely removed and CFLAGS/CXXFLAGS/LDFLAGS can be tweaked directly # instead: https://github.com/google/oss-fuzz/pull/7583#issuecomment-1104011067 MESON_CFLAGS=${CFLAGS:-} MESON_CXXFLAGS=${CXXFLAGS:-} MESON_LDFLAGS=${LDFLAGS:-} if [[ "$SANITIZER" == introspector ]]; then MESON_CFLAGS="${MESON_CFLAGS//-fuse-ld=gold/ }" MESON_CXXFLAGS="${MESON_CXXFLAGS//-fuse-ld=gold/ }" MESON_LDFLAGS="${MESON_LDFLAGS//-fuse-ld=gold/ }" MESON_LDFLAGS+=" -flto" export CC_LD=gold export CXX_LD=gold fi apt-get update -y apt-get install -y libclang-dev if [[ "$ARCHITECTURE" == i386 ]]; then apt-get install -y pkg-config:i386 RUST_TARGET=i686-unknown-linux-gnu rustup target add "$RUST_TARGET" export RUSTC="rustc --target=$RUST_TARGET" export BINDGEN_EXTRA_CLANG_ARGS="--target=$RUST_TARGET" else apt-get install -y pkg-config fi if [[ "$SANITIZER" == undefined ]]; then additional_ubsan_checks=alignment UBSAN_FLAGS="-fsanitize=$additional_ubsan_checks -fno-sanitize-recover=$additional_ubsan_checks" CFLAGS+=" $UBSAN_FLAGS" CXXFLAGS+=" $UBSAN_FLAGS" MESON_CFLAGS+=" $UBSAN_FLAGS" MESON_CXXFLAGS+=" $UBSAN_FLAGS" fi pip3 install meson ninja if ! CFLAGS="$MESON_CFLAGS" CXXFLAGS="$MESON_CXXFLAGS" LDFLAGS="$MESON_LDFLAGS" meson -Db_lundef=false -Dlauncher=false build; then cat build/meson-logs/meson-log.txt exit 1 fi ninja -C ./build -v $CC $CFLAGS -c -o fuzz-message.o -Isrc -I subprojects/libcstdaux-*/src -std=c11 -D_GNU_SOURCE "$SRC/fuzz-message.c" $CXX $CXXFLAGS -o "$OUT/fuzz-message" \ fuzz-message.o \ build/src/libbus-static.a \ build/subprojects/libcdvar-*/src/libcdvar-*.a \ build/subprojects/libcutf8-*/src/libcutf8-*.a \ $LIB_FUZZING_ENGINE ================================================ FILE: projects/dbus-broker/fuzz-message.c ================================================ /* # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # */ #include #include #include "dbus/message.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { _c_cleanup_(message_unrefp) Message *message = NULL; MessageHeader *header = (void *)data; int r; if (size < sizeof(MessageHeader)) return 0; r = message_new_incoming(&message, *header); if (r != 0) return 0; if (message->n_data > size) return 0; memcpy(message->data + sizeof(*header), data + sizeof(*header), message->n_data - sizeof(*header)); r = message_parse_metadata(message); if (r) return 0; message_stitch_sender(message, 1); return 0; } ================================================ FILE: projects/dbus-broker/project.yaml ================================================ homepage: "https://github.com/bus1/dbus-broker" language: c primary_contact: "david.rheinsberg@gmail.com" builds_per_day: 4 sanitizers: - address - undefined - memory auto_ccs: - evverx@gmail.com - fsumsal@redhat.com main_repo: "https://github.com/bus1/dbus-broker" architectures: - x86_64 - i386 file_github_issue: True fuzzing_engines: - afl - honggfuzz - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/dcmtk/Dockerfile ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y --no-install-recommends cmake ninja-build make pkg-config zlib1g-dev python3 && rm -rf /var/lib/apt/lists/* RUN git clone --depth 1 https://github.com/DCMTK/dcmtk $SRC/dcmtk RUN git clone --depth 1 https://github.com/DCMTK/dcmtk-fuzzers $SRC/dcmtk-fuzzers COPY build.sh $SRC/ COPY dcmtk_dicom_fuzzer.dict make_seed_corpus.py $SRC/dcmtk-fuzzers/ COPY dcmtk_dicom_fuzzer.cc dcmtk_meta_fuzzer.cc $SRC/dcmtk-fuzzers/ WORKDIR $SRC/dcmtk-fuzzers ================================================ FILE: projects/dcmtk/build.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FUZZERS=( dcmtk_dicom_fuzzer dcmtk_meta_fuzzer ) # Build DCMTK (static) with iconv enabled so liboficonv is present. cd "$SRC" cmake -S dcmtk -B dcmtk-build \ -DBUILD_SHARED_LIBS=OFF \ -DDCMTK_WITH_OPENSSL=OFF \ -DDCMTK_WITH_PNG=OFF \ -DDCMTK_WITH_TIFF=OFF \ -DDCMTK_WITH_XML=OFF \ -DDCMTK_WITH_ICONV=ON \ -DDCMTK_WITH_ZLIB=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX="$WORK/dcmtk-install" cmake --build dcmtk-build -j"$(nproc)" cmake --install dcmtk-build # Ship the DICOM dictionary (for cleaner logs at runtime). DICT_SRC=$(ls "$WORK"/dcmtk-install/share/dcmtk-*/dicom.dic 2>/dev/null || true) if [ -n "$DICT_SRC" ]; then cp "$DICT_SRC" "$OUT/dicom.dic" || true fi cd "$SRC/dcmtk-fuzzers" DCMTK_INC="$WORK/dcmtk-install/include" DCMTK_LIBDIR="$WORK/dcmtk-install/lib" # Derive robust link set from pkg-config and filter to installed libs. export PKG_CONFIG_PATH="$DCMTK_LIBDIR/pkgconfig:${PKG_CONFIG_PATH:-}" RAW_LIBS="$(pkg-config --static --libs dcmtk 2>/dev/null || true)" FILTERED_LIBS="" for tok in $RAW_LIBS; do # Keep every token: -L paths, -l libs (both DCMTK and system ones like -lz) FILTERED_LIBS+=" $tok" done [ -z "$FILTERED_LIBS" ] && FILTERED_LIBS="-ldcmdata -loflog -lofstd -loficonv -lz" DCMTK_LIBS="-Wl,--start-group ${FILTERED_LIBS} -Wl,--end-group -lpthread -ldl" build_one() { local src="$1" local out="$2" "$CXX" $CXXFLAGS -std=c++17 -I"$DCMTK_INC" \ "$src" -o "$OUT/$out" \ $LIB_FUZZING_ENGINE -L"$DCMTK_LIBDIR" ${DCMTK_LIBS} } for fz in "${FUZZERS[@]}"; do echo "Building $fz..." build_one "${fz}.cc" "$fz" done # .options: use *relative* dictionary path so check_build works after files are copied. cat > "$OUT/dcmtk_dicom_fuzzer.options" << 'EOF' [libfuzzer] max_len = 131072 timeout = 25 rss_limit_mb = 2560 dict = dcmtk_dicom_fuzzer.dict EOF cat > "$OUT/dcmtk_meta_fuzzer.options" << 'EOF' [libfuzzer] max_len = 65536 timeout = 25 rss_limit_mb = 2560 dict = dcmtk_dicom_fuzzer.dict EOF # Seed corpus next to binaries python3 "$SRC/dcmtk-fuzzers/make_seed_corpus.py" # Copy dictionary next to binaries under both names (defensive) cp "$SRC/dcmtk-fuzzers/dcmtk_dicom_fuzzer.dict" "$OUT/dcmtk_dicom_fuzzer.dict" || true cp "$SRC/dcmtk-fuzzers/dcmtk_dicom_fuzzer.dict" "$OUT/dcmtk_meta_fuzzer.dict" || true ================================================ FILE: projects/dcmtk/dcmtk_dicom_fuzzer.cc ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "dcmtk/dcmdata/dctk.h" #include "dcmtk/dcmdata/dcistrmb.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcxfer.h" static constexpr std::size_t kNewNothrowCap = 8 * 1024 * 1024; void* operator new(std::size_t n, const std::nothrow_t&) noexcept { if (n > kNewNothrowCap) return nullptr; try { return ::operator new(n); } catch (...) { return nullptr; } } void* operator new[](std::size_t n, const std::nothrow_t&) noexcept { if (n > kNewNothrowCap) return nullptr; try { return ::operator new[](n); } catch (...) { return nullptr; } } static void walkDataset(DcmItem* item) { if (!item) return; DcmStack stack; if (item->nextObject(stack, OFTrue).good()) { do { DcmObject* obj = stack.top(); if (!obj) break; (void)obj->ident(); (void)obj->getTag(); } while (item->nextObject(stack, OFFalse).good()); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static bool dict_set = (setenv("DCMDICTPATH", "/out/dicom.dic", 0), true); (void)dict_set; DcmInputBufferStream in; in.setBuffer((void*)data, size); in.setEos(); DcmFileFormat file; const Uint32 kMaxReadLen = 256 * 1024; if (file.read(in, EXS_Unknown, EGL_noChange, kMaxReadLen).good()) { if (auto* ds = file.getDataset()) { (void)ds->chooseRepresentation(EXS_LittleEndianExplicit, nullptr); (void)ds->calcElementLength(EXS_LittleEndianExplicit, EET_ExplicitLength); OFString s; (void)ds->findAndGetOFString(DCM_PatientName, s); (void)ds->findAndGetOFString(DCM_StudyInstanceUID, s); (void)ds->findAndGetOFString(DCM_SOPClassUID, s); walkDataset(ds); } } return 0; } ================================================ FILE: projects/dcmtk/dcmtk_dicom_fuzzer.dict ================================================ "DICM" "AE" "AS" "AT" "CS" "DA" "DS" "DT" "FL" "FD" "IS" "LO" "LT" "OB" "OD" "OF" "OL" "OW" "PN" "SH" "SL" "SQ" "SS" "ST" "TM" "UC" "UI" "UL" "UN" "UR" "US" "UT" "ISO_IR 100" "ISO_IR 192" "ISO 2022 IR 87" "ISO 2022 IR 149" "1.2.840.10008.1.2" "1.2.840.10008.1.2.1" "1.2.840.10008.1.2.2" "1.2.840.10008.5.1.4.1.1.2" "1.2.840.10008.5.1.4.1.1.4" "1.2.840.10008.5.1.4.1.1.128" "\xFE\xFF\x00\xE0" "\xFE\xFF\x0D\xE0" "\xFE\xFF\xDD\xE0" ================================================ FILE: projects/dcmtk/dcmtk_meta_fuzzer.cc ================================================ // Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// #include #include #include #include "dcmtk/dcmdata/dcmetinf.h" #include "dcmtk/dcmdata/dcistrmb.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcxfer.h" static constexpr std::size_t kNewCap = 2 * 1024 * 1024; void* operator new(std::size_t n, const std::nothrow_t&) noexcept { if (n > kNewCap) return nullptr; try { return ::operator new(n); } catch (...) { return nullptr; } } void* operator new[](std::size_t n, const std::nothrow_t&) noexcept { if (n > kNewCap) return nullptr; try { return ::operator new[](n); } catch (...) { return nullptr; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { DcmInputBufferStream in; in.setBuffer((void*)data, size); in.setEos(); DcmMetaInfo mi; const Uint32 kMaxReadLen = 128 * 1024; if (mi.read(in, EXS_LittleEndianExplicit, EGL_noChange, kMaxReadLen).good()) { OFString s; (void)mi.findAndGetOFString(DCM_TransferSyntaxUID, s); (void)mi.findAndGetOFString(DCM_SourceApplicationEntityTitle, s); } return 0; } ================================================ FILE: projects/dcmtk/make_seed_corpus.py ================================================ ################################################################################## ## Copyright 2026 Google LLC ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## you may not use this file except in compliance with the License. ## You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## See the License for the specific language governing permissions and ## limitations under the License. ## ################################################################################## #!/usr/bin/env python3 import struct, os, zipfile, io def u16(x, be=False): return struct.pack('>H' if be else 'I' if be else ' bytes: if vr == b'UI': b = s.encode('ascii') if len(b) % 2: b += b'\x00' else: b = s.encode(text_enc, 'replace') if len(b) % 2: b += b' ' return b def el_explicit(g,e,vr,val,be=False): if isinstance(vr, str): vr = vr.encode('ascii') out = io.BytesIO() out.write(u16(g,be)); out.write(u16(e,be)) out.write(vr) if vr in LONG_VR: out.write(b'\x00\x00'); out.write(u32(len(val), be)); out.write(val) else: out.write(u16(len(val), be)); out.write(val) return out.getvalue() def el_implicit(g,e,val,be=False): out = io.BytesIO() out.write(u16(g,be)); out.write(u16(e,be)) out.write(u32(len(val), be)); out.write(val) return out.getvalue() def item_defined(payload, be=False): return u16(0xFFFE,be) + u16(0xE000,be) + u32(len(payload),be) + payload def item_undef(payload, be=False): return (u16(0xFFFE,be) + u16(0xE000,be) + u32(0xFFFFFFFF,be) + payload + u16(0xFFFE,be) + u16(0xE00D,be) + u32(0,be)) def seq_defined_explicit(g,e,items, be=False): body = b''.join(item_defined(p, be) for p in items) return el_explicit(g,e,b'SQ', body, be) def seq_undef_explicit(g,e,items, be=False): body = b''.join(item_undef(p, be) for p in items) + (u16(0xFFFE,be)+u16(0xE0DD,be)+u32(0,be)) hdr = u16(g,be)+u16(e,be)+b'SQ'+b'\x00\x00'+u32(0xFFFFFFFF,be) return hdr + body def seq_defined_implicit(g,e,items, be=False): body = b''.join(item_defined(p, be) for p in items) return el_implicit(g,e, body, be) def seq_undef_implicit(g,e,items, be=False): body = b''.join(item_undef(p, be) for p in items) + (u16(0xFFFE,be)+u16(0xE0DD,be)+u32(0,be)) return u16(g,be)+u16(e,be)+u32(0xFFFFFFFF,be)+body def meta_group(ts_uid: str, with_gl=True): parts = [] parts.append(el_explicit(0x0002,0x0001,b'OB', b'\x00\x01', be=False)) parts.append(el_explicit(0x0002,0x0002,b'UI', pad(b'UI','1.2.840.10008.5.1.4.1.1.2'), be=False)) parts.append(el_explicit(0x0002,0x0003,b'UI', pad(b'UI','1.2.826.0.1.3680043.8.498.1000001'), be=False)) parts.append(el_explicit(0x0002,0x0010,b'UI', pad(b'UI', ts_uid), be=False)) parts.append(el_explicit(0x0002,0x0012,b'UI', pad(b'UI','1.2.826.0.1.3680043.8.498.1'), be=False)) parts.append(el_explicit(0x0002,0x0016,b'AE', pad(b'AE','FUZZ'), be=False)) body = b''.join(parts) if not with_gl: return body gl = el_explicit(0x0002,0x0000,b'UL', struct.pack(' register.go go mod tidy compile_native_go_fuzzer github.com/ianlancetaylor/demangle FuzzTest FuzzTest ================================================ FILE: projects/demangle/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package demangle import ( "testing" ) func FuzzTest(f *testing.F) { f.Fuzz(func(t *testing.T, data string) { _, _ = ToString(data) }) } ================================================ FILE: projects/demangle/project.yaml ================================================ homepage: "https://github.com/ianlancetaylor/demangle" language: go main_repo: "https://github.com/ianlancetaylor/demangle" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/deno/Dockerfile ================================================ # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && \ apt-get install --no-install-recommends -y \ cmake protobuf-compiler pkg-config python3 libclang-dev \ libdbus-1-dev lld ENV RUSTUP_TOOLCHAIN nightly-2025-12-15 RUN rustup install $RUSTUP_TOOLCHAIN RUN rustup component add rust-src --toolchain $RUSTUP_TOOLCHAIN RUN git clone --depth 1 https://github.com/denoland/deno $SRC/deno WORKDIR $SRC/deno COPY build.sh $SRC/ ================================================ FILE: projects/deno/build.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/deno export CARGO_INCREMENTAL=0 # Strip sanitizer and coverage flags from C/C++ compiler flags. # The Rust compiler handles sanitizer instrumentation via RUSTFLAGS. export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only" export CXXFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -stdlib=libc++" # Deno uses --export-dynamic-symbol-list which requires lld export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-fuse-ld=lld" cargo build --release --target x86_64-unknown-linux-gnu -j$(($(nproc) / 8)) cp target/x86_64-unknown-linux-gnu/release/deno $OUT/ ================================================ FILE: projects/deno/project.yaml ================================================ homepage: "https://github.com/denoland/deno" language: rust main_repo: "https://github.com/denoland/deno" fuzzing_engines: - none sanitizers: - address indexer: targets: - deno vendor_ccs: - david@adalogics.com ================================================ FILE: projects/dgraph/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN wget https://go.dev/dl/go1.24.3.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.24.3.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.24.3.linux-amd64.tar.gz RUN git clone --depth 1 https://github.com/dgraph-io/dgraph COPY build.sh fuzz_parser_test.go $SRC/ WORKDIR $SRC/dgraph ================================================ FILE: projects/dgraph/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/fuzz_parser_test.go $SRC/dgraph/dql/ printf "package dql\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > dql/register.go go mod tidy compile_native_go_fuzzer github.com/dgraph-io/dgraph/v25/dql FuzzParserTest parser_fuzzer ================================================ FILE: projects/dgraph/fuzz_parser_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package dql import ( "testing" ) func FuzzParserTest(f *testing.F) { f.Fuzz(func(t *testing.T, in []byte) { _, _ = Parse(Request{Str: string(in)}) }) } ================================================ FILE: projects/dgraph/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://dgraph.io" main_repo: "https://github.com/dgraph-io/dgraph" primary_contact: "security@hypermode.com" auto_ccs : - "harshil@hypermode.com" - "ryan@hypermode.com" - "aman@hypermode.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/digest/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/bmc/digest digest WORKDIR digest COPY build.sh *.py $SRC/ ================================================ FILE: projects/digest/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/digest/fuzz_digest.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import io import digest def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) alg = fdp.ConsumeUnicodeNoSurrogates(15) b1 = fdp.ConsumeBytes(sys.maxsize) try: s1 = digest.digest(io.BytesIO(b1), alg, len(b1)) except SystemExit: pass except TypeError as e: if "name must be a string" in str(e): # non-interesting bug. Let the fuzzer continue pass else: raise e def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/digest/project.yaml ================================================ base_os_version: ubuntu-24-04 fuzzing_engines: - libfuzzer homepage: https://github.com/bmc/digest language: python main_repo: https://github.com/bmc/digest sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/dill/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Held back because of github.com/google/oss-fuzz/pull/13407 # Please fix the build failure + upgrade. FROM gcr.io/oss-fuzz-base/base-builder-python@sha256:d223a882810372830fd7968eb3e64533f3a2318c90be43ac753a46a15946faec RUN pip3 install --upgrade pip RUN git clone https://github.com/uqfoundation/dill dill COPY *.sh *py $SRC/ WORKDIR $SRC/dill ================================================ FILE: projects/dill/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/dill/fuzz_dumps.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from dill import dumps, loads def TestOneInput(data): # Anything loadable should be dumpable try: dilled = loads(data) except: return try: dumps(dilled) except RecursionError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/dill/project.yaml ================================================ homepage: https://github.com/uqfoundation/dill main_repo: https://github.com/uqfoundation/dill language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/distlib/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/pypa/distlib distlib COPY *.sh *py $SRC/ WORKDIR $SRC/distlib ================================================ FILE: projects/distlib/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/distlib/fuzz_marker.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from distlib.markers import interpret def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: interpret(fdp.ConsumeUnicodeNoSurrogates(1024)) except SyntaxError: return def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/distlib/fuzz_metadata.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from distlib import DistlibException from distlib.compat import StringIO from distlib.metadata import (LegacyMetadata, Metadata) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: metadata = LegacyMetadata() metadata.read_file(StringIO(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)))) except ValueError: # ValueErrors are raised varies places, e.g. # https://github.com/pypa/distlib/blob/05375908c1b2d6b0e74bdeb574569d3609db9f56/distlib/version.py#L106 pass except SyntaxError: pass try: metadata = Metadata(fileobj=StringIO(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)))) except ValueError: # ValueErrors are raised varies places, e.g. # https://github.com/pypa/distlib/blob/05375908c1b2d6b0e74bdeb574569d3609db9f56/distlib/version.py#L106 pass except SyntaxError: pass except DistlibException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/distlib/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pypa/distlib language: python main_repo: https://github.com/pypa/distlib sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/distribution/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/distribution/distribution RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN git clone --depth 1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=november-backup RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.23.4.linux-amd64.tar.gz COPY build.sh $SRC/ WORKDIR $SRC/distribution ================================================ FILE: projects/distribution/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/distribution/build.sh ================================================ FILE: projects/distribution/project.yaml ================================================ homepage: "https://github.com/distribution/distribution" main_repo: "https://github.com/distribution/distribution" primary_contact: "cncf-distribution-security@lists.cncf.io" auto_ccs : - "adam@adalogics.com" - "david@adalogics.com" - "chrispat@github.com" - "clarkbw@github.com" - "csnider@mirantis.com" - "hswimelar@gitlab.com" - "hweiwei@vmware.com" - "jpereira@gitlab.com" - "justin.cormack@docker.com" - "ksquizzato@mirantis.com" - "milos.gajdos@docker.com" - "sargun@sargun.me" - "wwarren@digitalocean.com" - "wangyan@vmware.com" - "steve.lasker@microsoft.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/django/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python # Install dependencies for building Python from source RUN apt-get update && apt-get install -y \ build-essential \ zlib1g-dev \ libncurses5-dev \ libgdbm-dev \ libnss3-dev \ libssl-dev \ libreadline-dev \ libffi-dev \ libsqlite3-dev \ libbz2-dev \ liblzma-dev \ && rm -rf /var/lib/apt/lists/* # Build and install Python 3.12 from source (Django main branch requires Python 3.12+) RUN cd /tmp && \ curl -O https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tgz && \ tar -xzf Python-3.12.12.tgz && \ cd Python-3.12.12 && \ ./configure --enable-optimizations --enable-shared --prefix=/usr/local/python3.12 && \ make -j$(nproc) && \ make install && \ rm -rf /tmp/Python-3.12.12* # Add Python 3.12 libs to LD_LIBRARY_PATH ENV LD_LIBRARY_PATH="/usr/local/python3.12/lib:$LD_LIBRARY_PATH" # Create symlinks for python3.12 RUN ln -sf /usr/local/python3.12/bin/python3.12 /usr/local/bin/python3.12 && \ ln -sf /usr/local/python3.12/bin/pip3.12 /usr/local/bin/pip3.12 RUN python3.12 -m pip install --upgrade pip cython RUN git clone --depth 1 https://github.com/django/django.git RUN git clone --depth 1 https://github.com/django/django-fuzzers.git COPY build.sh $SRC/ WORKDIR $SRC/django ================================================ FILE: projects/django/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Make Python 3.12 the default python3 for this build export PATH="/usr/local/python3.12/bin:$PATH" export LD_LIBRARY_PATH="/usr/local/python3.12/lib:$LD_LIBRARY_PATH" ln -sf /usr/local/python3.12/bin/python3.12 /usr/local/bin/python3 ln -sf /usr/local/python3.12/bin/pip3.12 /usr/local/bin/pip3 # Install atheris and pyinstaller for Python 3.12 python3 -m pip install atheris pyinstaller # Build and install project (using current CFLAGS, CXXFLAGS). This is required # for projects with C extensions so that they're built with the proper flags. python3 -m pip install . export DJANGO_SETTINGS_MODULE=fuzzer_project.settings # Build fuzzers into $OUT. These could be detected in other ways. for fuzzer in $(find $SRC -name '*_fuzzer.py'); do compile_python_fuzzer $fuzzer --add-data django/conf/locale/en/LC_MESSAGES:django/conf/locale/en/LC_MESSAGES done ================================================ FILE: projects/django/project.yaml ================================================ auto_ccs: - jammamarkus@gmail.com - guidovranken@gmail.com - info+django+security@markusholtermann.eu - jacobtylerwalls@gmail.com fuzzing_engines: - libfuzzer homepage: https://www.djangoproject.com/ language: python main_repo: https://github.com/django/django.git primary_contact: f.apolloner@gmail.com sanitizers: - address - undefined ================================================ FILE: projects/dlplibs/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 # install build requirements RUN apt-get update && \ apt-get install -y wget xz-utils autoconf automake libtool pkg-config \ gperf libglm-dev patch libboost-dev ADD https://dev-www.libreoffice.org/src/lcms2-2.8.tar.gz \ https://dev-www.libreoffice.org/src/zlib-1.2.11.tar.xz \ https://dev-www.libreoffice.org/src/libpng-1.6.34.tar.xz \ https://dev-www.libreoffice.org/src/libxml2-2.9.7.tar.gz \ https://dev-www.libreoffice.org/src/icu4c-60_2-src.tgz \ https://dev-www.libreoffice.org/src/mdds-1.3.1.tar.bz2 \ $SRC/ # download fuzzing corpora ADD https://dev-www.libreoffice.org/corpus/olefuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/pubfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/zipfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/cdrfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/vsdfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/zmffuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/pmdfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/fhfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/cmxfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/sdcfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/bmifuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/abwfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/sdafuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/sddfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/sdwfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/key6fuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/vsdxfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/vdxfuzzer_seed_corpus.zip \ https://dev-www.libreoffice.org/corpus/qxpfuzzer_seed_corpus.zip \ $SRC/ RUN wget -q --show-progress --progress=bar:force \ https://sourceforge.net/projects/libwpd/files/corpus/wpdfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwpg/files/corpus/wpgfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/wpsfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/actafuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libebook/files/corpus/lrffuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/wksfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/wdbfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/docfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/wrifuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/powerpointfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/mswrdfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/mswksfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/123fuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/wqfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libebook/files/corpus/pdbfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/beaglewksfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/clariswksfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/greatwksfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/applepictfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/clarisdrawfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/cricketdrawfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/freehandfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/macdraftfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/macdrawfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/macpaintfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/pixelpaintfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/superpaintfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/wingzfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/docmkrfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/edocfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/fullwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/hanmacwrdfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/lightwaytxtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/macdocfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/macwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/marinerwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/maxwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/mindwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/morefuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/mousewrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/nisuswrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/ragtimefuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/stylefuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/teachtxtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/writenowfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/writerplsfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/zwrtfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libmwaw/files/corpus/multiplanfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libwps/files/corpus/mpfuzzer_seed_corpus.zip \ https://sourceforge.net/projects/libebook/files/corpus/fb2fuzzer_seed_corpus.zip \ -P $SRC # clone sources RUN git clone --depth 1 git://git.code.sf.net/p/libwpd/librevenge RUN git clone --depth 1 git://gerrit.libreoffice.org/libmspub RUN git clone --depth 1 git://gerrit.libreoffice.org/libcdr RUN git clone --depth 1 git://gerrit.libreoffice.org/libvisio RUN git clone --depth 1 git://gerrit.libreoffice.org/libzmf RUN git clone --depth 1 git://gerrit.libreoffice.org/libpagemaker RUN git clone --depth 1 git://gerrit.libreoffice.org/libfreehand RUN git clone --depth 1 git://git.code.sf.net/p/libwpd/code libwpd RUN git clone --depth 1 git://git.code.sf.net/p/libwpg/code libwpg RUN git clone --depth 1 https://github.com/fosnola/libstaroffice RUN git clone --depth 1 git://git.code.sf.net/p/libwps/code libwps RUN git clone --depth 1 git://git.code.sf.net/p/libmwaw/libmwaw RUN git clone --depth 1 git://git.code.sf.net/p/libebook/code libe-book RUN git clone --depth 1 git://gerrit.libreoffice.org/libabw RUN git clone --depth 1 git://gerrit.libreoffice.org/libetonyek RUN git clone --depth 1 git://gerrit.libreoffice.org/libqxp WORKDIR $SRC COPY build.sh *.options *.patch $SRC/ ================================================ FILE: projects/dlplibs/abwfuzzer.options ================================================ [libfuzzer] dict = abw.dict ================================================ FILE: projects/dlplibs/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Suppress C++17 errors from old dependency headers (lcms2 uses 'register') export CXXFLAGS="$CXXFLAGS -Wno-register" tar -xJf $SRC/zlib-1.2.11.tar.xz pushd zlib-1.2.11 ./configure --static make -j$(nproc) export ZLIB_CFLAGS="-I$(pwd)" export ZLIB_LIBS="-L$(pwd) -lz" popd tar -xzf $SRC/lcms2-2.8.tar.gz pushd lcms2-2.8 ./configure --disable-shared --enable-static --without-jpeg --without-tiff make -C src -j$(nproc) export LCMS2_CFLAGS="-I$(pwd)/include" export LCMS2_LIBS="-L$(pwd)/src -llcms2" popd tar -xJf $SRC/libpng-1.6.34.tar.xz pushd libpng-1.6.34 ./configure --disable-shared --enable-static CPPFLAGS="$ZLIB_CFLAGS" LDFLAGS="$ZLIB_LIBS" make -j$(nproc) export LIBPNG_CFLAGS="-I$(pwd)" export LIBPNG_LIBS="-L$(pwd) -lpng16" popd tar -xzf $SRC/libxml2-2.9.7.tar.gz pushd libxml2-2.9.7 ./configure --disable-shared --enable-static --disable-ipv6 --without-python --without-zlib --without-lzma make -j$(nproc) export LIBXML_CFLAGS="-I$(pwd)/include" export LIBXML_LIBS="-L$(pwd) -lxml2" export XML_CFLAGS="$LIBXML_CFLAGS" export XML_LIBS="$LIBXML_LIBS" popd tar -xzf $SRC/icu4c-60_2-src.tgz pushd icu/source patch -p2 < $SRC/icu4c-ubsan.patch patch -p3 < $SRC/ofz3670.patch patch -p3 < $SRC/ofz4860.patch ./configure --disable-shared --enable-static --with-data-packaging=static --disable-dyload --disable-strict \ --disable-layout --disable-samples --disable-extras --disable-icuio --disable-plugins \ CPPFLAGS=-DU_USE_STRTOD_L=0 make -j$(nproc) export ICU_CFLAGS="-I$(pwd) -I$(pwd)/i18n -I$(pwd)/common" export ICU_LIBS="-L$(pwd)/lib -licui18n -licuuc -licudata" popd # System boost from libboost-dev package is used (headers in /usr/include/boost/) tar -xjf $SRC/mdds-1.3.1.tar.bz2 pushd mdds-1.3.1 ./configure export MDDS_CFLAGS="-I$(pwd)/include" export MDDS_LIBS=' ' popd pushd librevenge ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tests --enable-fuzzers make -j$(nproc) rvnginc=$(pwd)/inc rvnglib=$(pwd)/src/lib export REVENGE_CFLAGS="-I$(pwd)/inc" export REVENGE_LIBS="-L$(pwd)/src/lib -lrevenge-0.0" export REVENGE_STREAM_CFLAGS="-I$(pwd)/inc" export REVENGE_STREAM_LIBS="-L$(pwd)/src/lib -lrevenge-stream-0.0" export REVENGE_GENERATORS_CFLAGS="-I$(pwd)/inc" export REVENGE_GENERATORS_LIBS="-L$(pwd)/src/lib -lrevenge-generators-0.0" popd pushd libmspub ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libcdr ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers --disable-tests make -j$(nproc) popd pushd libvisio ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers --disable-tests make -j$(nproc) popd pushd libzmf ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers --disable-tests make -j$(nproc) popd pushd libpagemaker ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libfreehand ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers --disable-tests make -j$(nproc) popd pushd libwpd ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) export WPD_CFLAGS=-I$(pwd)/inc export WPD_LIBS="-L$(pwd)/src/lib -lwpd-0.10" popd pushd libwpg ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libstaroffice ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libwps ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libmwaw ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --disable-zip --enable-fuzzers make -C src/lib -j$(nproc) # Link with less parallelism to avoid memory problems on the builders make -j2 popd pushd libe-book ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static \ --without-tools --enable-fuzzers --without-liblangtag --disable-tests make -j$(nproc) popd pushd libabw ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers make -j$(nproc) popd pushd libetonyek ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static \ --without-tools --enable-fuzzers --with-mdds=0.x --without-liblangtag --disable-tests make -j$(nproc) popd pushd libqxp ./autogen.sh ./configure --without-docs --disable-werror --disable-shared --enable-static --disable-tools --enable-fuzzers --disable-tests make -j$(nproc) popd cp */src/fuzz/*fuzzer $OUT cp */src/fuzz/*.dict $OUT cp *_seed_corpus.zip $OUT cp *.options $OUT ================================================ FILE: projects/dlplibs/fb2fuzzer.options ================================================ [libfuzzer] dict = fb2.dict ================================================ FILE: projects/dlplibs/icu4c-ubsan.patch ================================================ diff -ur icu.org/source/common/rbbidata.h icu/source/common/rbbidata.h --- icu.org/source/common/rbbidata.h 2017-02-03 19:57:23.000000000 +0100 +++ icu/source/common/rbbidata.h 2017-04-21 22:46:25.371651160 +0200 @@ -115,7 +115,7 @@ /* StatusTable of the set of matching */ /* tags (rule status values) */ int16_t fReserved; - uint16_t fNextState[2]; /* Next State, indexed by char category. */ + uint16_t fNextState[1]; /* Next State, indexed by char category. */ /* This array does not have two elements */ /* Array Size is actually fData->fHeader->fCatCount */ /* CAUTION: see RBBITableBuilder::getTableSize() */ @@ -128,7 +128,7 @@ uint32_t fRowLen; /* Length of a state table row, in bytes. */ uint32_t fFlags; /* Option Flags for this state table */ uint32_t fReserved; /* reserved */ - char fTableData[4]; /* First RBBIStateTableRow begins here. */ + char fTableData[1]; /* First RBBIStateTableRow begins here. */ /* (making it char[] simplifies ugly address */ /* arithmetic for indexing variable length rows.) */ }; diff -ur icu.org/source/common/rbbitblb.cpp icu/source/common/rbbitblb.cpp --- icu.org/source/common/rbbitblb.cpp 2017-01-20 01:20:31.000000000 +0100 +++ icu/source/common/rbbitblb.cpp 2017-04-21 22:46:25.373651159 +0200 @@ -1095,15 +1095,15 @@ return 0; } - size = sizeof(RBBIStateTable) - 4; // The header, with no rows to the table. + size = offsetof(RBBIStateTable, fTableData); // The header, with no rows to the table. numRows = fDStates->size(); numCols = fRB->fSetBuilder->getNumCharCategories(); - // Note The declaration of RBBIStateTableRow is for a table of two columns. - // Therefore we subtract two from numCols when determining + // Note The declaration of RBBIStateTableRow is for a table of one columns. + // Therefore we subtract one from numCols when determining // how much storage to add to a row for the total columns. - rowSize = sizeof(RBBIStateTableRow) + sizeof(uint16_t)*(numCols-2); + rowSize = sizeof(RBBIStateTableRow) + sizeof(uint16_t)*(numCols-1); size += numRows * rowSize; return size; } @@ -1133,7 +1133,7 @@ } table->fRowLen = sizeof(RBBIStateTableRow) + - sizeof(uint16_t) * (fRB->fSetBuilder->getNumCharCategories() - 2); + sizeof(uint16_t) * (fRB->fSetBuilder->getNumCharCategories() - 1); table->fNumStates = fDStates->size(); table->fFlags = 0; if (fRB->fLookAheadHardBreak) { diff -ur icu.org/source/common/ubidiimp.h icu/source/common/ubidiimp.h --- icu.org/source/common/ubidiimp.h 2017-02-03 19:57:23.000000000 +0100 +++ icu/source/common/ubidiimp.h 2017-04-21 22:46:25.374651159 +0200 @@ -198,8 +198,8 @@ /* in a Run, logicalStart will get this bit set if the run level is odd */ #define INDEX_ODD_BIT (1UL<<31) -#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)(level)<<31)) -#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)(level)<<31)) +#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((uint32_t)(level)<<31)) +#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((uint32_t)(level)<<31)) #define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT) #define GET_INDEX(x) ((x)&~INDEX_ODD_BIT) diff -ur icu.org/source/common/ucmndata.cpp icu/source/common/ucmndata.cpp --- icu.org/source/common/ucmndata.cpp 2017-03-08 16:34:47.000000000 +0100 +++ icu/source/common/ucmndata.cpp 2017-04-21 22:46:25.376651159 +0200 @@ -77,7 +77,7 @@ typedef struct { uint32_t count; uint32_t reserved; - PointerTOCEntry entry[2]; /* Actual size is from count. */ + PointerTOCEntry entry[1]; /* Actual size is from count. */ } PointerTOC; diff -ur icu.org/source/common/ucmndata.h icu/source/common/ucmndata.h --- icu.org/source/common/ucmndata.h 2017-01-20 01:20:31.000000000 +0100 +++ icu/source/common/ucmndata.h 2017-04-21 22:46:25.377651159 +0200 @@ -52,7 +52,7 @@ typedef struct { uint32_t count; - UDataOffsetTOCEntry entry[2]; /* Actual size of array is from count. */ + UDataOffsetTOCEntry entry[1]; /* Actual size of array is from count. */ } UDataOffsetTOC; /** ================================================ FILE: projects/dlplibs/ofz2894.patch ================================================ From 3d8a80c4f3470fea0169f6774320e61619bac52b Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 2 Oct 2017 16:22:36 +0200 Subject: [PATCH] ofz#2894 avoid signed integer overflow /usr/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp:86:48: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself --- include/boost/spirit/home/qi/numeric/detail/real_impl.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp b/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp index 9aa5bb8bb..3e7ab18a9 100644 --- a/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp +++ b/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp @@ -81,12 +81,13 @@ namespace boost { namespace spirit { namespace traits detail::compensate_roundoff(n, acc_n); n /= pow10(-min_exp); - // return false if (-exp + min_exp) exceeds the -min_exp + // return false if exp still exceeds the min_exp // do this check only for primitive types! - if (is_floating_point() && (-exp + min_exp) > -min_exp) + exp += -min_exp; + if (is_floating_point() && exp < min_exp) return false; - n /= pow10(-exp + min_exp); + n /= pow10(-exp); } else { -- 2.14.1 ================================================ FILE: projects/dlplibs/ofz3670.patch ================================================ From b0537ec9a7047d55d365a64e9ec9559cf1f28792 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Mon, 13 Nov 2017 16:56:23 +0100 Subject: [PATCH] avoid target buffer overflow --- icu4c/source/common/ucnv_u8.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/icu4c/source/common/ucnv_u8.cpp b/icu4c/source/common/ucnv_u8.cpp index 951988ed9..caaf18ae3 100644 --- a/icu4c/source/common/ucnv_u8.cpp +++ b/icu4c/source/common/ucnv_u8.cpp @@ -770,6 +770,11 @@ ucnv_UTF8FromUTF8(UConverterFromUnicodeArgs *pFromUArgs, oldToULength=0; toULength=1; toULimit=U8_COUNT_BYTES_NON_ASCII(b); + if (toULimit > (const uint8_t *)pFromUArgs->targetLimit - target) + { + *pErrorCode = U_BUFFER_OVERFLOW_ERROR; + break; + } c=b; moreBytes: while(toULength Date: Sat, 18 Nov 2017 10:06:24 +0100 Subject: [PATCH] ofz#4303 avoid signed integer overflow /usr/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp:110:26: runtime error: signed integer overflow: -2147483647 - 19 cannot be represented in type 'int' --- include/boost/spirit/home/qi/numeric/detail/real_impl.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp b/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp index 3e7ab18a9..4a65bd79c 100644 --- a/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp +++ b/include/boost/spirit/home/qi/numeric/detail/real_impl.hpp @@ -108,6 +108,8 @@ namespace boost { namespace spirit { namespace traits inline bool scale(int exp, int frac, T& n, AccT acc_n) { + if (exp < std::numeric_limits::min() + frac) + return false; return scale(exp - frac, n, acc_n); } -- 2.14.3 ================================================ FILE: projects/dlplibs/ofz4860.patch ================================================ From 529ba01ee606940ca273b187be8ce9ba31cf2d90 Mon Sep 17 00:00:00 2001 From: David Tardon Date: Fri, 19 Jan 2018 10:41:02 +0100 Subject: [PATCH] ofz#4860 fix past-the-end read from array --- icu4c/source/common/locmap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icu4c/source/common/locmap.cpp b/icu4c/source/common/locmap.cpp index cbb2b810a..6d62d8310 100644 --- a/icu4c/source/common/locmap.cpp +++ b/icu4c/source/common/locmap.cpp @@ -1015,7 +1015,7 @@ static const char* getPosixID(const ILcidPosixMap *this_0, uint32_t hostID) { uint32_t i; - for (i = 0; i <= this_0->numRegions; i++) + for (i = 0; i < this_0->numRegions; i++) { if (this_0->regionMaps[i].hostID == hostID) { -- 2.14.3 ================================================ FILE: projects/dlplibs/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.documentliberation.org" language: c++ primary_contact: "dtardon@redhat.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dlplibs/vdxfuzzer.options ================================================ [libfuzzer] dict = vdx.dict ================================================ FILE: projects/dlplibs/vsdxfuzzer.options ================================================ [libfuzzer] dict = vsdx.dict ================================================ FILE: projects/dng_sdk/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake libjpeg-turbo8-dev zlib1g-dev libxmp-dev RUN git clone https://android.googlesource.com/platform/external/dng_sdk/ # For seed corpus RUN git clone --depth=1 https://github.com/ianare/exif-samples exif-samples RUN git clone --depth=1 https://github.com/image-rs/image-tiff image-tiff RUN git clone --depth=1 https://github.com/yigolden/TiffLibrary TiffLibrary COPY build.sh $SRC/ COPY *_fuzzer.cpp $SRC/ WORKDIR dng_sdk ================================================ FILE: projects/dng_sdk/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # compile source cd ./source rm dng_xmp* find . -name "*.cpp" -exec $CXX $CXXFLAGS -DqDNGUseLibJPEG=1 -DqDNGUseXMP=0 -DqDNGThreadSafe=1 -c {} \; ar cr libdns_sdk.a *.o # compile fuzzer $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ../fuzzer/dng_parser_fuzzer.cpp -o $OUT/dng_parser_fuzzer \ ./libdns_sdk.a -I./ -l:libjpeg.a -lz $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/dng_stage_fuzzer.cpp -o $OUT/dng_stage_fuzzer \ ./libdns_sdk.a -I./ -l:libjpeg.a -lz $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/dng_camera_profile_fuzzer.cpp -o $OUT/dng_camera_profile_fuzzer \ ./libdns_sdk.a -I./ -l:libjpeg.a -lz sed -i 's/main/main2/g' $SRC/dng_sdk/source/dng_validate.cpp sed -i 's/printf ("Val/\/\//g' $SRC/dng_sdk/source/dng_validate.cpp sed -i 's/static//g' $SRC/dng_sdk/source/dng_validate.cpp cat $SRC/dng_sdk/source/dng_validate.cpp $SRC/dng_validate_fuzzer.cpp >> $SRC/dng_validate_fuzzer.tmp mv $SRC/dng_validate_fuzzer.tmp $SRC/dng_validate_fuzzer.cpp $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -DqDNGValidateTarget \ $SRC/dng_sdk/source/dng_globals.cpp \ $SRC/dng_validate_fuzzer.cpp \ -o $OUT/dng_validate_fuzzer \ ./libdns_sdk.a -I./ -l:libjpeg.a -lz cat $SRC/dng_sdk/source/dng_validate.cpp $SRC/dng_fixed_validate_fuzzer.cpp >> $SRC/dng_fixed_validate_fuzzer.tmp mv $SRC/dng_fixed_validate_fuzzer.tmp $SRC/dng_fixed_validate_fuzzer.cpp $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -DqDNGValidateTarget \ $SRC/dng_sdk/source/dng_globals.cpp \ $SRC/dng_fixed_validate_fuzzer.cpp \ -o $OUT/dng_fixed_validate_fuzzer \ ./libdns_sdk.a -I./ -l:libjpeg.a -lz # Create seed corpus and distribute to fuzzers mkdir $SRC/seed_corpus cp $SRC/dng_sdk/fuzzer/seeds/CVE_2020_9589/*.dng $SRC/seed_corpus/ find $SRC/image-tiff/ -regextype sed -regex ".*\.\(pbm\|pgm\|tif\|tiff\|png\|ppm\|jpg\|exif\)" -exec cp {} $SRC/seed_corpus/ \; find $SRC/TiffLibrary/ -regextype sed -regex ".*\.\(pbm\|pgm\|tif\|tiff\|png\|ppm\|jpg\|exif\)" -exec cp {} $SRC/seed_corpus/ \; find $SRC/exif-samples/ -regextype sed -regex ".*\.\(pbm\|pgm\|tif\|tiff\|png\|ppm\|jpg\|exif\)" -exec cp {} $SRC/seed_corpus/ \; # Download a compressed JPEG wget https://upload.wikimedia.org/wikipedia/commons/b/b2/JPEG_compression_Example.jpg -O $SRC/seed_corpus/compressed_JPEG.jpg zip -r -j $OUT/dng_parser_fuzzer_seed_corpus.zip $SRC/seed_corpus cp $OUT/dng_parser_fuzzer_seed_corpus.zip $OUT/dng_stage_fuzzer_seed_corpus.zip cp $OUT/dng_parser_fuzzer_seed_corpus.zip $OUT/dng_fixed_validate_fuzzer_seed_corpus.zip ================================================ FILE: projects/dng_sdk/dng_camera_profile_fuzzer.cpp ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "dng_color_space.h" #include "dng_date_time.h" #include "dng_exceptions.h" #include "dng_file_stream.h" #include "dng_globals.h" #include "dng_host.h" #include "dng_ifd.h" #include "dng_image_writer.h" #include "dng_info.h" #include "dng_linearization_info.h" #include "dng_mosaic_info.h" #include "dng_negative.h" #include "dng_preview.h" #include "dng_render.h" #include "dng_simple_image.h" #include "dng_tag_codes.h" #include "dng_tag_types.h" #include "dng_tag_values.h" #include "dng_camera_profile.h" #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider provider(data, size); std::string s1 = provider.ConsumeRandomLengthString(); char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(s1.c_str(), s1.size(), 1, fp); fclose(fp); // Create a file stream dng_file_stream fStream(filename, false, 0); // Create a custom camera profile based on the fstream above try { AutoPtr customCameraProfile (new dng_camera_profile ()); customCameraProfile->ParseExtended(fStream); // The profile is not stubeed, so we can calculate the fingerprint. const dng_fingerprint &fPrint = customCameraProfile->Fingerprint(); } catch (dng_exception &e) {} unlink(filename); return 0; } ================================================ FILE: projects/dng_sdk/dng_fixed_validate_fuzzer.cpp ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Set the various sizes gPreferredSize = 0; gMinimumSize = 0; gMaximumSize = 0; gDumpDNG.Clear(); char dumpDNGFilename[256]; sprintf(dumpDNGFilename, "/tmp/libfuzzer-dng.%d.dng", getpid()); gDumpDNG.Set(dumpDNGFilename); gDumpStage1.Clear(); char dumpStage1Filename[256]; sprintf(dumpStage1Filename, "/tmp/libfuzzer-stage1.%d.dng", getpid()); gDumpStage1.Set(dumpStage1Filename); gDumpStage2.Clear(); char dumpStage2Filename[256]; sprintf(dumpStage2Filename, "/tmp/libfuzzer-stage2.%d.dng", getpid()); gDumpStage2.Set(dumpStage2Filename); gDumpStage3.Clear(); char dumpStage3Filename[256]; sprintf(dumpStage3Filename, "/tmp/libfuzzer-stage3.%d.dng", getpid()); gDumpStage3.Set(dumpStage3Filename); gDumpTIF.Clear(); char dumpTifFilename[256]; sprintf(dumpTifFilename, "/tmp/libfuzzer-tif.%d.tif", getpid()); gDumpTIF.Set(dumpTifFilename); gProxyDNGSize = 1024; gMosaicPlane = 32; gFourColorBayer = true; gFinalSpace = &dng_space_sRGB::Get (); char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); // Target dng_validate(filename); // cleanup file unlink(filename); return 0; } ================================================ FILE: projects/dng_sdk/dng_stage_fuzzer.cpp ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "dng_color_space.h" #include "dng_date_time.h" #include "dng_exceptions.h" #include "dng_file_stream.h" #include "dng_globals.h" #include "dng_host.h" #include "dng_ifd.h" #include "dng_image_writer.h" #include "dng_info.h" #include "dng_linearization_info.h" #include "dng_mosaic_info.h" #include "dng_negative.h" #include "dng_preview.h" #include "dng_render.h" #include "dng_simple_image.h" #include "dng_tag_codes.h" #include "dng_tag_types.h" #include "dng_tag_values.h" #include "dng_camera_profile.h" // Run a set of the operations high-level operations on the dng_sdk // This code is inspired by dng_validate.cpp and performs many of the same // operations in a simplified manner. void runFuzzerWithVariableHost(char *filename, uint32_t dng_version, bool linear, bool preview, bool should_proxy, bool KeepOriginalFile, bool NeedsMeta, bool NeedsImage, int do_color_coding, bool setFuji) { dng_host host; host.SetPreferredSize(0); host.SetMinimumSize(0); host.SetMaximumSize(0); host.SetSaveDNGVersion(dng_version); host.SetSaveLinearDNG(linear); host.SetForPreview(preview); host.ValidateSizes(); host.SetKeepOriginalFile(KeepOriginalFile); host.SetNeedsMeta(NeedsMeta); host.SetNeedsImage(NeedsImage); AutoPtr customCameraProfile (new dng_camera_profile ()); customCameraProfile->SetName("custom profile"); AutoPtr negative; try { dng_info info; dng_file_stream stream((const char *)filename); info.Parse(host, stream); info.PostParse(host); if (setFuji && info.fIFDCount > 0) { info.fIFD[0]->CanRead(); } if (info.IsValidDNG()) { negative.Reset(host.Make_dng_negative()); negative->AddProfile(customCameraProfile); if (do_color_coding == 1) { negative->SetDefaultCropSize((uint32)100,(uint32)100); negative->SetDefaultCropOrigin((uint32)50,(uint32)100); } else if (do_color_coding == 2) { negative->ResetDefaultUserCrop(); } else { negative->SetDefaultUserCropT(dng_urational(0, 1)); } negative->SetStage3Gain(2); negative->SetIsPreview(true); negative->Parse(host, stream, info); negative->PostParse(host, stream, info); negative->ReadStage1Image(host, stream, info); if (info.fMaskIndex != -1) { negative->ReadTransparencyMask(host, stream, info); } if (do_color_coding == 2) { const char fingerprint_raw[32] = { 'a', 'a','a','a','a','a', 'a','a','a','a','a','a','a','a','a','a','a','a','a', 'a','a','a','a','a','a','a','a','a','a','a','a','a'}; dng_fingerprint fp; fp.FromUtf8HexString(fingerprint_raw); dng_camera_profile_id dcpi("random id", fp); negative->ProfileByID(dcpi, true); } negative->SynchronizeMetadata(); negative->SetFourColorBayer(); if (do_color_coding == 1) { negative->SetRGB(); } else if (do_color_coding == 2) { negative->SetCMY(); } else if (do_color_coding == 3) { negative->SetGMCY(); } negative->BuildStage2Image(host); negative->BuildStage3Image(host, 1); if (should_proxy) { dng_image_writer writer; negative->ConvertToProxy(host, writer, 1); } if (negative->NeedFlattenTransparency(host)) { negative->FlattenTransparency(host); } // Write DNG dng_file_stream stream3("/tmp/randdng1", true); dng_image_writer writer3; dng_preview_list previewList; writer3.WriteDNG(host, stream3, *negative.Get(), &previewList, dng_version, false); // Write TIFF uint32_t compression_arr[8] = { ccUncompressed, ccLZW, ccOldJPEG, ccJPEG, ccDeflate, ccPackBits, ccOldDeflate, ccLossyJPEG}; for (int c = 0; c < 8; c++) { dng_file_stream stream2("/tmp/randpng", true); const dng_image &stage3 = *negative->Stage3Image(); dng_image_writer writer2; writer2.WriteTIFF(host, stream2, stage3, stage3.Planes() >= 3 ? piRGB : piBlackIsZero, compression_arr[c]); } // Create a renderer dng_render render(host, *negative); AutoPtr finalImage; finalImage.Reset(render.Render()); // Use a random var to determine if we should clear profiles from disk. if (do_color_coding == 3) { negative->ClearProfiles(true, true); } } } catch (dng_exception &e) { // dng_sdk throws C++ exceptions on errors // catch them here to prevent libFuzzer from crashing. } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); // parse the data using a variable set of options for dng_host runFuzzerWithVariableHost(filename, dngVersion_None, true, false, false, true, true, true, 1, true); runFuzzerWithVariableHost(filename, dngVersion_1_0_0_0, true, true, false, true, true, true, 2, false); runFuzzerWithVariableHost(filename, dngVersion_1_1_0_0, true, true, false, true, true, true, 3, true); runFuzzerWithVariableHost(filename, dngVersion_1_2_0_0, true, true, false, true, true, true, 4, false); runFuzzerWithVariableHost(filename, dngVersion_1_3_0_0, true, true, false, true, true, true, 1, true); runFuzzerWithVariableHost(filename, dngVersion_1_4_0_0, true, true, false, true, true, true, 2, false); runFuzzerWithVariableHost(filename, dngVersion_1_4_0_0, false, false, true, true, true, true, 3, false); runFuzzerWithVariableHost(filename, dngVersion_1_4_0_0, false, false, true, true, true, true, 3, true); unlink(filename); return 0; } ================================================ FILE: projects/dng_sdk/dng_validate_fuzzer.cpp ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider provider(data, size); // Set the various sizes gPreferredSize = provider.ConsumeIntegral(); gMinimumSize = provider.ConsumeIntegral(); gMaximumSize = provider.ConsumeIntegral(); gDumpDNG.Clear(); char dumpDNGFilename[256]; if (provider.ConsumeBool()) { sprintf(dumpDNGFilename, "/tmp/libfuzzer-dng.%d.dng", getpid()); gDumpDNG.Set(dumpDNGFilename); } gDumpStage1.Clear(); char dumpStage1Filename[256]; if (provider.ConsumeBool()) { sprintf(dumpStage1Filename, "/tmp/libfuzzer-stage1.%d.dng", getpid()); gDumpStage1.Set(dumpStage1Filename); } gDumpStage2.Clear(); char dumpStage2Filename[256]; if (provider.ConsumeBool()) { sprintf(dumpStage2Filename, "/tmp/libfuzzer-stage2.%d.dng", getpid()); gDumpStage2.Set(dumpStage2Filename); } gDumpStage3.Clear(); char dumpStage3Filename[256]; if (provider.ConsumeBool()) { sprintf(dumpStage3Filename, "/tmp/libfuzzer-stage3.%d.dng", getpid()); gDumpStage3.Set(dumpStage3Filename); } gDumpTIF.Clear(); char dumpTifFilename[256]; if (provider.ConsumeBool()) { sprintf(dumpTifFilename, "/tmp/libfuzzer-tif.%d.tif", getpid()); gDumpTIF.Set(dumpTifFilename); } gProxyDNGSize = provider.ConsumeIntegral(); gMosaicPlane = provider.ConsumeIntegral(); gFourColorBayer = provider.ConsumeBool(); switch (provider.ConsumeIntegralInRange(0, 7)) { case 0: gFinalSpace = &dng_space_sRGB::Get (); break; case 1: gFinalSpace = &dng_space_AdobeRGB::Get (); break; case 2: gFinalSpace = &dng_space_ProPhoto::Get (); break; case 3: gFinalSpace = &dng_space_ColorMatch::Get (); break; case 4: gFinalSpace = &dng_space_GrayGamma18::Get (); break; case 5: gFinalSpace = &dng_space_GrayGamma22::Get (); break; default: gFinalSpace = &dng_space_sRGB::Get (); break; } char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); std::string restData = provider.ConsumeRemainingBytesAsString(); if (restData.size() > 0) { FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(restData.c_str(), restData.size(), 1, fp); fclose(fp); // Target dng_validate(filename); // cleanup file unlink(filename); } return 0; } ================================================ FILE: projects/dng_sdk/project.yaml ================================================ homepage: "https://android.googlesource.com/platform/external/dng_sdk/" language: c++ primary_contact: "adaubert@google.com" auto_ccs: - david@adalogics.com main_repo: 'https://android.googlesource.com/platform/external/dng_sdk/' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dnsmasq/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 git://thekelleys.org.uk/dnsmasq.git dnsmasq WORKDIR dnsmasq COPY build.sh $SRC/ COPY fuzz*.c $SRC/ COPY fuzz*.cc $SRC/ COPY fuzz*.h $SRC/ COPY fuzz_patch.patch $SRC/ ================================================ FILE: projects/dnsmasq/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" #git apply --ignore-space-change --ignore-whitespace $SRC/fuzz_patch.patch export OSS_CFLAGS="$CFLAGS -g" sed -i 's/CFLAGS =/CFLAGS = ${OSS_CFLAGS} /g' ./Makefile sed -i 's/LDFLAGS =/LDFLAGS = ${OSS_CFLAGS} /g' ./Makefile # Do some modificatiosn to the source #sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/dhcp-common.c #sed -i 's/recvmsg(/fuzz_recvmsg(/g' ./src/netlink.c #sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/dhcp.c #sed -i 's/ioctl(/fuzz_ioctl(/g' ./src/network.c #sed -i 's/if (errno != 0/if (errno == 123123/g' ./src/netlink.c #echo "" >> ./src/dnsmasq.c #echo "ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) {return -1;}" >> ./src/dnsmasq.c #echo "int fuzz_ioctl(int fd, unsigned long request, void *arg) {return -1;}" >> ./src/dnsmasq.c make # Remove main function and create an archive cd ./src sed -i 's/int main (/int main2 (/g' ./dnsmasq.c #sed -i 's/fuzz_recvmsg(/fuzz_recvmsg2(/g' ./dnsmasq.c #sed -i 's/fuzz_ioctl(/fuzz_ioctl2(/g' ./dnsmasq.c rm dnsmasq.o $CC $CFLAGS -c dnsmasq.c -o dnsmasq.o -I./ -DVERSION=\'\"UNKNOWN\"\' ar cr libdnsmasq.a *.o sed -i 's/class/class2/g' ./dnsmasq.h sed -i 's/new/new2/g' ./dnsmasq.h # Build the fuzzers $CXX $CXXFLAGS -c $SRC/fuzz_util.cc -I./ -I$SRC/ -DVERSION=\'\"UNKNOWN\"\' -g $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./fuzz_util.o libdnsmasq.a -o $OUT/fuzz_util ================================================ FILE: projects/dnsmasq/fuzz_auth.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "fuzz_header.h" /* * Targets answer_auth */ void FuzzAuth(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; int i1 = get_int(&data, &size); int i2 = get_int(&data, &size); int i3 = get_int(&data, &size); if (size > (sizeof(struct dns_header) +50)) { char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; time_t now; union mysockaddr peer_addr; answer_auth((struct dns_header *)new_data, new_data + size, size, now, &peer_addr, i1, i2, i3); } } /* * Fuzzer entrypoint. */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { daemon = NULL; if (size < 1) { return 0; } // Initialize mini garbage collector gb_init(); // Get a value we can use to decide which target to hit. int i = (int)data[0]; data += 1; size -= 1; int succ = init_daemon(&data, &size); if (succ == 0) { cache_init(); blockdata_init(); FuzzAuth(&data, &size); cache_start_insert(); fuzz_blockdata_cleanup(); } // Free data in mini garbage collector. gb_cleanup(); return 0; } ================================================ FILE: projects/dnsmasq/fuzz_dhcp.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "fuzz_header.h" /* * Targets answer_auth */ void FuzzDhcp(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; time_t now; int pxe_fd = 0; struct iovec *dhpa = malloc(sizeof(struct iovec)); if (dhpa == NULL) return; char *content = malloc(sizeof(struct dhcp_packet)); if (content == NULL) { free(dhpa); return; } dhpa->iov_base = content; dhpa->iov_len = sizeof(struct dhcp_packet); daemon->dhcp_packet = *dhpa; syscall_data = data; syscall_size = size; dhcp_packet(now, pxe_fd); // dnsmasq may change the iov_base if the buffer needs expansion. // Do not free in that case, only free if the buffer stays that same. free(daemon->dhcp_packet.iov_base); free(dhpa); } /* * Fuzzer entrypoint. */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { daemon = NULL; if (size < 1) { return 0; } // Initialize mini garbage collector gb_init(); // Get a value we can use to decide which target to hit. int i = (int)data[0]; data += 1; size -= 1; int succ = init_daemon(&data, &size); if (succ == 0) { cache_init(); blockdata_init(); FuzzDhcp(&data, &size); cache_start_insert(); fuzz_blockdata_cleanup(); } // Free data in mini garbage collector. gb_cleanup(); return 0; } ================================================ FILE: projects/dnsmasq/fuzz_dhcp6.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "fuzz_header.h" /* * Targets answer_auth */ static int val213 = 0; void FuzzDhcp(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; time_t now; int pxe_fd = 0; struct iovec *dhpa = malloc(sizeof(struct iovec)); if (dhpa == NULL) return; char *content = malloc(300); if (content == NULL) { free(dhpa); return; } dhpa->iov_base = content; dhpa->iov_len = 300; daemon->dhcp_packet = *dhpa; syscall_data = data; syscall_size = size; dhcp6_packet(now); free(dhpa); free(content); } /* * Fuzzer entrypoint. */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { daemon = NULL; if (size < 1) { return 0; } // Initialize mini garbage collector gb_init(); // Get a value we can use to decide which target to hit. int i = (int)data[0]; data += 1; size -= 1; int succ = init_daemon(&data, &size); if (succ == 0) { cache_init(); blockdata_init(); FuzzDhcp(&data, &size); cache_start_insert(); fuzz_blockdata_cleanup(); } // Free data in mini garbage collector. gb_cleanup(); return 0; } ================================================ FILE: projects/dnsmasq/fuzz_header.h ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "dnsmasq.h" extern void fuzz_blockdata_cleanup(); // Simple garbage collector #define GB_SIZE 100 void *pointer_arr[GB_SIZE]; static int pointer_idx = 0; // If the garbage collector is used then this must be called as first thing // during a fuzz run. void gb_init() { pointer_idx = 0; for (int i = 0; i < GB_SIZE; i++) { pointer_arr[i] = NULL; } } void gb_cleanup() { for(int i = 0; i < GB_SIZE; i++) { if (pointer_arr[i] != NULL) { free(pointer_arr[i]); } } } char *get_len_null_terminated(const uint8_t **data, size_t *size, size_t to_get) { if (*size < to_get || (int)*size < 0) { return NULL; } char *new_s = malloc(to_get + 1); memcpy(new_s, *data, to_get); new_s[to_get] = '\0'; *data = *data+to_get; *size -= to_get; return new_s; } char *get_null_terminated(const uint8_t **data, size_t *size) { #define STR_SIZE 75 return get_len_null_terminated(data, size, STR_SIZE); } char *gb_get_random_data(const uint8_t **data, size_t *size, size_t to_get) { if (*size < to_get || (int)*size < 0) { return NULL; } char *new_s = malloc(to_get); memcpy(new_s, *data, to_get); pointer_arr[pointer_idx++] = (void*)new_s; *data = *data + to_get; *size -= to_get; return new_s; } char *gb_get_null_terminated(const uint8_t **data, size_t *size) { char *nstr = get_null_terminated(data, size); if (nstr == NULL) { return NULL; } pointer_arr[pointer_idx++] = (void*)nstr; return nstr; } char *gb_get_len_null_terminated(const uint8_t **data, size_t *size, size_t to_get) { char *nstr = get_len_null_terminated(data, size, to_get); if (nstr != NULL) { pointer_arr[pointer_idx++] = (void*)nstr; } return nstr; } char *gb_alloc_data(size_t len) { char *ptr = calloc(1, len); pointer_arr[pointer_idx++] = (void*)ptr; return ptr; } short get_short(const uint8_t **data, size_t *size) { if (*size <= 0) return 0; short c = (short)(*data)[0]; *data += 1; *size-=1; return c; } int get_int(const uint8_t **data, size_t *size) { if (*size <= 4) return 0; const uint8_t *ptr = *data; int val = *((int*)ptr); *data += 4; *size -= 4; return val; } // end simple garbage collector. const uint8_t *syscall_data = NULL; size_t syscall_size = 0; int fuzz_ioctl(int fd, unsigned long request, void *arg) { int fd2 = fd; unsigned long request2 = request; void *arg_ptr = arg; // SIOCGSTAMP if (request == SIOCGSTAMP) { struct timeval *tv = (struct timeval*)arg_ptr; if (tv == NULL) { return 0; } char *rand_tv = gb_get_random_data(&syscall_data, &syscall_size, sizeof(struct timeval)); if (rand_tv == NULL) { return -1; } memcpy(tv, rand_tv, sizeof(struct timeval)); return 0; } if (request == SIOCGIFNAME) { //printf("We got a SIOCGIFNAME\n"); struct ifreq *ifr = (struct ifreq*)arg_ptr; if (ifr == NULL) { return -1; } for (int i = 0; i < IF_NAMESIZE; i++) { if (syscall_size > 0 && syscall_data != NULL) { ifr->ifr_name[i] = (char)*syscall_data; syscall_data += 1; syscall_size -= 1; } else { ifr->ifr_name[i] = 'A'; } } ifr->ifr_name[IF_NAMESIZE-1] = '\0'; return 0; //return -1; } if (request == SIOCGIFFLAGS) { return 0; } if (request == SIOCGIFADDR) { return 0; } // int retval = ioctl(fd2, request2, arg_ptr); return retval; } // Sysytem call wrappers static char v = 0; ssize_t fuzz_recvmsg(int sockfd, struct msghdr *msg, int flags) { struct iovec *target = msg->msg_iov; //printf("recvmsg 1 \n"); if (syscall_size > 1) { char r = *syscall_data; syscall_data += 1; syscall_size -= 1; if (r == 12) { //printf("recvmsg 2\n"); return -1; } } int j = 0; if (msg->msg_control != NULL) { for (;j < CMSG_SPACE(sizeof(struct in_pktinfo)); j++) { if (syscall_size > 0 && syscall_data != NULL) { ((char*)msg->msg_control)[j] = *syscall_data; syscall_data += 1; syscall_size -= 1; } else { ((char*)msg->msg_control)[j] = 'A'; } } } int i = 0; for (; i < target->iov_len; i++) { if (syscall_size > 0 && syscall_data != NULL) { ((char*)target->iov_base)[i] = *syscall_data; syscall_data += 1; syscall_size -= 1; } else { ((char*)target->iov_base)[i] = 'A'; } } if (msg->msg_namelen > 0) { memset(msg->msg_name, 0, msg->msg_namelen); } return i; } // dnsmasq specific stuff int init_daemon(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; int retval = 0; #define CLEAN_IF_NULL(arg) if (arg == NULL) goto cleanup; // Initialize daemon daemon = (struct daemon*)gb_alloc_data(sizeof(struct daemon)); CLEAN_IF_NULL(daemon) // daemon misc daemon->max_ttl = get_int(&data, &size); daemon->neg_ttl = get_int(&data, &size); daemon->local_ttl = get_int(&data, &size); daemon->min_cache_ttl = get_int(&data, &size); // daemon->namebuff. char *daemon_namebuff = gb_get_len_null_terminated(&data, &size, MAXDNAME); daemon->namebuff = daemon_namebuff; // daemon->naptr struct naptr *naptr_ptr = (struct naptr*)gb_alloc_data(sizeof(struct naptr)); char *naptr_name = gb_get_null_terminated(&data, &size); char *naptr_replace = gb_get_null_terminated(&data, &size); char *naptr_regexp = gb_get_null_terminated(&data, &size); char *naptr_services = gb_get_null_terminated(&data, &size); char *naptr_flags = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(naptr_ptr) CLEAN_IF_NULL(naptr_name) CLEAN_IF_NULL(naptr_replace) CLEAN_IF_NULL(naptr_regexp) CLEAN_IF_NULL(naptr_services) CLEAN_IF_NULL(naptr_flags) naptr_ptr->name = naptr_name; naptr_ptr->replace = naptr_replace; naptr_ptr->regexp = naptr_regexp; naptr_ptr->services = naptr_services; naptr_ptr->flags = naptr_flags; daemon->naptr = naptr_ptr; // daemon->int_names struct interface_name *int_namses = (struct interface_name*)gb_alloc_data(sizeof(struct interface_name)); char *int_name = gb_get_null_terminated(&data, &size); char *int_intr = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(int_namses) CLEAN_IF_NULL(int_name) CLEAN_IF_NULL(int_intr) int_namses->name = int_name; int_namses->intr = int_intr; struct addrlist *d_addrlist = (struct addrlist*)gb_alloc_data(sizeof(struct addrlist)); CLEAN_IF_NULL(d_addrlist) d_addrlist->flags = get_int(&data, &size); d_addrlist->prefixlen = get_int(&data, &size); int_namses->addr = d_addrlist; daemon->int_names = int_namses; if (size > *size2) { goto cleanup; } // daemon->addrbuf char *adbuf = gb_alloc_data(200); CLEAN_IF_NULL(adbuf) daemon->addrbuff = adbuf; // daemon->auth_zones struct auth_zone *d_az = (struct auth_zone*)gb_alloc_data(sizeof(struct auth_zone)); char *auth_domain = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(d_az) CLEAN_IF_NULL(auth_domain) d_az->domain = auth_domain; daemon->auth_zones = d_az; // deamon->mxnames struct mx_srv_record *mx_srv_rec = (struct mx_srv_record*)gb_alloc_data(sizeof(struct mx_srv_record)); char *mx_name = gb_get_null_terminated(&data, &size); char *mx_target = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(mx_srv_rec) CLEAN_IF_NULL(mx_target) CLEAN_IF_NULL(mx_name) mx_srv_rec->next = daemon->mxnames; daemon->mxnames = mx_srv_rec; mx_srv_rec->name = mx_name; mx_srv_rec->target = mx_target; mx_srv_rec->issrv = get_int(&data, &size); mx_srv_rec->weight = get_int(&data, &size); mx_srv_rec->priority = get_int(&data, &size); mx_srv_rec->srvport = get_int(&data, &size); //data += 40; //size -= 40; if (size > *size2) { goto cleanup; } // daemon->txt struct txt_record *txt_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record)); char *txt_record_name = gb_get_null_terminated(&data, &size); char *txt_record_txt = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(txt_record) CLEAN_IF_NULL(txt_record_name) CLEAN_IF_NULL(txt_record_txt) txt_record->name = txt_record_name; txt_record->txt = (unsigned char*)txt_record_txt; txt_record->class2 = (get_short(&data, &size) % 10); daemon->txt = txt_record; // daemon->rr struct txt_record *rr_record = (struct txt_record *)gb_alloc_data(sizeof(struct txt_record)); char *rr_record_name = gb_get_null_terminated(&data, &size); char *rr_record_txt = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(rr_record) CLEAN_IF_NULL(rr_record_name) CLEAN_IF_NULL(rr_record_txt) rr_record->name = rr_record_name; rr_record->txt = (unsigned char*)rr_record_txt; rr_record->class2 = (get_short(&data, &size) % 10); daemon->rr = rr_record; if (size > *size2) { goto cleanup; } // daemon->relay4 //struct dhcp_relay *dr = (struct dhcp_relay*)gb_alloc_data(sizeof(struct dhcp_relay)); struct dhcp_relay *dr = (struct dhcp_relay*)gb_get_random_data(&data, &size, sizeof(struct dhcp_relay)); char *dr_interface = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(dr) CLEAN_IF_NULL(dr_interface) dr->interface = dr_interface; dr->next = NULL; //dr->current = NULL; daemon->relay4 = dr; // deamon->bridges struct dhcp_bridge *db = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge)); char *db_interface = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(db) CLEAN_IF_NULL(db_interface) if (strlen(db_interface) > IF_NAMESIZE) { for (int i = 0; i < IF_NAMESIZE; i++) { db->iface[i] = db_interface[i]; } } else { for (int i = 0; i < strlen(db_interface); i++) { db->iface[i] = db_interface[i]; } } struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_alloc_data(sizeof(struct dhcp_bridge)); //struct dhcp_bridge *db_alias = (struct dhcp_bridge*)gb_get_random_data(&data, &size, sizeof(struct dhcp_bridge)); char *db_alias_interface = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(db_alias) CLEAN_IF_NULL(db_alias_interface) if (strlen(db_alias_interface) > IF_NAMESIZE) { for (int i = 0; i < IF_NAMESIZE; i++) { db_alias->iface[i] = db_alias_interface[i]; } } else { for (int i = 0; i < strlen(db_alias_interface); i++) { db_alias->iface[i] = db_alias_interface[i]; } } db->alias = db_alias; daemon->bridges = db; // daemon->if_names struct iname *in = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname)); char *iname_name = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(in) CLEAN_IF_NULL(iname_name) in->name = iname_name; in->next = NULL; daemon->if_names = in; // daemon->if_addrs struct iname *in_addr = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname)); char *iname_name_addr = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(in_addr) CLEAN_IF_NULL(iname_name_addr) in_addr->name = iname_name_addr; in_addr->next = NULL; daemon->if_addrs = in_addr; // daemon->if_except struct iname *in_except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname)); char *iname_name_except = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(in_except) CLEAN_IF_NULL(iname_name_except) in_except->name = iname_name_except; in_except->next = NULL; daemon->if_except = in_except; // daemon->dhcp_except struct iname *except = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname)); char *name_except = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(except) CLEAN_IF_NULL(name_except) except->name = name_except; except->next = NULL; daemon->dhcp_except = except; // daemon->authinterface struct iname *auth_interface = (struct iname*)gb_get_random_data(&data, &size, sizeof(struct iname)); char *auth_name = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(auth_interface) CLEAN_IF_NULL(auth_name) auth_interface->name = auth_name; auth_interface->next = NULL; daemon->authinterface = auth_interface; // daemon->cnames struct cname *cn = (struct cname*)gb_alloc_data(sizeof(struct cname)); char *cname_alias = gb_get_null_terminated(&data, &size); char *cname_target = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(cn) CLEAN_IF_NULL(cname_alias) CLEAN_IF_NULL(cname_target) cn->alias = cname_alias; cn->target = cname_target; daemon->cnames = cn; // daemon->ptr struct ptr_record *ptr = (struct ptr_record *)gb_alloc_data(sizeof(struct ptr_record)); CLEAN_IF_NULL(ptr) char *ptr_name = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(ptr_name) ptr->name = ptr_name; daemon->ptr = ptr; if (size > *size2) { goto cleanup; } // daemon->dhcp struct dhcp_context *dhcp_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context)); char *dhcp_c_temp_in = gb_get_null_terminated(&data, &size); struct dhcp_netid *dhcp_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid)); char *dhcp_netid_net = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(dhcp_c) CLEAN_IF_NULL(dhcp_c_temp_in) CLEAN_IF_NULL(dhcp_c_netid) CLEAN_IF_NULL(dhcp_netid_net) dhcp_c->next = NULL; dhcp_c->current = NULL; dhcp_c_netid->net = dhcp_netid_net; dhcp_c->filter = dhcp_c_netid; dhcp_c->template_interface = dhcp_c_temp_in; daemon->dhcp = dhcp_c; // daemon->dhcp6 struct dhcp_context *dhcp6_c = (struct dhcp_context *) gb_get_random_data(&data, &size, sizeof(struct dhcp_context)); char *dhcp6_c_temp_in = gb_get_null_terminated(&data, &size); struct dhcp_netid *dhcp6_c_netid = (struct dhcp_netid *) gb_alloc_data(sizeof(struct dhcp_netid)); char *dhcp6_netid_net = gb_get_null_terminated(&data, &size); CLEAN_IF_NULL(dhcp6_c) CLEAN_IF_NULL(dhcp6_c_temp_in) CLEAN_IF_NULL(dhcp6_c_netid) CLEAN_IF_NULL(dhcp6_netid_net) dhcp6_c->next = NULL; dhcp6_c->current = NULL; dhcp6_c_netid->net = dhcp6_netid_net; dhcp6_c->filter = dhcp6_c_netid; dhcp6_c->template_interface = dhcp6_c_temp_in; daemon->dhcp6 = dhcp6_c; // daemon->doing_dhcp6 daemon->doing_dhcp6 = 1; // daemon->dhcp_buffs char *dhcp_buff = gb_alloc_data(DHCP_BUFF_SZ); char *dhcp_buff2 = gb_alloc_data(DHCP_BUFF_SZ); char *dhcp_buff3 = gb_alloc_data(DHCP_BUFF_SZ); CLEAN_IF_NULL(dhcp_buff) CLEAN_IF_NULL(dhcp_buff2) CLEAN_IF_NULL(dhcp_buff3) daemon->dhcp_buff = dhcp_buff; daemon->dhcp_buff2 = dhcp_buff2; daemon->dhcp_buff3 = dhcp_buff3; // daemon->ignore_addr struct bogus_addr *bb = (struct bogus_addr *)gb_alloc_data(sizeof(struct bogus_addr)); CLEAN_IF_NULL(bb) daemon->ignore_addr = bb; // daemon->doctors if (size > *size2) { goto cleanup; } struct doctor *doctors = (struct doctor *)gb_alloc_data(sizeof(struct doctor)); CLEAN_IF_NULL(doctors) doctors->next = NULL; daemon->doctors = doctors; retval = 0; goto ret; cleanup: retval = -1; ret: return retval; } ================================================ FILE: projects/dnsmasq/fuzz_patch.patch ================================================ diff --git a/Makefile b/Makefile index a503c82..331ee3b 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ MANDIR = $(PREFIX)/share/man LOCALEDIR = $(PREFIX)/share/locale BUILDDIR = $(SRC) DESTDIR = -CFLAGS = -Wall -W -O2 -LDFLAGS = +#CFLAGS = -Wall -W -O2 +LDFLAGS = $(CFLAGS) COPTS = RPM_OPT_FLAGS = LIBS = ================================================ FILE: projects/dnsmasq/fuzz_rfc1035.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "fuzz_header.h" /* * Targets "extract_addresses" */ void FuzzExtractTheAddress(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *new_name = NULL; new_name = get_len_null_terminated(&data, &size, MAXDNAME); pointer_arr[pointer_idx++] = (void*)new_name; int is_sign = get_int(&data, &size); int check_rebind = get_int(&data, &size); int secure = get_int(&data, &size); if (size > (sizeof(struct dns_header) +50)) { char *new_data = malloc(size); memset(new_data, 0, size); memcpy(new_data, data, size); pointer_arr[pointer_idx++] = (void*)new_data; time_t now; int doctored = 0; extract_addresses((struct dns_header *)new_data, size, new_name, now, NULL, NULL, is_sign, check_rebind, 0, secure, &doctored); } } /* * Targets "answer_request" */ void FuzzAnswerTheRequest(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; struct in_addr local_addr; struct in_addr local_netmask; time_t now; int i1 = get_int(&data, &size); int i2 = get_int(&data, &size); int i3 = get_int(&data, &size); if (size > (sizeof(struct dns_header) +50)) { char *new_data = malloc(size); memset(new_data, 0, size); memcpy(new_data, data, size); pointer_arr[pointer_idx++] = (void*)new_data; answer_request((struct dns_header *)new_data, new_data+size, size, local_addr, local_netmask, now, i1, i2, i3); } } /* * Targets "check_for_ignored_address" */ void FuzzIgnoredAddress(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; if (size > (sizeof(struct dns_header) +50)) { //return 0; char *new_data = malloc(size); memset(new_data, 0, size); memcpy(new_data, data, size); pointer_arr[pointer_idx++] = (void*)new_data; check_for_ignored_address((struct dns_header *)new_data, size); } } /* * Targets "check_for_local_domain" */ void FuzzCheckLocalDomain(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; time_t now; check_for_local_domain(new_data, now); } /* * Targets "extract_request" */ void FuzzExtractRequest(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *new_name = NULL; new_name = get_len_null_terminated(&data, &size, MAXDNAME); if (new_name == NULL) { return ; } pointer_arr[pointer_idx++] = (void*)new_name; if (size > (sizeof(struct dns_header) +50)) { char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; unsigned short typeb; extract_request((struct dns_header *)new_data, size, new_name, &typeb); } } /* * Targets "in_arpa_name_2_addr" */ void FuzzArpaName2Addr(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *new_name = NULL; new_name = get_null_terminated(&data, &size); if (new_name == NULL) { return ; } pointer_arr[pointer_idx++] = (void*)new_name; union all_addr addr; in_arpa_name_2_addr(new_name, &addr); return; } void FuzzResizePacket(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *new_packet = malloc(50); if (size > (sizeof(struct dns_header) + 50)) { char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; resize_packet((struct dns_header *)new_data, size, (unsigned char*)new_packet, 50); } free(new_packet); } void FuzzSetupReply(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; if (size > (sizeof(struct dns_header) + 50)) { char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; setup_reply((struct dns_header *)new_data, 0, 0); } } void FuzzCheckForBogusWildcard(const uint8_t **data2, size_t *size2) { const uint8_t *data = *data2; size_t size = *size2; char *nname = gb_get_len_null_terminated(&data, &size, MAXDNAME); if (nname == NULL) { return; } if (size > (sizeof(struct dns_header) + 50)) { char *new_data = malloc(size+1); memset(new_data, 0, size); memcpy(new_data, data, size); new_data[size] = '\0'; pointer_arr[pointer_idx++] = (void*)new_data; time_t now; check_for_bogus_wildcard((struct dns_header *)new_data, size, nname, now); } } /* * Fuzzer entrypoint. */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { daemon = NULL; //printf("Running fuzzer\n"); if (size < 1) { return 0; } // Initialize mini garbage collector gb_init(); // Get a value we can use to decide which target to hit. int i = (int)data[0]; data += 1; size -= 1; int succ = init_daemon(&data, &size); if (succ == 0) { cache_init(); blockdata_init(); //i = 7; #define TS 9 if ((i % TS) == 0) { FuzzExtractTheAddress(&data,&size); } else if ((i % TS) == 1) { FuzzAnswerTheRequest(&data,&size); } else if ((i % TS) == 2) { FuzzCheckLocalDomain(&data, &size); } else if ((i % TS) == 3) { FuzzExtractRequest(&data, &size); } else if ((i % TS) == 4) { FuzzArpaName2Addr(&data, &size); } else if ((i %TS) == 5) { FuzzResizePacket(&data, &size); } else if ((i %TS) == 6) { FuzzSetupReply(&data, &size); } else if ((i % TS) == 7) { FuzzCheckForBogusWildcard(&data, &size); } else { FuzzIgnoredAddress(&data, &size); } cache_start_insert(); fuzz_blockdata_cleanup(); } // Free data in mini garbage collector. gb_cleanup(); return 0; } ================================================ FILE: projects/dnsmasq/fuzz_util.cc ================================================ /* Copyright 2026 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ extern "C" { #include "dnsmasq.h" } #include #include #include #include #include #define STR_SIZE 75 static int init_daemon(FuzzedDataProvider &provider, std::vector &allocs, std::vector &strings) { auto alloc = [&](size_t sz) -> void * { void *p = calloc(1, sz); if (p) allocs.push_back(p); return p; }; auto make_string = [&](size_t max_len) -> char * { strings.push_back(provider.ConsumeRandomLengthString(max_len)); return strings.back().data(); }; // Allocate daemon separately (not via alloc) so it can be freed last. // dnsmasq's free_real() dereferences daemon for metrics tracking. daemon = (struct daemon *)calloc(1, sizeof(struct daemon)); if (!daemon) return -1; daemon->max_ttl = provider.ConsumeIntegral(); daemon->neg_ttl = provider.ConsumeIntegral(); daemon->local_ttl = provider.ConsumeIntegral(); daemon->min_cache_ttl = provider.ConsumeIntegral(); daemon->namebuff = make_string(MAXDNAME); // daemon->naptr struct naptr *naptr_ptr = (struct naptr *)alloc(sizeof(struct naptr)); if (!naptr_ptr) return -1; naptr_ptr->name = make_string(STR_SIZE); naptr_ptr->replace = make_string(STR_SIZE); naptr_ptr->regexp = make_string(STR_SIZE); naptr_ptr->services = make_string(STR_SIZE); naptr_ptr->flags = make_string(STR_SIZE); daemon->naptr = naptr_ptr; // daemon->int_names struct interface_name *int_namses = (struct interface_name *)alloc(sizeof(struct interface_name)); if (!int_namses) return -1; int_namses->name = make_string(STR_SIZE); int_namses->intr = make_string(STR_SIZE); struct addrlist *d_addrlist = (struct addrlist *)alloc(sizeof(struct addrlist)); if (!d_addrlist) return -1; d_addrlist->flags = provider.ConsumeIntegral(); d_addrlist->prefixlen = provider.ConsumeIntegral(); int_namses->addr = d_addrlist; daemon->int_names = int_namses; // daemon->addrbuf char *adbuf = (char *)alloc(200); if (!adbuf) return -1; daemon->addrbuff = adbuf; // daemon->auth_zones struct auth_zone *d_az = (struct auth_zone *)alloc(sizeof(struct auth_zone)); if (!d_az) return -1; d_az->domain = make_string(STR_SIZE); daemon->auth_zones = d_az; // daemon->mxnames struct mx_srv_record *mx_srv_rec = (struct mx_srv_record *)alloc(sizeof(struct mx_srv_record)); if (!mx_srv_rec) return -1; mx_srv_rec->next = daemon->mxnames; daemon->mxnames = mx_srv_rec; mx_srv_rec->name = make_string(STR_SIZE); mx_srv_rec->target = make_string(STR_SIZE); mx_srv_rec->issrv = provider.ConsumeIntegral(); mx_srv_rec->weight = provider.ConsumeIntegral(); mx_srv_rec->priority = provider.ConsumeIntegral(); mx_srv_rec->srvport = provider.ConsumeIntegral(); // daemon->txt struct txt_record *txt_record = (struct txt_record *)alloc(sizeof(struct txt_record)); if (!txt_record) return -1; txt_record->name = make_string(STR_SIZE); txt_record->txt = (unsigned char *)make_string(STR_SIZE); txt_record->class2 = provider.ConsumeIntegralInRange(0, 9); daemon->txt = txt_record; // daemon->rr struct txt_record *rr_record = (struct txt_record *)alloc(sizeof(struct txt_record)); if (!rr_record) return -1; rr_record->name = make_string(STR_SIZE); rr_record->txt = (unsigned char *)make_string(STR_SIZE); rr_record->class2 = provider.ConsumeIntegralInRange(0, 9); daemon->rr = rr_record; // daemon->relay4 struct dhcp_relay *dr = (struct dhcp_relay *)alloc(sizeof(struct dhcp_relay)); if (!dr) return -1; dr->interface = make_string(STR_SIZE); dr->next = NULL; daemon->relay4 = dr; // daemon->bridges struct dhcp_bridge *db = (struct dhcp_bridge *)alloc(sizeof(struct dhcp_bridge)); if (!db) return -1; { std::string iface_str = provider.ConsumeRandomLengthString(IF_NAMESIZE - 1); memcpy(db->iface, iface_str.c_str(), iface_str.size() + 1); } struct dhcp_bridge *db_alias = (struct dhcp_bridge *)alloc(sizeof(struct dhcp_bridge)); if (!db_alias) return -1; { std::string alias_str = provider.ConsumeRandomLengthString(IF_NAMESIZE - 1); memcpy(db_alias->iface, alias_str.c_str(), alias_str.size() + 1); } db->alias = db_alias; daemon->bridges = db; // daemon->if_names, if_addrs, if_except, dhcp_except, authinterface auto make_iname = [&]() -> struct iname * { struct iname *in = (struct iname *)alloc(sizeof(struct iname)); if (!in) return nullptr; in->name = make_string(STR_SIZE); in->next = NULL; return in; }; daemon->if_names = make_iname(); daemon->if_addrs = make_iname(); daemon->if_except = make_iname(); daemon->dhcp_except = make_iname(); daemon->authinterface = make_iname(); if (!daemon->if_names || !daemon->if_addrs || !daemon->if_except || !daemon->dhcp_except || !daemon->authinterface) return -1; // daemon->cnames struct cname *cn = (struct cname *)alloc(sizeof(struct cname)); if (!cn) return -1; cn->alias = make_string(STR_SIZE); cn->target = make_string(STR_SIZE); daemon->cnames = cn; // daemon->ptr struct ptr_record *ptr = (struct ptr_record *)alloc(sizeof(struct ptr_record)); if (!ptr) return -1; ptr->name = make_string(STR_SIZE); daemon->ptr = ptr; // daemon->dhcp struct dhcp_context *dhcp_c = (struct dhcp_context *)alloc(sizeof(struct dhcp_context)); if (!dhcp_c) return -1; dhcp_c->next = NULL; dhcp_c->current = NULL; struct dhcp_netid *dhcp_c_netid = (struct dhcp_netid *)alloc(sizeof(struct dhcp_netid)); if (!dhcp_c_netid) return -1; dhcp_c_netid->net = make_string(STR_SIZE); dhcp_c->filter = dhcp_c_netid; dhcp_c->template_interface = make_string(STR_SIZE); daemon->dhcp = dhcp_c; // daemon->dhcp6 struct dhcp_context *dhcp6_c = (struct dhcp_context *)alloc(sizeof(struct dhcp_context)); if (!dhcp6_c) return -1; dhcp6_c->next = NULL; dhcp6_c->current = NULL; struct dhcp_netid *dhcp6_c_netid = (struct dhcp_netid *)alloc(sizeof(struct dhcp_netid)); if (!dhcp6_c_netid) return -1; dhcp6_c_netid->net = make_string(STR_SIZE); dhcp6_c->filter = dhcp6_c_netid; dhcp6_c->template_interface = make_string(STR_SIZE); daemon->dhcp6 = dhcp6_c; daemon->doing_dhcp6 = 1; // daemon->dhcp_buffs daemon->dhcp_buff = (char *)alloc(DHCP_BUFF_SZ); daemon->dhcp_buff2 = (char *)alloc(DHCP_BUFF_SZ); daemon->dhcp_buff3 = (char *)alloc(DHCP_BUFF_SZ); if (!daemon->dhcp_buff || !daemon->dhcp_buff2 || !daemon->dhcp_buff3) return -1; // daemon->ignore_addr struct bogus_addr *bb = (struct bogus_addr *)alloc(sizeof(struct bogus_addr)); if (!bb) return -1; daemon->ignore_addr = bb; // daemon->doctors struct doctor *doctors = (struct doctor *)alloc(sizeof(struct doctor)); if (!doctors) return -1; doctors->next = NULL; daemon->doctors = doctors; return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider provider(data, size); std::vector allocs; std::vector strings; strings.reserve(40); int succ = init_daemon(provider, allocs, strings); if (succ == 0) { std::string t1_str = provider.ConsumeRandomLengthString(MAXDNAME); std::string t2_str = provider.ConsumeRandomLengthString(MAXDNAME); if (t1_str.empty() || t2_str.empty()) goto cleanup; char *t1 = t1_str.data(); char *t2 = t2_str.data(); // Util logic hostname_isequal(t1, t2); legal_hostname(t1); char *tmp = canonicalise(t2, NULL); if (tmp != NULL) { free(tmp); } char *tmp_out = (char *)malloc(30); if (tmp_out) { int mac_type; parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, NULL); parse_hex(t1, (unsigned char *)tmp_out, 30, NULL, &mac_type); free(tmp_out); } wildcard_match(t1, t2); if (t1_str.size() < t2_str.size()) { wildcard_matchn(t1, t2, t1_str.size()); } else { wildcard_matchn(t1, t2, t2_str.size()); } hostname_issubdomain(t1, t2); union all_addr addr1; memset(&addr1, 0, sizeof(union all_addr)); is_name_synthetic(0, t1, &addr1); } cleanup: for (void *p : allocs) free(p); // Free daemon last since dnsmasq's free_real() dereferences it. free(daemon); daemon = NULL; return 0; } ================================================ FILE: projects/dnsmasq/project.yaml ================================================ homepage: "https://thekelleys.org.uk/dnsmasq/doc.html" language: c primary_contact: "simon@thekelleys.org.uk" main_repo: "git://thekelleys.org.uk/dnsmasq.git" auto_ccs: - "david@adalogics.com" - "pemensik@redhat.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dnspython/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/rthalley/dnspython dnspython COPY *.sh *py $SRC/ WORKDIR $SRC/dnspython ================================================ FILE: projects/dnspython/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/dnspython/fuzz_message.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import dns.message import dns.exception def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: dns.message.from_text(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except dns.exception.DNSException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/dnspython/fuzz_token.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import dns.tokenizer import dns.exception def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) token = dns.tokenizer.Tokenizer(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) try: list(iter(token)) except dns.exception.DNSException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/dnspython/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/rthalley/dnspython language: python main_repo: https://github.com/rthalley/dnspython sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/docker-client/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/spotify/docker-client docker-client COPY *.sh *.java $SRC/ WORKDIR $SRC/docker-client ================================================ FILE: projects/docker-client/RegistryAuthFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.spotify.docker.client.DockerConfigReader; import com.spotify.docker.client.messages.RegistryAuth; import java.io.File; import java.nio.file.Files; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Path; import java.io.IOException; import java.io.PrintWriter; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-6 // Heuristic name: jvm-autofuzz-heuristics-6 // Target method: [com.spotify.docker.client.DockerConfigReader] public com.spotify.docker.client.messages.RegistryAuth fromConfig(java.nio.file.Path,java.lang.String) throws java.io.IOException public class RegistryAuthFuzzer { private static File tempDirectory; private static File tempFile; public static void fuzzerInitialize() { try { tempDirectory = Files.createTempDirectory("oss-fuzz").toFile().getAbsoluteFile(); tempFile = new File(tempDirectory, "oss-fuzz-temp").getAbsoluteFile(); } catch (IOException e) { // Known exception } } public static void fuzzerTearDown() { tempFile.delete(); tempDirectory.delete(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { PrintWriter printWriter = new PrintWriter(new FileWriter(tempFile)); printWriter.print(data.consumeString(data.remainingBytes() / 2)); printWriter.close(); } catch (IOException e) { // Known exception } try { DockerConfigReader obj = new DockerConfigReader(); obj.fromConfig(tempFile.toPath(), data.consumeRemainingAsString()); } catch (IOException e1) { } } } ================================================ FILE: projects/docker-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True dependency:copy-dependencies \ org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "./target/docker-client-$CURRENT_VERSION-shaded.jar" $OUT/docker-client.jar ls -d ./target/dependency/slf4j-api-*.jar | head -1 | xargs -I {} cp {} $OUT/slf4j-api.jar ALL_JARS='docker-client.jar slf4j-api.jar' # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/docker-client/project.yaml ================================================ homepage: https://github.com/spotify/docker-client main_repo: https://github.com/spotify/docker-client language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/docutils/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone --depth=1 https://github.com/jwilk-mirrors/docutils docutils COPY *.sh *py $SRC/ WORKDIR $SRC/docutils ================================================ FILE: projects/docutils/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/docutils/fuzz_rst.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from docutils.parsers.rst import Parser from docutils.frontend import get_default_settings from docutils.utils import new_document from docutils import nodes from docutils import ApplicationError from docutils.parsers.rst import tableparser from docutils.statemachine import StringList, string2lines from docutils.transforms.universal import (SmartQuotes, TestMessages, Decorations, ExposeInternals, Messages, FilterMessages, StripComments, StripClassesAndElements) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) parser = Parser() settings = get_default_settings(Parser) settings.warning_stream = "" settings.smart_quotes = fdp.ConsumeBool() settings.trim_footnote_ref_space = fdp.ConsumeBool() settings.report = fdp.ConsumeIntInRange(0, 5) doc = new_document(fdp.ConsumeUnicodeNoSurrogates(64), settings.copy()) try: parser.parse(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 2048)), doc) if fdp.ConsumeBool(): doc.transformer.add_transforms([TestMessages]) if fdp.ConsumeBool(): doc.transformer.add_transform(SmartQuotes) if fdp.ConsumeBool(): doc.transformer.add_transform(Decorations) if fdp.ConsumeBool(): doc.transformer.add_transform(ExposeInternals) if fdp.ConsumeBool(): doc.transformer.add_transform(Messages) if fdp.ConsumeBool(): doc.transformer.add_transform(FilterMessages) if fdp.ConsumeBool(): doc.transformer.add_transform(StripComments) if fdp.ConsumeBool(): doc.transformer.add_transform(StripClassesAndElements) doc.transformer.apply_transforms() o = doc.pformat() visitor = nodes.TreeCopyVisitor(doc) doc.walkabout(visitor) newtree = visitor.get_tree_copy() except ApplicationError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/docutils/fuzz_rst_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from docutils import parsers, frontend, utils, ApplicationError def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) rst_parser_class = parsers.get_parser_class('rst') parser = rst_parser_class() document = utils.new_document( fdp.ConsumeUnicodeNoSurrogates(124), frontend.get_default_settings(parser) ) try: parser.parse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize), document) except ApplicationError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/docutils/fuzz_table.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from docutils import ApplicationError from docutils.parsers.rst import tableparser from docutils.statemachine import StringList, string2lines def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) parser = tableparser.GridTableParser() lines_input = StringList( string2lines(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)), 'fuzz data') if len(lines_input) < 1: return parser.setup(lines_input) try: parser.find_head_body_sep() parser.parse_table() except ApplicationError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/docutils/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/jwilk-mirrors/docutils language: python main_repo: https://github.com/jwilk-mirrors/docutils sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/dom4j/DOMReaderFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.BugDetectors; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.dom4j.io.DOMReader; import java.io.IOException; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.lang.IllegalArgumentException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.util.List; public class DOMReaderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try (AutoCloseable ignored = BugDetectors.allowNetworkConnections()) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; org.w3c.dom.Document doc; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { return; } try { doc = builder.parse(new ByteArrayInputStream(data.consumeRemainingAsBytes())); } catch (SAXException | IOException e) { return; } DOMReader reader = new DOMReader(); try { reader.read(doc); } catch (IllegalArgumentException e) { return; } } catch (Exception e) { return; } } } ================================================ FILE: projects/dom4j/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # Ensure Java 11 is installed RUN apt-get update && \ apt-get install -y openjdk-11-jdk && \ rm -rf /var/lib/apt/lists/* ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64 ENV JVM_LD_LIBRARY_PATH $JAVA_HOME/lib/server ENV PATH $JAVA_HOME/bin:$PATH RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/xml.dict $SRC/xml.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/DOMReaderFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/dom4j/dom4j.git COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/dom4j ================================================ FILE: projects/dom4j/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT # Set UTF-8 encoding and skip Javadoc ./gradlew -x test -x javadoc build -Dfile.encoding=UTF-8 cp "build/libs/dom4j.jar" $OUT/dom4j.jar ALL_JARS="dom4j.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/dom4j/project.yaml ================================================ homepage: "https://github.com/dom4j/dom4j" language: jvm main_repo: "https://github.com/dom4j/dom4j.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/double-conversion/Dockerfile ================================================ # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y --no-install-recommends \ cmake ninja-build && \ apt-get clean RUN git clone --single-branch \ https://github.com/google/double-conversion.git double-conversion WORKDIR double-conversion COPY run_tests.sh build.sh $SRC/ COPY *.cc $SRC/ ================================================ FILE: projects/double-conversion/build.sh ================================================ #!/bin/bash -eu # # Copyright 2019 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir -p ${WORK}/double-conversion cd ${WORK}/double-conversion cmake -GNinja -DBUILD_TESTING=ON ${SRC}/double-conversion/ ninja fuzzer="string_to_double_fuzzer" ${CXX} ${CXXFLAGS} -std=c++11 -I${SRC}/double-conversion/double-conversion \ -c ${SRC}/${fuzzer}.cc \ -o ${fuzzer}.o ${CXX} ${CXXFLAGS} -std=c++11 ${fuzzer}.o \ -o ${OUT}/${fuzzer} "${LIB_FUZZING_ENGINE}" libdouble-conversion.a ================================================ FILE: projects/double-conversion/project.yaml ================================================ homepage: "https://github.com/google/double-conversion" language: c++ primary_contact: "florian@loitsch.com" auto_ccs: - "sbucur@google.com" sanitizers: - address - memory - undefined labels: string_to_double_fuzzer: - sundew architectures: - x86_64 - i386 main_repo: 'https://github.com/google/double-conversion.git' file_github_issue: True ================================================ FILE: projects/double-conversion/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $WORK/double-conversion ninja test ================================================ FILE: projects/double-conversion/string_to_double_fuzzer.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "double-conversion.h" using double_conversion::StringToDoubleConverter; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { StringToDoubleConverter converter( StringToDoubleConverter::ALLOW_HEX | StringToDoubleConverter::ALLOW_OCTALS | StringToDoubleConverter::ALLOW_TRAILING_JUNK | StringToDoubleConverter::ALLOW_LEADING_SPACES | StringToDoubleConverter::ALLOW_TRAILING_SPACES | StringToDoubleConverter::ALLOW_SPACES_AFTER_SIGN | StringToDoubleConverter::ALLOW_CASE_INSENSIBILITY | StringToDoubleConverter::ALLOW_HEX_FLOATS, /*empty_string_value=*/0.0, /*junk_string_value=*/0.0, "inf", "nan"); int num_digits_unused; converter.StringToDouble(reinterpret_cast(data), size, &num_digits_unused); return 0; } ================================================ FILE: projects/dovecot/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool wget gettext automake libxml2-dev m4 pkg-config bison flex python3.8-venv libssl-dev zlib1g-dev libtool-bin RUN git clone --depth 1 --single-branch --branch main https://github.com/dovecot/core dovecot RUN git clone --depth 1 --single-branch --branch main https://github.com/dovecot/pigeonhole pigeonhole COPY build.sh $SRC/ #COPY fuzz-* $SRC/ ================================================ FILE: projects/dovecot/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd dovecot # Patch ldflags find . -name "Makefile.am" -exec sed -i -e 's,(FUZZER_LDFLAGS),(FUZZER_LDFLAGS) -static-libtool-libs,' {} \; ./autogen.sh ./configure PANDOC=false --with-fuzzer=clang --prefix=$OUT make -j$(nproc) # Copy over the fuzzers find . -name "fuzz-*" -executable -exec libtool install install -m0755 {} $OUT/ \; cd ../pigeonhole find . -name "Makefile.am" -exec sed -i -e 's,(FUZZER_LDFLAGS),(FUZZER_LDFLAGS) -static-libtool-libs,' {} \; ./autogen.sh ./configure --with-dovecot=../dovecot --with-fuzzer=clang --prefix=$OUT make -j$(nproc) # Copy over the fuzzers find . -name "fuzz-*" -executable -exec libtool install install -m0755 {} $OUT/ \; ================================================ FILE: projects/dovecot/project.yaml ================================================ homepage: "https://www.dovecot.org/" language: c primary_contact: "oss-fuzz@open-xchange.com" auto_ccs: - "david@adalogics.com" - "p.antoine@catenacyber.fr" - "cmousefi@gmail.com" - "boschstephan@gmail.com" - "timo.sirainen@gmail.com" main_repo: 'https://github.com/dovecot/core' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dpp/project.yaml ================================================ homepage: "https://github.com/brainboxdotcc/DPP" language: c++ primary_contact: "craigedwardsbrainbox@gmail.com" auto_ccs: - "craigedwards@brainbox.cc" sanitizers: - address - memory: experimental: True - undefined main_repo: 'https://github.com/brainboxdotcc/DPP.git' ================================================ FILE: projects/draco/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y git cmake make pkg-config RUN git clone --depth 1 https://github.com/google/draco draco COPY build.sh $SRC/ WORKDIR $WORK/ ================================================ FILE: projects/draco/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sh $SRC/draco/src/draco/tools/fuzz/build.sh ================================================ FILE: projects/draco/project.yaml ================================================ homepage: "https://github.com/google/draco" language: c++ primary_contact: "fgalligan@google.com" auto_ccs: - "ostava@google.com" - "vytyaz@google.com" fuzzing_engines: - libfuzzer - honggfuzz - centipede main_repo: 'https://github.com/google/draco' file_github_issue: True ================================================ FILE: projects/dragonfly/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone https://github.com/dragonflyoss/Dragonfly COPY build.sh $SRC/ WORKDIR $SRC/Dragonfly ================================================ FILE: projects/dragonfly/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/dragonflyoss/Dragonfly/dfget/core/uploader FuzzParseParams uploader_fuzz compile_go_fuzzer github.com/dragonflyoss/Dragonfly/supernode/daemon/mgr/cdn Fuzz cdn_fuzz ================================================ FILE: projects/dragonfly/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/dragonflyoss/Dragonfly" primary_contact: "zj3142063@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/dragonflyoss/Dragonfly' ================================================ FILE: projects/dropbear/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y libz-dev autoconf mercurial RUN hg clone https://hg.ucc.asn.au/dropbear-fuzzcorpus dropbear-corpus RUN git clone https://github.com/mkj/dropbear dropbear WORKDIR dropbear COPY build.sh *.options $SRC/ ================================================ FILE: projects/dropbear/build.sh ================================================ #!/bin/bash # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/dropbear/configure --enable-fuzz --disable-harden --disable-zlib make -j$(nproc) fuzz-targets FUZZLIB=$LIB_FUZZING_ENGINE TARGETS="$(make list-fuzz-targets)" make -C $SRC/dropbear-corpus cp -v $TARGETS $OUT/ cp -v *.options $OUT/ cp -v $SRC/dropbear-corpus/*.zip $OUT/ cp -v $SRC/dropbear-corpus/*.dict $OUT/ ================================================ FILE: projects/dropbear/project.yaml ================================================ homepage: "https://matt.ucc.asn.au/dropbear/dropbear.html" language: c++ primary_contact: "matt@ucc.asn.au" builds_per_day: 4 main_repo: "https://github.com/mkj/dropbear" ================================================ FILE: projects/dropwizard/DefaultServerFactoryFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.health.HealthCheckRegistry; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactoryBuilder; import com.fasterxml.jackson.databind.ObjectMapper; import io.dropwizard.core.Configuration; import io.dropwizard.core.server.DefaultServerFactory; import io.dropwizard.core.setup.Environment; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-6 // Heuristic name: jvm-autofuzz-heuristics-6 // Target method: [io.dropwizard.core.server.DefaultServerFactory] public void // configure(io.dropwizard.core.setup.Environment) public class DefaultServerFactoryFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { DefaultServerFactory obj = new DefaultServerFactory(); obj.setAdminMaxThreads(data.consumeInt()); obj.setAdminMinThreads(data.consumeInt()); obj.setApplicationContextPath(data.consumeString(data.remainingBytes() / 2)); obj.setAdminContextPath(data.consumeString(data.remainingBytes() / 2)); obj.configure(new Environment(data.consumeRemainingAsString())); } } ================================================ FILE: projects/dropwizard/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN curl -L https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz -o jdk.tar.gz && \ tar zxf jdk.tar.gz && \ rm -rf jdk.tar.gz ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn ENV JAVA_HOME="$SRC/jdk-17" RUN git clone --depth 1 https://github.com/dropwizard/dropwizard dropwizard COPY *.sh *.java $SRC/ WORKDIR $SRC/dropwizard ================================================ FILE: projects/dropwizard/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) JARFILE_LIST= for JARFILE in $(find ./ -name *.jar) do if [[ "$JARFILE" == *"target/"* ]] && [[ "$JARFILE" != *original*.jar ]] then if [[ "$JARFILE" != *sources.jar ]] && [[ "$JARFILE" != *javadoc.jar ]] && [[ "$JARFILE" != *tests.jar ]] then cp $JARFILE $OUT/ JARFILE_LIST="$JARFILE_LIST$(basename $JARFILE) " fi fi done curr_dir=$(pwd) rm -rf $OUT/jar_temp mkdir $OUT/jar_temp cd $OUT/jar_temp for JARFILE in $JARFILE_LIST do jar -xf $OUT/$JARFILE done cd $curr_dir cp -r $JAVA_HOME $OUT/ BUILD_CLASSPATH=$JAZZER_API_PATH:$OUT/jar_temp RUNTIME_CLASSPATH=\$this_dir/jar_temp:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) $JAVA_HOME/bin/javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi export JAVA_HOME=\$this_dir/$(basename $JAVA_HOME) export LD_LIBRARY_PATH="\$JAVA_HOME/lib/server":\$this_dir export PATH=\$JAVA_HOME/bin:\$PATH \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/dropwizard/project.yaml ================================================ homepage: https://github.com/dropwizard/dropwizard main_repo: https://github.com/dropwizard/dropwizard language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/duckdb/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth=1 https://github.com/duckdb/duckdb duckdb WORKDIR duckdb COPY build.sh $SRC/ ================================================ FILE: projects/duckdb/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make relassert CRASH_ON_ASSERT=1 DISABLE_SANITIZER=1 EXTENSION_LIBS=$(find ./build/relassert/extension/ -name "*.a") THIRD_PARTY_LIBS=$(find ./build/relassert/third_party/ -name "*.a") $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./test/ossfuzz/parse_fuzz_test.cpp \ -o $OUT/parse_fuzz_test -I./ -I./src/include \ ./build/relassert/src/libduckdb_static.a \ ${EXTENSION_LIBS} ${THIRD_PARTY_LIBS} ================================================ FILE: projects/duckdb/project.yaml ================================================ homepage: "https://duckdb.org/" language: c++ primary_contact: "quack@duckdb.org" main_repo: "https://github.com/duckdb/duckdb/" auto_ccs: - "hannes.muehleisen@gmail.com" - "mark@duckdblabs.com" - "david@adalogics.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/dulwich/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN git clone https://github.com/jelmer/dulwich.git dulwich RUN $SRC/dulwich/fuzzing/oss-fuzz-scripts/container-environment-bootstrap.sh COPY *.sh $SRC/ WORKDIR $SRC/dulwich ================================================ FILE: projects/dulwich/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ . "$SRC/dulwich/fuzzing/oss-fuzz-scripts/build.sh" ================================================ FILE: projects/dulwich/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/jelmer/dulwich" main_repo: "https://github.com/jelmer/dulwich" language: python primary_contact: "jvernooij@gmail.com" auto_ccs: - "david.js.lakin@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/e2fsprogs/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y git make texinfo RUN git clone --depth 1 https://github.com/tytso/e2fsprogs COPY build.sh $SRC/ COPY fuzz/ $SRC/fuzz/ WORKDIR $SRC/e2fsprogs ================================================ FILE: projects/e2fsprogs/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project export LDFLAGS="$CXXFLAGS" $SRC/e2fsprogs/configure make -j$(nproc) all # build fuzzers for fuzzer in $(find $SRC/fuzz -name '*_fuzzer.cc'); do fuzzer_basename=$(basename -s .cc $fuzzer) $CXX $CXXFLAGS \ $LIB_FUZZING_ENGINE \ -I $SRC/e2fsprogs/lib \ $fuzzer \ -L'./lib/ext2fs' -lext2fs \ -L'./lib/et' -lcom_err \ -o $OUT/$fuzzer_basename done ================================================ FILE: projects/e2fsprogs/fuzz/ext2fs_check_directory_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include "ext2fs/ext2fs.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { static const char* fname = "/tmp/ext2_test_file"; // Write our data to a temp file. int fd = open(fname, O_RDWR|O_CREAT|O_TRUNC); write(fd, data, size); close(fd); ext2_filsys fs; errcode_t retval = ext2fs_open( fname, EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, unix_io_manager, &fs); if (!retval) { retval = ext2fs_check_directory(fs, EXT2_ROOT_INO); ext2fs_close(fs); } return 0; } ================================================ FILE: projects/e2fsprogs/fuzz/ext2fs_image_read_write_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include "ext2fs/ext2fs.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { enum FuzzerType { ext2fsImageBitmapRead, ext2fsImageInodeRead, ext2fsImageSuperRead, ext2fsImageBitmapWrite, ext2fsImageInodeWrite, ext2fsImageSuperWrite, kMaxValue = ext2fsImageSuperWrite }; FuzzedDataProvider stream(data, size); const FuzzerType f = stream.ConsumeEnum(); (void) stream.ConsumeIntegral(); // Keep this here to not spoil the corpus or reproducers static const char* fname = "ext2_test_file"; // Write our data to a temp file. int fd = syscall(SYS_memfd_create, fname, 0); std::vector buffer = stream.ConsumeRemainingBytes(); write(fd, buffer.data(), buffer.size()); std::string fspath("/proc/self/fd/" + std::to_string(fd)); ext2_filsys fs; errcode_t retval = ext2fs_open( fspath.c_str(), EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, unix_io_manager, &fs); if (!retval) { switch (f) { case ext2fsImageBitmapRead: { ext2fs_image_bitmap_read(fs, fd, 0); break; } case ext2fsImageInodeRead: { ext2fs_image_inode_read(fs, fd, 0); break; } case ext2fsImageSuperRead: { ext2fs_image_super_read(fs, fd, 0); break; } case ext2fsImageBitmapWrite: { ext2fs_image_bitmap_write(fs, fd, 0); break; } case ext2fsImageInodeWrite: { ext2fs_image_inode_write(fs, fd, 0); break; } case ext2fsImageSuperWrite: { ext2fs_image_super_write(fs, fd, 0); break; } default: { assert(false); } } ext2fs_close(fs); } close(fd); return 0; } ================================================ FILE: projects/e2fsprogs/fuzz/ext2fs_read_bitmap_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include "ext2fs/ext2fs.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { enum FuzzerType { ext2fsReadBlockBitmap, ext2fsReadInodeBitmap, kMaxValue = ext2fsReadInodeBitmap }; FuzzedDataProvider stream(data, size); const FuzzerType f = stream.ConsumeEnum(); (void) stream.ConsumeIntegral(); static const char* fname = "ext2_test_file"; // Write our data to a temp file. int fd = syscall(SYS_memfd_create, fname, 0); std::vector buffer = stream.ConsumeRemainingBytes(); write(fd, buffer.data(), buffer.size()); std::string fspath("/proc/self/fd/" + std::to_string(fd)); ext2_filsys fs; errcode_t retval = ext2fs_open( fspath.c_str(), EXT2_FLAG_IGNORE_CSUM_ERRORS, 0, 0, unix_io_manager, &fs); if (!retval) { switch (f) { case ext2fsReadBlockBitmap: { ext2fs_read_block_bitmap(fs); break; } case ext2fsReadInodeBitmap: { ext2fs_read_inode_bitmap(fs); break; } default: { assert(false); } } ext2fs_close(fs); } close(fd); return 0; } ================================================ FILE: projects/e2fsprogs/project.yaml ================================================ homepage: "https://github.com/tytso/e2fsprogs" language: c primary_contact: "tytso@mit.edu" auto_ccs: - "theodore.tso@gmail.com" - "tytso@google.com" - "mxms@google.com" main_repo: 'https://github.com/tytso/e2fsprogs' base_os_version: ubuntu-24-04 fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/easywsclient/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/dhbaird/easywsclient easywsclient WORKDIR easywsclient COPY build.sh *.cpp $SRC/ ================================================ FILE: projects/easywsclient/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ for f in $(find $SRC -name '*_fuzzer.cpp'); do b=$(basename -s .cpp $f) $CXX $CXXFLAGS -std=c++17 -g easywsclient.cpp -I. \ $f -o $OUT/$b $LIB_FUZZING_ENGINE done ================================================ FILE: projects/easywsclient/easyws_fuzzer.cpp ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "easywsclient.hpp" #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string str(reinterpret_cast(data), size); easywsclient::WebSocket::from_url(str); return 0; } ================================================ FILE: projects/easywsclient/project.yaml ================================================ homepage: "https://github.com/dhbaird/easywsclient" language: c++ primary_contact: "dhbaird@gmail.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/dhbaird/easywsclient' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/ecc-diff-fuzzer/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust ENV GOPATH /root/go ENV PATH $PATH:/root/.go/bin:$GOPATH/bin RUN install_go.sh RUN apt-get update && apt-get install -y make cmake bzip2 autoconf automake gettext libtool python curl RUN rustup target add i686-unknown-linux-gnu #use different package sources for recent npm RUN curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh RUN bash nodesource_setup.sh RUN apt install -y nodejs RUN npm install -g browserify RUN npm install elliptic # mbedtls needs jsonschema which needs rpds-py which needs pip>=20 # or a Rust toolchain. RUN pip3 install 'pip>=20' RUN git clone --depth 1 https://github.com/bellard/quickjs quickjs RUN git clone --depth 1 https://github.com/catenacyber/elliptic-curve-differential-fuzzer.git ecfuzzer RUN git clone --recursive --depth 1 -b development https://github.com/Mbed-TLS/mbedtls.git mbedtls # needed to compile mbedtls RUN pip3 install -r $SRC/mbedtls/scripts/basic.requirements.txt RUN git clone --depth 1 https://github.com/libecc/libecc.git libecc RUN git clone --depth 1 https://github.com/openssl/openssl.git openssl RUN git clone --depth 1 git://git.gnupg.org/libgpg-error.git libgpg-error RUN git clone --depth 1 git://git.gnupg.org/libgcrypt.git gcrypt RUN git clone --depth 1 https://github.com/weidai11/cryptopp cryptopp ADD https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.bz2 gmp-6.2.1.tar.bz2 RUN git clone --depth 1 https://github.com/gnutls/nettle.git nettle RUN git clone --depth 1 https://github.com/randombit/botan.git botan WORKDIR $SRC/ COPY build.sh $SRC/ ================================================ FILE: projects/ecc-diff-fuzzer/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # use a linker that supports Dwarf v5 export LDFLAGS="-fuse-ld=lld" # build projects #nettle ( cd nettle tar -xvf ../gmp-6.2.1.tar.bz2 cd gmp-6.2.1 #do not use assembly instructions as we do not know if they will be available on the machine who will run the fuzzer #we could do instead --enable-fat ./configure --disable-shared --disable-assembly make -j$(nproc) make install cd .. autoreconf ./configure --disable-shared --disable-openssl make -j$(nproc) make install ) #cryptopp ( cd cryptopp make -j$(nproc) make install ) #gcrypt ( cd libgpg-error # fix for following error # error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version 0.19 but the autoconf macros are from gettext version 0.20 timeout 3 gettextize -f || true ./autogen.sh if [ "$ARCHITECTURE" = 'i386' ]; then ./configure -host=i386 --disable-doc --enable-static --disable-shared else ./configure --disable-doc --enable-static --disable-shared fi make -j$(nproc) make install cd ../gcrypt ./autogen.sh if [ "$ARCHITECTURE" = 'i386' ]; then ./configure -host=i386 --enable-static --disable-shared --disable-doc --enable-maintainer-mode else ./configure --enable-static --disable-shared --disable-doc --enable-maintainer-mode fi make -j$(nproc) make install # defined at aria.o:(aria_encrypt) in archive /lib/x86_64-linux-gnu/libcrypto.a sed -i -e s/aria_encrypt/ariagencrypt/ /usr/local/lib/libgcrypt.a ) #mbedtls ( cd mbedtls if [ "$ARCHITECTURE" = 'i386' ]; then export CFLAGS="$CFLAGS -maes -mpclmul" fi cmake . -DENABLE_PROGRAMS=0 -DENABLE_TESTING=0 make -j$(nproc) all make install ) #openssl ( cd openssl #option to not have the same exported function poly1305_blocks as in gcrypt if [ "$ARCHITECTURE" = 'i386' ]; then setarch i386 ./config no-poly1305 no-shared no-threads -m32 else ./config no-poly1305 no-shared no-threads fi make build_generated libcrypto.a make install ) #libecc ( cd libecc #required by libecc (export CFLAGS="$CFLAGS -fPIC"; make; cp build/*.a /usr/local/lib; cp -r include/* /usr/local/include/) ) #botan ( cd botan if [ "$ARCHITECTURE" = 'i386' ]; then ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" \ --disable-shared --disable-modules=locking_allocator --disable-shared-library \ --without-os-features=getrandom,getentropy --cpu x86_32 else ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" \ --disable-shared --disable-modules=locking_allocator --disable-shared-library \ --without-os-features=getrandom,getentropy fi make -j$(nproc) libs make install ) #quickjs ( cd quickjs if [ "$ARCHITECTURE" = 'i386' ]; then make qjsc cp qjsc /usr/local/bin/ make clean # Makefile should not override CFLAGS sed -i -e 's/CFLAGS=/CFLAGS+=/' Makefile CFLAGS="-m32" make libquickjs.a else make && make install fi cp quickjs*.h /usr/local/include/ cp libquickjs.a /usr/local/lib/ ) export CARGO_BUILD_TARGET="x86_64-unknown-linux-gnu" #build fuzz target cd ecfuzzer if [ "$ARCHITECTURE" = 'i386' ]; then export GOARCH=386 #needed explicitly because of cross compilation cf https://golang.org/cmd/cgo/ export CGO_ENABLED=1 export CARGO_BUILD_TARGET=i686-unknown-linux-gnu fi zip -r fuzz_ec_seed_corpus.zip corpus/ cp fuzz_ec_seed_corpus.zip $OUT/ cp fuzz_ec.dict $OUT/ cp fuzz_ec.dict $OUT/fuzz_ec_noblocker.dict mkdir build cd build #no afl with long javascript initialization if [ "$FUZZING_ENGINE" != 'afl' ]; then cmake .. make -j$(nproc) cp ecfuzzer $OUT/fuzz_ec rm -Rf * fi #another target without javascript cmake -DDISABLE_JS=ON .. make -j$(nproc) cp ecfuzzer $OUT/fuzz_ec_noblocker ================================================ FILE: projects/ecc-diff-fuzzer/project.yaml ================================================ homepage: "https://github.com/catenacyber/elliptic-curve-differential-fuzzer" language: c++ primary_contact: "p.antoine@catenacyber.fr" fuzzing_engines: - afl - honggfuzz - libfuzzer main_repo: https://github.com/catenacyber/elliptic-curve-differential-fuzzer architectures: - x86_64 - i386 ================================================ FILE: projects/ecdsa-python/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/starkbank/ecdsa-python/ WORKDIR $SRC COPY build.sh $SRC/ COPY fuzz_* $SRC/ ================================================ FILE: projects/ecdsa-python/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd ecdsa-python python3 ./setup.py install # Build fuzzers for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/ecdsa-python/fuzz_private_key.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): from ellipticcurve import Ecdsa, Signature, PublicKey, PrivateKey @atheris.instrument_func def TestOneInput(input_bytes): fdp = atheris.FuzzedDataProvider(input_bytes) privateKey1 = PrivateKey() publicKey1 = privateKey1.publicKey() privateKeyPem = privateKey1.toPem() publicKeyPem = publicKey1.toPem() privateKey2 = PrivateKey.fromPem(privateKeyPem) publicKey2 = PublicKey.fromPem(publicKeyPem) message = fdp.ConsumeUnicode(sys.maxsize) signatureBase64 = Ecdsa.sign(message=message, privateKey=privateKey2).toBase64() signature = Signature.fromBase64(signatureBase64) assert(Ecdsa.verify(message=message, signature=signature, publicKey=publicKey2)) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ecdsa-python/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/starkbank/ecdsa-python language: python main_repo: https://github.com/starkbank/ecdsa-python/ sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/eclipse-equinox/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # # install maven configuration, which is also used by gradles's publishToMavenLocal # ADD maven-settings.xml ${SRC}/ RUN apt-get install -y xmlstarlet RUN mkdir -p ~/.m2 && \ xmlstarlet ed \ -u "settings/localRepository" -v "${OUT}/m2/repository" \ < ${SRC}/maven-settings.xml > ~/.m2/settings.xml # # install maven and gradle # RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.8.7 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.8.7/apache-maven-3.8.7/bin/mvn RUN curl -L https://services.gradle.org/distributions/gradle-7.6-bin.zip -o gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE $SRC/gradle/gradle-7.6/bin/gradle ENV LIBRARY_NAME equinox WORKDIR ${SRC} # # Clone repository. eclipse-equinox has an auxillary repository, which # also has to be cloned... # RUN git clone https://github.com/eclipse-equinox/equinox RUN git clone https://github.com/eclipse-equinox/equinox.binaries # # Multiple JDK versions are required in order to build equinox, and they # also need to be configured into a maven toolchain for concurrent use. # RUN apt update && apt install -y openjdk-8-jdk-headless openjdk-11-jdk-headless openjdk-17-jdk-headless ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64 ADD maven-toolchains.xml ${SRC}/ RUN mkdir -p ~/.m2 && \ cp ${SRC}/maven-toolchains.xml ~/.m2/toolchains.xml ADD build.sh ${SRC}/ ADD ${LIBRARY_NAME}-fuzzer ${SRC}/${LIBRARY_NAME}-fuzzer/ WORKDIR ${SRC}/${LIBRARY_NAME} ================================================ FILE: projects/eclipse-equinox/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SRC_SUBDIR="" #MVN_FLAGS="-Djavac.src.version=17 -Djavac.target.version=17 -DskipTests -Drt.equinox.binaries.loc=${SRC}/equinox.binaries" MVN_FLAGS="-DskipTests -Drt.equinox.binaries.loc=${SRC}/equinox.binaries -Pbuild-individual-bundles -Pbree-libs -Papi-check -Dcompare-version-with-baselines.skip=false -Dproject.build.sourceEncoding=UTF-8 -Dmaven.test.failure.ignore=true" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.14.0" \ -Dpackaging=jar popd # Build needs to be run in the CVSROOT pushd "${SRC}/${LIBRARY_NAME}/${SRC_SUBDIR}" ${MVN} install ${MVN_FLAGS} popd # ... while the subprojects have varying versions pushd "${SRC}/${LIBRARY_NAME}/bundles/org.eclipse.osgi" CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}-fuzzer" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/eclipse-equinox/equinox-fuzzer/pom.xml ================================================ 4.0.0 ossfuzz equinox-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 3.18.200 com.code-intelligence jazzer-api 0.14.0 org.eclipse.osgi org.eclipse.osgi ${fuzzedLibaryVersion} org.eclipse.platform org.eclipse.core.runtime 3.26.100 org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/eclipse-equinox/equinox-fuzzer/src/main/java/org/eclipse/osgi/ConditionInfoFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package org.eclipse.osgi; import org.osgi.service.condpermadmin.ConditionInfo; import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ConditionInfoFuzzer { private FuzzedDataProvider fuzzedDataProvider; public ConditionInfoFuzzer(FuzzedDataProvider fuzzedDataProvider) throws Exception { this.fuzzedDataProvider = fuzzedDataProvider; } void test() { try { ConditionInfo info = new ConditionInfo(fuzzedDataProvider.consumeRemainingAsAsciiString()); info.toString(); } catch (IllegalArgumentException ex) { /* ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { ConditionInfoFuzzer fixture = new ConditionInfoFuzzer(fuzzedDataProvider); fixture.test(); } } ================================================ FILE: projects/eclipse-equinox/maven-settings.xml ================================================ ${user.home}/.m2/repository ================================================ FILE: projects/eclipse-equinox/maven-toolchains.xml ================================================ jdk JavaSE-1.8 /usr/lib/jvm/java-8-openjdk-amd64 jdk 11 /usr/lib/jvm/java-11-openjdk-amd64 jdk 17 /usr/lib/jvm/java-17-openjdk-amd64 ================================================ FILE: projects/eclipse-equinox/project.yaml ================================================ homepage: "https://github.com/eclipse-equinox/equinox" language: jvm main_repo: "https://github.com/eclipse-equinox/equinox" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/edk2/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ python3 nasm uuid-dev RUN git clone https://github.com/tianocore/edk2.git --recursive RUN git clone https://github.com/intel/hbfa-fl COPY build.sh $SRC/ ================================================ FILE: projects/edk2/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Fix hbfa-fl compatibility with edk2 that removed GCC5/GCC48/GCC49 toolchains. # Replace GCC5_/GCC48_/GCC49_ macro references with GCC_ in the customized tools_def. sed -i 's/GCC5_/GCC_/g; s/GCC48_/GCC_/g; s/GCC49_/GCC_/g' \ $SRC/hbfa-fl/HBFA/UefiHostFuzzTestPkg/Conf/tools_def.customized # Fix HBFAEnvSetup.py regex to match new GCC_ALL_CC_FLAGS (no version digits). sed -i 's/GCC\\\\d{1,2}_ALL_CC_FLAGS/GCC\\\\d{0,2}_ALL_CC_FLAGS/' \ $SRC/hbfa-fl/HBFA/UefiHostTestTools/HBFAEnvSetup.py # Fix RunLibFuzzer.py to use GCC toolchain instead of removed GCC5. sed -i 's/BuildCmdList.append(.GCC5.)/BuildCmdList.append("GCC")/' \ $SRC/hbfa-fl/HBFA/UefiHostTestTools/RunLibFuzzer.py hbfa-fl/oss-fuzz/build.sh ================================================ FILE: projects/edk2/project.yaml ================================================ homepage: "https://www.tianocore.org" language: c fuzzing_engines: - libfuzzer sanitizers: - address - undefined primary_contact: "tamas.k.lengyel@gmail.com" auto_ccs: - "rowanbhart@gmail.com" vendor_ccs: - "edk2-hbfa-ossfuzz@intel.com" main_repo: "https://github.com/tianocore/edk2" file_github_issue: false ================================================ FILE: projects/eigen/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install --yes cmake mercurial RUN git clone https://gitlab.com/libeigen/eigen.git WORKDIR eigen COPY build.sh *.cc $SRC/ ================================================ FILE: projects/eigen/basicstuff_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "Eigen/Core" namespace { static constexpr Eigen::Index kEigenTestMaxSize = 64; static constexpr Eigen::Index kEigenIndexOne = static_cast(1); template T ConsumeValue(FuzzedDataProvider* stream) { return stream->ConsumeIntegral(); } template <> float ConsumeValue(FuzzedDataProvider* stream) { return stream->ConsumeFloatingPoint(); } template <> double ConsumeValue(FuzzedDataProvider* stream) { return stream->ConsumeFloatingPoint(); } template <> long double ConsumeValue(FuzzedDataProvider* stream) { return stream->ConsumeFloatingPoint(); } template <> std::complex ConsumeValue(FuzzedDataProvider* stream) { return std::complex(stream->ConsumeFloatingPoint(), stream->ConsumeFloatingPoint()); } template <> std::complex ConsumeValue(FuzzedDataProvider* stream) { return std::complex(stream->ConsumeFloatingPoint(), stream->ConsumeFloatingPoint()); } template MatrixType GenerateTestMatrix(size_t rows, size_t cols, FuzzedDataProvider* stream) { std::vector test_data(rows * cols); for (auto& value : test_data) { value = ConsumeValue(stream); } Eigen::Map mapped_map(test_data.data(), rows, cols); return MatrixType(mapped_map); } template void basicStuff(const MatrixType& m, FuzzedDataProvider* stream) { typedef typename MatrixType::Scalar Scalar; typedef Eigen::Matrix VectorType; typedef Eigen::Matrix SquareMatrixType; Eigen::Index rows = m.rows(); Eigen::Index cols = m.cols(); MatrixType m1 = GenerateTestMatrix(rows, cols, stream), m2 = GenerateTestMatrix(rows, cols, stream), m3(rows, cols), mzero = MatrixType::Zero(rows, cols), square = GenerateTestMatrix< Eigen::Matrix>(rows, rows, stream); VectorType v1 = GenerateTestMatrix(rows, 1, stream), vzero = VectorType::Zero(rows); SquareMatrixType sm1 = SquareMatrixType::Random(rows, rows), sm2(rows, rows); Scalar x = ConsumeValue(stream); Eigen::Index r = stream->ConsumeIntegralInRange( std::min(kEigenIndexOne, rows - 1), rows - 1), c = stream->ConsumeIntegralInRange( std::min(kEigenIndexOne, cols - 1), cols - 1); m1.coeffRef(r, c) = x; m1(r, c) = x; v1.coeffRef(r) = x; v1(r) = x; v1[r] = x; Eigen::Index r1 = stream->ConsumeIntegralInRange( static_cast(0), std::min(static_cast(127), rows - 1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); x = v1(static_cast(r1)); // now test copying a row-vector into a (column-)vector and conversely. square.col(r) = square.row(r).eval(); Eigen::Matrix rv(rows); Eigen::Matrix cv(rows); rv = square.row(r); cv = square.col(r); cv.transpose(); m3.real() = m1.real(); m1 = m2; sm2.setZero(); for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i) = sm1.row(i); sm2.setZero(); for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() = sm1.row(i); sm2.setZero(); for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() += sm1.row(i); sm2.setZero(); for (Eigen::Index i = 0; i < rows; ++i) sm2.col(i).noalias() -= sm1.row(i); } template void basicStuffComplex(const MatrixType& m, FuzzedDataProvider* stream) { typedef typename MatrixType::Scalar Scalar; typedef typename Eigen::NumTraits::Real RealScalar; typedef Eigen::Matrix RealMatrixType; Eigen::Index rows = m.rows(); Eigen::Index cols = m.cols(); RealMatrixType rm1 = GenerateTestMatrix(rows, cols, stream), rm2 = GenerateTestMatrix(rows, cols, stream); MatrixType cm(rows, cols); cm.real() = rm1; cm.imag() = rm2; rm1.setZero(); rm2.setZero(); rm1 = cm.real(); rm2 = cm.imag(); cm.real().setZero(); } } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider stream(data, size); basicStuff( Eigen::MatrixXcf( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); basicStuff( Eigen::MatrixXi( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); basicStuff( Eigen::MatrixXcd( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); basicStuff( Eigen::Matrix( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); basicStuffComplex( Eigen::MatrixXcf( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); basicStuffComplex( Eigen::MatrixXcd( stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize), stream.ConsumeIntegralInRange(kEigenIndexOne, kEigenTestMaxSize)), &stream); return 0; } ================================================ FILE: projects/eigen/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project mkdir build_dir && cd build_dir cmake .. make install cd .. # build fuzzers for fuzzers in $(find $SRC -name '*_fuzzer.cc'); do fuzz_basename=$(basename -s .cc $fuzzers) $CXX $CXXFLAGS -I. -Isrc/Eigen/Core \ $fuzzers -o $OUT/$fuzz_basename $LIB_FUZZING_ENGINE done ================================================ FILE: projects/eigen/project.yaml ================================================ homepage: "http://eigen.tuxfamily.org/index.php?title=Main_Page" language: c++ primary_contact: "eigen-core-team@lists.tuxfamily.org" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://gitlab.com/libeigen/eigen.git' ================================================ FILE: projects/eigen/solver_fuzzer.cc ================================================ // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include "Eigen/Core" using ::Eigen::Matrix; using ::Eigen::Dynamic; using ::Eigen::Lower; using ::Eigen::Upper; int ConsumeNextInt(const uint8_t** data, size_t* size) { if (*size < sizeof(int)) { return 0; } int result; memcpy(&result, *data, sizeof(int)); *size -= sizeof(int); *data += sizeof(int); return result; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { const size_t rows = static_cast(ConsumeNextInt(&data, &size)); const size_t columns = static_cast(ConsumeNextInt(&data, &size)); if (rows == 0 || columns == 0) { return 0; } if (rows > 1024 || columns > 1024) { return 0; } // We can do this same fuzz test with other templated types. Here, we just use // an int. Matrix vec(rows); for (size_t i = 0; i < rows; ++i) { vec(i) = ConsumeNextInt(&data, &size); } Matrix matrix(rows, columns); for (int i = 0; i < rows; ++i) { for (int j = 0; j < columns; ++j) { matrix(i, j) = ConsumeNextInt(&data, &size); } } matrix.template triangularView().solve(vec); matrix.template triangularView().solve(vec); matrix.conjugate().template triangularView().solve(vec); matrix.conjugate().template triangularView().solve(vec); matrix.transpose().template triangularView().solve(vec); matrix.transpose().template triangularView().solve(vec); return 0; } ================================================ FILE: projects/elfutils/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && \ apt-get install -y pkg-config make autoconf autopoint zlib1g-dev zlib1g-dev:i386 flex gawk bison RUN git clone --depth 1 https://sourceware.org/git/elfutils.git WORKDIR elfutils COPY build.sh *.c *.zip $SRC/ ================================================ FILE: projects/elfutils/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This script is supposed to be compatible with OSS-Fuzz, i.e. it has to use # environment variables like $CC, $CFLAGS, $OUT, link the fuzz targets with CXX # (even though the project is written in C) and so on: # https://google.github.io/oss-fuzz/getting-started/new-project-guide/#buildsh # It can be used to build and run the fuzz targets using Docker and the images # provided by the OSS-Fuzz project: https://google.github.io/oss-fuzz/advanced-topics/reproducing/#building-using-docker # It can also be used to build and run the fuzz target locally without Docker. # After installing clang and the build dependencies of libelf by running something # like `dnf build-dep elfutils-devel` on Fedora or `apt-get build-dep libelf-dev` # on Debian/Ubuntu, the following commands should be run: # # $ git clone https://github.com/google/oss-fuzz # $ cd oss-fuzz/projects/elfutils # $ git clone https://sourceware.org/git/elfutils.git # $ ./build.sh # $ wget -O fuzz-dwfl-core-corpus.zip "https://storage.googleapis.com/elfutils-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/elfutils_fuzz-dwfl-core/public.zip" # $ unzip -d CORPUS fuzz-dwfl-core-corpus.zip # $ ./out/fuzz-dwfl-core CORPUS/ set -eux SANITIZER=${SANITIZER:-address} flags="-O1 -fno-omit-frame-pointer -g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link" export CC=${CC:-clang} export CFLAGS=${CFLAGS:-$flags} export CXX=${CXX:-clang++} export CXXFLAGS=${CXXFLAGS:-$flags} export SRC=${SRC:-$(realpath -- $(dirname -- "$0"))} export OUT=${OUT:-"$SRC/out"} mkdir -p "$OUT" export LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE:--fsanitize=fuzzer} cd "$SRC/elfutils" # ASan isn't compatible with -Wl,--no-undefined: https://github.com/google/sanitizers/issues/380 sed -i 's/^\(NO_UNDEFINED=\).*/\1/' configure.ac # ASan isn't compatible with -Wl,-z,defs either: # https://clang.llvm.org/docs/AddressSanitizer.html#usage sed -i 's/^\(ZDEFS_LDFLAGS=\).*/\1/' configure.ac # srcfiles.cxx started failing to compile with the OSS-Fuzz toolchain # when it was switched from clang-18.0.0 to clang-18.1.8 in # https://github.com/google/oss-fuzz/pull/12365. # https://github.com/google/oss-fuzz/pull/12365#discussion_r1784702452 # It's probably an OSS-Fuzz toolchain bug but it doesn't matter much # because the srcfiles binary isn't relevant in terms of fuzzing and # can safely be excluded. sed -i 's/^\(srcfiles_\)/#/' src/Makefile.am sed -i 's/\bsrcfiles\b//' src/Makefile.am if [[ "$SANITIZER" == undefined ]]; then additional_ubsan_checks=alignment UBSAN_FLAGS="-fsanitize=$additional_ubsan_checks -fno-sanitize-recover=$additional_ubsan_checks" CFLAGS="$CFLAGS $UBSAN_FLAGS" CXXFLAGS="$CXXFLAGS $UBSAN_FLAGS" # That's basicaly what --enable-sanitize-undefined does to turn off unaligned access # elfutils heavily relies on on i386/x86_64 but without changing compiler flags along the way sed -i 's/\(check_undefined_val\)=[0-9]/\1=1/' configure.ac fi if [[ "$SANITIZER" == memory ]]; then CFLAGS+=" -U_FORTIFY_SOURCE" CXXFLAGS+=" -U_FORTIFY_SOURCE" fi $CC --version autoreconf -i -f if ! ./configure --enable-maintainer-mode --disable-debuginfod --disable-libdebuginfod \ --disable-demangler --without-bzlib --without-lzma --without-zstd \ CC="$CC" CFLAGS="-Wno-error $CFLAGS" CXX="$CXX" CXXFLAGS="-Wno-error $CXXFLAGS" LDFLAGS="$CFLAGS"; then cat config.log exit 1 fi ASAN_OPTIONS=detect_leaks=0 make -j$(nproc) V=1 # External dependencies used by the fuzz targets have to be built # with MSan explicitly to avoid bogus "security" bug reports like # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=45630, # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=45631 and # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=45633 # To make sure all the fuzz targets use the same version of zlib # it's also built with ASan and UBSan. git clone https://github.com/madler/zlib pushd zlib git checkout v1.3.1 if ! ./configure --static; then cat configure.log exit 1 fi make -j$(nproc) V=1 popd zlib=zlib/libz.a # When new fuzz targets are added it usually makes sense to notify the maintainers of # the elfutils project using the mailing list: elfutils-devel@sourceware.org. There # fuzz targets can be reviewed properly (to make sure they don't fail to compile # with -Werror for example), their names can be chosen accordingly (so as not to spam # the mailing list with bogus bug reports that are opened and closed once they are renamed) # and so on. Also since a lot of bug reports coming out of the blue aren't exactly helpful # fuzz targets should probably be added one at a time to make it easier to keep track # of them. CFLAGS+=" -Werror -Wall -Wextra" CXXFLAGS+=" -Werror -Wall -Wextra" # fuzz-dwfl-core is kind of a systemd fuzz target in the sense that it resembles the # code systemd uses to parse coredumps. Please ping @evverx if it's changed. $CC $CFLAGS \ -D_GNU_SOURCE -DHAVE_CONFIG_H \ -I. -I./lib -I./libelf -I./libebl -I./libdw -I./libdwelf -I./libdwfl -I./libasm \ -c "$SRC/fuzz-dwfl-core.c" -o fuzz-dwfl-core.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-dwfl-core.o \ ./libdw/libdw.a ./libelf/libelf.a ./lib/libeu.a "$zlib" \ -o "$OUT/fuzz-dwfl-core" $CC $CFLAGS \ -D_GNU_SOURCE -DHAVE_CONFIG_H \ -I. -I./lib -I./libelf -I./libebl -I./libdw -I./libdwelf -I./libdwfl -I./libasm \ -c "$SRC/fuzz-libelf.c" -o fuzz-libelf.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-libelf.o \ ./libasm/libasm.a ./libebl/libebl.a ./backends/libebl_backends.a ./libcpu/libcpu.a \ ./libdw/libdw.a ./libelf/libelf.a ./lib/libeu.a "$zlib" \ -o "$OUT/fuzz-libelf" $CC $CFLAGS \ -D_GNU_SOURCE -DHAVE_CONFIG_H \ -I. -I./lib -I./libelf -I./libebl -I./libdw -I./libdwelf -I./libdwfl -I./libasm \ -c "$SRC/fuzz-libdwfl.c" -o fuzz-libdwfl.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz-libdwfl.o \ ./libasm/libasm.a ./libebl/libebl.a ./backends/libebl_backends.a ./libcpu/libcpu.a \ ./libdw/libdw.a ./libelf/libelf.a ./lib/libeu.a "$zlib" \ -o "$OUT/fuzz-libdwfl" ================================================ FILE: projects/elfutils/fuzz-dwfl-core.c ================================================ /* # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include ELFUTILS_HEADER(dwfl) static const Dwfl_Callbacks core_callbacks = { .find_elf = dwfl_build_id_find_elf, .find_debuginfo = dwfl_standard_find_debuginfo, }; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char name[] = "/tmp/fuzz-dwfl-core.XXXXXX"; int fd = -1; ssize_t n; off_t offset; Elf *core = NULL; Dwfl *dwfl = NULL; fd = mkstemp(name); assert(fd >= 0); n = write(fd, data, size); assert(n == (ssize_t) size); offset = lseek(fd, 0, SEEK_SET); assert(offset == 0); elf_version(EV_CURRENT); core = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (core == NULL) goto cleanup; dwfl = dwfl_begin(&core_callbacks); assert(dwfl != NULL); if (dwfl_core_file_report(dwfl, core, NULL) < 0) goto cleanup; if (dwfl_report_end(dwfl, NULL, NULL) != 0) goto cleanup; if (dwfl_core_file_attach(dwfl, core) < 0) goto cleanup; cleanup: dwfl_end(dwfl); elf_end(core); close(fd); unlink(name); return 0; } ================================================ FILE: projects/elfutils/fuzz-libdwfl.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "libdwfl.h" #include "system.h" static const char *debuginfo_path = ""; static const Dwfl_Callbacks cb = { NULL, dwfl_standard_find_debuginfo, NULL, (char **)&debuginfo_path, }; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[] = "/tmp/fuzz-libdwfl.XXXXXX"; int fd; ssize_t n; fd = mkstemp(filename); assert(fd >= 0); n = write_retry(fd, data, size); assert(n == (ssize_t) size); close(fd); Dwarf_Addr bias = 0; Dwfl *dwfl = dwfl_begin(&cb); dwfl_report_begin(dwfl); Dwfl_Module *mod = dwfl_report_offline(dwfl, filename, filename, -1); dwfl_module_getdwarf(mod, &bias); dwfl_end (dwfl); unlink(filename); return 0; } ================================================ FILE: projects/elfutils/fuzz-libelf.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "system.h" void fuzz_logic_one(char *filename, int compression_type) { (void)elf_version(EV_CURRENT); int fd = open(filename, O_RDONLY); Elf *elf = elf_begin(fd, ELF_C_READ, NULL); if (elf != NULL) { size_t strndx; elf_getshdrstrndx(elf, &strndx); Elf_Scn *scn = NULL; // Iterate through sections while ((scn = elf_nextscn(elf, scn)) != NULL) { GElf_Shdr mem; GElf_Shdr *shdr = gelf_getshdr(scn, &mem); const char *name = elf_strptr(elf, strndx, shdr->sh_name); // Two options for reading sections. We keep the code structure // so it resembles the test code. // Compress and get data of the section if ((shdr->sh_flags & SHF_COMPRESSED) != 0) { if (elf_compress(scn, compression_type, 0) >= 0) { elf_getdata(scn, NULL); } } else if (name != NULL) { if (name[0] == '.' && name[1] == 'z') { if (elf_compress_gnu(scn, 0, 0) >= 0) { elf_getdata(scn, NULL); } } } } elf_end(elf); } close(fd); } void fuzz_logic_twice(char *filename, int open_flags, Elf_Cmd cmd) { (void)elf_version(EV_CURRENT); int fd = open(filename, open_flags); Elf *elf = elf_begin(fd, cmd, NULL); if (elf != NULL) { size_t elf_size = 0; elf_rawfile(elf, &elf_size); elf_end(elf); } close(fd); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[] = "/tmp/fuzz-libelf.XXXXXX"; int fd; ssize_t n; fd = mkstemp(filename); assert(fd >= 0); n = write_retry(fd, data, size); assert(n == (ssize_t) size); close(fd); fuzz_logic_one(filename, 0); fuzz_logic_one(filename, 1); fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ); fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR); fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ_MMAP); fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR_MMAP); unlink(filename); return 0; } ================================================ FILE: projects/elfutils/project.yaml ================================================ homepage: "https://sourceware.org/elfutils/" language: c++ builds_per_day: 4 primary_contact: "david@adalogics.com" main_repo: "https://sourceware.org/git/elfutils.git" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined architectures: - x86_64 - i386 view_restrictions: none auto_ccs: - amerey@redhat.com - izzeem@google.com base_os_version: ubuntu-24-04 ================================================ FILE: projects/envoy/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder@sha256:56905c98ae0083d14da0e7371184e694560a74750533f321ac0e9145af0e8d2e # ! This project was pinned after a clang bump. Please remove the pin, Try to fix any build warnings and errors, as well as runtime errors # see https://github.com/google/oss-fuzz/pull/12365 RUN apt-get update && apt-get -y install \ build-essential \ openjdk-8-jdk \ make \ ninja-build \ curl \ autoconf \ libtool \ wget \ golang \ rsync \ python3 RUN git clone https://github.com/envoyproxy/envoy.git WORKDIR $SRC/envoy/ COPY build.sh $SRC/ COPY WORKSPACE $SRC/envoy/ ================================================ FILE: projects/envoy/WORKSPACE ================================================ workspace(name = "envoy") load("//bazel:api_binding.bzl", "envoy_api_binding") envoy_api_binding() load("//bazel:api_repositories.bzl", "envoy_api_dependencies") envoy_api_dependencies() load("//bazel:repositories.bzl", "envoy_dependencies") envoy_dependencies() load("//bazel:bazel_deps.bzl", "envoy_bazel_dependencies") envoy_bazel_dependencies() load("//bazel:repositories_extra.bzl", "envoy_dependencies_extra") envoy_dependencies_extra(ignore_root_user_error=True) load("//bazel:python_dependencies.bzl", "envoy_python_dependencies") envoy_python_dependencies() load("//bazel:dependency_imports.bzl", "envoy_dependency_imports") envoy_dependency_imports() load("//bazel:repo.bzl", "envoy_repo") envoy_repo() load("//bazel:toolchains.bzl", "envoy_toolchains") envoy_toolchains() ================================================ FILE: projects/envoy/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Overcome missing dependency declaration with path mapping issue. This is # similar to the current abseil build (see # https://github.com/google/oss-fuzz/pull/12858), to overcome the issue # mentioned in https://github.com/bazelbuild/bazel/issues/23681. export USE_BAZEL_VERSION=7.4.0 declare -r FUZZ_TARGET_QUERY=' let all_fuzz_tests = attr(tags, "fuzz_target", "test/...") in $all_fuzz_tests - attr(tags, "no_fuzz", $all_fuzz_tests) ' if [ -n "${OSS_FUZZ_CI-}" ] then # CI has fewer resources so restricting to a small number of fuzz targets. # Choosing the header_parser, and header_map_impl. declare -r OSS_FUZZ_TARGETS="$(bazel query "${FUZZ_TARGET_QUERY}" | grep ':header' | sed 's/$/_oss_fuzz/')" else declare -r OSS_FUZZ_TARGETS="$(bazel query "${FUZZ_TARGET_QUERY}" | sed 's/$/_oss_fuzz/')" fi declare -r EXTRA_BAZEL_FLAGS="$( # Disabling layering_check because it breaks the abseil build. See # https://github.com/google/oss-fuzz/blob/f0fa8b5cd3f99b5905e91b336d07a870ca1bc2e3/projects/abseil-cpp/build.sh#L17-L21. echo "--features=-layering_check" if [ -n "$CC" ]; then echo "--action_env=CC=${CC}" fi if [ -n "$CXX" ]; then echo "--action_env=CXX=${CXX}" fi echo "--host_action_env=CC=gcc" if [ "$SANITIZER" = "undefined" ] then # Bazel uses clang to link binary, which does not link clang_rt ubsan library for C++ automatically. # See issue: https://github.com/bazelbuild/bazel/issues/8777 echo "--linkopt=$(clang -print-file-name=libclang_rt.ubsan_standalone_cxx.a)" echo "--linkopt=-fsanitize=undefined" elif [ "$SANITIZER" = "address" ] then echo "--copt=-D__SANITIZE_ADDRESS__" "--copt=-DADDRESS_SANITIZER=1" "--linkopt=-fsanitize=address" fi )" # The Envoy build configuration may clobber CFLAGS/CXXFLAGS, so we use separate # environment variables that are understood by rules_fuzzing. export FUZZING_CFLAGS="$CFLAGS" export FUZZING_CXXFLAGS="$CXXFLAGS" # Disable instrumentation in various external libraries. These # are fuzzed elsewhere. # The following disables both coverage-instrumentation and other sanitizer instrumentation. # We disable instrumentation in: # antlr4 # google_protobuf # absl # googltest # grpc # boringssl # re2 # upb # brotli # cel_cpp # yaml_cpp # wasm_cpp_host # libprotobuf-mutator # google_url (gurl) # lightstep_tracer # In addition to this, we disable instrumentation in all *.pb.cc (protobuf-generated files) # and everything in the bazel-out directory. declare -r DI="$( if [ "$SANITIZER" != "coverage" ] then # Envoy code. Disable coverage instrumentation echo " --per_file_copt=^.*source/extensions/access_loggers/.*\.cc\$@-fsanitize-coverage=0" echo " --per_file_copt=^.*source/common/protobuf/.*\.cc\$@-fsanitize-coverage=0" # Envoy test code. Disable coverage instrumentation echo " --per_file_copt=^.*test/.*\.cc\$@-fsanitize-coverage=0" # External dependencies. Disable all instrumentation. echo " --per_file_copt=^.*com_google_protobuf.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_google_absl.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_github_grpc_grpc.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*boringssl.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_googlesource_code_re2.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*upb.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*org_brotli.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_github_jbeder_yaml_cpp.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*proxy_wasm_cpp_host/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_github_google_libprotobuf_mutator/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_googlesource_googleurl/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*com_lightstep_tracer_cpp/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" # External dependency which needs to be compiled with sanitizers. Disable # coverage instrumentation. echo " --per_file_copt=^.*com_google_cel_cpp.*\.cpp\$@-fsanitize-coverage=0" echo " --per_file_copt=^.*antlr4_runtimes.*\.cpp\$@-fsanitize-coverage=0" echo " --per_file_copt=^.*googletest.*\.cc\$@-fsanitize-coverage=0" # All protobuf code and code in bazel-out echo " --per_file_copt=^.*\.pb\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" echo " --per_file_copt=^.*bazel-out/.*\.cc\$@-fsanitize-coverage=0,-fno-sanitize=all" fi )" # Asssuming we have ~32 cores and ~28.8 GiB RAM. By limiting the # number of CPUs (--local_cpu_resources) we limit the per-CPU mem-usage. # Benchmark about 3.6 GB per CPU (8 threads for 28.8 GB RAM) # TODO(asraa): Remove deprecation warnings when Envoy and deps moves to C++17 bazel build --verbose_failures --dynamic_mode=off ${DI} \ --spawn_strategy=standalone --genrule_strategy=standalone \ --local_cpu_resources=HOST_CPUS*0.256 \ --//source/extensions/wasm_runtime/v8:enabled=false \ --build_tag_filters=-no_asan --config=oss-fuzz \ ${EXTRA_BAZEL_FLAGS} \ ${OSS_FUZZ_TARGETS[*]} # Profiling with coverage requires that we resolve+copy all Bazel symlinks and # also remap everything under proc/self/cwd to correspond to Bazel build paths. if [ "$SANITIZER" = "coverage" ] then # The build invoker looks for sources in $SRC, but it turns out that we need # to not be buried under src/, paths are expected at out/proc/self/cwd by # the profiler. declare -r REMAP_PATH="${OUT}/proc/self/cwd" mkdir -p "${REMAP_PATH}" # Copy the cc and header files that will be covered. rsync -av "${SRC}"/envoy/source "${REMAP_PATH}" rsync -av "${SRC}"/envoy/test "${REMAP_PATH}" rsync -av "${SRC}"/envoy/envoy "${REMAP_PATH}" # Envoy currently uses a modified version of http_parser (see: # https://github.com/envoyproxy/envoy/issues/19749). declare -r BAZEL_EXTERNAL_REMAP_PATH="${REMAP_PATH}/external/envoy/bazel/external" mkdir -p "${BAZEL_EXTERNAL_REMAP_PATH}" rsync -av "${SRC}"/envoy/bazel/external/http_parser "${BAZEL_EXTERNAL_REMAP_PATH}" # Remove filesystem loop manually. rm -rf "${SRC}"/envoy/bazel-envoy/external/envoy # Clean up symlinks with a missing referrant. find "${SRC}"/envoy/bazel-envoy/external -follow -type l -ls -delete || echo "Symlink cleanup soft fail" rsync -avLk "${SRC}"/envoy/bazel-envoy/external "${REMAP_PATH}" # For .h, and some generated artifacts, we need bazel-out/. Need to heavily # filter out the build objects from bazel-out/. Also need to resolve symlinks, # since they don't make sense outside the build container. declare -r RSYNC_FILTER_ARGS=("--include" "*.h" "--include" "*.cc" "--include" \ "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*/" "--exclude" "*") rsync -avLk "${RSYNC_FILTER_ARGS[@]}" "${SRC}"/envoy/bazel-out "${REMAP_PATH}" rsync -avLkR "${RSYNC_FILTER_ARGS[@]}" "${HOME}" "${OUT}" rsync -avLkR "${RSYNC_FILTER_ARGS[@]}" /tmp "${OUT}" fi for oss_fuzz_archive in $(find bazel-bin/ -name '*_oss_fuzz.tar'); do tar -xvf "${oss_fuzz_archive}" -C "${OUT}" done # Cleanup bazel- symlinks to avoid oss-fuzz trying to copy out of the build # cache. rm -f bazel-* ================================================ FILE: projects/envoy/project.yaml ================================================ homepage: "https://www.envoyproxy.io/" language: c++ primary_contact: "htuch@google.com" auto_ccs: - "mattklein123@gmail.com" - "jmarantz@google.com" - "envoy-security@googlegroups.com" - "yavlasov@google.com" - "adip@google.com" - "yanjunxiang@google.com" - "tgschwen@google.com" - "boteng@google.com" - "pgal@google.com" - "leonti@google.com" - "copybara-watcher-pod-watcher-git@system.gserviceaccount.com" - "copybara-worker@system.gserviceaccount.com" coverage_extra_args: -ignore-filename-regex=.*\.cache.*envoy_deps_cache.* main_repo: 'https://github.com/envoyproxy/envoy.git' sanitizers: - address - undefined fuzzing_engines: - libfuzzer - honggfuzz labels: "*": - ossfuzz-bugz-1149782 ================================================ FILE: projects/esp-v2/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ## This file was copied from envoy (with minor changes). FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get -y install \ build-essential \ openjdk-8-jdk \ make \ ninja-build \ curl \ autoconf \ libtool \ wget \ golang \ python \ rsync # Install Bazelisk RUN wget -O /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/download/v0.0.8/bazelisk-linux-amd64; \ chmod +x /usr/local/bin/bazel RUN git clone --depth 1 https://github.com/GoogleCloudPlatform/esp-v2.git WORKDIR $SRC/esp-v2/ COPY build.sh $SRC/ ================================================ FILE: projects/esp-v2/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cat <> .bazelrc #build:oss-fuzz --config=fuzzing build:oss-fuzz --define=FUZZING_ENGINE=oss-fuzz build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none build:oss-fuzz --dynamic_mode=off build:oss-fuzz --strip=never build:oss-fuzz --copt=-fno-sanitize=vptr build:oss-fuzz --linkopt=-fno-sanitize=vptr build:oss-fuzz --define=tcmalloc=disabled build:oss-fuzz --define=signal_trace=disabled build:oss-fuzz --copt=-D_LIBCPP_DISABLE_DEPRECATION_WARNINGS build:oss-fuzz --define=force_libcpp=enabled build:oss-fuzz --linkopt=-lc++ build:oss-fuzz --linkopt=-pthread EOF ## Copied from envoy export CFLAGS="$CFLAGS" export CXXFLAGS="$CXXFLAGS" # Copy $CFLAGS and $CXXFLAGS into Bazel command-line flags, for both # compilation and linking. # # Some flags, such as `-stdlib=libc++`, generate warnings if used on a C source # file. Since the build runs with `-Werror` this will cause it to break, so we # use `--conlyopt` and `--cxxopt` instead of `--copt`. # declare -r EXTRA_BAZEL_FLAGS="$( for f in ${CFLAGS}; do echo "--conlyopt=${f}" "--linkopt=${f}" done for f in ${CXXFLAGS}; do echo "--cxxopt=${f}" "--linkopt=${f}" done if [ "$SANITIZER" = "undefined" ] then # Bazel uses clang to link binary, which does not link clang_rt ubsan library for C++ automatically. # See issue: https://github.com/bazelbuild/bazel/issues/8777 echo "--linkopt=$(find $(llvm-config --libdir) -name libclang_rt.ubsan_standalone_cxx-x86_64.a | head -1)" echo "--linkopt=-fsanitize=undefined" elif [ "$SANITIZER" = "address" ] then echo "--copt=-D__SANITIZE_ADDRESS__" "--copt=-DADDRESS_SANITIZER=1" "--linkopt=-fsanitize=address" fi )" # Find targets declare BAZEL_BUILD_TARGETS="" declare BAZEL_CORPUS_TARGETS="" declare FILTERED_FUZZER_TARGETS="" # In CI we only build a single target as otherwise we exhaust resources in the CI if [ -n "${OSS_FUZZ_CI-}" ]; then fuzz_suffix='json_struct_fuzz_test$' else fuzz_suffix='_fuzz_test$' fi for t in $(bazel query 'src/...' --output label | grep $fuzz_suffix) do declare TAGGED=$(bazel query "attr('tags', 'no_fuzz', ${t})") if [ -z "${TAGGED}" ] then BASE_PATH=${t//://} BASE_PATH=${BASE_PATH#"//"} FILTERED_FUZZER_TARGETS+="${BASE_PATH} " BAZEL_BUILD_TARGETS+="${t} " BAZEL_CORPUS_TARGETS+="${t}_corpus " fi done # Build driverless libraries. # Benchmark about 3 GB per CPU (10 threads for 28.8 GB RAM) # TODO(nareddyt): Remove deprecation warnings when Envoy and deps moves to C++17 bazel build --verbose_failures --dynamic_mode=off --spawn_strategy=sandboxed \ --local_cpu_resources=HOST_CPUS*0.32 \ --genrule_strategy=standalone --strip=never \ --copt=-fno-sanitize=vptr --linkopt=-fno-sanitize=vptr \ --define tcmalloc=disabled --define signal_trace=disabled \ --define ENVOY_CONFIG_ASAN=1 \ --define force_libcpp=enabled --build_tag_filters=-no_asan \ --linkopt=-lc++ --linkopt=-pthread ${EXTRA_BAZEL_FLAGS} --config=oss-fuzz \ ${BAZEL_BUILD_TARGETS[*]} ${BAZEL_CORPUS_TARGETS[*]} # Profiling with coverage requires that we resolve+copy all Bazel symlinks and # also remap everything under proc/self/cwd to correspond to Bazel build paths. if [ "$SANITIZER" = "coverage" ] then # The build invoker looks for sources in $SRC, but it turns out that we need # to not be buried under src/, paths are expected at out/proc/self/cwd by # the profiler. declare -r REMAP_PATH="${OUT}/proc/self/cwd" mkdir -p "${REMAP_PATH}" rsync -av "${SRC}"/esp-v2/src "${REMAP_PATH}" # Remove filesystem loop manually. rm -rf "${SRC}"/esp-v2/bazel-esp-v2/external/esp-v2 # Clean up symlinks with a missing referrant. find "${SRC}"/esp-v2/bazel-esp-v2/external -follow -type l -ls -delete || echo "Symlink cleanup soft fail" rsync -avLk "${SRC}"/esp-v2/bazel-esp-v2/external "${REMAP_PATH}" # For .h, and some generated artifacts, we need bazel-out/. Need to heavily # filter out the build objects from bazel-out/. Also need to resolve symlinks, # since they don't make sense outside the build container. declare -r RSYNC_FILTER_ARGS=("--include" "*.h" "--include" "*.cc" "--include" \ "*.hpp" "--include" "*.cpp" "--include" "*.c" "--include" "*/" "--exclude" "*") rsync -avLk "${RSYNC_FILTER_ARGS[@]}" "${SRC}"/esp-v2/bazel-out "${REMAP_PATH}" rsync -avLkR "${RSYNC_FILTER_ARGS[@]}" "${HOME}" "${OUT}" # Some low-level libraries are built located /tmp. # But ESPv2 engineeers don't really look at them. # rsync -avLkR "${RSYNC_FILTER_ARGS[@]}" /tmp "${OUT}" fi # Copy out test driverless binaries from bazel-bin/. for t in ${FILTERED_FUZZER_TARGETS} do TARGET_BASE="$(expr "$t" : '.*/\(.*\)_fuzz_test')" TARGET_DRIVERLESS=bazel-bin/"${t}" echo "Copying fuzzer $t" cp "${TARGET_DRIVERLESS}" "${OUT}"/"${TARGET_BASE}"_fuzz_test done # Zip up related test corpuses. # TODO(nareddyt): just use the .tar directly when # https://github.com/google/oss-fuzz/issues/1918 is fixed. CORPUS_UNTAR_PATH="${PWD}"/_tmp_corpus for t in ${FILTERED_FUZZER_TARGETS} do echo "Extracting and zipping fuzzer $t corpus" TARGET_BASE="$(expr "$t" : '.*/\(.*\)_fuzz_test')" zip "${OUT}/${TARGET_BASE}"_seed_corpus.zip bazel-bin/"${t}"_corpus/* done # Cleanup bazel- symlinks to avoid oss-fuzz trying to copy out of the build # cache. rm -f bazel-* ================================================ FILE: projects/esp-v2/project.yaml ================================================ homepage: "https://github.com/GoogleCloudPlatform/esp-v2" language: c++ primary_contact: "nareddyt@google.com" auto_ccs: - "taoxuy@google.com" - "qiwzhang@google.com" sanitizers: - address - undefined coverage_extra_args: -ignore-filename-regex=.*\.cache.* -ignore-filename-regex=.*bazel-out.* main_repo: 'https://github.com/GoogleCloudPlatform/esp-v2.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/espeak-ng/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt install -y cmake pkg-config RUN git clone --depth 1 https://github.com/espeak-ng/espeak-ng COPY build.sh $SRC WORKDIR $SRC/espeak-ng ================================================ FILE: projects/espeak-ng/build.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project with cmake export ASAN_OPTIONS=detect_leaks=0 mkdir -p build cd build cmake .. -DCMAKE_C_COMPILER="$CC" \ -DCMAKE_CXX_COMPILER="$CXX" \ -DCMAKE_C_FLAGS="$CFLAGS" \ -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_SHARED_LIBS=OFF make -j$(nproc) cd .. # Build the ssml-fuzzer manually with $LIB_FUZZING_ENGINE $CC $CFLAGS -Ibuild/src/libespeak-ng/include -I. -Isrc/include -c tests/ssml-fuzzer.c -o tests/ssml-fuzzer.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE tests/ssml-fuzzer.o \ build/src/libespeak-ng/libespeak-ng.a \ build/src/speechPlayer/libspeechPlayer.a \ build/src/ucd-tools/libucd.a -o $OUT/ssml-fuzzer -lm cp -r build/espeak-ng-data/ $OUT/ ================================================ FILE: projects/espeak-ng/project.yaml ================================================ homepage: "https://github.com/espeak-ng/espeak-ng" language: c++ primary_contact: "msclrhd@googlemail.com" auto_ccs: - "valdis.vitolins@gmail.com" - "p.antoine@catenacyber.fr" - "sascha.brawer@gmail.com" sanitizers: - address fuzzing_engines: - libfuzzer - afl main_repo: 'https://github.com/espeak-ng/espeak-ng' ================================================ FILE: projects/et-xmlfile/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/lxml/lxml RUN apt-get install -y libxml2-dev libxslt-dev zlib1g-dev RUN pip3 install Cython RUN git clone --depth 1 https://github.com/biydnd/et_xmlfile et_xmlfile WORKDIR et_xmlfile RUN mkdir $SRC/et-xmlfile-fuzzers COPY *.py $SRC/et-xmlfile-fuzzers/ COPY build.sh $SRC/ ================================================ FILE: projects/et-xmlfile/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/lxml python3 ./setup.py install cd $SRC/et_xmlfile pip3 install . for fuzzer in $(find $SRC/et-xmlfile-fuzzers/ -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/et-xmlfile/fuzz_write.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from io import BytesIO try: import lxml except ImportError: raise ImportError("lxml is required to run the tests.") from et_xmlfile import xmlfile def recursive_write(xf, fdp, level): if level == 1: xf.write(fdp.ConsumeUnicodeNoSurrogates(50)) else: with xf.element(fdp.ConsumeUnicodeNoSurrogates(50)): recursive_write(xf, fdp, level-1) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) f2 = BytesIO() # Call write on et_xmlfile 10 times. with xmlfile(f2) as xf: recursive_write(xf, fdp, 10) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/et-xmlfile/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/biydnd/et_xmlfile language: python main_repo: https://github.com/biydnd/et_xmlfile sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/etcd/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/etcd-io/etcd RUN git clone --depth 1 https://github.com/etcd-io/raft RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ COPY build.sh $SRC/ WORKDIR $SRC/etcd ================================================ FILE: projects/etcd/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/etcd/build.sh ================================================ FILE: projects/etcd/project.yaml ================================================ homepage: "https://etcd.io" main_repo: "https://github.com/etcd-io/etcd" primary_contact: "ptab@google.com" auto_ccs : - "etcd-maintainers@googlegroups.com" - "adam@adalogics.com" - "david@adalogics.com" - "sahdev.zala1@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/evo-inflector/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/atteo/evo-inflector evo-inflector COPY *.sh *.java $SRC/ WORKDIR $SRC/evo-inflector ================================================ FILE: projects/evo-inflector/EnglishFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.atteo.evo.inflector.English; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [org.atteo.evo.inflector.English] public static java.lang.String // plural(java.lang.String) public class EnglishFuzzer { private static English.MODE[] mode = { English.MODE.ENGLISH_ANGLICIZED, English.MODE.ENGLISH_CLASSICAL}; public static void fuzzerTestOneInput(FuzzedDataProvider data) { English.setMode(data.pickValue(mode)); Boolean choice = data.consumeBoolean(); if (choice) { English.plural(data.consumeRemainingAsString()); } else { Integer int1 = data.consumeInt(); English.plural(data.consumeRemainingAsString(), int1); } } } ================================================ FILE: projects/evo-inflector/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## find ./ -name pom.xml -exec sed -i 's/source>1.61.81.61.8 $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/evo-inflector/project.yaml ================================================ homepage: https://github.com/atteo/evo-inflector main_repo: https://github.com/atteo/evo-inflector language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/example/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make # Get *your* source code here. RUN git clone https://github.com/google/oss-fuzz.git my-git-repo WORKDIR my-git-repo COPY build.sh $SRC/ ================================================ FILE: projects/example/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd projects/example/my-api-repo make clean # Not strictly necessary, since we are building in a fresh dir. make -j$(nproc) all # Build the fuzz targets. make -j$(nproc) check # Sanity check, not strictly required, but nice to have. # Copy the fuzzer executables, zip-ed corpora, option and dictionary files to $OUT find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' # If you have dictionaries. find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' # If you have custom options. find . -name '*_fuzzer_seed_corpus.zip' -exec cp -v '{}' $OUT ';' # If you have seed corpora (you better have them!) ================================================ FILE: projects/example/my-api-repo/Makefile ================================================ # Copyright 2017 Google Inc. All Rights Reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # Simple example of a build file that nicely integrates a fuzz target # with the rest of the project. # # We use 'make' as the build system, but these ideas are applicable # to any other build system # By default, use our own standalone_fuzz_target_runner. # This runner does no fuzzing, but simply executes the inputs # provided via parameters. # Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a" # to link the fuzzer(s) against a real fuzzing engine. # # OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE. LIB_FUZZING_ENGINE ?= standalone_fuzz_target_runner.o # Values for CC, CFLAGS, CXX, CXXFLAGS are provided by OSS-Fuzz. # Outside of OSS-Fuzz use the ones you prefer or rely on the default values. # Do not use the -fsanitize=* flags by default. # OSS-Fuzz will use different -fsanitize=* flags for different builds (asan, ubsan, msan, ...) # You may add extra compiler flags like this: CXXFLAGS += -std=c++11 all: do_stuff_unittest do_stuff_fuzzer clean: rm -fv *.a *.o *unittest *_fuzzer *_seed_corpus.zip crash-* *.zip # Continuos integration system should run "make clean && make check" check: all ./do_stuff_unittest ./do_stuff_fuzzer do_stuff_test_data/* # Unit tests do_stuff_unittest: do_stuff_unittest.cpp my_api.a ${CXX} ${CXXFLAGS} $< my_api.a -o $@ # Fuzz target, links against $LIB_FUZZING_ENGINE, so that # you may choose which fuzzing engine to use. do_stuff_fuzzer: do_stuff_fuzzer.cpp my_api.a standalone_fuzz_target_runner.o ${CXX} ${CXXFLAGS} $< my_api.a ${LIB_FUZZING_ENGINE} -o $@ zip -q -r do_stuff_fuzzer_seed_corpus.zip do_stuff_test_data # The library itself. my_api.a: my_api.cpp my_api.h ${CXX} ${CXXFLAGS} $< -c ar ruv my_api.a my_api.o # The standalone fuzz target runner. standalone_fuzz_target_runner.o: standalone_fuzz_target_runner.cpp ================================================ FILE: projects/example/my-api-repo/README.md ================================================ Example of [OSS-Fuzz ideal integration](https://google.github.io/oss-fuzz/advanced-topics/ideal-integration/). This directory contains an example software project that has most of the traits of [ideal](https://google.github.io/oss-fuzz/advanced-topics/ideal-integration/) support for fuzzing. ## Files in my-api-repo Imagine that these files reside in your project's repository: * [my_api.h](my_api.h): and [my_api.cpp](my_api.cpp) implement the API we want to test/fuzz. The function `DoStuff()` inside [my_api.cpp](my_api.cpp) contains a bug. (Find it!) * [do_stuff_unittest.cpp](do_stuff_unittest.cpp): is a unit test for `DoStuff()`. Unit tests are not necessary for fuzzing but are generally a good practice. * [do_stuff_fuzzer.cpp](do_stuff_fuzzer.cpp): is a [fuzz target](https://llvm.org/docs/LibFuzzer.html#fuzz-target) for `DoStuff()`. * [do_stuff_test_data](do_stuff_test_data): corpus directory for [do_stuff_fuzzer.cpp](do_stuff_fuzzer.cpp). * [do_stuff_fuzzer.dict](do_stuff_fuzzer.dict): a [fuzzing dictionary file](https://google.github.io/oss-fuzz/getting-started/new-project-guide#dictionaries) for `DoStuff()`. Optional, but may improve fuzzing in many cases. * [Makefile](Makefile): is a build file (the same can be done with other build systems): * accepts external compiler flags via `$CC`, `$CXX`, `$CFLAGS`, `$CXXFLAGS` * accepts external fuzzing engine via `$LIB_FUZZING_ENGINE`, by default uses [standalone_fuzz_target_runner.cpp](standalone_fuzz_target_runner.cpp) * builds the fuzz target(s) and their corpus archive(s) * `make check` executes [do_stuff_fuzzer.cpp](do_stuff_fuzzer.cpp) on [`do_stuff_test_data/*`](do_stuff_test_data), thus ensures that the fuzz target is up to date and uses it as a regression test. * [standalone_fuzz_target_runner.cpp](standalone_fuzz_target_runner.cpp): is a simple standalone runner for fuzz targets. You may use it to execute a fuzz target on given files w/o having to link in libFuzzer or other fuzzing engine. ## Files in OSS-Fuzz repository * [oss-fuzz/projects/example](..) * [Dockerfile](../Dockerfile): sets up the build environment * [build.sh](../build.sh): builds the fuzz target(s). The smaller this file the better (most of the logic should be inside the project's build system). * [project.yaml](../project.yaml): short project description and contact info. ## Example bug Example bug report filed automatically: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=1562 ================================================ FILE: projects/example/my-api-repo/do_stuff_fuzzer.cpp ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "my_api.h" #include // Simple fuzz target for DoStuff(). // See https://llvm.org/docs/LibFuzzer.html for details. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { std::string str(reinterpret_cast(data), size); DoStuff(str); // Disregard the output. return 0; } ================================================ FILE: projects/example/my-api-repo/do_stuff_fuzzer.dict ================================================ # A dictionary for more efficient fuzzing of DoStuff(). # If the inputs contain multi-byte tokens, list them here. # See https://llvm.org/docs/LibFuzzer.html#dictionaries "foo" "bar" "ouch" ================================================ FILE: projects/example/my-api-repo/do_stuff_test_data/410c23d234e7f97a2dd6265eb2909324deb8c13a ================================================ fomgo ================================================ FILE: projects/example/my-api-repo/do_stuff_test_data/7a74862169c3375f4149daff75187cbca7372a38 ================================================ fbaro ================================================ FILE: projects/example/my-api-repo/do_stuff_test_data/a835d6f1c6b2ae4a35e8c0a4a0576715c8b27283 ================================================ fo ================================================ FILE: projects/example/my-api-repo/do_stuff_test_data/fc09d362f05ab97efdfcd873dacad6a9c29e57ff ================================================ _oouch ================================================ FILE: projects/example/my-api-repo/do_stuff_unittest.cpp ================================================ // Copyright 2017 Google Inc. All Rights Reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // Simple unit test for DoStuff(). // This unit test does not cover the existing bug in DoStuff(), // unless you pass an extra parameter ("BUG"). #include "my_api.h" #include #include void TestDoStuff(const std::string &str, size_t Expected) { size_t Result = DoStuff(str); std::cerr << str << " => " << Result << std::endl; assert(Result == Expected); } int main(int argc, char **argv) { // Test some simple inputs, verify the output. TestDoStuff("", 0); TestDoStuff("foo", 1); TestDoStuff("omg", 1); TestDoStuff("bar", 1); TestDoStuff("ouch", 1); TestDoStuff("foobar", 3); TestDoStuff("foouchbar", 4); if (argc == 2 && std::string(argv[1]) == "BUG") { // This is the missing test that actually triggers the bug. TestDoStuff("foouchbaromg", 4); } } ================================================ FILE: projects/example/my-api-repo/my_api.cpp ================================================ // Copyright 2017 Google Inc. All Rights Reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // Implementation of "my_api". #include "my_api.h" #include // Do some computations with 'str', return the result. // This function contains a bug. Can you spot it? size_t DoStuff(const std::string &str) { std::vector Vec({0, 1, 2, 3, 4}); size_t Idx = 0; if (str.size() > 5) Idx++; if (str.find("foo") != std::string::npos) Idx++; if (str.find("bar") != std::string::npos) Idx++; if (str.find("ouch") != std::string::npos) Idx++; if (str.find("omg") != std::string::npos) Idx++; return Vec[Idx]; } ================================================ FILE: projects/example/my-api-repo/my_api.h ================================================ // Copyright 2017 Google Inc. All Rights Reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // A library that does ... stuff. // Serves as an example of good fuzz testing and OSS-Fuzz integration. #include size_t DoStuff(const std::string &str); ================================================ FILE: projects/example/my-api-repo/standalone_fuzz_target_runner.cpp ================================================ // Copyright 2017 Google Inc. All Rights Reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // Example of a standalone runner for "fuzz targets". // It reads all files passed as parameters and feeds their contents // one by one into the fuzz target (LLVMFuzzerTestOneInput). // This runner does not do any fuzzing, but allows us to run the fuzz target // on the test corpus (e.g. "do_stuff_test_data") or on a single file, // e.g. the one that comes from a bug report. #include #include #include #include // Forward declare the "fuzz target" interface. // We deliberately keep this inteface simple and header-free. extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { std::ifstream in(argv[i]); in.seekg(0, in.end); size_t length = in.tellg(); in.seekg (0, in.beg); std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; // Allocate exactly length bytes so that we reliably catch buffer overflows. std::vector bytes(length); in.read(bytes.data(), bytes.size()); assert(in); LLVMFuzzerTestOneInput(reinterpret_cast(bytes.data()), bytes.size()); std::cout << "Execution successful" << std::endl; } return 0; } ================================================ FILE: projects/example/project.yaml ================================================ disabled: true homepage: https://my-api.example.com main_repo: https://github.com/example/my-api language: c++ vendor_ccs: [] fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/exiv2/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone https://github.com/Exiv2/exiv2 exiv2 RUN ./exiv2/ci/install_dependencies.sh WORKDIR exiv2 COPY *.sh $SRC/ ================================================ FILE: projects/exiv2/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Added to fix a false positive result: https://github.com/google/oss-fuzz/issues/6489 CXXFLAGS="${CXXFLAGS} -fno-sanitize=float-divide-by-zero" # Build Exiv2 mkdir -p build cd build cmake -DEXIV2_ENABLE_PNG=ON -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=OFF -DEXIV2_ENABLE_BMFF=ON -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_CXX_FLAGS="${CXXFLAGS}" -DEXIV2_BUILD_FUZZ_TESTS=ON -DEXIV2_TEAM_OSS_FUZZ=ON -DLIB_FUZZING_ENGINE="${LIB_FUZZING_ENGINE}" -DEXIV2_ENABLE_INIH=OFF -DCMAKE_CXX_STANDARD=20 .. make -j $(nproc) # Copy binaries and dictionary to $OUT cp ./bin/fuzz-read-print-write $OUT cp ./bin/fuzz-read-write $OUT cp ./bin/fuzz-preview $OUT cp ../fuzz/exiv2.dict $OUT/fuzz-read-print-write.dict cp ../fuzz/exiv2.dict $OUT/fuzz-read-write.dict cp ../fuzz/exiv2.dict $OUT/fuzz-preview.dict # Initialize the corpus, using the files in test/data mkdir corpus for f in $(find ../test/data -type f -size -20k); do s=$(sha1sum "$f" | awk '{print $1}') cp $f corpus/$s done zip -j $OUT/fuzz-read-print-write.zip corpus/* zip -j $OUT/fuzz-read-write.zip corpus/* zip -j $OUT/fuzz-preview.zip corpus/* ================================================ FILE: projects/exiv2/project.yaml ================================================ homepage: "https://www.exiv2.org" language: c++ primary_contact: "kevinbackhouse@github.com" auto_ccs: - "piponazo@gmail.com" sanitizers: - address - undefined architectures: - x86_64 main_repo: 'https://github.com/Exiv2/exiv2' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/exiv2/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build -R bugfixTests --output-on-failure ctest --test-dir build -R tiffTests --output-on-failure ctest --test-dir build -R versionTests --output-on-failure ctest --test-dir build -R regressionTests --output-on-failure ================================================ FILE: projects/exp4j/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/fasseg/exp4j exp4j COPY *.sh *.java $SRC/ WORKDIR $SRC/exp4j ================================================ FILE: projects/exp4j/ExpressionBuilderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.EmptyStackException; import net.objecthunter.exp4j.ExpressionBuilder; import net.objecthunter.exp4j.function.Function; import net.objecthunter.exp4j.function.Functions; import net.objecthunter.exp4j.operator.Operator; import net.objecthunter.exp4j.operator.Operators; public class ExpressionBuilderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 10)); ExpressionBuilder builder = new ExpressionBuilder(data.consumeString(data.remainingBytes() / 2)); for (Integer choice : choices) { String string = data.consumeString(data.remainingBytes() / choices.length); switch (choice % 3) { case 0: Function func = Functions.getBuiltinFunction(string); if (func != null) { builder = builder.function(func); } break; case 1: Operator op = Operators.getBuiltinOperator(string.charAt(choice % string.length()), 1); if (op != null) { builder = builder.operator(op); } break; case 2: builder = builder.variable(string); break; } } builder.build(); } catch (IllegalArgumentException | EmptyStackException | ArithmeticException e) { // Known exception } } } ================================================ FILE: projects/exp4j/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/exp4j-$CURRENT_VERSION.jar" $OUT/exp4j.jar ALL_JARS="exp4j.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/exp4j/project.yaml ================================================ homepage: https://github.com/fasseg/exp4j main_repo: https://github.com/fasseg/exp4j language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/expat/Dockerfile ================================================ # Copyright 2016 Google Inc. # Copyright 2025 Sebastian Pipping # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ cmake \ libprotobuf-dev:amd64 \ libprotobuf-dev:i386 \ libstdc++-9-dev:i386 \ make \ protobuf-compiler RUN git clone --depth 1 https://github.com/libexpat/libexpat expat WORKDIR expat COPY run_tests.sh build.sh *.dict $SRC/ ================================================ FILE: projects/expat/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # Copyright 2025 Sebastian Pipping # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # NOTE: We need to drop -stdlib=libc++ to not get (pages of) link errors when # linking against system Protobuf that is linked against GCC's libstdc++ # rather than Clang's own libstdc++ CXXFLAGS="${CXXFLAGS/-stdlib=libc++/ }" # NOTE: Without -static-libstdc++, the bad build checker in base-runner # will fail with output: # > error while loading shared libraries: libstdc++.so.6: # > cannot open shared object file: No such file or directory # The addition of -Wno-unused-command-line-argument silences Clang's # misleading output on argument -static-libstdc++ appearing as unused. CXXFLAGS="${CXXFLAGS} -static-libstdc++ -Wno-unused-command-line-argument" : ${LD:="${CXX}"} : ${LDFLAGS:="${CXXFLAGS}"} # to make sure we link with sanitizer runtime cmake_args=( # Specific to Expat -DEXPAT_BUILD_DOCS=OFF -DEXPAT_BUILD_EXAMPLES=OFF -DEXPAT_BUILD_FUZZERS=ON -DEXPAT_BUILD_TESTS=ON -DEXPAT_BUILD_TOOLS=OFF -DEXPAT_OSSFUZZ_BUILD=ON -DEXPAT_SHARED_LIBS=OFF -DProtobuf_USE_STATIC_LIBS=ON # C compiler -DCMAKE_C_COMPILER="${CC}" -DCMAKE_C_FLAGS="${CFLAGS}" # C++ compiler -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_CXX_FLAGS="${CXXFLAGS}" # Linker -DCMAKE_LINKER="${LD}" -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" ) mkdir -p build cd build cmake ../expat "${cmake_args[@]}" make -j$(nproc) for fuzzer in fuzz/*; do cp $fuzzer $OUT fuzzer_name=$(basename $fuzzer) if [[ ${fuzzer_name} =~ ^.*UTF-16$ ]]; then cp $SRC/xml_UTF_16.dict $OUT/${fuzzer_name}.dict elif [[ ${fuzzer_name} =~ ^.*UTF-16LE$ ]]; then cp $SRC/xml_UTF_16LE.dict $OUT/${fuzzer_name}.dict elif [[ ${fuzzer_name} =~ ^.*UTF-16BE$ ]]; then cp $SRC/xml_UTF_16BE.dict $OUT/${fuzzer_name}.dict else cp $SRC/xml.dict $OUT/${fuzzer_name}.dict fi done ================================================ FILE: projects/expat/project.yaml ================================================ homepage: "https://github.com/libexpat/libexpat" language: c++ primary_contact: "sebastian@pipping.org" auto_ccs: - "berkay.ueruen@siemens.com" - "hanno@hboeck.de" - "webmaster@hartwork.org" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/libexpat/libexpat' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/expat/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ cd build make test ================================================ FILE: projects/expat/xml.dict ================================================ # # AFL dictionary for XML # ---------------------- # # Several basic syntax elements and attributes, modeled on libxml2. # # Created by Michal Zalewski # attr_encoding=" encoding=\"1\"" attr_generic=" a=\"1\"" attr_href=" href=\"1\"" attr_standalone=" standalone=\"no\"" attr_version=" version=\"1\"" attr_xml_base=" xml:base=\"1\"" attr_xml_id=" xml:id=\"1\"" attr_xml_lang=" xml:lang=\"1\"" attr_xml_space=" xml:space=\"1\"" attr_xmlns=" xmlns=\"1\"" entity_builtin="<" entity_decimal="" entity_external="&a;" entity_hex="" # keywords "ANY" "ATTLIST" "CDATA" "DOCTYPE" "ELEMENT" "EMPTY" "ENTITIES" "ENTITY" "FIXED" "ID" "IDREF" "IDREFS" "IGNORE" "IMPLIED" "INCLUDE" "NDATA" "NMTOKEN" "NMTOKENS" "NOTATION" "PCDATA" "PUBLIC" "REQUIRED" "SYSTEM" # Various tag parts "<" ">" "/>" "" "" "[]" "]]" "" "\"\"" "''" "=\"\"" "=''" # DTD "" tag_open="" tag_open_close="" "" "http://docboo" "http://www.w" "he30" "he2" "IET" "FDF-10" "aDUCS-4OPveb:" "a>" "UT" "xMl" "/usr/share/sg" "ha07" "http://www.oa" "cle" ================================================ FILE: projects/expat/xml_UTF_16.dict ================================================ # xml.dict converted to UTF-16 encoding. "\xff\xfe \x00e\x00n\x00c\x00o\x00d\x00i\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00a\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00h\x00r\x00e\x00f\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00s\x00t\x00a\x00n\x00d\x00a\x00l\x00o\x00n\x00e\x00=\x00\\\x00"\x00n\x00o\x00\\\x00"\x00" "\xff\xfe \x00v\x00e\x00r\x00s\x00i\x00o\x00n\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00x\x00m\x00l\x00:\x00b\x00a\x00s\x00e\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00x\x00m\x00l\x00:\x00i\x00d\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00x\x00m\x00l\x00:\x00l\x00a\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00x\x00m\x00l\x00:\x00s\x00p\x00a\x00c\x00e\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe \x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "\xff\xfe&\x00l\x00t\x00;\x00" "\xff\xfe&\x00#\x001\x00;\x00" "\xff\xfe&\x00a\x00;\x00" "\xff\xfe&\x00#\x00x\x001\x00;\x00" "\xff\xfeA\x00N\x00Y\x00" "\xff\xfeA\x00T\x00T\x00L\x00I\x00S\x00T\x00" "\xff\xfeC\x00D\x00A\x00T\x00A\x00" "\xff\xfeD\x00O\x00C\x00T\x00Y\x00P\x00E\x00" "\xff\xfeE\x00L\x00E\x00M\x00E\x00N\x00T\x00" "\xff\xfeE\x00M\x00P\x00T\x00Y\x00" "\xff\xfeE\x00N\x00T\x00I\x00T\x00I\x00E\x00S\x00" "\xff\xfeE\x00N\x00T\x00I\x00T\x00Y\x00" "\xff\xfeF\x00I\x00X\x00E\x00D\x00" "\xff\xfeI\x00D\x00" "\xff\xfeI\x00D\x00R\x00E\x00F\x00" "\xff\xfeI\x00D\x00R\x00E\x00F\x00S\x00" "\xff\xfeI\x00G\x00N\x00O\x00R\x00E\x00" "\xff\xfeI\x00M\x00P\x00L\x00I\x00E\x00D\x00" "\xff\xfeI\x00N\x00C\x00L\x00U\x00D\x00E\x00" "\xff\xfeN\x00D\x00A\x00T\x00A\x00" "\xff\xfeN\x00M\x00T\x00O\x00K\x00E\x00N\x00" "\xff\xfeN\x00M\x00T\x00O\x00K\x00E\x00N\x00S\x00" "\xff\xfeN\x00O\x00T\x00A\x00T\x00I\x00O\x00N\x00" "\xff\xfeP\x00C\x00D\x00A\x00T\x00A\x00" "\xff\xfeP\x00U\x00B\x00L\x00I\x00C\x00" "\xff\xfeR\x00E\x00Q\x00U\x00I\x00R\x00E\x00D\x00" "\xff\xfeS\x00Y\x00S\x00T\x00E\x00M\x00" "\xff\xfe<\x00" "\xff\xfe>\x00" "\xff\xfe/\x00>\x00" "\xff\xfe<\x00/\x00" "\xff\xfe<\x00?\x00" "\xff\xfe?\x00>\x00" "\xff\xfe<\x00!\x00" "\xff\xfe!\x00>\x00" "\xff\xfe[\x00]\x00" "\xff\xfe]\x00]\x00" "\xff\xfe<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[\x00" "\xff\xfe<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[\x00]\x00]\x00>\x00" "\xff\xfe\\\x00"\x00\\\x00"\x00" "\xff\xfe'\x00'\x00" "\xff\xfe=\x00\\\x00"\x00\\\x00"\x00" "\xff\xfe=\x00'\x00'\x00" "\xff\xfe<\x00!\x00A\x00T\x00T\x00L\x00I\x00S\x00T\x00" "\xff\xfe<\x00!\x00D\x00O\x00C\x00T\x00Y\x00P\x00E\x00" "\xff\xfe<\x00!\x00E\x00L\x00E\x00M\x00E\x00N\x00T\x00" "\xff\xfe<\x00!\x00E\x00N\x00T\x00I\x00T\x00Y\x00" "\xff\xfe<\x00!\x00[\x00I\x00G\x00N\x00O\x00R\x00E\x00[\x00" "\xff\xfe<\x00!\x00[\x00I\x00N\x00C\x00L\x00U\x00D\x00E\x00[\x00" "\xff\xfe<\x00!\x00N\x00O\x00T\x00A\x00T\x00I\x00O\x00N\x00" "\xff\xfe#\x00C\x00D\x00A\x00T\x00A\x00" "\xff\xfe#\x00F\x00I\x00X\x00E\x00D\x00" "\xff\xfe#\x00I\x00M\x00P\x00L\x00I\x00E\x00D\x00" "\xff\xfe#\x00P\x00C\x00D\x00A\x00T\x00A\x00" "\xff\xfe#\x00R\x00E\x00Q\x00U\x00I\x00R\x00E\x00D\x00" "\xff\xfeI\x00S\x00O\x00-\x008\x008\x005\x009\x00-\x001\x00" "\xff\xfeU\x00S\x00-\x00A\x00S\x00C\x00I\x00I\x00" "\xff\xfeU\x00T\x00F\x00-\x008\x00" "\xff\xfeU\x00T\x00F\x00-\x001\x006\x00" "\xff\xfeU\x00T\x00F\x00-\x001\x006\x00B\x00E\x00" "\xff\xfeU\x00T\x00F\x00-\x001\x006\x00L\x00E\x00" "\xff\xfex\x00m\x00l\x00n\x00s\x00" "\xff\xfex\x00m\x00l\x00n\x00s\x00:\x00" "\xff\xfex\x00m\x00l\x00n\x00s\x00:\x00x\x00h\x00t\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x001\x009\x009\x009\x00/\x00x\x00h\x00t\x00m\x00l\x00\\\x00"\x00" "\xff\xfex\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x00X\x00M\x00L\x00/\x001\x009\x009\x008\x00/\x00n\x00a\x00m\x00e\x00s\x00p\x00a\x00c\x00e\x00\\\x00"\x00" "\xff\xfex\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x002\x000\x000\x000\x00/\x00x\x00m\x00l\x00n\x00s\x00\\\x00"\x00" "\xff\xfe:\x00f\x00a\x00l\x00l\x00b\x00a\x00c\x00k\x00" "\xff\xfe:\x00a\x00" "\xff\xfe:\x00i\x00n\x00c\x00l\x00u\x00d\x00e\x00" "\xff\xfe-\x00-\x00" "\xff\xfe(\x00)\x00" "\xff\xfe%\x00a\x00" "\xff\xfe:\x00s\x00c\x00h\x00e\x00m\x00a\x00" "\xff\xfeU\x00C\x00S\x00-\x004\x00" "\xff\xfe<\x00/\x00a\x00>\x00" "\xff\xfe<\x00a\x00>\x00" "\xff\xfe<\x00a\x00 \x00/\x00>\x00" "\xff\xfe<\x00?\x00x\x00m\x00l\x00?\x00>\x00" "\xff\xfeh\x00t\x00t\x00p\x00:\x00/\x00/\x00d\x00o\x00c\x00b\x00o\x00o\x00" "\xff\xfeh\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x00" "\xff\xfeh\x00e\x003\x000\x00" "\xff\xfeh\x00e\x002\x00" "\xff\xfeI\x00E\x00T\x00" "\xff\xfeF\x00D\x00F\x00-\x001\x000\x00" "\xff\xfea\x00D\x00U\x00C\x00S\x00-\x004\x00O\x00P\x00v\x00e\x00b\x00:\x00" "\xff\xfea\x00>\x00" "\xff\xfeU\x00T\x00" "\xff\xfex\x00M\x00l\x00" "\xff\xfe/\x00u\x00s\x00r\x00/\x00s\x00h\x00a\x00r\x00e\x00/\x00s\x00g\x00" "\xff\xfeh\x00a\x000\x007\x00" "\xff\xfeh\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00o\x00a\x00" "\xff\xfec\x00l\x00e\x00" ================================================ FILE: projects/expat/xml_UTF_16BE.dict ================================================ # xml.dict converted to UTF-16BE encoding. "\x00 \x00e\x00n\x00c\x00o\x00d\x00i\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00a\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00h\x00r\x00e\x00f\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00s\x00t\x00a\x00n\x00d\x00a\x00l\x00o\x00n\x00e\x00=\x00\\\x00"\x00n\x00o\x00\\\x00"" "\x00 \x00v\x00e\x00r\x00s\x00i\x00o\x00n\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00x\x00m\x00l\x00:\x00b\x00a\x00s\x00e\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00x\x00m\x00l\x00:\x00i\x00d\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00x\x00m\x00l\x00:\x00l\x00a\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00x\x00m\x00l\x00:\x00s\x00p\x00a\x00c\x00e\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00 \x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x001\x00\\\x00"" "\x00&\x00l\x00t\x00;" "\x00&\x00#\x001\x00;" "\x00&\x00a\x00;" "\x00&\x00#\x00x\x001\x00;" "\x00A\x00N\x00Y" "\x00A\x00T\x00T\x00L\x00I\x00S\x00T" "\x00C\x00D\x00A\x00T\x00A" "\x00D\x00O\x00C\x00T\x00Y\x00P\x00E" "\x00E\x00L\x00E\x00M\x00E\x00N\x00T" "\x00E\x00M\x00P\x00T\x00Y" "\x00E\x00N\x00T\x00I\x00T\x00I\x00E\x00S" "\x00E\x00N\x00T\x00I\x00T\x00Y" "\x00F\x00I\x00X\x00E\x00D" "\x00I\x00D" "\x00I\x00D\x00R\x00E\x00F" "\x00I\x00D\x00R\x00E\x00F\x00S" "\x00I\x00G\x00N\x00O\x00R\x00E" "\x00I\x00M\x00P\x00L\x00I\x00E\x00D" "\x00I\x00N\x00C\x00L\x00U\x00D\x00E" "\x00N\x00D\x00A\x00T\x00A" "\x00N\x00M\x00T\x00O\x00K\x00E\x00N" "\x00N\x00M\x00T\x00O\x00K\x00E\x00N\x00S" "\x00N\x00O\x00T\x00A\x00T\x00I\x00O\x00N" "\x00P\x00C\x00D\x00A\x00T\x00A" "\x00P\x00U\x00B\x00L\x00I\x00C" "\x00R\x00E\x00Q\x00U\x00I\x00R\x00E\x00D" "\x00S\x00Y\x00S\x00T\x00E\x00M" "\x00<" "\x00>" "\x00/\x00>" "\x00<\x00/" "\x00<\x00?" "\x00?\x00>" "\x00<\x00!" "\x00!\x00>" "\x00[\x00]" "\x00]\x00]" "\x00<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[" "\x00<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[\x00]\x00]\x00>" "\x00\\\x00"\x00\\\x00"" "\x00'\x00'" "\x00=\x00\\\x00"\x00\\\x00"" "\x00=\x00'\x00'" "\x00<\x00!\x00A\x00T\x00T\x00L\x00I\x00S\x00T" "\x00<\x00!\x00D\x00O\x00C\x00T\x00Y\x00P\x00E" "\x00<\x00!\x00E\x00L\x00E\x00M\x00E\x00N\x00T" "\x00<\x00!\x00E\x00N\x00T\x00I\x00T\x00Y" "\x00<\x00!\x00[\x00I\x00G\x00N\x00O\x00R\x00E\x00[" "\x00<\x00!\x00[\x00I\x00N\x00C\x00L\x00U\x00D\x00E\x00[" "\x00<\x00!\x00N\x00O\x00T\x00A\x00T\x00I\x00O\x00N" "\x00#\x00C\x00D\x00A\x00T\x00A" "\x00#\x00F\x00I\x00X\x00E\x00D" "\x00#\x00I\x00M\x00P\x00L\x00I\x00E\x00D" "\x00#\x00P\x00C\x00D\x00A\x00T\x00A" "\x00#\x00R\x00E\x00Q\x00U\x00I\x00R\x00E\x00D" "\x00I\x00S\x00O\x00-\x008\x008\x005\x009\x00-\x001" "\x00U\x00S\x00-\x00A\x00S\x00C\x00I\x00I" "\x00U\x00T\x00F\x00-\x008" "\x00U\x00T\x00F\x00-\x001\x006" "\x00U\x00T\x00F\x00-\x001\x006\x00B\x00E" "\x00U\x00T\x00F\x00-\x001\x006\x00L\x00E" "\x00x\x00m\x00l\x00n\x00s" "\x00x\x00m\x00l\x00n\x00s\x00:" "\x00x\x00m\x00l\x00n\x00s\x00:\x00x\x00h\x00t\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x001\x009\x009\x009\x00/\x00x\x00h\x00t\x00m\x00l\x00\\\x00"" "\x00x\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x00X\x00M\x00L\x00/\x001\x009\x009\x008\x00/\x00n\x00a\x00m\x00e\x00s\x00p\x00a\x00c\x00e\x00\\\x00"" "\x00x\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x002\x000\x000\x000\x00/\x00x\x00m\x00l\x00n\x00s\x00\\\x00"" "\x00:\x00f\x00a\x00l\x00l\x00b\x00a\x00c\x00k" "\x00:\x00a" "\x00:\x00i\x00n\x00c\x00l\x00u\x00d\x00e" "\x00-\x00-" "\x00(\x00)" "\x00%\x00a" "\x00:\x00s\x00c\x00h\x00e\x00m\x00a" "\x00U\x00C\x00S\x00-\x004" "\x00<\x00/\x00a\x00>" "\x00<\x00a\x00>" "\x00<\x00a\x00 \x00/\x00>" "\x00<\x00?\x00x\x00m\x00l\x00?\x00>" "\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00d\x00o\x00c\x00b\x00o\x00o" "\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w" "\x00h\x00e\x003\x000" "\x00h\x00e\x002" "\x00I\x00E\x00T" "\x00F\x00D\x00F\x00-\x001\x000" "\x00a\x00D\x00U\x00C\x00S\x00-\x004\x00O\x00P\x00v\x00e\x00b\x00:" "\x00a\x00>" "\x00U\x00T" "\x00x\x00M\x00l" "\x00/\x00u\x00s\x00r\x00/\x00s\x00h\x00a\x00r\x00e\x00/\x00s\x00g" "\x00h\x00a\x000\x007" "\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00o\x00a" "\x00c\x00l\x00e" ================================================ FILE: projects/expat/xml_UTF_16LE.dict ================================================ # xml.dict converted to UTF-16LE encoding. " \x00e\x00n\x00c\x00o\x00d\x00i\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00a\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00h\x00r\x00e\x00f\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00s\x00t\x00a\x00n\x00d\x00a\x00l\x00o\x00n\x00e\x00=\x00\\\x00"\x00n\x00o\x00\\\x00"\x00" " \x00v\x00e\x00r\x00s\x00i\x00o\x00n\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00x\x00m\x00l\x00:\x00b\x00a\x00s\x00e\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00x\x00m\x00l\x00:\x00i\x00d\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00x\x00m\x00l\x00:\x00l\x00a\x00n\x00g\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00x\x00m\x00l\x00:\x00s\x00p\x00a\x00c\x00e\x00=\x00\\\x00"\x001\x00\\\x00"\x00" " \x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x001\x00\\\x00"\x00" "&\x00l\x00t\x00;\x00" "&\x00#\x001\x00;\x00" "&\x00a\x00;\x00" "&\x00#\x00x\x001\x00;\x00" "A\x00N\x00Y\x00" "A\x00T\x00T\x00L\x00I\x00S\x00T\x00" "C\x00D\x00A\x00T\x00A\x00" "D\x00O\x00C\x00T\x00Y\x00P\x00E\x00" "E\x00L\x00E\x00M\x00E\x00N\x00T\x00" "E\x00M\x00P\x00T\x00Y\x00" "E\x00N\x00T\x00I\x00T\x00I\x00E\x00S\x00" "E\x00N\x00T\x00I\x00T\x00Y\x00" "F\x00I\x00X\x00E\x00D\x00" "I\x00D\x00" "I\x00D\x00R\x00E\x00F\x00" "I\x00D\x00R\x00E\x00F\x00S\x00" "I\x00G\x00N\x00O\x00R\x00E\x00" "I\x00M\x00P\x00L\x00I\x00E\x00D\x00" "I\x00N\x00C\x00L\x00U\x00D\x00E\x00" "N\x00D\x00A\x00T\x00A\x00" "N\x00M\x00T\x00O\x00K\x00E\x00N\x00" "N\x00M\x00T\x00O\x00K\x00E\x00N\x00S\x00" "N\x00O\x00T\x00A\x00T\x00I\x00O\x00N\x00" "P\x00C\x00D\x00A\x00T\x00A\x00" "P\x00U\x00B\x00L\x00I\x00C\x00" "R\x00E\x00Q\x00U\x00I\x00R\x00E\x00D\x00" "S\x00Y\x00S\x00T\x00E\x00M\x00" "<\x00" ">\x00" "/\x00>\x00" "<\x00/\x00" "<\x00?\x00" "?\x00>\x00" "<\x00!\x00" "!\x00>\x00" "[\x00]\x00" "]\x00]\x00" "<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[\x00" "<\x00!\x00[\x00C\x00D\x00A\x00T\x00A\x00[\x00]\x00]\x00>\x00" "\\\x00"\x00\\\x00"\x00" "'\x00'\x00" "=\x00\\\x00"\x00\\\x00"\x00" "=\x00'\x00'\x00" "<\x00!\x00A\x00T\x00T\x00L\x00I\x00S\x00T\x00" "<\x00!\x00D\x00O\x00C\x00T\x00Y\x00P\x00E\x00" "<\x00!\x00E\x00L\x00E\x00M\x00E\x00N\x00T\x00" "<\x00!\x00E\x00N\x00T\x00I\x00T\x00Y\x00" "<\x00!\x00[\x00I\x00G\x00N\x00O\x00R\x00E\x00[\x00" "<\x00!\x00[\x00I\x00N\x00C\x00L\x00U\x00D\x00E\x00[\x00" "<\x00!\x00N\x00O\x00T\x00A\x00T\x00I\x00O\x00N\x00" "#\x00C\x00D\x00A\x00T\x00A\x00" "#\x00F\x00I\x00X\x00E\x00D\x00" "#\x00I\x00M\x00P\x00L\x00I\x00E\x00D\x00" "#\x00P\x00C\x00D\x00A\x00T\x00A\x00" "#\x00R\x00E\x00Q\x00U\x00I\x00R\x00E\x00D\x00" "I\x00S\x00O\x00-\x008\x008\x005\x009\x00-\x001\x00" "U\x00S\x00-\x00A\x00S\x00C\x00I\x00I\x00" "U\x00T\x00F\x00-\x008\x00" "U\x00T\x00F\x00-\x001\x006\x00" "U\x00T\x00F\x00-\x001\x006\x00B\x00E\x00" "U\x00T\x00F\x00-\x001\x006\x00L\x00E\x00" "x\x00m\x00l\x00n\x00s\x00" "x\x00m\x00l\x00n\x00s\x00:\x00" "x\x00m\x00l\x00n\x00s\x00:\x00x\x00h\x00t\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x001\x009\x009\x009\x00/\x00x\x00h\x00t\x00m\x00l\x00\\\x00"\x00" "x\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x00X\x00M\x00L\x00/\x001\x009\x009\x008\x00/\x00n\x00a\x00m\x00e\x00s\x00p\x00a\x00c\x00e\x00\\\x00"\x00" "x\x00m\x00l\x00n\x00s\x00:\x00x\x00m\x00l\x00n\x00s\x00=\x00\\\x00"\x00h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x003\x00.\x00o\x00r\x00g\x00/\x002\x000\x000\x000\x00/\x00x\x00m\x00l\x00n\x00s\x00\\\x00"\x00" ":\x00f\x00a\x00l\x00l\x00b\x00a\x00c\x00k\x00" ":\x00a\x00" ":\x00i\x00n\x00c\x00l\x00u\x00d\x00e\x00" "-\x00-\x00" "(\x00)\x00" "%\x00a\x00" ":\x00s\x00c\x00h\x00e\x00m\x00a\x00" "U\x00C\x00S\x00-\x004\x00" "<\x00/\x00a\x00>\x00" "<\x00a\x00>\x00" "<\x00a\x00 \x00/\x00>\x00" "<\x00?\x00x\x00m\x00l\x00?\x00>\x00" "h\x00t\x00t\x00p\x00:\x00/\x00/\x00d\x00o\x00c\x00b\x00o\x00o\x00" "h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00w\x00" "h\x00e\x003\x000\x00" "h\x00e\x002\x00" "I\x00E\x00T\x00" "F\x00D\x00F\x00-\x001\x000\x00" "a\x00D\x00U\x00C\x00S\x00-\x004\x00O\x00P\x00v\x00e\x00b\x00:\x00" "a\x00>\x00" "U\x00T\x00" "x\x00M\x00l\x00" "/\x00u\x00s\x00r\x00/\x00s\x00h\x00a\x00r\x00e\x00/\x00s\x00g\x00" "h\x00a\x000\x007\x00" "h\x00t\x00t\x00p\x00:\x00/\x00/\x00w\x00w\x00w\x00.\x00o\x00a\x00" "c\x00l\x00e\x00" ================================================ FILE: projects/expr/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/expr-lang/expr.git COPY build.sh $SRC/ WORKDIR $SRC/expr ================================================ FILE: projects/expr/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/expr/test/fuzz/fuzz_expr_seed_corpus.zip $OUT/ cp $SRC/expr/test/fuzz/fuzz_expr.dict $OUT/ go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer github.com/expr-lang/expr/test/fuzz FuzzExpr fuzz_expr ================================================ FILE: projects/expr/project.yaml ================================================ homepage: "https://github.com/expr-lang/expr" primary_contact: "martin.swende@ethereum.org" auto_ccs: - "antonmedvio@gmail.com" - "ville@vesilehto.fi" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/expr-lang/expr.git" file_github_issue: True ================================================ FILE: projects/exprtk/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/ArashPartow/exprtk.git exprtk WORKDIR exprtk COPY build.sh exprtk_fuzzer.cpp exprtk_test_expressions.dict $SRC/ ================================================ FILE: projects/exprtk/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/*.dict $OUT/ CXXFLAGS="${CXXFLAGS} -O2 -fno-sanitize=integer-divide-by-zero,float-divide-by-zero" $CXX -std=c++11 $CXXFLAGS -I. -I$SRC/exprtk \ $SRC/exprtk_fuzzer.cpp -o $OUT/exprtk_fuzzer \ $LIB_FUZZING_ENGINE ================================================ FILE: projects/exprtk/exprtk_fuzzer.cpp ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #define exprtk_enable_range_runtime_checks #include "exprtk.hpp" constexpr auto max_test_duration = std::chrono::seconds(58); // OSSFuzz test time is 60seconds const auto global_timeout_tp = std::chrono::steady_clock::now() + max_test_duration; struct timeout_rtc_handler : public exprtk::loop_runtime_check { timeout_rtc_handler() : exprtk::loop_runtime_check() {} class timeout_exception : public std::runtime_error { public: timeout_exception(const std::string& what = "") : std::runtime_error(what) {} }; static constexpr std::size_t max_iterations = 5000000; using time_point_t = std::chrono::time_point; void set_timeout_time(const time_point_t& timeout_tp) { timeout_tp_ = timeout_tp; } bool check() override { if (++iterations_ >= max_iterations) { if (std::chrono::steady_clock::now() >= timeout_tp_) { return false; } iterations_ = 0; } return true; } void handle_runtime_violation(const violation_context& /*context*/) override { throw timeout_exception("ExprTk Loop run-time timeout violation."); } std::size_t iterations_ = 0; time_point_t timeout_tp_; }; struct compilation_timeout_check final : public exprtk::compilation_check { static constexpr std::size_t max_iters_per_check = 500; bool continue_compilation(compilation_context& context) override { if (++iterations_ >= max_iters_per_check) { if (std::chrono::steady_clock::now() >= timeout_tp_) { context.error_message = "Compilation has timed-out"; return false; } iterations_ = 0; } return true; } using time_point_t = std::chrono::time_point; void set_timeout_time(const time_point_t& timeout_tp) { timeout_tp_ = timeout_tp; } std::size_t iterations_ = max_iters_per_check; time_point_t timeout_tp_; }; struct vector_access_rtc final : public exprtk::vector_access_runtime_check { bool handle_runtime_violation(violation_context& /*context*/) override { throw std::runtime_error("Runtime vector access violation."); return false; } }; struct assert_handler final : public exprtk::assert_check { void handle_assert(const assert_context& /*context*/) override { throw std::runtime_error("assert: vector access violation."); } }; template void run(const std::string& expression_string) { using symbol_table_t = exprtk::symbol_table; using expression_t = exprtk::expression; using parser_t = exprtk::parser; using loop_runtime_check_t = exprtk::loop_runtime_check; T x = T(1.2345); T y = T(2.2345); T z = T(3.2345); T w = T(4.2345); symbol_table_t symbol_table; symbol_table.add_variable("x",x); symbol_table.add_variable("y",y); symbol_table.add_variable("z",z); symbol_table.add_variable("w",w); symbol_table.add_constants(); expression_t expression; expression.register_symbol_table(symbol_table); timeout_rtc_handler loop_runtime_check; loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops; loop_runtime_check.max_loop_iterations = 100000; compilation_timeout_check compilation_timeout_chck; vector_access_rtc vector_rtc; assert_handler asrt_handler; parser_t parser; parser.settings().set_max_stack_depth(400); parser.settings().set_max_node_depth (400); parser.settings().set_max_local_vector_size(10000000); // double: 80MB float: 40MB parser.register_compilation_timeout_check (compilation_timeout_chck); parser.register_loop_runtime_check (loop_runtime_check ); parser.register_vector_access_runtime_check(vector_rtc ); parser.register_assert_check (asrt_handler ); compilation_timeout_chck.set_timeout_time(global_timeout_tp); if (parser.compile(expression_string, expression)) { const std::size_t max_expression_size = 64 * 1024; if (expression_string.size() <= max_expression_size) { loop_runtime_check.set_timeout_time(global_timeout_tp); try { expression.value(); } catch (std::runtime_error& rte) {} catch (...) {} parser.clear_loop_runtime_check(); } } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { const std::string expression(reinterpret_cast(data), size); run(expression); run (expression); return 0; } ================================================ FILE: projects/exprtk/exprtk_test_expressions.dict ================================================ "1" "a" "()" "a*2" "a+1" "a+b" "(())" "a+-b" "(a*e)" "(a+e)" "(a-a)" "(b*e)" "(b+a)" "(b-b)" "(e*e)" "1+a^2" "2*a+1" "a*2.2" "a*b*c" "a*b+c" "a+1.1" "a+b*c" "a+b+c" "a+b-c" "a-b-c" "a/b/c" "a^2+1" "a^2^3" "b^2*2" "x*y*z" "x*y+z" "x*y-z" "x*y/z" "x+y*z" "x+y+z" "x+y-z" "x+y/z" "x-y*z" "x-y/z" "x/y*z" "x/y+z" "x/y-z" "x/y/z" "((()))" "(pi*b)" "(pi+b)" "(x)(x)" "[x][x]" "abs(a)" "cos(a)" "sin(a)" "tan(a)" "{x}{x}" "(a+b)*3" "(pi+pi)" "1.1*a^2" "1.1+a^2" "2*(a+b)" "2.2*b^2" "2.2*y*z" "2.2*y+z" "2.2*y-z" "2.2*y/z" "2.2+y*z" "2.2+y+z" "2.2+y-z" "2.2+y/z" "2.2-y*z" "2.2-y/z" "2.2/y*z" "2.2/y+z" "2.2/y-z" "2.2/y/z" "a*2+b*2" "a^2+b^2" "sqrt(a)" "x*3.3*z" "x*3.3+z" "x*3.3-z" "x*3.3/z" "x*y*4.4" "x*y*z+w" "x*y*z-w" "x*y+4.4" "x*y+z*w" "x*y+z+w" "x*y+z-w" "x*y+z/w" "x*y-4.4" "x*y-z*w" "x*y-z+w" "x*y-z-w" "x*y-z/w" "x*y/4.4" "x*y/z+w" "x*y/z-w" "x+3.3*z" "x+3.3+z" "x+3.3-z" "x+3.3/z" "x+y*4.4" "x+y*z*w" "x+y*z-w" "x+y*z/w" "x+y+4.4" "x+y+z*w" "x+y+z-w" "x+y+z/w" "x+y-4.4" "x+y-z*w" "x+y-z-w" "x+y-z/w" "x+y/4.4" "x+y/z*w" "x+y/z+w" "x+y/z-w" "x+y/z/w" "x-3.3*z" "x-3.3/z" "x-y*4.4" "x-y*z*w" "x-y*z-w" "x-y*z/w" "x-y+z*w" "x-y+z+w" "x-y+z/w" "x-y-z*w" "x-y-z+w" "x-y-z/w" "x-y/4.4" "x-y/z*w" "x-y/z-w" "x-y/z/w" "x/3.3*z" "x/3.3+z" "x/3.3-z" "x/3.3/z" "x/y*4.4" "x/y*z+w" "x/y*z-w" "x/y+4.4" "x/y+z*w" "x/y+z+w" "x/y+z-w" "x/y+z/w" "x/y-4.4" "x/y-z*w" "x/y-z+w" "x/y-z-w" "x/y-z/w" "x/y/4.4" "x/y/z+w" "x/y/z-w" "(3.70/b)" "(a/0.20)" "(b+2.07)" "(b+3.52)" "-(b^1.1)" "((a/a)+e)" "((b/a)/a)" "((e/b)+e)" "((x*y*z))" "((x*y+z))" "((x*y-z))" "((x*y/z))" "((x+y*z))" "((x+y+z))" "((x+y-z))" "((x+y/z))" "((x-y*z))" "((x-y+z))" "((x-y-z))" "((x-y/z))" "((x/y*z))" "((x/y+z))" "((x/y-z))" "((x/y/z))" "(2*a+1)*3" "(2*a+2*a)" "(3.00+pi)" "(a+b)*3.3" "2.2*(a+b)" "2.2*a+1.1" "2.2*y*4.4" "2.2*y*z+w" "2.2*y*z-w" "2.2*y+4.4" "2.2*y+z*w" "2.2*y+z+w" "2.2*y+z-w" "2.2*y+z/w" "2.2*y-4.4" "2.2*y-z*w" "2.2*y-z+w" "2.2*y-z-w" "2.2*y-z/w" "2.2*y/4.4" "2.2*y/z+w" "2.2*y/z-w" "2.2+y*4.4" "2.2+y*z*w" "2.2+y*z-w" "2.2+y*z/w" "2.2+y+4.4" "2.2+y+z*w" "2.2+y+z-w" "2.2+y+z/w" "2.2+y-4.4" "2.2+y-z*w" "2.2+y-z-w" "2.2+y-z/w" "2.2+y/4.4" "2.2+y/z*w" "2.2+y/z+w" "2.2+y/z-w" "2.2+y/z/w" "2.2-y*4.4" "2.2-y*z*w" "2.2-y*z-w" "2.2-y*z/w" "2.2-y+z*w" "2.2-y+z+w" "2.2-y+z/w" "2.2-y-z*w" "2.2-y-z+w" "2.2-y-z/w" "2.2-y/4.4" "2.2-y/z*w" "2.2-y/z-w" "2.2-y/z/w" "2.2/y*4.4" "2.2/y*z+w" "2.2/y*z-w" "2.2/y+4.4" "2.2/y+z*w" "2.2/y+z+w" "2.2/y+z-w" "2.2/y+z/w" "2.2/y-4.4" "2.2/y-z*w" "2.2/y-z+w" "2.2/y-z-w" "2.2/y-z/w" "2.2/y/4.4" "2.2/y/z+w" "2.2/y/z-w" "a+b*(a+b)" "a^2^3-a^8" "tan(1.29)" "x*3.3*4.4" "x*3.3*z+w" "x*3.3*z-w" "x*3.3+4.4" "x*3.3+z*w" "x*3.3+z+w" "x*3.3+z-w" "x*3.3+z/w" "x*3.3-4.4" "x*3.3-z*w" "x*3.3-z+w" "x*3.3-z-w" "x*3.3-z/w" "x*3.3/4.4" "x*3.3/z+w" "x*3.3/z-w" "x*y*4.4+w" "x*y*4.4-w" "x*y*z+5.5" "x*y*z-5.5" "x*y+4.4*w" "x*y+4.4+w" "x*y+4.4-w" "x*y+4.4/w" "x*y+z*5.5" "x*y+z+5.5" "x*y+z-5.5" "x*y+z/5.5" "x*y-4.4*w" "x*y-4.4+w" "x*y-4.4-w" "x*y-4.4/w" "x*y-z*5.5" "x*y-z+5.5" "x*y-z-5.5" "x*y-z/5.5" "x*y/4.4+w" "x*y/4.4-w" "x*y/z+5.5" "x*y/z-5.5" "x+3.3*4.4" "x+3.3*z*w" "x+3.3*z-w" "x+3.3*z/w" "x+3.3+4.4" "x+3.3+z*w" "x+3.3+z-w" "x+3.3+z/w" "x+3.3-4.4" "x+3.3-z*w" "x+3.3-z-w" "x+3.3-z/w" "x+3.3/4.4" "x+3.3/z*w" "x+3.3/z+w" "x+3.3/z-w" "x+3.3/z/w" "x+y*4.4*w" "x+y*4.4-w" "x+y*4.4/w" "x+y*z*5.5" "x+y*z-5.5" "x+y*z/5.5" "x+y+4.4*w" "x+y+4.4-w" "x+y+4.4/w" "x+y+z*5.5" "x+y+z-5.5" "x+y+z/5.5" "x+y-4.4*w" "x+y-4.4-w" "x+y-4.4/w" "x+y-z*5.5" "x+y-z-5.5" "x+y-z/5.5" "x+y/4.4*w" "x+y/4.4+w" "x+y/4.4-w" "x+y/4.4/w" "x+y/z*5.5" "x+y/z+5.5" "x+y/z-5.5" "x+y/z/5.5" "x-3.3*4.4" "x-3.3*z*w" "x-3.3*z-w" "x-3.3*z/w" "x-3.3+z*w" "x-3.3+z+w" "x-3.3+z/w" "x-3.3-z*w" "x-3.3-z+w" "x-3.3-z/w" "x-3.3/4.4" "x-3.3/z*w" "x-3.3/z-w" "x-3.3/z/w" "x-y*4.4*w" "x-y*4.4-w" "x-y*4.4/w" "x-y*z*5.5" "x-y*z-5.5" "x-y*z/5.5" "x-y+4.4*w" "x-y+4.4+w" "x-y+4.4/w" "x-y+z*5.5" "x-y+z+5.5" "x-y+z/5.5" "x-y-4.4*w" "x-y-4.4+w" "x-y-4.4/w" "x-y-z*5.5" "x-y-z+5.5" "x-y-z/5.5" "x-y/4.4*w" "x-y/4.4-w" "x-y/4.4/w" "x-y/z*5.5" "x-y/z-5.5" "x-y/z/5.5" "x/3.3*4.4" "x/3.3*z+w" "x/3.3*z-w" "x/3.3+4.4" "x/3.3+z*w" "x/3.3+z+w" "x/3.3+z-w" "x/3.3+z/w" "x/3.3-4.4" "x/3.3-z*w" "x/3.3-z+w" "x/3.3-z-w" "x/3.3-z/w" "x/3.3/4.4" "x/3.3/z+w" "x/3.3/z-w" "x/y*4.4+w" "x/y*4.4-w" "x/y*z+5.5" "x/y*z-5.5" "x/y+4.4*w" "x/y+4.4+w" "x/y+4.4-w" "x/y+4.4/w" "x/y+z*5.5" "x/y+z+5.5" "x/y+z-5.5" "x/y+z/5.5" "x/y-4.4*w" "x/y-4.4+w" "x/y-4.4-w" "x/y-4.4/w" "x/y-z*5.5" "x/y-z+5.5" "x/y-z-5.5" "x/y-z/5.5" "x/y/4.4+w" "x/y/4.4-w" "x/y/z+5.5" "x/y/z-5.5" "((b/b)/pi)" "((x))((x))" "(1+b)*(-3)" "(b+(pi*a))" "-a^2^3-a^8" "1.1*a^2.01" "[[x]][[x]]" "e^log(7*a)" "{{x}}{{x}}" "(((x*y)*z))" "(((x*y)+z))" "(((x*y)-z))" "(((x*y)/z))" "(((x+y)*z))" "(((x+y)+z))" "(((x+y)-z))" "(((x+y)/z))" "(((x-y)*z))" "(((x-y)/z))" "(((x/y)*z))" "(((x/y)+z))" "(((x/y)-z))" "(((x/y)/z))" "((a-pi)*pi)" "((x*(y*z)))" "((x*(y+z)))" "((x*(y-z)))" "((x*(y/z)))" "((x*y*z+w))" "((x*y*z-w))" "((x*y+z*w))" "((x*y+z+w))" "((x*y+z-w))" "((x*y+z/w))" "((x*y-z*w))" "((x*y-z+w))" "((x*y-z-w))" "((x*y-z/w))" "((x*y/z+w))" "((x*y/z-w))" "((x+(y*z)))" "((x+(y+z)))" "((x+(y-z)))" "((x+(y/z)))" "((x+y*z*w))" "((x+y*z-w))" "((x+y*z/w))" "((x+y+z*w))" "((x+y+z-w))" "((x+y+z/w))" "((x+y-z*w))" "((x+y-z-w))" "((x+y-z/w))" "((x+y/z*w))" "((x+y/z+w))" "((x+y/z-w))" "((x+y/z/w))" "((x-(y*z)))" "((x-(y+z)))" "((x-(y-z)))" "((x-(y/z)))" "((x-y*z*w))" "((x-y*z+w))" "((x-y*z-w))" "((x-y*z/w))" "((x-y+z*w))" "((x-y+z+w))" "((x-y+z/w))" "((x-y-z*w))" "((x-y-z+w))" "((x-y-z/w))" "((x-y/z*w))" "((x-y/z+w))" "((x-y/z-w))" "((x-y/z/w))" "((x/(y*z)))" "((x/(y+z)))" "((x/(y-z)))" "((x/(y/z)))" "((x/y*z+w))" "((x/y*z-w))" "((x/y+z*w))" "((x/y+z+w))" "((x/y+z-w))" "((x/y+z/w))" "((x/y-z*w))" "((x/y-z+w))" "((x/y-z-w))" "((x/y-z/w))" "((x/y/z+w))" "((x/y/z-w))" "1-(a/b*0.5)" "10^log(3+b)" "2.2*a^1+1.1" "2.2*y*4.4+w" "2.2*y*4.4-w" "2.2*y*z+5.5" "2.2*y*z-5.5" "2.2*y+4.4*w" "2.2*y+4.4+w" "2.2*y+4.4-w" "2.2*y+4.4/w" "2.2*y+z*5.5" "2.2*y+z+5.5" "2.2*y+z-5.5" "2.2*y+z/5.5" "2.2*y-4.4*w" "2.2*y-4.4+w" "2.2*y-4.4-w" "2.2*y-4.4/w" "2.2*y-z*5.5" "2.2*y-z+5.5" "2.2*y-z-5.5" "2.2*y-z/5.5" "2.2*y/4.4+w" "2.2*y/4.4-w" "2.2*y/z+5.5" "2.2*y/z-5.5" "2.2+y*4.4*w" "2.2+y*4.4-w" "2.2+y*4.4/w" "2.2+y*z*5.5" "2.2+y*z-5.5" "2.2+y*z/5.5" "2.2+y+4.4*w" "2.2+y+4.4-w" "2.2+y+4.4/w" "2.2+y+z*5.5" "2.2+y+z-5.5" "2.2+y+z/5.5" "2.2+y-4.4*w" "2.2+y-4.4-w" "2.2+y-4.4/w" "2.2+y-z*5.5" "2.2+y-z-5.5" "2.2+y-z/5.5" "2.2+y/4.4*w" "2.2+y/4.4+w" "2.2+y/4.4-w" "2.2+y/4.4/w" "2.2+y/z*5.5" "2.2+y/z+5.5" "2.2+y/z-5.5" "2.2+y/z/5.5" "2.2-y*4.4*w" "2.2-y*4.4-w" "2.2-y*4.4/w" "2.2-y*z*5.5" "2.2-y*z-5.5" "2.2-y*z/5.5" "2.2-y+4.4*w" "2.2-y+4.4+w" "2.2-y+4.4/w" "2.2-y+z*5.5" "2.2-y+z+5.5" "2.2-y+z/5.5" "2.2-y-4.4*w" "2.2-y-4.4+w" "2.2-y-4.4/w" "2.2-y-z*5.5" "2.2-y-z+5.5" "2.2-y-z/5.5" "2.2-y/4.4*w" "2.2-y/4.4-w" "2.2-y/4.4/w" "2.2-y/z*5.5" "2.2-y/z-5.5" "2.2-y/z/5.5" "2.2/y*4.4+w" "2.2/y*4.4-w" "2.2/y*z+5.5" "2.2/y*z-5.5" "2.2/y+4.4*w" "2.2/y+4.4+w" "2.2/y+4.4-w" "2.2/y+4.4/w" "2.2/y+z*5.5" "2.2/y+z+5.5" "2.2/y+z-5.5" "2.2/y+z/5.5" "2.2/y-4.4*w" "2.2/y-4.4+w" "2.2/y-4.4-w" "2.2/y-4.4/w" "2.2/y-z*5.5" "2.2/y-z+5.5" "2.2/y-z-5.5" "2.2/y-z/5.5" "2.2/y/4.4+w" "2.2/y/4.4-w" "2.2/y/z+5.5" "2.2/y/z-5.5" "sin(tan(b))" "x*3.3*4.4+w" "x*3.3*4.4-w" "x*3.3*z+5.5" "x*3.3*z-5.5" "x*3.3+4.4*w" "x*3.3+4.4+w" "x*3.3+4.4-w" "x*3.3+4.4/w" "x*3.3+z*5.5" "x*3.3+z+5.5" "x*3.3+z-5.5" "x*3.3+z/5.5" "x*3.3-4.4*w" "x*3.3-4.4+w" "x*3.3-4.4-w" "x*3.3-4.4/w" "x*3.3-z*5.5" "x*3.3-z+5.5" "x*3.3-z-5.5" "x*3.3-z/5.5" "x*3.3/4.4+w" "x*3.3/4.4-w" "x*3.3/z+5.5" "x*3.3/z-5.5" "x*y*z-x*y/z" "x*y+z+x*y-z" "x*y/z-x*y*z" "x+3.3*4.4*w" "x+3.3*4.4-w" "x+3.3*4.4/w" "x+3.3*z*5.5" "x+3.3*z-5.5" "x+3.3*z/5.5" "x+3.3+4.4*w" "x+3.3+4.4-w" "x+3.3+4.4/w" "x+3.3+z*5.5" "x+3.3+z-5.5" "x+3.3+z/5.5" "x+3.3-4.4*w" "x+3.3-4.4-w" "x+3.3-4.4/w" "x+3.3-z*5.5" "x+3.3-z-5.5" "x+3.3-z/5.5" "x+3.3/4.4*w" "x+3.3/4.4-w" "x+3.3/4.4/w" "x+3.3/z*5.5" "x+3.3/z+5.5" "x+3.3/z-5.5" "x+3.3/z/5.5" "x+y-z-x+y+z" "x+y/z+x+y*z" "x+y/z-x+y+z" "x-3.3*4.4*w" "x-3.3*4.4-w" "x-3.3*4.4/w" "x-3.3*z*5.5" "x-3.3*z-5.5" "x-3.3*z/5.5" "x-3.3+4.4*w" "x-3.3+4.4+w" "x-3.3+4.4/w" "x-3.3+z*5.5" "x-3.3+z+5.5" "x-3.3+z/5.5" "x-3.3-4.4*w" "x-3.3-4.4+w" "x-3.3-4.4/w" "x-3.3-z*5.5" "x-3.3-z+5.5" "x-3.3-z/5.5" "x-3.3/4.4*w" "x-3.3/4.4-w" "x-3.3/4.4/w" "x-3.3/z*5.5" "x-3.3/z-5.5" "x-3.3/z/5.5" "x-y*z+x+y*z" "x-y/z*x-y*z" "x-y/z*x-y/z" "x/3.3*4.4+w" "x/3.3*4.4-w" "x/3.3*z+5.5" "x/3.3*z-5.5" "x/3.3+4.4*w" "x/3.3+4.4+w" "x/3.3+4.4-w" "x/3.3+4.4/w" "x/3.3+z*5.5" "x/3.3+z+5.5" "x/3.3+z-5.5" "x/3.3+z/5.5" "x/3.3-4.4*w" "x/3.3-4.4+w" "x/3.3-4.4-w" "x/3.3-4.4/w" "x/3.3-z*5.5" "x/3.3-z+5.5" "x/3.3-z-5.5" "x/3.3-z/5.5" "x/3.3/4.4+w" "x/3.3/4.4-w" "x/3.3/z+5.5" "x/3.3/z-5.5" "x/y*z*x/y/z" "x/y+z*x/y-z" "x/y+z-x/y-z" "x/y/z+x/y*z" "(((((())))))" "((1.11+a)*a)" "((3.08+e)-b)" "((a+b)+3.55)" "((b*b)*2.41)" "(b/(b*0.06))" "a+b-e*pi/5^6" "a^-2^3-1/a^8" "a^b/e*pi-5+6" "(((a-a)+e)/a)" "(((b+e)+a)-a)" "((0.73+pi)*e)" "((3.123*y*z))" "((3.123*y+z))" "((3.123*y-z))" "((3.123*y/z))" "((3.123+y*z))" "((3.123+y+z))" "((3.123+y-z))" "((3.123+y/z))" "((3.123-y*z))" "((3.123-y+z))" "((3.123-y-z))" "((3.123-y/z))" "((3.123/y*z))" "((3.123/y+z))" "((3.123/y-z))" "((3.123/y/z))" "((a/pi)-2.55)" "((b*(b+b))*b)" "((pi/2.23)-a)" "((x*5.123*z))" "((x*5.123+z))" "((x*5.123-z))" "((x*5.123/z))" "((x*y*7.123))" "((x*y+7.123))" "((x*y-7.123))" "((x*y/7.123))" "((x+5.123*z))" "((x+5.123+z))" "((x+5.123-z))" "((x+5.123/z))" "((x+y*7.123))" "((x+y+7.123))" "((x+y-7.123))" "((x+y/7.123))" "((x-5.123*z))" "((x-5.123+z))" "((x-5.123-z))" "((x-5.123/z))" "((x-y*7.123))" "((x-y+7.123))" "((x-y-7.123))" "((x-y/7.123))" "((x/5.123*z))" "((x/5.123+z))" "((x/5.123-z))" "((x/5.123/z))" "((x/y*7.123))" "((x/y+7.123))" "((x/y-7.123))" "((x/y/7.123))" "(a*(b-(b/b)))" "(cos(2.41)/b)" "+a^+2^+3-a^+8" "123456.123456" "2.2*y*4.4-5.5" "2.2*y/4.4-5.5" "2.2+y*4.4*5.5" "2.2+y*4.4-5.5" "2.2+y*4.4/5.5" "2.2+y+4.4*5.5" "2.2+y+4.4/5.5" "2.2+y-4.4*5.5" "2.2+y-4.4/5.5" "2.2+y/4.4*5.5" "2.2+y/4.4+5.5" "2.2+y/4.4-5.5" "2.2+y/4.4/5.5" "2.2-y*4.4*5.5" "2.2-y*4.4-5.5" "2.2-y*4.4/5.5" "2.2-y+4.4*5.5" "2.2-y+4.4/5.5" "2.2-y-4.4*5.5" "2.2-y-4.4/5.5" "2.2-y/4.4*5.5" "2.2-y/4.4-5.5" "2.2-y/4.4/5.5" "2.2/y*4.4-5.5" "2.2/y/4.4-5.5" "sin(a)+sin(b)" "sqrt(a^2+b^2)" "tan((3.59-e))" "x*3.3*4.4-5.5" "x*3.3/4.4-5.5" "x+3.3*4.4-5.5" "x+3.3/4.4-5.5" "x-3.3*4.4-5.5" "x-3.3/4.4-5.5" "x/3.3*4.4-5.5" "x/3.3/4.4-5.5" "(((x)))(((x)))" "(1.1+b)*(-3.3)" "-(sin(pi+a)+1)" "[[[x]]][[[x]]]" "sqrt(a) 3 + 3 ? 7 : 9) == 9" "(1 + 1 < 3 ? 7 : 9) == 7" "(1 + 1 > 3 ? 7 : 9) == 9" "(1 < 2 ? 3 : 4) == 3" "(1 > 2 ? 3 : 4) == 4" "'123456789'[0:] != '01234567890123456789'[0:9]" "'123456789'[:] != '01234567890123456789'[0:9]" "'123456789' != '01234567890123456789'[0:9]" "'123456789'[:] != '01234567890123456789'[10:]" "'123456789'[:8] != '01234567890123456789'[0:9]" "'123456789'[:8] != '01234567890123456789'[:9]" "(1 > 2 ? 3 : 4 + 5) == 9" "(1 < 2 ? 3 + 5 : 4) == 8" "'123' in 'aaa123'" "12 == (if (1 > 2) { var x:= 2; } else { var x[3] := {7,2,3}; sum(x); })" "12 == (if (1 < 2) { var x[3] := {7,2,3}; sum(x); } else { var x:= 2; })" " 1 ? 3 : 4" "(1 ? 3 : 4) == 3" "1 == (for (var i := 0; i < 10; i += 1) { ~{break[i += 1]; continue; i += i} })" "'1XYZ2' ilike '*xyz*'" "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; i += 1; i += 2; i += 3; }; })" "21 == (for (var i := 0; i < 10; i += 1) { if (i > 2) { break [i * 7]; return [i * 8]; i += 1; i += 2; i += 3; }; })" "(2 < 3 + 3 ? 7 : 9) == 7" "(2 > 3 + 3 ? 7 : 9) == 9" "'23456' == '01234567890123456789'[1+1:r1]" "'23456' == '01234567890123456789'[2*6:10+6]" "'23456' == '01234567890123456789'[2: r1]" "'23456' == '01234567890123456789'[r0:3*2]" "'23456' == '01234567890123456789'[r0: 6]" "'23456' == '01234567890123456789'[r0:r1]" "'2345678' == '01234567890123456789'[r0:r1+2]" "'234567890123456789' == '01234567890123456789'[r0: ]" "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; i += 1; i += 2; i += 3; } else i; }" "2 == for (var i := 0; i < 10; i += 1) { if (i > 2) { continue; return [i * 8]; i += 1; i += 2; i += 3; } else i; }" "'456' == '01234567890123456789'[r0+2:r1]" "'4567890123456789' == '01234567890123456789'[r1-r0:]" "7 == (for (var i := 0; i < 10; i += 1) { ~{break[7]; continue; i += i} })" "'a123b' like '*123*'" "'aaa' + '123' == 'aaa123'" "'aaa123' == 'aaa' + '123'" "'aaa' == 'aaa'" "'aaa' <= 'bbb'" "'aaa' < 'bbb'" "'aaa' in 'aaa123'" "'bbb' >= 'aaa'" "'bbb' > 'aaa'" "[*] { case 1 < 2 : 1 / 2; case (1 < 3) : 2 / 2; case 1 < 4 : 3 / 2; case (1 < 5) : 4 / 2; }" "[*]{ case x < y : x + y; case y < x : y - x; }" "equal((2.2*pi^2.2^3.3),2.2*(pi^13.4894687605338489))" "equal((2*pi^2^3),2*(pi^8))" "equal((pi^2.2^3.3*2),2*(pi^13.4894687605338489))" "equal((pi^2.2^3.3/2.2),(pi^13.4894687605338489)/2.2)" "equal((pi^2.2^3.3),(pi^13.4894687605338489))" "equal((pi^-2^-3),1/(pi^(1/8)))" "equal((pi^-2^3),1/(pi^8))" "equal((pi^2^3*2),2*(pi^8))" "equal((pi^2^3/2),(pi^8)/2)" "equal((pi^2^-3),(pi^(1/8)))" "equal((pi^2^3),(pi^8))" "equal(pi^2^3-pi^8,0)" "equal(\t \n(\n \r1.1\t\t - \n\n 2.2\n\n/\r3.3\t),(1.1-2.2/3.3))" "for(var i := 0; (i < 10) and (i != y); i+=2) { x += i; }; x;" "for(var i := 0; (i < 10) and (i != y);) { x += i; i+=2; }; x;" "for(var i := 0; (i < 10);) { i += 1; }; x;" "for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) continue; else x += i; }; x;" "for(var i := 0; (i < y); i += 1) { if (i <= (y / 2)) x += i; else break; }; x;" "if (1 < 2) { 1+2; 3;} == 3" "if (1 < 2) { 1+2; 3;} else {1+2; 4;} == 3" "if (1 > 2) { 1+2; 3;} else {1+2; 4;} == 4" "if (1 < 2) { 1+2; 3;} else 4; == 3" "if (1 > 2) { 1+2; 3;} else 4; == 4" "if (1 < 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 3" "if (1 > 2) { 1+2; 3;} else if (1 < 2) {1+2; 4;} == 4" "if (1 > 2) { 1+2; 3;} else if (1 > 2) {1+2; 4;} == null" "if (1 < 2) { 1+2; 3;} else if (1 < 2) 4; == 3" "if (1 > 2) { 1+2; 3;} else if (1 < 2) 4; == 4" "if (1 > 2) { 1+2; 3;} else if (1 > 2) 4; == null" "if (1 > 2) { 1+2; 3;} == null" "if (1 < 2) 3; == 3" "if (1 < 2) 3; else {1+2; 4;} == 3" "if (1 > 2) 3; else {1+2; 4;} == 4" "if (1 < 2) 3; else 4; == 3" "if (1 > 2) 3; else 4; == 4" "if (1 < 2) 3; else if (1 < 2) {1+2; 4;} == 3" "if (1 > 2) 3; else if (1 < 2) {1+2; 4;} == 4" "if (1 > 2) 3; else if (1 > 2) {1+2; 4;} == null" "if (1 < 2) 3; else if (1 < 2) 4; == 3" "if (1 > 2) 3; else if (1 < 2) 4; == 4" "if (1 > 2) 3; else if (1 > 2) 4; == null" "if (1 > 2) 3; == null" "inrange('aaa','bbb','ccc')" "(min(0,1) ? 1 + 3 : 1 + 4) == 5" "(min(1,2) ? 1 + 3 : 1 + 4) == 4" "repeat 1.1 + 2.2 until (1 < 2)" "repeat 1.1234; 1 < 2; 1.1 + 2.2 until (1 < 2)" "switch { case 1 > 1 : 1; case 2 > 2 : 2; case 3 = 3 : 3; case 4 > 4 : 4; default : 5; }" "switch { case (1 > 2) : 0; case (1 <= 2) : 1; default: 1.12345; }" "switch { case (1 <= 2) : 1; default: 1.12345; }" "switch { case (1 <= 2) : switch { case (1 <= 2) : 1; default: 1.12345; }; default: 1.12345; }" "switch { case ([x > y]) : [0]; case ([x <= y]) : [y - x]; default: 1.12345; }" "switch { case (x > y) : 0; case (x <= y) : (y - x); default: 1.12345; }" "switch { case {(x <= y)} : switch { case ({x <= y}) : x; default: 1.12345; }; default: 1.12345; }" "switch { case {x <= y} : switch { case {x <= y} : x; default: 1.12345; }; default: 1.12345; }" "switch { case (x <= y) : switch { case (x <= y) : (y - x); default: 1.12345; }; default: 1.12345; }" "switch { case {x <= y} : x; default: 1.12345; }" "switch { case [(x <= y)] : {y - x}; default: 1.12345; }" "switch { case (x <= y) : (y - x); default: 1.12345; }" "var s := 'abc'; ~{1 + 2; 'abc' + s; s} == s" "var s := 'abc'; ~{1 + 2; var x := 'ab'; x + 'c'} == s" "var s := 'abc'; ~{'ab' + 'c'} == s" "var s := 'abc'; ~{'abc' } == s" "var s := 'abc'; s == ~{'ab' + 'c'}" "var s := 'abc'; s == ~{'abc' }" "var s := 'abc'; ~{s } == s" "var s := 'abc'; s == ~{s }" "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 -= v1; (v0[0] == 0) and (v0[1] == 1) and (v0[2] == 2)" "var v0[3] := {1,2, 3}; var v1[3] := {1,1,1}; v0 += v1; (v0[0] == 2) and (v0[1] == 3) and (v0[2] == 4)" "var v0[3] := {1,2, 3}; var v1[3] := {2,2,2}; v0 *= v1; (v0[0] == 2) and (v0[1] == 4) and (v0[2] == 6)" "var v0[3] := [1]; var v1[3] := [1]; v0 -= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 0)" "var v0[3] := [1]; var v1[3] := [1]; v0 += v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)" "var v0[3] := [1]; var v1[3] := [2]; v0 *= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 2)" "var v0[3] := {3,9,15}; var v1[3] := {3,3,3}; v0 /= v1; (v0[0] == 1) and (v0[1] == 3) and (v0[2] == 5)" "var v0[3] := [3]; var v1[3] := [3]; v0 /= v1; (v0[0] == v0[1]) and (v0[0] == v0[2]) and (v0[0] == 1)" "var v[2] := {1,2}; swap(v[0],v[1]); (v[0] == 2) and (v[1] == 1)" "var v[2] := {1,2}; swap(v[2 * zero],v[(2 * one) / (1 + 1)]); (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)" "var v[2] := {1,2}; swap(v[zero],v[one]); (v[zero] == 2) and (v[one] == 1)" "var v[2] := {1,2}; v[0] <=> v[1] ; (v[0] == 2) and (v[1] == 1)" "var v[2] := {1,2}; ~(v[2 * zero] <=> v[(2 * one) / (1 + 1)] , (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1))" "var v[2] := {1,2}; v[2 * zero] <=> v[(2*one)/(1+1)] ; (v[2 * zero] == 2) and (v[(2 * one) / (1 + 1)] == 1)" "var v[2] := {1,2}; v[zero] <=> v[one] ; (v[zero] == 2) and (v[one] == 1)" "var v[3] := {1,2, 3}; v -= 1; (v[0] == 0) and (v[1] == 1) and (v[2] == 2)" "var v[3] := {1,2, 3}; v += 1; (v[0] == 2) and (v[1] == 3) and (v[2] == 4)" "var v[3] := {1,2, 3}; v *= 2; (v[0] == 2) and (v[1] == 4) and (v[2] == 6)" "var v[3] := [1]; v -= 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 0)" "var v[3] := [1]; v += 1; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)" "var v[3] := [1]; v *= 2; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 2)" "var v[3] := {3,9,15}; v /= 3; (v[0] == 1) and (v[1] == 3) and (v[2] == 5)" "var v[3] := [3]; v /= 3; (v[0] == v[1]) and (v[0] == v[2]) and (v[0] == 1)" "var x; 1" "var x[10] := [-1]; var y[10] := [-1]; for (var i := 0; i < 10; i += 1) { x[i] := i; y[i] := 2 * x[i]; }; (sum(x) == 45) and (sum(y) == (2 * sum(x)));" "var x[10^6]:=[2];var y[10^6]:=[3]; var s:=0;equal(for(var i:=0; i<10;i+=1){s+= sum(5 *(2x-y/3)) + i;},150000045.0)" "var x[10^6] := null; var y[10^7] := null; 0 * (min(x) + min(y)) + x[] + y[] == 10^7 + 10^6" "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6" "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x := [2] }}) == 6" "(~{~{ var x[1] := [1] }} + ~{ var x[1] := [1] } + ~{ var x := [2] } + ~{{ var x[1] := [2] }}) == 6" "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6" "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x := [2] }}) == 6" "(~{~{~{var x[1] := [1]}}} + ~{~{var x[1] := [2]}} + ~{var x[1] := [3]}) == 6" "(~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{~{ var x := [1] } + ~{ var x[1] := [2] }}) == 6" "(~{~{ var x[1] := [1] }} + ~{ var x := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6" "(~{ var x[1] := [1] } + ~{ var x := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6" "var x:=1; 2-(3+abs(x)) == -2" "var x:=1; 2/(3*abs(x)) == (2/3)" "var x:=1; 2+(3-abs(x)) == 4" "var x:=1; 2+(3+abs(x)) == 6" "~{var x := '123'; x[]} + ~{~{var x := '1234'; x[]}} == 7" "~{var x := '123'; x[]} + ~{var x := '1234'; x[]} == 7" "~{var x := '123'; x[]} + ~{~{var x := 4}} == 7" "~{var x := '123'; x[]} + ~{var x := 4} == 7" "var x:=1; 2+(abs(x)-3) == 0" "var x:=1; 2-(abs(x)+3) == -2" "var x:=1; 2*(abs(x)/3) == (2/3)" "var x:=1; 2+(abs(x)+3) == 6" "var x:=1; (3+abs(x))-2 == 2" "var x:=1; (3*abs(x))/2 == (3/2)" "var x:=1; (3-abs(x))+2 == 4" "var x:=1; (3+abs(x))+2 == 6" "var x:=1; (abs(x)-3)+2 == 0" "var x:=1; (abs(x)/3)/2 == (1/6)" "var x:=1; (abs(x)+3)-2 == 2" "var x:=1; (abs(x)/3)*2 == (2/3)" "var x:=1; (abs(x)*3)/2 == (3/2)" "var x:=1; (abs(x)+3)+2 == 6" "(~{~{ var x := [1] }} + ~{ var x[1] := [1] } + ~{ var x[1] := [2] } + ~{{ var x[1] := [2] }}) == 6" "(~{ var x := [1] } + ~{ var x[1] := [2] } + ~{~{ var x[1] := [1] } + ~{ var x[1] := [2] }}) == 6" "~{ var x := 1 } + ~{ var x := 2 } == 3" "(~{ var x := 1 } + ~{ var x := 2 } + ~{~{ var x := 1 } + ~{ var x := 2 }}) == 6" "(~{ var x := 1 } + ~{ var x := 2 }) == (~{ var x := 2 } + ~{ var x := 1 })" "(~{ var x := 1 } + ~{ var x[6] := {6,5,4,3,2,1} }) == 7" "var x := 1; var y := 2; 1" "var x := 1; var y := 2; swap(x,y); (x == 2) and (y == 1)" "var x := 1; var y := 2; ~(swap(x,y),(x == 2) and (y == 1))" "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[0]); swap(v[1],y); (x == 3) and (y == 4)" "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[2 * zero]); swap(v[(2 * one) / (1 + 1)],y); (x == 3) and (y == 4)" "var x := 1; var y := 2; var v[2] := {3,4}; swap(x,v[zero]); swap(v[one],y); (x == 3) and (y == 4)" "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[0]; v[1] <=> y; (x == 3) and (y == 4)" "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero / 3]; v[(2 * one)/(1 + 1)] <=> y; (x == 3) and (y == 4)" "var x := 1; var y := 2; var v[2] := {3,4}; x <=> v[zero]; v[one] <=> y; (x == 3) and (y == 4)" "var x := 1; var y := 2; x" "var x := 1; var y := 2; x <=> y ; (x == 2) and (y == 1)" "var x := 1; x" "var x := 2; (~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } else break[i + j]; } } } + ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) { var y := 3; if ((i + j + y + x) < 6) { y += x; continue; } else break[i + j]; } } }) == 18" "var x := 2; var v0[3] := {1,2,3}; ( ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) { var y := 3; var v2[3] := {1,2,3}; if ( (i + j + y + x + abs(v0[i % v0[]] - v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; continue; } else break[i + j]; } } } + ~{ for (var i := 0; i < 10; i += 1) { for (var j := 0; j <= i; j += 1) { var y := 3; var v2[3] := {1,2,3}; if ((i + j + y + x + abs(v0[i % v0[]] - v2[j % v2[]])) < 6) { var v3[3] := {1,2,3}; y += x / v3[j % v3[]]; continue; } else break[i + j]; } } } ) == 18" "var x:= 2; var y := 3; (-abs(x + 0)+abs(y - 0)) == 1" "var x:= 2; var y := 3; (-abs(x + 0)--abs(y - 0)) == 1" "var x:= 2; var y := 3; (-abs(x + 0)/-abs(y - 0)) == (2/3)" "var x:= 2; var y := 3; (abs(x + 0)--abs(y - 0)) == 5" "var x:= 2; var y := 3; (-abs(x + 0)-abs(y - 0)) == -5" "var x:= 2; var y := 3; (-abs(x + 0)+-abs(y - 0)) == -5" "var x:= 2; var y := 3; (-abs(x + 0)*-abs(y - 0)) == 6" "var x:= 2; var y := 3; (-abs(x)+abs(y)) == 1" "var x:= 2; var y := 3; (-abs(x)--abs(y)) == 1" "var x:= 2; var y := 3; (-abs(x)/-abs(y)) == (2/3)" "var x:= 2; var y := 3; (abs(x)--abs(y)) == 5" "var x:= 2; var y := 3; (-abs(x)-abs(y)) == -5" "var x:= 2; var y := 3; (-abs(x)+-abs(y)) == -5" "var x:= 2; var y := 3; (-abs(x)*-abs(y)) == 6" "var x[3] := {0.1,0.2,0.3}; sum(trunc(x)) == 0" "var x[3] := [0]; var y[1] := {1}; x <= y" "var x[3] := [0]; var y[1] := {1}; x < Y" "var x[3] := [0]; var y[1] := {1}; x < (y += 1)" "var x[3] := [0]; var y[1] := {5}; (x += 1) < y" "var x[3] := [0]; var y[1] := {5}; (x += 1) < (y += 1)" "var x[3] := [0]; var y[2] := {1,2}; x <= y" "var x[3] := [0]; var y[2] := {1,2}; X < y" "var x[3] := [0]; var y[2] := {1,2}; x < (y += 1)" "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < y" "var x[3] := [0]; var y[2] := {5,6}; (x += 1) < (y += 1)" "var x[3] := [0]; var y[3] := {1,2,3}; x <= y" "var x[3] := [0]; var y[3] := {1,2,3}; x < Y" "var x[3] := [0]; var y[3] := {1,2,3}; x < (y += 1)" "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < y" "var x[3] := [0]; var y[3] := {5,6,7}; (x += 1) < (y += 1)" "var x[3] := [0]; var y[4] := {1,2,3,4}; x <= y" "var x[3] := [0]; var y[4] := {1,2,3,4}; X < y" "var x[3] := [0]; var y[4] := {1,2,3,4}; x < (y += 1)" "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < y" "var x[3] := [0]; var y[4] := {5,6,7,8}; (x += 1) < (y += 1)" "var x[3] := {1,1,1}; var y := 1; x == y" "var x[3] := {1,1,1}; var y := 1; y == x" "var x[3] := {1,1,1}; var y := 2; x == y - 1" "var x[3] := {1,1,1}; var y := 2; y - 1 == x" "var x[3] := {-1,-2,-3}; sum(abs(x) ) == 6" "var x[3] := {1,2,3}; var y := 3; equal(true,(x -= 1) < y + 1)" "var x[3] := {1,2,3}; var y := 3; x <= y + 1" "var x[3] := {1,2,3}; var y := 3; x < y + 1" "var x[3] := {1,2,3}; var y := 3; y >= x" "var x[3] := {1,2,3}; var y := 5; equal(true,(x -= 1) <= y)" "var x[3] := {1,2,3}; var y := 5; equal(true,(x += 1) < y)" "var x[3] := {1,2,3}; var y := 5; x <= y" "var x[3] := {1,2,3}; var y := 5; x < y" "var x[3] := {1,2,3}; var y := 5; y + 1 > x" "var x[3] := {1,2,3}; var y := 5; y + 1 > (x += 1)" "var x[3] := {1,2,3}; var y := 5; y > x" "var x[3] := {1,2,3}; var y := 5; y > (x += 1)" "var x[3] := {1,2,3}; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)" "var x[3] := {1,2}; (x[0] == 1) and (x[1] == 2) and (x[2] == 0)" "(~{ var x[3] := [1] } + ~{ var x[6] := {6,5,4,3,2,1}}) == 7" "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y)/3; z == 2(x * y)/3" "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := 2(x * y); z == (x * y)2" "var x[3] := [1]; var y[1] := {1}; var z[3] := [1]; z := (x * y); z == (x * y)" "var x[3] := [1]; var y[1] := [1]; x == y" "var x[3] := [1]; var y[1] := [2]; x != y" "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y)/3; z == 2(x / y)/3" "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := 2(x / y); z == (x / y)2" "var x[3] := [1]; var y[2] := {1,2}; var z[3] := [1]; z := (x / y); z == (x / y)" "var x[3] := [1]; var y[2] := [1]; x == y" "var x[3] := [1]; var y[2] := [2]; x != y" "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y)/3; z == 2(x - y)/3" "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := 2(x - y); z == (x - y)2" "var x[3] := [1]; var y[3] := {1,2,3}; var z[3] := [1]; z := (x - y); z == (x - y)" "var x[3] := [1]; var y[3] := [1]; x == y" "var x[3] := [1]; var y[3] := [2]; x != y" "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y)/3; z == 2(x + y)/3" "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := 2(x + y); z == (x + y)2" "var x[3] := [1]; var y[4] := {1,2,3,4}; var z[3] := [1]; z := (x + y); z == (x + y)" "var x[3] := [1]; var y[4] := [1]; x == y" "var x[3] := [1]; var y[4] := [2]; x != y" "var x[3] := [1]; (x[0] == 1) and (x[1] == 1) and (x[2] == 1)" "var x[3] := {2,2,2}; var y := 0; y + 1 == (x -= 1)" "var x[3] := {2,2,2}; var y := 1; (x -= 1) == y" "var x[3] := {2,2,2}; var y := 1; y == (x -= 1)" "var x[3] := [5]; var y[1] := {1}; x >= y" "var x[3] := [5]; var y[1] := {1}; x > y" "var x[3] := [5]; var y[2] := {1,2}; x >= y" "var x[3] := [5]; var y[2] := {1,2}; x > y" "var x[3] := [5]; var y[3] := {1,2,3}; x >= y" "var x[3] := [5]; var y[3] := {1,2,3}; x > y" "var x[3] := [5]; var y[4] := {1,2,3,4}; x >= y" "var x[3] := [5]; var y[4] := {1,2,3,4}; x > y" "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)" "var x[3] := [8]; var y[1] := {1}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)" "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)" "var x[3] := [8]; var y[2] := {1,2}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)" "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)" "var x[3] := [8]; var y[3] := {1,2,3}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)" "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)" "var x[3] := [8]; var y[4] := {1,2,3,4}; (x += 1) <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)" "var x[3] := [9]; var y[1] := {1}; x <=> (y += 1); (x[0] == 2) and (x[1] == 9) and (x[2] == 9)" "var x[3] := [9]; var y[1] := {1}; x <=> y; (x[0] == 1) and (x[1] == 9) and (x[2] == 9)" "var x[3] := [9]; var y[2] := {1,2}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 9)" "var x[3] := [9]; var y[2] := {1,2}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 9)" "var x[3] := [9]; var y[3] := {1,2,3}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)" "var x[3] := [9]; var y[3] := {1,2,3}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)" "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> (y += 1); (x[0] == 2) and (x[1] == 3) and (x[2] == 4)" "var x[3] := [9]; var y[4] := {1,2,3,4}; x <=> y; (x[0] == 1) and (x[1] == 2) and (x[2] == 3)" "~{~{var x := 3}} + ~{var x := '1234'; x[]} == 7" "~{var x := 3} + ~{var x := '1234'; x[]} == 7" "var x[3] := {}; var y[1] := {1}; x := (y+=1); (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)" "var x[3] := {}; var y[1] := {1}; x := y; (x[0] == y[0]) and (x[1] == 0) and (x[2] == 0)" "var x[3] := {}; var y[2] := {1,2}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)" "var x[3] := {}; var y[2] := {1,2}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == 0)" "var x[3] := {}; var y[3] := {1,2,3}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])" "var x[3] := {}; var y[3] := {1,2,3}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])" "var x[3] := {}; var y[4] := {1,2,3,4}; x := (y+=1); (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])" "var x[3] := {}; var y[4] := {1,2,3,4}; x := y; (x[0] == y[0]) and (x[1] == y[1]) and (x[2] == y[2])" "var x := 3; var y := 6; -x * -y == 18" "var x:=3; var y:=6; -(-(-x))*-(-(-y)) == 18" "var x:=3; var y:=6; -(-x)*-(-(-y)) == -18" "var x:=3; var y:=6; -(-x)*-(-y) == 18" "var x := 3; var y := 6; x + -y == -3" "var x := 3; var y := 6; -x - -y == 3" "var x := 3; var y := 6; x - -y == 9" "var x := 3; var y := 6; -x + -y == -9" "var x:=3; var y:=6; -(-(-(x+y)))*-(-(-(y+x))) == 81" "var x:=3; var y:=6; -(-(-(x+y)))*-(-(y+x)) == -81" "var x:=3; var y:=6; -(-(x+y))*-(-(y+x)) == 81" "var x[3] := {}; (x[0] == 0) and (x[1] == 0) and (x[2] == 0)" "var x[6] := {1,2,3,4,5,6}; equal(sqrt(sum([x - avg(x)]^2) / x[]),1.7078251277)" "(~{ var x[6] := {6,5,4,3,2,1} } + ~{ var x := 1 }) == 7" "var x := 6; var y := 3; -x / -y == 2" "var x:=6; var y:=4; 3 / -x == -0.5" "var x:=6; var y:=4; -3 / -x == 0.5" "var x:=6; var y:=4; 3 * -x == -18" "var x:=6; var y:=4; -3 * -x == 18" "var x:=6; var y:=4; 3 + -x == -3" "var x:=6; var y:=4; -3 - -x == 3" "var x:=6; var y:=4; 3 - -x == 9" "var x:=6; var y:=4; -3 + -x == -9" "var x:=6; var y:=4; x * -3 == -18" "var x:=6; var y:=4; x / -3 == -2" "var x:=6; var y:=4; -x - -3 == -3" "var x:=6; var y:=4; x + -3 == 3" "var x:=6; var y:=4; -x + -3 == -9" "var x:=6; var y:=4; x - -3 == 9" "var x := 'abc'; var y := '123'; x != y" "var x := 'abc'; var y := '123' + x; y == '123abc'" "var x := 'abc'; var y := x + '123'; y == 'abc123'" "var x := 'abc'; x == 'abc'" "~{var x := 'xxx'; var y := 'yyy';~{((x + '2') != x ? x : y) == x }}" "~{var x := 'xxx'; var y := 'yyy';~{(x == (x + '1') ? x : y) == y }}" "~{var x := 'xxx'; var y := 'yyy';~{'xxx1' == (x < y ? x + '1' : y)}}" "~{var x := 'xxx'; var y := 'yyy';~{x == (x != (x + '2') ? x : y) }}" "~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x + '1' : y) == 'xxx1'}}" "~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y + '2') == 'yyy2'}}" "~{var x := 'xxx'; var y := 'yyy';~{(x < y ? x : y) == x }}" "~{var x := 'xxx'; var y := 'yyy';~{(x > y ? x : y) == y }}" "~{var x := 'xxx'; var y := 'yyy';~{y == (x == (x + '1') ? x : y) }}" "~{var x := 'xxx'; var y := 'yyy';~{'yyy2' == (x > y ? x : y + '2')}}" "'abcd' like 'abcd*'" "'abcd' like 'abc*'" "'abcd' like 'ab*'" "'abcd' like 'a*'" "'abcd' like 'abcd?'" "'abcd' like 'abc?'" "'abcd' like 'abc??'" "'abcd' like 'ab???'" "'abcd' like 'a????'" "'abcd' like '?????'" "'a' like 'a*'" "'ab' like 'a*'" "'abcd' like 'abcd*'" "'' like ''" "'abcd' like 'abcd'" "'abcd' like 'abc*'" "'abcd' like '*bcd'" "'abcd' like 'abc?'" "'abcd' like '?bcd'" "'abcd' like 'ab?d'" "'abcd' like 'ab*d'" "'abcd' like 'a?cd'" "'abcd' like 'a*cd'" "'abcd' like 'a??d'" "'abcd' like 'a*?d'" "'abcd' like '*bc*'" "'abcd' like '?bc?'" "'abcd' like '????'" "'abcd' like 'a???'" "'abcd' like 'ab??'" "'abcd' like 'abc?'" "'abcd' like '???d'" "'abcd' like '??cd'" "'abcd' like '?bcd'" "'abcd' like '?b?d'" "'abcd' like 'a?c?'" "'abcd' like 'a??d'" "'abcd' like '?bc?'" "'abcd' like 'ab**'" "'abcd' like 'ab*?'" "'abcd' like 'a***'" "'abcd' like '**cd'" "'abcd' like '*?cd'" "'abcd' like '***d'" "'abcd' like '?*?d'" "'abcd' like '?*?d'" "'abcd' like '*bc*'" "'abcd' like '*bc?'" "'abcd' like '*b??'" "'abcd' like '?bc*'" "'abcd' like '??c*'" "'abcd' like '*b?*'" "'abcd' like '*b*d'" "'abcd' like 'a*c*'" "'abcd' like '?*cd'" "'abcd' like 'ab?*'" "'abcd' like 'ab*?'" "'abcd' like 'a?*d'" "'ab' like 'a*'" "'ab' like 'a?'" "'a' like 'a*'" "'a' like 'a?'" "'xalabcd' like '*abcd*'" "'xablabcd' like '*abcd*'" "'xabclabcd' like '*abcd*'" "'aaaaa' like '*aa?'" "'abcd' like 'xyzw'" "'abcd' like 'xyz'" "'abc' like 'xyzw'" "'abcd' like 'ab?'" "'abcd' like 'a?'" "'abcd' ilike 'abcd*'" "'abcd' ilike 'abc*'" "'abcd' ilike 'ab*'" "'abcd' ilike 'a*'" "'abcd' ilike 'abcd?'" "'abcd' ilike 'abc?'" "'abcd' ilike 'abc??'" "'abcd' ilike 'ab???'" "'abcd' ilike 'a????'" "'abcd' ilike '?????'" "'a' ilike 'a*'" "'ab' ilike 'a*'" "'abcd' ilike 'abcd*'" "'' ilike ''" "'abcd' ilike 'abcd'" "'abcd' ilike 'abc*'" "'abcd' ilike '*bcd'" "'abcd' ilike 'abc?'" "'abcd' ilike '?bcd'" "'abcd' ilike 'ab?d'" "'abcd' ilike 'ab*d'" "'abcd' ilike 'a?cd'" "'abcd' ilike 'a*cd'" "'abcd' ilike 'a??d'" "'abcd' ilike 'a*?d'" "'abcd' ilike '*bc*'" "'abcd' ilike '?bc?'" "'abcd' ilike '????'" "'abcd' ilike 'a???'" "'abcd' ilike 'ab??'" "'abcd' ilike 'abc?'" "'abcd' ilike '???d'" "'abcd' ilike '??cd'" "'abcd' ilike '?bcd'" "'abcd' ilike '?b?d'" "'abcd' ilike 'a?c?'" "'abcd' ilike 'a??d'" "'abcd' ilike '?bc?'" "'abcd' ilike 'ab**'" "'abcd' ilike 'ab*?'" "'abcd' ilike 'a***'" "'abcd' ilike '**cd'" "'abcd' ilike '*?cd'" "'abcd' ilike '***d'" "'abcd' ilike '?*?d'" "'abcd' ilike '?*?d'" "'abcd' ilike '*bc*'" "'abcd' ilike '*bc?'" "'abcd' ilike '*b??'" "'abcd' ilike '?bc*'" "'abcd' ilike '??c*'" "'abcd' ilike '*b?*'" "'abcd' ilike '*b*d'" "'abcd' ilike 'a*c*'" "'abcd' ilike '?*cd'" "'abcd' ilike 'ab?*'" "'abcd' ilike 'ab*?'" "'abcd' ilike 'a?*d'" "'ab' ilike 'a*'" "'ab' ilike 'a?'" "'a' ilike 'a*'" "'a' ilike 'a?'" "'xalabcd' ilike '*abcd*'" "'xablabcd' ilike '*abcd*'" "'xabclabcd' ilike '*abcd*'" "'aaaaa' ilike '*aa?'" "'abcd' ilike 'xyzw'" "'abcd' ilike 'xyz'" "'abc' ilike 'xyzw'" "'abcd' ilike 'ab?'" "'abcd' ilike 'a?'" "~{var s := ~{var n := 1; var m := 2; if (n < m) 'n < m'; else 'n >= m'; }; (s == 'n < m')}" "~{var s := ~{var n := 1; var m := 2; if (n > m) 'n <= m'; else 'n > m'; }; (s == 'n > m')}" "~{var s := ~{var n := 1; var m := 2; if (n < m) 'n < m'; else 'n >' + '= m'; }; (s == 'n < m')}" "~{var s := ~{var n := 1; var m := 2; if (n < m) 'n ' + '< m'; else 'n >= m'; }; (s == 'n < m')}" "~{var s := ~{var n := 1; var m := 2; if (n > m) 'n <= m'; else 'n ' + '> m'; }; (s == 'n > m')}" "~{var s := ~{var n := 1; var m := 2; if (n > m) 'n <' + '= m'; else 'n > m'; }; (s == 'n > m')}" "~{var s := ~{var n := 1; var m := 2; var r0 := 'n < m'; var r1 := 'n >= m'; if (n < m) r0; else r1; }; (s == 'n < m')}" "~{var s := ~{var n := 1; var m := 2; var r0 := 'n < m'; var r1 := 'n >= m'; if (n < m) r0 + ''; else r1 + ''; }; (s == 'n < m')}" "~{var s := ~{var n := 1; var m := 2; var r0 := 'n < m'; var r1 := 'n >= m'; if (n < m) '' + r0; else '' + r1; }; (s == 'n < m')}" ================================================ FILE: projects/exprtk/project.yaml ================================================ homepage: "https://www.partow.net/programming/exprtk/index.html" language: c++ primary_contact: "exprtk.dev@gmail.com" auto_ccs: - "exprtk.dev@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory main_repo: 'https://github.com/ArashPartow/exprtk.git' ================================================ FILE: projects/faad2/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y python3 RUN git clone https://github.com/knik0/faad2 faad2 WORKDIR faad2 COPY build.sh $SRC/ ================================================ FILE: projects/faad2/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export USE_BAZEL_VERSION=7.4.0 bazel_build_fuzz_tests ================================================ FILE: projects/faad2/project.yaml ================================================ homepage: "https://sourceforge.net/projects/faac" main_repo: "https://github.com/knik0/faad2" language: c primary_contact: "eustas@chromium.org" auto_ccs: - "david@adalogics.com" sanitizers: - address - memory - undefined ================================================ FILE: projects/fabric/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/hyperledger/fabric RUN git clone --depth 1 https://github.com/hyperledger/fabric-lib-go COPY build.sh ccprovider_fuzzer.go \ persistence_fuzzer.go \ policydsl_fuzzer.go \ fabenc_fuzzer.go \ msp_fuzzer.go $SRC/ WORKDIR $SRC/fabric COPY *.options $SRC/ ================================================ FILE: projects/fabric/FuzzExtractFileEntries.options ================================================ [libfuzzer] max_len = 1800000 len_control = 0 ================================================ FILE: projects/fabric/FuzzParseChaincodePackage.options ================================================ [libfuzzer] max_len = 1800000 len_control = 0 ================================================ FILE: projects/fabric/FuzzPersistence.options ================================================ [libfuzzer] max_len = 1800000 len_control = 0 ================================================ FILE: projects/fabric/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Temporarily disable coverage build in OSS-Fuzz's CI if [ -n "${OSS_FUZZ_CI-}" ] then if [ "${SANITIZER}" = 'coverage' ] then exit 0 fi fi rm -r $SRC/fabric/cmd/cryptogen cp $SRC/ccprovider_fuzzer.go ./core/common/ccprovider/ cp $SRC/persistence_fuzzer.go ./core/chaincode/persistence/mock/ cp $SRC/policydsl_fuzzer.go $SRC/fabric/common/policydsl/ cp $SRC/msp_fuzzer.go $SRC/fabric/msp/ cp $SRC/fabenc_fuzzer.go $SRC/fabric-lib-go/common/flogging/fabenc/ cd $SRC/fabric go mod tidy && go mod vendor go get github.com/AdaLogics/go-fuzz-headers go mod tidy go mod vendor compile_go_fuzzer github.com/hyperledger/fabric/core/chaincode/persistence/mock FuzzPersistence fuzz_persistence compile_go_fuzzer github.com/hyperledger/fabric/core/chaincode/persistence/mock FuzzChaincodePackageStreamerMetadatabytes FuzzChaincodePackageStreamerMetadatabytes compile_go_fuzzer github.com/hyperledger/fabric/core/chaincode/persistence/mock FuzzParseChaincodePackage FuzzParseChaincodePackage compile_go_fuzzer github.com/hyperledger/fabric/core/common/ccprovider FuzzExtractFileEntries FuzzExtractFileEntries compile_go_fuzzer github.com/hyperledger/fabric/common/policydsl FuzzFromString fuzz_from_string compile_go_fuzzer github.com/hyperledger/fabric/msp FuzzDeserializeIdentity fuzz_deserialize_identity cd $SRC/fabric-lib-go compile_go_fuzzer github.com/hyperledger/fabric-lib-go/common/flogging/fabenc FuzzParseFormat fuzz_parse_format cp $SRC/*.options $OUT/ ================================================ FILE: projects/fabric/ccprovider_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ccprovider import ( fuzz "github.com/AdaLogics/go-fuzz-headers" ) func FuzzExtractFileEntries(data []byte) int { f := fuzz.NewConsumer(data) tarBytes, err := f.TarBytes() if err != nil { return 0 } databaseType, err := f.GetString() if err != nil { return 0 } _, _ = ExtractFileEntries(tarBytes, databaseType) return 1 } ================================================ FILE: projects/fabric/fabenc_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fabenc func FuzzParseFormat(data []byte) int { _, _ = ParseFormat(string(data)) return 1 } ================================================ FILE: projects/fabric/msp_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package msp func FuzzDeserializeIdentity(data []byte) int { m := &mspManagerImpl{} m.up = true _, _ = m.DeserializeIdentity(data) return 1 } ================================================ FILE: projects/fabric/persistence_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package mock import ( "bytes" "compress/gzip" fuzz "github.com/AdaLogics/go-fuzz-headers" "github.com/hyperledger/fabric/core/chaincode/persistence" tm "github.com/stretchr/testify/mock" "os" ) func FuzzPersistence(data []byte) int { var ccpp persistence.ChaincodePackageParser mockMetaProvider := &MetadataProvider{} mockMetaProvider.On("GetDBArtifacts", tm.Anything).Return([]byte("DB artefacts"), nil) ccpp.MetadataProvider = mockMetaProvider _, _ = ccpp.Parse(data) return 1 } func FuzzChaincodePackageStreamerMetadatabytes(data []byte) int { err := os.WriteFile("demoTar.tar", data, 0666) if err != nil { return 0 } defer os.Remove("demoTar.tar") cps := &persistence.ChaincodePackageStreamer{PackagePath: "demoTar.tar"} _, _ = cps.MetadataBytes() return 1 } func FuzzParseChaincodePackage(data []byte) int { f := fuzz.NewConsumer(data) source, err := f.TarBytes() if err != nil { return 0 } var b bytes.Buffer w := gzip.NewWriter(&b) w.Write(source) w.Close() _, _, _ = persistence.ParseChaincodePackage(b.Bytes()) return 1 } ================================================ FILE: projects/fabric/policydsl_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package policydsl func FuzzFromString(data []byte) int { _, _ = FromString(string(data)) return 1 } ================================================ FILE: projects/fabric/project.yaml ================================================ homepage: "https://www.hyperledger.org" main_repo: "https://github.com/hyperledger/fabric" primary_contact: "ale.linux@sopit.net" auto_ccs: - "gari.r.singh@gmail.com" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/face/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/mahmoud/face face COPY *.sh *py $SRC/ WORKDIR $SRC/face ================================================ FILE: projects/face/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/face/fuzz_command.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import face def empty(): return def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) args = [] for idx in range(fdp.ConsumeIntInRange(1, 100)): args.append(fdp.ConsumeUnicodeNoSurrogates(124)) cmd = face.Command(empty, name='fuzz') for idx in range(fdp.ConsumeIntInRange(1, 15)): try: cmd.add(fdp.ConsumeUnicodeNoSurrogates(64), char=fdp.ConsumeUnicodeNoSurrogates(5), parse_as=fdp.ConsumeBool(), doc=fdp.ConsumeUnicodeNoSurrogates(64)) except face.errors.FaceException: pass except ValueError: # Raised by face: https://github.com/mahmoud/face/blob/eb56873b9081852f4500b1a61f178ca0cc8666bc/face/utils.py#L80 pass # Create a command and parse the args try: cmd.parse(args) except face.errors.FaceException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/face/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import face def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) args = [] for idx in range(fdp.ConsumeIntInRange(1, 100)): args.append(fdp.ConsumeUnicodeNoSurrogates(124)) # Create a command and parse the args cmd = face.Command(lambda flag, part: None, name='cmd') try: cmd.parse(args) except face.errors.FaceException: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/face/project.yaml ================================================ homepage: https://github.com/mahmoud/face main_repo: https://github.com/mahmoud/face language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/fast-dds/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt install -y autoconf automake pkg-config RUN git clone --depth 1 https://github.com/leethomason/tinyxml2 RUN git clone --depth 1 --branch asio-1-18-1 https://github.com/chriskohlhoff/asio/ RUN git clone --depth 1 https://github.com/eProsima/Fast-CDR.git RUN git clone --depth 1 https://github.com/eProsima/foonathan_memory_vendor.git RUN git clone --depth 1 https://github.com/eProsima/Fast-DDS.git COPY build.sh $SRC WORKDIR $SRC/Fast-DDS ================================================ FILE: projects/fast-dds/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ( cd ../tinyxml2 make clean make -j$(nproc) all cp libtinyxml2.a /usr/local/lib/ cp *.h /usr/local/include/ ) ( cd ../asio/asio sh autogen.sh ./configure make -j$(nproc) install ) ( cd .. mkdir Fast-CDR/build && cd Fast-CDR/build cmake .. -DBUILD_SHARED_LIBS=OFF cmake --build . --target install ) ( cd .. cd foonathan_memory_vendor mkdir build && cd build cmake .. -DBUILD_SHARED_LIBS=OFF cmake --build . --target install ) # build project export CFLAGS="${CFLAGS} -Wno-error=nonnull" export CXXFLAGS="${CXXFLAGS} -Wno-error=nonnull" mkdir build && cd build cmake .. -DBUILD_SHARED_LIBS=OFF make -j $(nproc) cd .. find build/fuzz -maxdepth 3 -type f -name 'fuzz_*' | while read fuzzer; do cp "$fuzzer" $OUT/ done find fuzz/ -type d -name 'fuzz_*_seed_corpus' | while read corpus_dir; do zip -j $OUT/$(basename "$corpus_dir").zip $corpus_dir/* done ================================================ FILE: projects/fast-dds/project.yaml ================================================ homepage: "https://www.eprosima.com/" language: c++ primary_contact: "miguelcompany@eprosima.com" auto_ccs: - "p.antoine@catenacyber.fr" - "federico.maggi@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/eProsima/Fast-DDS.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/fast-xml-parser/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/NaturalIntelligence/fast-xml-parser COPY fuzz.js $SRC/fast-xml-parser WORKDIR $SRC/fast-xml-parser ================================================ FILE: projects/fast-xml-parser/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies. npm install npm install --save-dev @jazzer.js/core # Build Fuzzers. compile_javascript_fuzzer fast-xml-parser fuzz.js -i fast-xml-parser --sync ================================================ FILE: projects/fast-xml-parser/fuzz.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const XMLParser = require('./src/xmlparser/XMLParser'); const XMLBuilder = require('./src/xmlbuilder/json2xml'); const XMLValidator = require('./src/fxp').XMLValidator; module.exports.fuzz = function(data) { try { const provider = new FuzzedDataProvider(data); const xmlString = provider.consumeString(1024); const parser = new XMLParser(); let jObj = parser.parse(xmlString); let builder = new XMLBuilder(); const xmlContent = builder.build(jObj); XMLValidator.validate(xmlContent, { allowBooleanAttributes: true, }); } catch (error) { if (!ignoredError(error)) throw error; } }; function ignoredError(error) { return !!ignored.find((message) => error.message.indexOf(message) !== -1); } const ignored = ['Cannot read properties', 'is not closed', 'Invalid Tag']; ================================================ FILE: projects/fast-xml-parser/project.yaml ================================================ homepage: https://naturalintelligence.github.io/fast-xml-parser/ language: javascript main_repo: https://github.com/NaturalIntelligence/fast-xml-parser fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/fast_float/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/fastfloat/fast_float.git fast_float WORKDIR fast_float COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/fast_float/build.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzzers sh ./fuzz/build.sh ================================================ FILE: projects/fast_float/project.yaml ================================================ homepage: "https://github.com/fastfloat/fast_float" language: c++ primary_contact: "lemire@gmail.com" auto_ccs: - "nathaniel.brough@gmail.com" main_repo: "https://github.com/fastfloat/fast_float.git" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/fast_float/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make test -j$(nproc) ================================================ FILE: projects/fastcsv/CsvReaderFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import de.siegmar.fastcsv.reader.CsvReader; import de.siegmar.fastcsv.reader.CsvParseException; public class CsvReaderFuzzer { public static void fuzzerTestOneInput(byte[] input) { try { CsvReader.builder() .ofCsvRecord(new InputStreamReader(new ByteArrayInputStream(input), StandardCharsets.UTF_8)) .stream() .toList(); } catch (CsvParseException e) { } } } ================================================ FILE: projects/fastcsv/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt update && apt install -y openjdk-17-jdk RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/csv.dict $SRC/csv.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/CSVParserFuzzer_seed_corpus.zip go-fuzz-corpus/csv/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/osiegmar/FastCSV.git fastcsv WORKDIR fastcsv COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ ================================================ FILE: projects/fastcsv/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" ./gradlew --console=plain lib:jar cp lib/build/libs/fastcsv-*.jar $OUT/fastcsv.jar ALL_JARS="fastcsv.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer --release 17 cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-17/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-17/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/fastcsv/project.yaml ================================================ homepage: "https://github.com/osiegmar/FastCSV" language: jvm primary_contact: "oliver@siegmar.de" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/osiegmar/FastCSV.git" ================================================ FILE: projects/fasthttp/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/valyala/fasthttp COPY build.sh $SRC/ WORKDIR $SRC/fasthttp ================================================ FILE: projects/fasthttp/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ rm lbclient_example_test.go rm client_example_test.go rm requestctx_setbodystreamwriter_example_test.go rm fs_handler_example_test.go rm server_example_test.go rm fs_example_test.go compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzCookieParse fuzzCookieParse compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzVisitHeaderParams fuzzVisitHeaderParams compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzResponseReadLimitBody fuzzResponseReadLimitBody compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzRequestReadLimitBody fuzzRequestReadLimitBody compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzURIUpdateBytes fuzzURIUpdateBytes compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzURIParse fuzzURIParse compile_native_go_fuzzer_v2 github.com/valyala/fasthttp FuzzTestHeaderScanner fuzzTestHeaderScanner ================================================ FILE: projects/fasthttp/project.yaml ================================================ homepage: "https://github.com/valyala/fasthttp" primary_contact: "erik@dubbelboer.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/valyala/fasthttp' ================================================ FILE: projects/fastify/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN npm install -g n && n 19.2 RUN git clone --depth 1 https://github.com/fastify/fastify fastify RUN git clone --depth 1 https://github.com/fastify/fast-json-stringify fast-json-stringify RUN git clone --depth 1 https://github.com/fastify/secure-json-parse secure-json-parse RUN git clone --depth 1 https://github.com/fastify/fastify-jwt fastify-jwt RUN git clone --depth 1 https://github.com/fastify/fastify-response-validation fastify-response-validation RUN git clone --depth 1 https://github.com/fastify/fastify-auth fastify-auth RUN git clone --depth 1 https://github.com/fastify/fast-content-type-parse fast-content-type-parse RUN git clone --depth 1 https://github.com/fastify/fastify-basic-auth fastify-basic-auth RUN git clone --depth 1 https://github.com/fastify/fastify-bearer-auth fastify-bearer-auth RUN git clone --depth 1 http://github.com/fastify/fastify-plugin fastify-plugin RUN git clone --depth 1 http://github.com/fastify/fastify-cookie fastify-cookie RUN git clone --depth 1 http://github.com/fastify/fastify-cors fastify-cors RUN git clone --depth 1 http://github.com/fastify/fastify-secure-session fastify-secure-session RUN git clone --depth 1 https://github.com/AdaLogics/ada-fuzzers fuzzers WORKDIR $SRC/fastify ================================================ FILE: projects/fastify/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzzers/projects/fastify/*.js $SRC/fastify $SRC/fuzzers/projects/fastify/build.sh ================================================ FILE: projects/fastify/project.yaml ================================================ homepage: https://www.fastify.dev language: javascript main_repo: https://github.com/fastify/fastify fuzzing_engines: - libfuzzer sanitizers: - none primary_contact: "matteo.collina@gmail.com" auto_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/fastjson/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/valyala/fastjson COPY build.sh $SRC/ WORKDIR $SRC/fastjson ================================================ FILE: projects/fastjson/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/valyala/fastjson Fuzz fuzz ================================================ FILE: projects/fastjson/project.yaml ================================================ homepage: "https://github.com/valyala/fastjson" primary_contact: "valyala@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/valyala/fastjson' ================================================ FILE: projects/fastjson2/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN apt-get update && apt-get install -y maven RUN git clone --depth 1 https://github.com/google/fuzzing && \ cat fuzzing/dictionaries/json.dict > $SRC/JsonFuzzer.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/JsonFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* RUN git clone --depth 1 https://github.com/alibaba/fastjson2 COPY build.sh $SRC/ COPY JsonFuzzer.java $SRC/ WORKDIR $SRC/fastjson2 ================================================ FILE: projects/fastjson2/JsonFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONException; import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class JsonFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JSON.parse(data.consumeRemainingAsString()); } catch (JSONException ignored) { } } } ================================================ FILE: projects/fastjson2/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Copy seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT mvn package -Dmaven.test.skip=true -Djdk.version=15 CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "core/target/fastjson2-$CURRENT_VERSION.jar" $OUT/fastjson2.jar PROJECT_JARS="fastjson2.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/fastjson2/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/alibaba/fastjson2" language: jvm primary_contact: "shaojin.wensj@alibaba-inc.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/alibaba/fastjson2" sanitizers: - address vendor_ccs: - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/feign/BodyTemplateFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import feign.template.BodyTemplate; import java.util.regex.Pattern; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [feign.template.BodyTemplate] public static feign.template.BodyTemplate create(java.lang.String) public class BodyTemplateFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { BodyTemplate.create(Pattern.quote(data.consumeRemainingAsString())); } catch (IllegalArgumentException e1) {} } } ================================================ FILE: projects/feign/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN curl -L https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz -o jdk.tar.gz && \ tar zxf jdk.tar.gz && \ rm -rf jdk.tar.gz ENV MVN="$SRC/maven/apache-maven-3.9.2/bin/mvn" ENV JAVA_HOME="$SRC/jdk-21.0.2" RUN git clone --depth 1 https://github.com/openfeign/feign feign COPY *.sh *.java *.xml $SRC/ WORKDIR $SRC/feign # Ensure the ~/.m2 directory exists and copy toolchains.xml there RUN mkdir -p ~/.m2 && cp $SRC/toolchains.xml ~/.m2/toolchains.xml # Use the Maven settings file to resolve dependencies RUN $MVN --settings $SRC/settings.xml clean package -Dmaven.javadoc.skip=true \ -DskipTests=true -Dpmd.skip=true -Dencoding=UTF-8 \ -Dmaven.antrun.skip=true -Dcheckstyle.skip=true -Denforcer.fail=false \ dependency:copy-dependencies ================================================ FILE: projects/feign/UriUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import feign.template.UriUtils; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [feign.template.UriUtils] public static java.lang.String // encode(java.lang.String,boolean) public class UriUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Boolean value = data.consumeBoolean(); UriUtils.encode(data.consumeRemainingAsString(), value); } } ================================================ FILE: projects/feign/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## # Ensure directories exist if [[ ! -d ~/.m2 ]]; then mkdir ~/.m2 fi cp $SRC/toolchains.xml ~/.m2/toolchains.xml $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false dependency:copy-dependencies JARFILE_LIST= for JARFILE in $(find ./ -name *.jar) do if [[ "$JARFILE" == *"target/"* ]] || [[ "$JARFILE" == *"build/"* ]] then if [[ "$JARFILE" != *sources.jar ]] && [[ "$JARFILE" != *javadoc.jar ]] && [[ "$JARFILE" != *tests.jar ]] then cp $JARFILE $OUT/ JARFILE_LIST="$JARFILE_LIST$(basename $JARFILE) " fi fi done curr_dir=$(pwd) rm -rf $OUT/jar_temp mkdir $OUT/jar_temp cd $OUT/jar_temp for JARFILE in $JARFILE_LIST do jar -xf $OUT/$JARFILE done cd $curr_dir BUILD_CLASSPATH=$JAZZER_API_PATH:$OUT/jar_temp RUNTIME_CLASSPATH=\$this_dir/jar_temp:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/feign/project.yaml ================================================ homepage: https://github.com/openfeign/feign main_repo: https://github.com/openfeign/feign language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/feign/settings.xml ================================================ snapshots ossrh https://oss.sonatype.org/content/repositories/snapshots true snapshots ================================================ FILE: projects/feign/toolchains.xml ================================================ jdk 1.8 ${env.JAVA_HOME} jdk11 ${env.JAVA_HOME} jdk14 ${env.JAVA_HOME} jdk15 ${env.JAVA_HOME} jdk17 ${env.JAVA_HOME} jdk21 ${env.JAVA_HOME} ================================================ FILE: projects/ffmpeg/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y nasm pkg-config rsync libtool gperf RUN curl -LO https://mirrors.kernel.org/ubuntu/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ apt install ./automake_1.16.5-1.3_all.deb RUN curl -LO https://mirrors.kernel.org/ubuntu/pool/main/a/autoconf/autoconf_2.72-3.1ubuntu1_all.deb && \ apt install ./autoconf_2.72-3.1ubuntu1_all.deb # Meson is pinned to get around https://github.com/mesonbuild/meson/issues/14533 RUN python3 -m pip install --upgrade pip && python3 -m pip install -U meson==1.7.2 ninja RUN git clone --depth 1 https://github.com/FFmpeg/FFmpeg ffmpeg RUN curl -O https://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.12.tar.bz2 RUN git clone --depth 1 https://github.com/mstorsjo/fdk-aac.git RUN git clone --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig.git RUN git clone --depth 1 https://gitlab.freedesktop.org/freetype/freetype.git RUN git clone --depth 1 https://github.com/fribidi/fribidi RUN git clone --depth 1 https://github.com/harfbuzz/harfbuzz RUN git clone --depth 1 https://github.com/libass/libass RUN git clone --depth 1 https://github.com/madler/zlib RUN git clone --depth 1 https://gitlab.com/federicomenaquintero/bzip2 RUN git clone --depth 1 https://chromium.googlesource.com/webm/libvpx RUN git clone --depth 1 https://gitlab.xiph.org/xiph/ogg.git RUN git clone --depth 1 https://gitlab.xiph.org/xiph/opus.git RUN git clone --depth 1 https://gitlab.xiph.org/xiph/theora.git RUN git clone --depth 1 https://gitlab.xiph.org/xiph/vorbis.git RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git COPY build.sh replay_build.sh run_tests.sh group_seed_corpus.py name_mappings.py $SRC/ ================================================ FILE: projects/ffmpeg/build.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable UBSan vptr since several targets built with -fno-rtti. export CFLAGS="$CFLAGS -fno-sanitize=vptr" export CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" if [[ "$CXXFLAGS" == *"-fsanitize=address"* ]]; then export CXXFLAGS="$CXXFLAGS -fno-sanitize-address-use-odr-indicator" fi if [[ "$CFLAGS" == *"-fsanitize=address"* ]]; then export CFLAGS="$CFLAGS -fno-sanitize-address-use-odr-indicator" fi if [[ "$ARCHITECTURE" == i386 ]]; then export CFLAGS="$CFLAGS -m32" export CXXFLAGS="$CXXFLAGS -m32" fi # Build dependencies. export FFMPEG_DEPS_PATH=$SRC/ffmpeg_deps mkdir -p $FFMPEG_DEPS_PATH if [[ "$ARCHITECTURE" == i386 ]]; then LIBDIR='lib/i386-linux-gnu' export PKG_CONFIG_PATH="$FFMPEG_DEPS_PATH/$LIBDIR/pkgconfig:$FFMPEG_DEPS_PATH/lib/pkgconfig" else LIBDIR='lib/x86_64-linux-gnu' export PKG_CONFIG_PATH="$FFMPEG_DEPS_PATH/$LIBDIR/pkgconfig:$FFMPEG_DEPS_PATH/lib/pkgconfig" fi # The option `-fuse-ld=gold` can't be passed via `CFLAGS` or `CXXFLAGS` because # Meson injects `-Werror=ignored-optimization-argument` during compile tests. # Remove the `-fuse-ld=` and let Meson handle it. # https://github.com/mesonbuild/meson/issues/6377#issuecomment-575977919 export MESON_CFLAGS="$CFLAGS" if [[ "$CFLAGS" == *"-fuse-ld=gold"* ]]; then export MESON_CFLAGS="${CFLAGS//-fuse-ld=gold/}" export CC_LD=gold fi export MESON_CXXFLAGS="$CXXFLAGS" if [[ "$CXXFLAGS" == *"-fuse-ld=gold"* ]]; then export MESON_CXXFLAGS="${CXXFLAGS//-fuse-ld=gold/}" export CXX_LD=gold fi meson_install() { cd $SRC/$1 CFLAGS="$MESON_CFLAGS" CXXFLAGS="$MESON_CXXFLAGS" \ meson setup build -Dprefix="$FFMPEG_DEPS_PATH" -Ddefault_library=static -Dprefer_static=true \ --wrap-mode=nofallback --libdir "$LIBDIR" ${2:-} meson install -C build } meson_install bzip2 cd $SRC/zlib ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared make -j$(nproc) install cd $SRC/libxml2 ./autogen.sh --prefix="$FFMPEG_DEPS_PATH" --enable-static \ --without-debug --without-ftp --without-http \ --without-legacy --without-python make -j$(nproc) install meson_install freetype "-Dharfbuzz=disabled" meson_install fribidi "-Ddocs=false -Dtests=false" meson_install harfbuzz "-Ddocs=disabled -Dtests=disabled" meson_install fontconfig "-Dtests=disabled -Dtools=disabled" cd $SRC/libass ./autogen.sh ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared --disable-asm make -j$(nproc) install cd $SRC bzip2 -f -d alsa-lib-* tar xf alsa-lib-* rm alsa-lib-*.tar cd alsa-lib-* ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared make -j$(nproc) install cd $SRC/fdk-aac autoreconf -fiv CXXFLAGS="$CXXFLAGS -fno-sanitize=shift-base,signed-integer-overflow" \ ./configure --prefix="$FFMPEG_DEPS_PATH" --disable-shared make -j$(nproc) install cd $SRC/libvpx if [[ "$SANITIZER" == "memory" ]] || [[ "$FUZZING_ENGINE" == "centipede" ]]; then LIBVPX_BUILD_ARGS="--disable-x86-asm" elif [[ "$ARCHITECTURE" == i386 ]]; then LIBVPX_BUILD_ARGS="--target=x86-linux-gcc" else LIBVPX_BUILD_ARGS="" fi LDFLAGS="$CXXFLAGS" ./configure --prefix="$FFMPEG_DEPS_PATH" \ --disable-docs --disable-examples --disable-tools --disable-unit-tests \ --enable-vp9-highbitdepth \ --size-limit=12288x12288 \ --extra-cflags="-DVPX_MAX_ALLOCABLE_MEMORY=1073741824" \ $LIBVPX_BUILD_ARGS make -j$(nproc) install cd $SRC/ogg ./autogen.sh ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-crc make -j$(nproc) install cd $SRC/opus ./autogen.sh ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static make -j$(nproc) install cd $SRC/theora if [[ "$ARCHITECTURE" == i386 ]]; then THEORA_BUILD_ARGS='--disable-asm' else THEORA_BUILD_ARGS='' fi # theora requires ogg, need to pass its location to the "configure" script. CFLAGS="$CFLAGS -fPIC" LDFLAGS="-L$FFMPEG_DEPS_PATH/lib/" \ CPPFLAGS="$CXXFLAGS -I$FFMPEG_DEPS_PATH/include/" \ LD_LIBRARY_PATH="$FFMPEG_DEPS_PATH/lib/" \ ./autogen.sh ./configure --with-ogg="$FFMPEG_DEPS_PATH" --prefix="$FFMPEG_DEPS_PATH" \ --enable-static --disable-examples $THEORA_BUILD_ARGS make -j$(nproc) install cd $SRC/vorbis ./autogen.sh ./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static make -j$(nproc) install # Remove shared libraries to avoid accidental linking against them. rm $FFMPEG_DEPS_PATH/lib/*.so rm $FFMPEG_DEPS_PATH/lib/*.so.* # Build ffmpeg. cd $SRC/ffmpeg if [[ "$ARCHITECTURE" == i386 ]]; then FFMPEG_BUILD_ARGS='--arch="i386" --cpu="i386" --disable-inline-asm --disable-asm' else FFMPEG_BUILD_ARGS='--disable-asm' fi if [ "$SANITIZER" = "memory" ] || [ "$FUZZING_ENGINE" = "centipede" ]; then FFMPEG_BUILD_ARGS="$FFMPEG_BUILD_ARGS --disable-asm" fi ./configure \ --cc=$CC --cxx=$CXX --ld="$CXX $CXXFLAGS -std=c++11" \ --extra-cflags="-I$FFMPEG_DEPS_PATH/include" \ --extra-ldflags="-L$FFMPEG_DEPS_PATH/lib" \ --prefix="$FFMPEG_DEPS_PATH" \ --pkg-config-flags="--static" \ --enable-ossfuzz \ --libfuzzer=$LIB_FUZZING_ENGINE \ --optflags=-O1 \ --enable-gpl \ --enable-nonfree \ --enable-libass \ --enable-libfdk-aac \ --enable-libfreetype \ --enable-libopus \ --enable-libtheora \ --enable-libvorbis \ --enable-libvpx \ --enable-libxml2 \ --enable-nonfree \ --disable-libdrm \ --disable-muxers \ --disable-protocols \ --disable-demuxer=rtp,rtsp,sdp \ --disable-devices \ --disable-shared \ --disable-doc \ --disable-programs \ --enable-demuxers \ --samples=fate-suite/ \ $FFMPEG_BUILD_ARGS # Download test samples, will be used as seed corpus. # DISABLED. # TODO: implement a better way to maintain a minimized seed corpora # for all targets. As of 2017-05-04 now the combined size of corpora # is too big for ClusterFuzz (over 10Gb compressed data). export TEST_SAMPLES_PATH=$SRC/ffmpeg/fate-suite/ make fate-rsync SAMPLES=$TEST_SAMPLES_PATH if [[ -n ${CAPTURE_REPLAY_SCRIPT-} ]]; then exit 0 fi rsync -av rsync://samples.ffmpeg.org/samples/avi/ffv1/testset/ $SRC/ffmpeg/ffv1testset # Build the fuzzers. cd $SRC/ffmpeg FUZZ_TARGET_SOURCE=$SRC/ffmpeg/tools/target_dec_fuzzer.c export TEMP_VAR_CODEC="AV_CODEC_ID_H264" export TEMP_VAR_CODEC_TYPE="VIDEO" declare -a BSF_TARGETS=() declare -a BSF_FUZZER_NAMES=() declare -a DECODER_TARGETS=() declare -a DECODER_FUZZER_NAMES=() declare -a ENCODER_TARGETS=() declare -a ENCODER_FUZZER_NAMES=() # Collect bitstream filters targets CONDITIONALS=$(grep 'BSF 1$' config_components.h | sed 's/#define CONFIG_\(.*\)_BSF 1/\1/') if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space CONDITIONALS=(${CONDITIONALS[@]:0:2}) fi for c in $CONDITIONALS; do fuzzer_name=$($SRC/name_mappings.py binary_name bsf ${c}) symbol=$(echo $c | sed "s/.*/\L\0/") BSF_TARGETS+=("tools/target_bsf_${symbol}_fuzzer") BSF_FUZZER_NAMES+=("${fuzzer_name}") done # Collect decoder targets CONDITIONALS=$(grep 'DECODER 1$' config_components.h | sed 's/#define CONFIG_\(.*\)_DECODER 1/\1/') if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space CONDITIONALS=(${CONDITIONALS[@]:0:2}) fi for c in $CONDITIONALS; do fuzzer_name=$($SRC/name_mappings.py binary_name decoder ${c}) symbol=$(echo $c | sed "s/.*/\L\0/") DECODER_TARGETS+=("tools/target_dec_${symbol}_fuzzer") DECODER_FUZZER_NAMES+=("${fuzzer_name}") done # Collect encoder targets CONDITIONALS=$(grep 'ENCODER 1$' config_components.h | sed 's/#define CONFIG_\(.*\)_ENCODER 1/\1/') if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space CONDITIONALS=(${CONDITIONALS[@]:0:2}) fi for c in $CONDITIONALS; do fuzzer_name=$($SRC/name_mappings.py binary_name encoder ${c}) symbol=$(echo $c | sed "s/.*/\L\0/") ENCODER_TARGETS+=("tools/target_enc_${symbol}_fuzzer") ENCODER_FUZZER_NAMES+=("${fuzzer_name}") done OTHER_TARGETS=("tools/target_sws_fuzzer" "tools/target_swr_fuzzer" "tools/target_dem_fuzzer" "tools/target_io_dem_fuzzer") ALL_TARGETS=("${BSF_TARGETS[@]}" "${DECODER_TARGETS[@]}" "${ENCODER_TARGETS[@]}" "${OTHER_TARGETS[@]}") if [ ${#ALL_TARGETS[@]} -eq 0 ]; then echo "ERROR: No targets found to build!" >&2 exit 1 fi make -j$(nproc) "${ALL_TARGETS[@]}" for i in "${!BSF_TARGETS[@]}"; do echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${BSF_FUZZER_NAMES[$i]}.options mv ${BSF_TARGETS[$i]} $OUT/${BSF_FUZZER_NAMES[$i]} done for i in "${!DECODER_TARGETS[@]}"; do echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${DECODER_FUZZER_NAMES[$i]}.options mv ${DECODER_TARGETS[$i]} $OUT/${DECODER_FUZZER_NAMES[$i]} done for i in "${!ENCODER_TARGETS[@]}"; do echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${ENCODER_FUZZER_NAMES[$i]}.options mv ${ENCODER_TARGETS[$i]} $OUT/${ENCODER_FUZZER_NAMES[$i]} done # Move fuzzer for sws fuzzer_name=$($SRC/name_mappings.py binary_name other SWS) echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${fuzzer_name}.options mv tools/target_sws_fuzzer $OUT/${fuzzer_name} # Move fuzzer for swr fuzzer_name=$($SRC/name_mappings.py binary_name other SWR) echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${fuzzer_name}.options mv tools/target_swr_fuzzer $OUT/${fuzzer_name} # Move fuzzer for demuxer fuzzer_name=$($SRC/name_mappings.py binary_name other DEM) echo -en "[libfuzzer]\nmax_len = 1000000\n" >$OUT/${fuzzer_name}.options mv tools/target_dem_fuzzer $OUT/${fuzzer_name} # We do not need raw reference files for the muxer rm $(find fate-suite -name '*.s16') rm $(find fate-suite -name '*.dec') rm $(find fate-suite -name '*.pcm') zip -r $OUT/${fuzzer_name}_seed_corpus.zip fate-suite zip -r $OUT/ffmpeg_AV_CODEC_ID_HEVC_fuzzer_seed_corpus.zip fate-suite/hevc fate-suite/hevc-conformance zip -r $OUT/ffmpeg_AV_CODEC_ID_FFV1_fuzzer_seed_corpus.zip ffv1testset # Build fuzzer for demuxer fed at IO level fuzzer_name=$($SRC/name_mappings.py binary_name other IO_DEM) mv tools/target_io_dem_fuzzer $OUT/${fuzzer_name} # Clean before reconfiguring for demuxers make distclean # Reduce size of demuxer fuzzers by disabling various components. ./configure \ --cc=$CC --cxx=$CXX --ld="$CXX $CXXFLAGS -std=c++11" \ --extra-cflags="-I$FFMPEG_DEPS_PATH/include" \ --extra-ldflags="-L$FFMPEG_DEPS_PATH/lib" \ --prefix="$FFMPEG_DEPS_PATH" \ --pkg-config-flags="--static" \ --enable-ossfuzz \ --libfuzzer=$LIB_FUZZING_ENGINE \ --optflags=-O1 \ --enable-gpl \ --enable-libxml2 \ --disable-libdrm \ --disable-muxers \ --disable-protocols \ --disable-devices \ --disable-shared \ --disable-encoders \ --disable-filters \ --disable-muxers \ --disable-parsers \ --disable-decoders \ --disable-hwaccels \ --disable-bsfs \ --disable-vaapi \ --disable-vdpau \ --disable-v4l2_m2m \ --disable-cuda_llvm \ --enable-demuxers \ --disable-demuxer=rtp,rtsp,sdp \ --disable-doc \ --disable-programs \ $FFMPEG_BUILD_ARGS declare -a DEMUXER_TARGETS=() declare -a DEMUXER_FUZZER_NAMES=() CONDITIONALS=$(grep 'DEMUXER 1$' config_components.h | sed 's/#define CONFIG_\(.*\)_DEMUXER 1/\1/') if [ -n "${OSS_FUZZ_CI-}" ]; then # When running in CI, check the first targets only to save time and disk space CONDITIONALS=(${CONDITIONALS[@]:0:2}) fi for c in $CONDITIONALS; do fuzzer_name=$($SRC/name_mappings.py binary_name demuxer ${c}) symbol=$(echo $c | sed "s/.*/\L\0/") DEMUXER_TARGETS+=("tools/target_dem_${symbol}_fuzzer") DEMUXER_FUZZER_NAMES+=("${fuzzer_name}") done if [ ${#DEMUXER_TARGETS[@]} -eq 0 ]; then echo "ERROR: No demuxer targets found to build!" >&2 exit 1 fi make -j$(nproc) "${DEMUXER_TARGETS[@]}" for i in "${!DEMUXER_TARGETS[@]}"; do mv ${DEMUXER_TARGETS[$i]} $OUT/${DEMUXER_FUZZER_NAMES[$i]} done # Find relevant corpus in test samples and archive them for every fuzzer. #cd $SRC #python group_seed_corpus.py $TEST_SAMPLES_PATH $OUT/ ================================================ FILE: projects/ffmpeg/group_seed_corpus.py ================================================ #!/usr/bin/env python # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ from __future__ import print_function import logging import os import re import sys import zipfile logging.basicConfig(level=logging.INFO, format='INFO: %(message)s') CODEC_NAME_REGEXP = re.compile(r'codec_id_(.+?)_fuzzer') def get_fuzzer_tags(fuzzer_name): """Extract tags (are used to filter samples) from the given fuzzer name.""" tags = [] fuzzer_name = fuzzer_name.lower() # All subtitle samples are in 'sub' directory, need to add 'sub' tag manually. if 'subtitle' in fuzzer_name: tags.append('sub') m = CODEC_NAME_REGEXP.search(fuzzer_name) if m: codec_name = m.group(1) # Some names are complex, need to split them and filter common strings. codec_name_parts = codec_name.split('_') for codec in codec_name_parts: # Remove common strings from codec names like 'mpeg1video' or 'msvideo1'. codec = codec.split('video')[0] codec = codec.split('audio')[0] codec = codec.split('subtitle')[0] codec = codec.split('text')[0] if codec: # Some codec names have trailing characters: 'VP6F','FLV1', 'JPEGLS'. # Use only first 3 characters for long enough codec names. if len(codec) > 3: tags.append(codec[:3]) else: tags.append(codec) return tags def parse_corpus(corpus_directory): """Recursively list all files in the given directory and ignore checksums.""" all_corpus_files = [] for root, dirs, files in os.walk(corpus_directory): for filename in files: # Skip checksum files, they are useless in corpus. if 'md5sum' in filename: continue path = os.path.join(root, filename) all_corpus_files.append(path) logging.info('Parsed %d corpus files from %s' % (len(all_corpus_files), corpus_directory)) return all_corpus_files def parse_fuzzers(fuzzers_directory): """Recursively list all fuzzers in the given directory.""" all_fuzzers = [] for filename in os.listdir(fuzzers_directory): # Skip non-ffmpeg and non-fuzzer files in the given directory, if not filename.startswith('ffmpeg_') or not filename.endswith('_fuzzer'): continue fuzzer_path = os.path.join(fuzzers_directory, filename) all_fuzzers.append(fuzzer_path) logging.info('Parsed %d fuzzers from %s' % (len(all_fuzzers), fuzzers_directory)) return all_fuzzers def zip_relevant_corpus(corpus_files, fuzzers): """Find relevant corpus files and archive them for every fuzzer given.""" for fuzzer in fuzzers: fuzzer_name = os.path.basename(fuzzer) fuzzer_directory = os.path.dirname(fuzzer) fuzzer_tags = get_fuzzer_tags(fuzzer_name) relevant_corpus_files = set() for filename in corpus_files: # Remove 'ffmpeg' substring to do not use everything for 'MPEG' codec. sanitized_filename = filename.replace('ffmpeg', '').lower() for tag in fuzzer_tags: if tag in sanitized_filename: relevant_corpus_files.add(filename) if not relevant_corpus_files: # Strip last symbol from tags if we haven't found relevant corpus. # It helps for such codecs as 'RV40' ('RV4' -> 'RV') or 'PCX' (-> 'PC'). for tag in fuzzer_tags: if tag[:-1] in sanitized_filename: relevant_corpus_files.add(filename) logging.info( 'Found %d relevant samples for %s' % (len(relevant_corpus_files), fuzzer_name)) if not relevant_corpus_files: continue zip_archive_name = fuzzer + "_seed_corpus.zip" with zipfile.ZipFile(zip_archive_name, 'w') as archive: for filename in relevant_corpus_files: archive.write(filename) def main(): if len(sys.argv) < 3: print('Usage: %s ' % __file__) sys.exit(1) seed_corpus_directory = sys.argv[1] fuzzers_directory = sys.argv[2] corpus_files = parse_corpus(seed_corpus_directory) fuzzers = parse_fuzzers(fuzzers_directory) zip_relevant_corpus(corpus_files, fuzzers) if __name__ == '__main__': sys.exit(main()) ================================================ FILE: projects/ffmpeg/name_mappings.py ================================================ #!/usr/bin/env python3 # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This script converts between OSS-Fuzz binary names and FFmpeg build targets. # Context: https://github.com/google/oss-fuzz/issues/13472 import argparse from enum import StrEnum, auto # List of "legacy" decoders where we need to keep the existing name the same # (ffmpeg_AV_CODEC_ID__fuzzer). # This is to ensure we don't break bisections, and don't have to migrate open # testcases and corpora. # # Any new decoder fuzzer with an ID not in this list must have the format # ffmpeg_AV_CODEC_ID__DEC_fuzzer. # # Any new encoder fuzzer with an ID in this list (e.g. a new encoder was added # where we previously only supported decoding) must have the format # ffmpeg_AV_CODEC_ID__ENC_fuzzer. LEGACY_DECODERS = ( 'AAC_FIXED', 'AAC_LATM', 'AASC', 'ACELP_KELVIN', 'ADPCM_4XM', 'ADPCM_AFC', 'ADPCM_AGM', 'ADPCM_AICA', 'ADPCM_CT', 'ADPCM_DTK', 'ADPCM_EA', 'ADPCM_EA_MAXIS_XA', 'ADPCM_EA_R1', 'ADPCM_EA_R2', 'ADPCM_EA_R3', 'ADPCM_EA_XAS', 'ADPCM_IMA_ACORN', 'ADPCM_IMA_APC', 'ADPCM_IMA_CUNNING', 'ADPCM_IMA_DAT4', 'ADPCM_IMA_DK3', 'ADPCM_IMA_DK4', 'ADPCM_IMA_EA_EACS', 'ADPCM_IMA_EA_SEAD', 'ADPCM_IMA_ISS', 'ADPCM_IMA_MOFLEX', 'ADPCM_IMA_MTF', 'ADPCM_IMA_OKI', 'ADPCM_IMA_RAD', 'ADPCM_IMA_SMJPEG', 'ADPCM_IMA_XBOX', 'ADPCM_MTAF', 'ADPCM_PSX', 'ADPCM_SBPRO_2', 'ADPCM_SBPRO_3', 'ADPCM_SBPRO_4', 'ADPCM_THP', 'ADPCM_THP_LE', 'ADPCM_VIMA', 'ADPCM_XA', 'ADPCM_XMD', 'ADPCM_ZORK', 'AGM', 'AIC', 'ALS', 'AMRNB', 'AMRWB', 'ANM', 'ANSI', 'APAC', 'APE', 'APV', 'ARBC', 'ARGO', 'ATRAC1', 'ATRAC3', 'ATRAC3AL', 'ATRAC3P', 'ATRAC3PAL', 'ATRAC9', 'AURA', 'AURA2', 'AV1', 'AVRN', 'AVS', 'BETHSOFTVID', 'BFI', 'BINK', 'BINKAUDIO_DCT', 'BINKAUDIO_RDFT', 'BINTEXT', 'BMV_AUDIO', 'BMV_VIDEO', 'BONK', 'BRENDER_PIX', 'C93', 'CAVS', 'CBD2_DPCM', 'CCAPTION', 'CDGRAPHICS', 'CDTOONS', 'CDXL', 'CLEARVIDEO', 'CLLC', 'COOK', 'CPIA', 'CRI', 'CSCD', 'CYUV', 'DDS', 'DERF_DPCM', 'DFA', 'DIRAC', 'DOLBY_E', 'DSD_LSBF', 'DSD_LSBF_PLANAR', 'DSD_MSBF', 'DSD_MSBF_PLANAR', 'DSICINAUDIO', 'DSICINVIDEO', 'DSS_SP', 'DST', 'DVAUDIO', 'DXA', 'DXTORY', 'EACMV', 'EAMAD', 'EATGQ', 'EATGV', 'EATQI', 'EIGHTBPS', 'EIGHTSVX_EXP', 'EIGHTSVX_FIB', 'ESCAPE124', 'ESCAPE130', 'EVRC', 'FASTAUDIO', 'FFWAVESYNTH', 'FIC', 'FLIC', 'FMVC', 'FOURXM', 'FRAPS', 'FRWU', 'FTR', 'G2M', 'G729', 'GDV', 'GEM', 'GREMLIN_DPCM', 'GSM', 'GSM_MS', 'H263I', 'H264', 'HAP', 'HCA', 'HCOM', 'HEVC', 'HNM4_VIDEO', 'HQX', 'HQ_HQA', 'HYMT', 'IAC', 'IDCIN', 'IDF', 'IFF_ILBM', 'ILBC', 'IMC', 'IMM4', 'IMM5', 'INDEO2', 'INDEO3', 'INDEO4', 'INDEO5', 'INTERPLAY_ACM', 'INTERPLAY_DPCM', 'INTERPLAY_VIDEO', 'IPU', 'JACOSUB', 'JV', 'KGV1', 'KMVC', 'LAGARITH', 'LEAD', 'LOCO', 'LSCR', 'M101', 'MACE3', 'MACE6', 'MDEC', 'MEDIA100', 'METASOUND', 'MICRODVD', 'MIMIC', 'MISC4', 'MJPEGB', 'MMVIDEO', 'MOBICLIP', 'MOTIONPIXELS', 'MP1', 'MP1FLOAT', 'MP2FLOAT', 'MP3', 'MP3ADU', 'MP3ADUFLOAT', 'MP3FLOAT', 'MP3ON4', 'MP3ON4FLOAT', 'MPC7', 'MPC8', 'MPEG1_V4L2M2M', 'MPEG2_V4L2M2M', 'MPEGVIDEO', 'MPL2', 'MSA1', 'MSCC', 'MSMPEG4V1', 'MSNSIREN', 'MSP2', 'MSS1', 'MSS2', 'MSZH', 'MTS2', 'MV30', 'MVC1', 'MVC2', 'MVDV', 'MVHA', 'MWSC', 'MXPEG', 'NOTCHLC', 'NUV', 'ON2AVC', 'OSQ', 'PAF_AUDIO', 'PAF_VIDEO', 'PCM_F16LE', 'PCM_F24LE', 'PCM_LXF', 'PCM_SGA', 'PDV', 'PGSSUB', 'PGX', 'PHOTOCD', 'PICTOR', 'PIXLET', 'PJS', 'PROSUMER', 'PSD', 'PTX', 'QCELP', 'QDM2', 'QDMC', 'QDRAW', 'QOA', 'QPEG', 'RALF', 'RASC', 'RA_288', 'REALTEXT', 'RKA', 'RL2', 'RSCC', 'RTV1', 'RV30', 'RV40', 'RV60', 'SAMI', 'SANM', 'SCPR', 'SCREENPRESSO', 'SDX2_DPCM', 'SGA', 'SGIRLE', 'SHEERVIDEO', 'SHORTEN', 'SIMBIOSIS_IMX', 'SIPR', 'SIREN', 'SMACKAUD', 'SMACKER', 'SMVJPEG', 'SOL_DPCM', 'SONIC', 'SP5X', 'SPEEX', 'SRGC', 'STL', 'SUBVIEWER', 'SUBVIEWER1', 'SVQ3', 'TAK', 'TARGA_Y216', 'TDSC', 'THEORA', 'THP', 'TIERTEXSEQVIDEO', 'TMV', 'TRUEMOTION1', 'TRUEMOTION2', 'TRUEMOTION2RT', 'TRUESPEECH', 'TSCC', 'TSCC2', 'TWINVQ', 'TXD', 'ULTI', 'V210X', 'VB', 'VBLE', 'VC1', 'VC1IMAGE', 'VC1_V4L2M2M', 'VCR1', 'VMDAUDIO', 'VMDVIDEO', 'VMIX', 'VMNC', 'VP3', 'VP4', 'VP5', 'VP6', 'VP6A', 'VP6F', 'VP7', 'VP8', 'VP9', 'VP9_V4L2M2M', 'VPLAYER', 'VQA', 'VQC', 'VVC', 'WADY_DPCM', 'WAVARC', 'WCMV', 'WEBP', 'WMALOSSLESS', 'WMAPRO', 'WMAVOICE', 'WMV3', 'WMV3IMAGE', 'WNV1', 'WS_SND1', 'XAN_DPCM', 'XAN_WC3', 'XAN_WC4', 'XBIN', 'XL', 'XMA1', 'XMA2', 'XPM', 'YLC', 'YOP', 'ZERO12V', 'ZEROCODEC', ) class IDType(StrEnum): DECODER = auto() ENCODER = auto() DEMUXER = auto() BSF = auto() OTHER = auto() def binary_name(type: IDType, id: str) -> str: if type == IDType.OTHER: id = id.upper().replace('DEM', 'DEMUXER') return f'ffmpeg_{id}_fuzzer' if type == IDType.DEMUXER: id = id.upper() return f'ffmpeg_dem_{id}_fuzzer' if type == IDType.BSF: id = id.upper() return f'ffmpeg_BSF_{id}_fuzzer' if id in LEGACY_DECODERS: if type == IDType.DECODER: return f'ffmpeg_AV_CODEC_ID_{id}_fuzzer' if type == IDType.ENCODER: # New encoder got added where there was previously only a decoder. # Differentiate it. return f'ffmpeg_AV_CODEC_ID_{id}_ENC_fuzzer' if type == IDType.DECODER: # New decoder. Differentiate it. return f'ffmpeg_AV_CODEC_ID_{id}_DEC_fuzzer' # By default, encoder fuzzers will map to this. return f'ffmpeg_AV_CODEC_ID_{id}_fuzzer' def build_target_name(binary_name: str) -> str: name = binary_name.removeprefix('ffmpeg_').removesuffix('_fuzzer') if name.startswith('AV_CODEC_ID_'): name = name.removeprefix('AV_CODEC_ID_') if name.endswith('_DEC') or name in LEGACY_DECODERS: name = name.removesuffix('_DEC') return f'target_dec_{name.lower()}_fuzzer' name = name.removesuffix('_ENC') return f'target_enc_{name.lower()}_fuzzer' return f'target_{name.lower().replace("demuxer", "dem")}_fuzzer' def main(): parser = argparse.ArgumentParser( description='FFmpeg fuzzer name mapping utility.') subparsers = parser.add_subparsers(dest='command', help='Available commands', required=True) binary_parser = subparsers.add_parser( 'binary_name', help='Generate binary name for a codec ID and type.') binary_parser.add_argument( 'type', type=IDType, choices=list(IDType), help='Type of ID (DECODER, ENCODER, DEMUXER, BSF, OTHER)') binary_parser.add_argument('id', type=str, help='Codec ID (e.g., AAC_FIXED)') binary_parser.set_defaults( func=lambda args: print(binary_name(args.type, args.id))) target_parser = subparsers.add_parser( 'build_target_name', help='Generate build target name from a binary name.') target_parser.add_argument( 'name', type=str, help='Binary name (e.g., ffmpeg_AV_CODEC_ID_AAC_FIXED_fuzzer)') target_parser.set_defaults( func=lambda args: print(build_target_name(args.name))) args = parser.parse_args() args.func(args) if __name__ == '__main__': main() ================================================ FILE: projects/ffmpeg/project.yaml ================================================ homepage: "https://www.ffmpeg.org" language: c++ primary_contact: "ffmpeg-security@ffmpeg.org" architectures: - x86_64 - i386 auto_ccs: - "michaelni@gmx.at" - "michael@niedermayer.cc" - "tfoucu@google.com" - "twsmith@mozilla.com" - "kempfjb@gmail.com" - "jordyzomer@google.com" - "epirat07@gmail.com" - "kasper93@gmail.com" - "jzern@google.com" fuzzing_engines: - afl - honggfuzz - libfuzzer sanitizers: - address - memory - undefined selective_unpack: true main_repo: 'https://github.com/FFmpeg/FFmpeg' ================================================ FILE: projects/ffmpeg/replay_build.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable UBSan vptr since several targets built with -fno-rtti. export CFLAGS="$CFLAGS -fno-sanitize=vptr" export CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" if [[ "$CXXFLAGS" == *"-fsanitize=address"* ]]; then export CXXFLAGS="$CXXFLAGS -fno-sanitize-address-use-odr-indicator" fi if [[ "$CFLAGS" == *"-fsanitize=address"* ]]; then export CFLAGS="$CFLAGS -fno-sanitize-address-use-odr-indicator" fi if [[ "$ARCHITECTURE" == i386 ]]; then export CFLAGS="$CFLAGS -m32" export CXXFLAGS="$CXXFLAGS -m32" fi # The option `-fuse-ld=gold` can't be passed via `CFLAGS` or `CXXFLAGS` because # Meson injects `-Werror=ignored-optimization-argument` during compile tests. # Remove the `-fuse-ld=` and let Meson handle it. # https://github.com/mesonbuild/meson/issues/6377#issuecomment-575977919 export MESON_CFLAGS="$CFLAGS" if [[ "$CFLAGS" == *"-fuse-ld=gold"* ]]; then export MESON_CFLAGS="${CFLAGS//-fuse-ld=gold/}" export CC_LD=gold fi export MESON_CXXFLAGS="$CXXFLAGS" if [[ "$CXXFLAGS" == *"-fuse-ld=gold"* ]]; then export MESON_CXXFLAGS="${CXXFLAGS//-fuse-ld=gold/}" export CXX_LD=gold fi cd $SRC/ffmpeg make -j$(nproc) install if [ "$#" -lt 1 ]; then exit 0 fi make_target=$($SRC/name_mappings.py build_target_name "$1") make tools/${make_target} mv tools/${make_target} $OUT/$1 ================================================ FILE: projects/ffmpeg/run_tests.sh ================================================ #!/bin/bash -e # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/ffmpeg # TODO: Since the h264dsp test is failing, we are using a patch to skip it # entirely. Although adding --ignore-tests=checkasm-h264dsp to ./configure is an #option, it still compiles the test and wastes a lot of time. mv tests/checkasm/h264dsp.c tests/checkasm/h264dsp.c.backup cp tests/checkasm/Makefile tests/checkasm/Makefile.backup cp tests/checkasm/checkasm.c tests/checkasm/checkasm.c.backup sed -i '/^AVCODECOBJS-\$(CONFIG_H264DSP)/d' tests/checkasm/Makefile sed -i -e '/extern.*checkasm_check_h264dsp/d' \ -e '/"h264dsp"/d' tests/checkasm/checkasm.c make -j"$(nproc)" fate SAMPLES=fate-suite/ # Undo patches. mv tests/checkasm/h264dsp.c.backup tests/checkasm/h264dsp.c mv tests/checkasm/Makefile.backup tests/checkasm/Makefile mv tests/checkasm/checkasm.c.backup tests/checkasm/checkasm.c ================================================ FILE: projects/ffms2/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y python-is-python3 build-essential \ autoconf automake libtool zlib1g-dev pkg-config nasm RUN git clone --depth 1 --branch n7.1 https://github.com/FFmpeg/FFmpeg.git ffmpeg RUN cd $SRC/ffmpeg && \ ./configure --prefix=/usr --enable-shared --disable-static \ --disable-doc --disable-programs --disable-debug \ --cc=clang --cxx=clang++ && \ make -j$(nproc) && \ make install && \ ldconfig RUN git clone https://github.com/FFMS/ffms2 ffms2 COPY build.sh $SRC/ COPY *_fuzzer.cc $SRC/ WORKDIR $SRC/ffms2 ================================================ FILE: projects/ffms2/build.sh ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./autogen.sh make install-libLTLIBRARIES # The media libraries has a significant set of dynamic library dependencies, # and to resolve this we copy them all over. find /usr/local/lib -name "libffms2.so*" -exec cp "{}" $OUT \; DYNLIBS_TO_COPY="libavformat.so* libavcodec.so* libavutil.so* libswscale.so* libswresample.so* libxml2.so* libgme.so* libopenmpt.so* libchromaprint.so* libbluray.so* libssh-gcrypt.so* libvpx.so* libwebpmux.so* libwebp.so* librsvg-2.so* libgobject-2.0.so* libglib-2.0.so* libcairo.so* libzvbi.so* libsnappy.so* libaom.so* libcodec2.so* libgsm.so* libmp3lame.so* libopenjp2.so* libopus.so* libshine.so* libspeex.so* libtheoraenc.so* libtheoradec.so* libtwolame.so* libvorbis.so* libvorbisenc.so* libwavpack.so* libx264.so* libx265.so* libxvidcore.so* libva.so* libva-drm.so* libva-x11.so* libvdpau.so* libX11.so* libxcb.so* libdrm.so* libOpenCL.so* libfontconfig.so* libfreetype.so* libpixman-1.so* libpng16.so* libxcb-shm.so* libxcb-render.so* libXrender.so* libXext.so* libmpg123.so* libvorbisfile.so* libcairo-gobject.so* libgdk_pixbuf-2.0.so* libgmodule-2.0.so* libgio-2.0.so* libpangocairo-1.0.so* libpango-1.0.so* libfribidi.so* libthai.so* libharfbuzz.so* libgraphite2.so* libpangoft2-1.0.so* libsoxr.so* libdatrie.so* libogg.so* libXfixes.so* libnuma.so* libXau.so* libXdmcp.so* libbsd.so* libicuuc.so* libicudata.so*" for dynlibname in $DYNLIBS_TO_COPY; do find /usr/lib -name "${dynlibname}" -exec cp {} $OUT \; done for f in $SRC/*_fuzzer.cc; do fuzzer=$(basename "$f" _fuzzer.cc) $CXX $CXXFLAGS -std=c++11 -I$SRC/ffms2/include \ $SRC/${fuzzer}_fuzzer.cc -o $OUT/${fuzzer}_fuzzer \ $LIB_FUZZING_ENGINE -lpthread $OUT/libffms2.so \ $OUT/*.so* patchelf --set-rpath '$ORIGIN/' $OUT/${fuzzer}_fuzzer done ================================================ FILE: projects/ffms2/ffms2_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include /* Overwrite atexit to make linker happy */ int atexit(void (*function)(void)) { return 1; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FFMS_Init(0, 0); char errmsg[1024]; FFMS_ErrorInfo errinfo; errinfo.Buffer = errmsg; errinfo.BufferSize = sizeof(errmsg); errinfo.ErrorType = FFMS_ERROR_SUCCESS; errinfo.SubType = FFMS_ERROR_SUCCESS; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); FFMS_Indexer *indexer = FFMS_CreateIndexer(filename, &errinfo); if (indexer != NULL) { FFMS_Index *index = FFMS_DoIndexing2(indexer, FFMS_IEH_ABORT, &errinfo); if (index != NULL) { int trackno = FFMS_GetFirstTrackOfType(index, FFMS_TYPE_VIDEO, &errinfo); } FFMS_DestroyIndex(index); } unlink(filename); return 0; } ================================================ FILE: projects/ffms2/project.yaml ================================================ homepage: "https://github.com/FFMS/ffms2" main_repo: "https://github.com/FFMS/ffms2" language: c++ fuzzing_engines: - libfuzzer - honggfuzz sanitizers: - address - undefined vendor_ccs: - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/fftw3/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y build-essential ocaml ocamlbuild texinfo \ autoconf automake indent libtool libnum-ocaml-dev fig2dev RUN git clone https://github.com/FFTW/fftw3 fftw3 COPY run_tests.sh build.sh *.cc $SRC/ WORKDIR $SRC/fftw3 ================================================ FILE: projects/fftw3/build.sh ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sh bootstrap.sh make -j4 for f in $SRC/*_fuzzer.cc; do fuzzer=$(basename "$f" _fuzzer.cc) $CXX $CXXFLAGS -I$SRC/fftw3 -I$SRC/fftw3/api \ $SRC/${fuzzer}_fuzzer.cc -o $OUT/${fuzzer}_fuzzer \ $LIB_FUZZING_ENGINE -lpthread ./.libs/libfftw3.a done ================================================ FILE: projects/fftw3/fftw3_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // For reference, fftw_compelx is defined: // typedef double fftw_complex[2] if (size < 1) { return 0; } uint8_t ARRAY_SIZE = (*data) % 250 + 1; data++; size -= 1; if ((ARRAY_SIZE * sizeof(double) * 2) > size) { return 0; } fftw_complex signal[ARRAY_SIZE]; fftw_complex result[ARRAY_SIZE]; // Seed the signals with fuzz data memcpy(signal, data, (ARRAY_SIZE * sizeof(double) * 2)); fftw_plan plan = fftw_plan_dft_1d(ARRAY_SIZE, signal, result, FFTW_FORWARD, FFTW_ESTIMATE); fftw_execute(plan); fftw_destroy_plan(plan); return 0; } ================================================ FILE: projects/fftw3/project.yaml ================================================ homepage: "http://fftw.org/" main_repo: "https://github.com/fftw/fftw3.git" language: c++ vendor_ccs: - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/fftw3/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### make check ================================================ FILE: projects/file/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt install -y make autoconf automake libtool shtool RUN apt-get update && apt install -y libbz2-dev liblzma-dev zlib1g-dev libzstd-dev liblz4-dev RUN apt-get update && apt install -y libbz2-dev:i386 liblzma-dev:i386 zlib1g-dev:i386 libzstd-dev:i386 liblz4-dev:i386 RUN git clone --depth 1 https://github.com/file/file.git # Supplement file's existing test files RUN git clone --depth 1 https://github.com/DavidKorczynski/binary-samples.git RUN git clone --depth 1 https://github.com/corkami/pocs WORKDIR file COPY build.sh fuzzer_temp_file.h magic_fuzzer.cc magic_fuzzer_loaddb.cc magic_fuzzer_fd.cc $SRC/ ================================================ FILE: projects/file/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ autoreconf -i ./configure --enable-static --enable-fsect-man5 make V=1 all $CXX $CXXFLAGS -std=c++11 -Isrc/ \ $SRC/magic_fuzzer.cc -o $OUT/magic_fuzzer \ $LIB_FUZZING_ENGINE ./src/.libs/libmagic.a -l:libz.a -l:liblz4.a -l:libbz2.a -l:liblzma.a -l:libzstd.a $CXX $CXXFLAGS -std=c++11 -Isrc/ \ $SRC/magic_fuzzer_loaddb.cc -o $OUT/magic_fuzzer_loaddb \ $LIB_FUZZING_ENGINE ./src/.libs/libmagic.a -l:libz.a -l:liblz4.a -l:libbz2.a -l:liblzma.a -l:libzstd.a $CXX $CXXFLAGS -std=c++11 -Isrc/ \ $SRC/magic_fuzzer_fd.cc -o $OUT/magic_fuzzer_fd \ $LIB_FUZZING_ENGINE ./src/.libs/libmagic.a -l:libz.a -l:liblz4.a -l:libbz2.a -l:liblzma.a -l:libzstd.a cp ./magic/magic.mgc $OUT/ mkdir pocs_all find $SRC/pocs/ -type f -print0 | xargs -0 -I % mv -f % ./pocs_all zip -j $OUT/magic_fuzzer_seed_corpus.zip ./tests/*.testfile $SRC/binary-samples/{elf,pe}-* $SRC/pocs_all ================================================ FILE: projects/file/fuzzer_temp_file.h ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that // require a file instead of an input buffer. #ifndef FUZZER_TEMP_FILE_H_ #define FUZZER_TEMP_FILE_H_ #include #include #include #include #include // Pure-C interface for creating and cleaning up temporary files. static char* fuzzer_get_tmpfile(const uint8_t* data, size_t size) { char* filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename_buffer) { perror("Failed to allocate file name buffer."); abort(); } const int file_descriptor = mkstemp(filename_buffer); if (file_descriptor < 0) { perror("Failed to make temporary file."); abort(); } FILE* file = fdopen(file_descriptor, "wb"); if (!file) { perror("Failed to open file descriptor."); close(file_descriptor); abort(); } const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file); if (bytes_written < size) { close(file_descriptor); fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size); abort(); } fclose(file); return filename_buffer; } static void fuzzer_release_tmpfile(char* filename) { if (unlink(filename) != 0) { perror("WARNING: Failed to delete temporary file."); } free(filename); } // C++ RAII object for creating temporary files. #ifdef __cplusplus class FuzzerTemporaryFile { public: FuzzerTemporaryFile(const uint8_t* data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) {} ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); } const char* filename() const { return filename_; } private: char* filename_; }; #endif #endif // FUZZER_TEMP_FILE_H_ ================================================ FILE: projects/file/magic_fuzzer.cc ================================================ // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include struct Environment { Environment(std::string data_dir) { magic = magic_open(MAGIC_COMPRESS|MAGIC_CONTINUE|MAGIC_NO_COMPRESS_FORK); std::string magic_path = data_dir + "/magic"; if (magic_load(magic, magic_path.c_str())) { fprintf(stderr, "error loading magic file: %s\n", magic_error(magic)); exit(1); } } magic_t magic; }; static Environment* env; extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { char* exe_path = (*argv)[0]; // dirname() can modify its argument. char* exe_path_copy = strdup(exe_path); char* dir = dirname(exe_path_copy); env = new Environment(dir); free(exe_path_copy); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 1) return 0; magic_buffer(env->magic, data, size); return 0; } ================================================ FILE: projects/file/magic_fuzzer_fd.cc ================================================ // Copyright 2022 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include #include "fuzzer_temp_file.h" #include struct Environment { Environment(std::string data_dir) { magic = magic_open(MAGIC_COMPRESS|MAGIC_CONTINUE|MAGIC_NO_COMPRESS_FORK); std::string magic_path = data_dir + "/magic"; if (magic_load(magic, magic_path.c_str())) { fprintf(stderr, "error loading magic file: %s\n", magic_error(magic)); exit(1); } } magic_t magic; }; static Environment* env; extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { char* exe_path = (*argv)[0]; // dirname() can modify its argument. char* exe_path_copy = strdup(exe_path); char* dir = dirname(exe_path_copy); env = new Environment(dir); free(exe_path_copy); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzerTemporaryFile ftf (data, size); int fd = open(ftf.filename(), O_RDONLY); magic_descriptor(env->magic, fd); close(fd); return 0; } ================================================ FILE: projects/file/magic_fuzzer_loaddb.cc ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include #include "fuzzer_temp_file.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 1) return 0; FuzzerTemporaryFile ftf (data, size); magic_t magic = magic_open(MAGIC_NONE); magic_check(magic, ftf.filename()); magic_compile(magic, ftf.filename()); magic_close(magic); return 0; } ================================================ FILE: projects/file/project.yaml ================================================ homepage: "http://www.darwinsys.com/file/" language: c++ primary_contact: "zoulasc@gmail.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/file/file.git' ================================================ FILE: projects/filelock/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN python3 -m pip install --upgrade pip RUN git clone --depth 1 https://github.com/tox-dev/py-filelock filelock WORKDIR filelock COPY build.sh *.py $SRC/ ================================================ FILE: projects/filelock/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/filelock/fuzz_filelock.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import filelock from filelock import BaseFileLock, FileLock, SoftFileLock, Timeout, UnixFileLock def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) filepath = os.path.join("/tmp/tmp1.txt") with open(filepath, "w") as f: f.write("random") lock = filelock.FileLock(filepath) for i in range(fdp.ConsumeIntInRange(10, 100)): try: lock.acquire() except IsADirectoryError: pass assert lock.is_locked lock.release(force=True) assert not lock.is_locked def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/filelock/project.yaml ================================================ homepage: "https://github.com/google/oss-fuzz/pull/8244" language: python primary_contact: "gaborjbernat@gmail.com" main_repo: "https://github.com/tox-dev/py-filelock" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined ================================================ FILE: projects/filesystem_spec/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip aiohttp requests RUN git clone https://github.com/fsspec/filesystem_spec filesystem_spec COPY *.sh *py $SRC/ WORKDIR $SRC/filesystem_spec ================================================ FILE: projects/filesystem_spec/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/filesystem_spec/fuzz_http.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import sys import atheris import pathlib from fsspec.implementations import http import fsspec from fsspec.exceptions import FSTimeoutError # Import aiohttp and requests for pyinstaller from requests import * from aiohttp import * from aiohttp.client_exceptions import ClientError @atheris.instrument_func def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) path = fdp.ConsumeUnicodeNoSurrogates(124) # Ensure it's a file vs directory path = path + "the_file.txt" h = fsspec.filesystem("http", use_listings_cache=True) tmp_path = pathlib.Path(path) try: tmp_path.write_bytes(data) except: # Don't care about errors in pathlib try: tmp_path.unlink() except: pass return try: h.put_file(tmp_path, path, method="put", timeout=0.5) except FSTimeoutError: try: tmp_path.unlink() except: pass return except ( ClientError, TypeError, AssertionError ) as e: # Abandon if aiohttp threw an error. try: tmp_path.unlink() except: pass return # Reading the file should be possible now. with h.open(path) as http_f: http_f.read() try: tmp_path.unlink() except: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/filesystem_spec/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/fsspec/filesystem_spec language: python main_repo: https://github.com/fsspec/filesystem_spec sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/fio/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make libcunit1 libcunit1-dev RUN git clone --depth 1 https://github.com/axboe/fio.git fio WORKDIR $SRC/fio COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/fio/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project export LDFLAGS="$CXXFLAGS" ./configure make -j$(nproc) make unittests/unittest cp t/fuzz/fuzz_parseini $OUT/ # builds corpus zip -r $OUT/fuzz_parseini_seed_corpus.zip examples ================================================ FILE: projects/fio/project.yaml ================================================ homepage: "http://git.kernel.dk/fio.git" language: c++ primary_contact: "axboe@kernel.dk" auto_ccs: - "p.antoine@catenacyber.fr" - "sitsofe@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/axboe/fio.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/fio/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" ./unittests/unittest ================================================ FILE: projects/fips203/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/integritychain/fips203 # or use other version control WORKDIR fips203 ENV FUZZING_LANGUAGE=rust COPY build.sh $SRC/ ================================================ FILE: projects/fips203/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build fuzzers, zip corpus cd $SRC/fips203 cargo fuzz build -O --debug-assertions cp fuzz/target/x86_64-unknown-linux-gnu/release/ml_kem_fuzz $OUT/ zip -q $OUT/ml_kem_fuzz_seed_corpus.zip fuzz/corpus/ml_kem_fuzz/* ================================================ FILE: projects/fips203/project.yaml ================================================ homepage: "https://crates.io/crates/fips203" main_repo: "https://github.com/integritychain/fips203" language: rust primary_contact: "eschorn@integritychain.com" auto_ccs: - "eschorn@gmail.com" file_github_issue: true sanitizers: - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/firefox/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y software-properties-common && \ add-apt-repository -y ppa:ubuntu-toolchain-r/test && \ apt-get update && \ apt-get upgrade -y && \ apt-get install -y --no-install-recommends \ cmake \ gawk \ git \ libstdc++6 \ m4 \ nasm \ python \ python3-pip \ python3-setuptools \ python3-wheel # install Firefox deps # built using https://packages.ubuntu.com/focal/firefox as a reference RUN apt-get update && apt-get install -y --no-install-recommends \ libasound2 \ libatk1.0-0 \ libc6 \ libcairo-gobject2 \ libcairo2 \ libdbus-1-3 \ libdbus-glib-1-2 \ libffi7 \ libfontconfig1 \ libfreetype6 \ libgcc-s1 \ libgdk-pixbuf2.0-0 \ libglib2.0-0 \ libgtk-3-0 \ libharfbuzz0b \ libpango-1.0-0 \ libpangocairo-1.0-0 \ libpangoft2-1.0-0 \ libstdc++6 \ libx11-6 \ libx11-xcb1 \ libxcb-shm0 \ libxcb1 \ libxcomposite1 \ libxcursor1 \ libxdamage1 \ libxext6 \ libxfixes3 \ libxi6 \ libxrandr2 \ libxrender1 \ libxt6 \ libxtst6 \ lsb-release \ libcanberra0 \ libdbusmenu-glib4 \ libdbusmenu-gtk3-4 RUN pip3 install meson ninja # This wrapper of cargo seems to interfere with our build system. RUN rm -f /usr/local/bin/cargo RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > $SRC/rustbuild.sh && \ chmod +x $SRC/rustbuild.sh && \ $SRC/rustbuild.sh -y RUN git clone --depth 1 https://github.com/mozilla/gecko-dev mozilla-central WORKDIR mozilla-central # Install OS dependencies. # Will be re-run in build.sh to install missing dependencies. ENV SHELL /bin/bash RUN ./mach --no-interactive bootstrap --application-choice browser COPY build.sh target.c *.options mozconfig.* $SRC/ ================================================ FILE: projects/firefox/ImageBMP.options ================================================ [libfuzzer] close_fd_mask = 3 ================================================ FILE: projects/firefox/ImageGIF.options ================================================ [libfuzzer] close_fd_mask = 3 ================================================ FILE: projects/firefox/SdpParser.options ================================================ [libfuzzer] max_len = 25600 ================================================ FILE: projects/firefox/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ "$SANITIZER" = "coverage" ] then touch $OUT/exit exit 0 fi source $HOME/.cargo/env # Case-sensitive names of internal Firefox fuzzing targets. Edit to add more. FUZZ_TARGETS=( ContentSecurityPolicyParser FeaturePolicyParser # WebRTC SdpParser StunParser # Image ImageGIF ImageICO ImageBMP # Demuxing MediaADTS MediaFlac MediaMP3 MediaOgg MediaWebM # MediaWAV disabled due to frequent OOMs ) # Firefox object (build) directory and configuration file. export MOZ_OBJDIR=$WORK/obj-fuzz export MOZCONFIG=$SRC/mozconfig.$SANITIZER # Without this, a host tool used during Rust part of the build will fail export ASAN_OPTIONS="detect_leaks=0" # Install remaining dependencies. export SHELL=/bin/bash rustup default nightly ./mach --no-interactive bootstrap --application-choice browser # Skip patches for now rm tools/fuzzing/libfuzzer/patches/*.patch touch tools/fuzzing/libfuzzer/patches/dummy.patch # Build! ./mach build ./mach gtest buildbutdontrun # Packages Firefox only to immediately extract the archive. Some files are # replaced with gtest-variants, which is required by the fuzzing interface. # Weighs in shy of 1GB afterwards. About double for coverage builds. ./mach package tar -xf $MOZ_OBJDIR/dist/firefox*.linux-x86_64.tar.xz -C $OUT cp -L $MOZ_OBJDIR/dist/bin/gtest/libxul.so $OUT/firefox cp $OUT/firefox/dependentlibs.list $OUT/firefox/dependentlibs.list.gtest # Get absolute paths of the required system libraries. LIBRARIES=$({ xargs -I{} ldd $OUT/firefox/{} | gawk '/=> [/]/ {print $3}' | sort -u } < $OUT/firefox/dependentlibs.list) # Copy libraries. Less than 50MB total. mkdir -p $OUT/lib for LIBRARY in $LIBRARIES; do cp -L $LIBRARY $OUT/lib; done # Build a wrapper binary for each target to set environment variables. for FUZZ_TARGET in ${FUZZ_TARGETS[@]} do $CC $CFLAGS -O0 \ -DFUZZ_TARGET=$FUZZ_TARGET \ $SRC/target.c -o $OUT/$FUZZ_TARGET done cp $SRC/*.options $OUT # SdpParser find media/webrtc -iname "*.sdp" \ -type f -exec zip -qu $OUT/SdpParser_seed_corpus.zip "{}" \; # StunParser find media/webrtc -iname "*.stun" \ -type f -exec zip -qu $OUT/StunParser_seed_corpus.zip "{}" \; ================================================ FILE: projects/firefox/mozconfig.address ================================================ . $SRC/mozconfig.coverage ac_add_options --enable-address-sanitizer # Don't use standard CFLAGS/CXXFLAGS provided by oss-fuzz export CFLAGS="" export CXXFLAGS="" ================================================ FILE: projects/firefox/mozconfig.coverage ================================================ mk_add_options AUTOCLOBBER=1 ac_add_options --disable-debug ac_add_options --disable-elf-hack ac_add_options --disable-jemalloc ac_add_options --disable-crashreporter ac_add_options --enable-fuzzing ac_add_options --enable-optimize=-O1 ac_add_options --enable-debug-symbols=-gline-tables-only ================================================ FILE: projects/firefox/mozconfig.undefined ================================================ . $SRC/mozconfig.coverage ac_add_options --enable-undefined-sanitizer=bool,bounds,return,pointer-overflow,signed-integer-overflow,vla-bound mk_add_options CFLAGS= CXXFLAGS= ================================================ FILE: projects/firefox/project.yaml ================================================ homepage: "https://www.mozilla.org/firefox/" language: c++ main_repo: https://hg.mozilla.org/mozilla-central/ primary_contact: "choller@mozilla.com" auto_ccs: - twsmith@mozilla.com - sledru@mozilla.com vendor_ccs: - oss-fuzz@mozilla-fuzzing.iam.gserviceaccount.com fuzzing_engines: - libfuzzer sanitizers: - address run_tests: False # libraries from $OUT/firefox/dependentlibs.list coverage_extra_args: > -object firefox/firefox -object firefox/libnspr4.so -object firefox/libplc4.so -object firefox/libplds4.so -object firefox/libmozsandbox.so -object firefox/liblgpllibs.so -object firefox/libnssutil3.so -object firefox/libnss3.so -object firefox/libsmime3.so -object firefox/libmozsqlite3.so -object firefox/libssl3.so -object firefox/libmozgtk.so -object firefox/libxul.so ================================================ FILE: projects/firefox/target.c ================================================ #include #include #include #include #include #define STRINGLIT(S) #S #define STRINGIFY(S) STRINGLIT(S) // Required for oss-fuzz to consider the binary a target. static const char* magic __attribute__((used)) = "LLVMFuzzerTestOneInput"; int main(int argc, char* argv[]) { char path[PATH_MAX] = {0}; // Handle (currently not used) relative binary path. if (**argv != '/') { if (!getcwd(path, PATH_MAX - 1)) { perror("getcwd"); exit(1); } strcat(path, "/"); } if (strlen(path) + strlen(*argv) + 40 >= PATH_MAX) { fprintf(stderr, "Path length would exceed PATH_MAX\n"); exit(1); } strcat(path, *argv); char* solidus = strrchr(path, '/'); *solidus = 0; // terminate path before last / char ld_path[PATH_MAX] = {0}; strcpy(ld_path, path); strcat(ld_path, "/lib"); // Expects LD_LIBRARY_PATH to not also be set by oss-fuzz. setenv("LD_LIBRARY_PATH", ld_path, 0); setenv("HOME", "/tmp", 0); setenv("FUZZER", STRINGIFY(FUZZ_TARGET), 1); // ContentParentIPC char blacklist_path[PATH_MAX] = {0}; strcpy(blacklist_path, path); strcat(blacklist_path, "/firefox/libfuzzer.content.blacklist.txt"); setenv("MOZ_IPC_MESSAGE_FUZZ_BLACKLIST", blacklist_path, 1); // Temporary (or permanent?) work-arounds for fuzzing interface bugs. char* options = getenv("ASAN_OPTIONS"); if (options) { char* ptr; char* new_options = strdup(options); // https://bugzilla.mozilla.org/1477846 ptr = strstr(new_options, "detect_stack_use_after_return=1"); if (ptr) ptr[30] = '0'; // https://bugzilla.mozilla.org/1477844 ptr = strstr(new_options, "detect_leaks=1"); if (ptr) ptr[13] = '0'; setenv("ASAN_OPTIONS", new_options, 1); free(new_options); } char ff_path[PATH_MAX] = {0}; strcpy(ff_path, path); strcat(ff_path, "/firefox/firefox"); int ret = execv(ff_path, argv); if (ret) perror("execv"); return ret; } ================================================ FILE: projects/firestore/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool wget golang python python-protobuf python-six RUN git clone --depth 1 https://github.com/firebase/firebase-ios-sdk.git COPY build.sh $SRC/ ================================================ FILE: projects/firestore/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $WORK # Disable UBSan vptr since Firestore depends on other libraries that are built # with -fno-rtti. export CFLAGS="$CFLAGS -Wno-error=unknown-warning-option -fno-sanitize=vptr -Wno-error=missing-template-arg-list-after-template-kw -Wno-error=deprecated-builtins -Wno-error=deprecated-literal-operator" export CXXFLAGS="$CXXFLAGS -Wno-error=unknown-warning-option -fno-sanitize=vptr -Wno-error=missing-template-arg-list-after-template-kw -Wno-error=deprecated-builtins -Wno-error=deprecated-literal-operator" # Build the project using cmake with FUZZING option enabled to link to OSS Fuzz # fuzzing library defined in ${LIB_FUZZING_ENGINE}. cd $SRC/firebase-ios-sdk # Do not use Werror anywhere sed -i 's/-Werror=reorder//g' ./cmake/compiler_setup.cmake sed -i 's/-Werror=return-type//g' ./cmake/compiler_setup.cmake sed -i 's/-Wall -Wextra -Werror//g' ./cmake/compiler_setup.cmake sed -i 's/-Wuninitialized/#-Wu/g' ./cmake/compiler_setup.cmake sed -i 's/-Wfno-common/#-Wu/g' ./cmake/compiler_setup.cmake sed -i 's/-Werror//g' ./scripts/sync_project.rb sed -i 's/-Werror=reorder//g' ./FirebaseFirestore.podspec sed -i 's/ReadContext context/\/\/ReadContext/g' ./Firestore/fuzzing/serializer_fuzzer.cc sed -i 's/serializer.Dec/\/\/serializer/g' ./Firestore/fuzzing/serializer_fuzzer.cc mkdir build && cd build cmake -DFIREBASE_IOS_BUILD_TESTS=OFF -DFIREBASE_IOS_BUILD_BENCHMARKS=OFF -DFUZZING=ON .. make -j$(nproc) # Copy fuzzing targets, dictionaries, and zipped corpora to $OUT. FUZZERS_DIR=Firestore/fuzzing find ${FUZZERS_DIR} -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find ${FUZZERS_DIR} -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find ${FUZZERS_DIR} -name "*_fuzzer_seed_corpus" -type d -execdir zip -r ${OUT}/{}.zip {} ';' ================================================ FILE: projects/firestore/project.yaml ================================================ homepage: "https://firebase.google.com/docs/firestore/" language: c++ primary_contact: "varconst@google.com" auto_ccs: - "varconst@google.com" - "rgowman@google.com" sanitizers: - address - undefined main_repo: 'https://github.com/firebase/firebase-ios-sdk.git' ================================================ FILE: projects/flac/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool libtool-bin pkg-config gettext sudo default-jdk RUN git clone --depth 1 https://github.com/xiph/flac.git RUN git clone --depth 1 https://github.com/xiph/ogg.git RUN git clone --depth 1 https://github.com/google/ExoPlayer.git COPY fuzzer_exo.cpp $SRC/ COPY build.sh $SRC/ ================================================ FILE: projects/flac/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" if [[ $CFLAGS = *sanitize=address* ]] then export CXXFLAGS="$CXXFLAGS -DASAN" fi if [[ $CFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi export CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=0" export CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=0 -D_GLIBCXX_DEBUG" # Build libogg mkdir $SRC/libogg-install cd $SRC/ogg ./autogen.sh ./configure --disable-crc --disable-shared --prefix="$SRC/libogg-install" make -j$(nproc) make install # Build libflac cd $SRC/flac/ ./autogen.sh if [[ $CFLAGS = *sanitize=memory* ]] then LD_LIBRARY_PATH="$SRC/libogg-install/lib" ./configure --with-ogg="$SRC/libogg-install" --enable-static --disable-shared --disable-oggtest --disable-examples --disable-programs --disable-xmms-plugin --disable-asm-optimizations --disable-sse --enable-oss-fuzzers else LD_LIBRARY_PATH="$SRC/libogg-install/lib" ./configure --with-ogg="$SRC/libogg-install" --enable-static --disable-shared --disable-oggtest --disable-examples --disable-programs --disable-xmms-plugin --enable-oss-fuzzers fi make -j$(nproc) # Copy decoder fuzzers cd $SRC/flac/oss-fuzz cp fuzzer_* $OUT cd $SRC # Build fuzzer_exo $CXX $CXXFLAGS -I $SRC/flac/oss-fuzz/ -I $SRC/flac/include/ -I $SRC/ExoPlayer/extensions/flac/src/main/jni/ -I /usr/lib/jvm/java-11-openjdk-amd64/include/ -I /usr/lib/jvm/java-11-openjdk-amd64/include/linux/ fuzzer_exo.cpp \ $SRC/flac/src/libFLAC++/.libs/libFLAC++.a $SRC/flac/src/libFLAC/.libs/libFLAC.a $SRC/libogg-install/lib/libogg.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer_exo # Build libflac again for encoder fuzzers, but now with additional define cd $SRC/flac/ echo "#define FUZZING_BUILD_MODE_FLAC_SANITIZE_SIGNED_INTEGER_OVERFLOW" >> config.h make -j$(nproc) # Copy encoder fuzzers cd $SRC/flac/oss-fuzz cp fuzzer_encoder fuzzer_encoder_v2 $OUT # Copy seed corpus cd $SRC/flac/oss-fuzz/seedcorpus || exit 0 for fuzzerName in *; do zip -j $OUT/${fuzzerName}_seed_corpus.zip ${fuzzerName}/* done ================================================ FILE: projects/flac/fuzzer_exo.cpp ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "include/flac_parser.h" #include // #include #include #include #include #include "common.h" #define LOG_TAG "FLACParser" #define LITERAL_TO_STRING_INTERNAL(x) #x #define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x) #define CHECK(x) if (!(x)) return 0; const int endian = 1; #define isBigEndian() (*(reinterpret_cast(&endian)) == 0) // The FLAC parser calls our C++ static callbacks using C calling conventions, // inside FLAC__stream_decoder_process_until_end_of_metadata // and FLAC__stream_decoder_process_single. // We immediately then call our corresponding C++ instance methods // with the same parameter list, but discard redundant information. FLAC__StreamDecoderReadStatus FLACParser::read_callback( const FLAC__StreamDecoder * /* decoder */, FLAC__byte buffer[], size_t *bytes, void *client_data) { return reinterpret_cast(client_data) ->readCallback(buffer, bytes); } FLAC__StreamDecoderSeekStatus FLACParser::seek_callback( const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 absolute_byte_offset, void *client_data) { return reinterpret_cast(client_data) ->seekCallback(absolute_byte_offset); } FLAC__StreamDecoderTellStatus FLACParser::tell_callback( const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *absolute_byte_offset, void *client_data) { return reinterpret_cast(client_data) ->tellCallback(absolute_byte_offset); } FLAC__StreamDecoderLengthStatus FLACParser::length_callback( const FLAC__StreamDecoder * /* decoder */, FLAC__uint64 *stream_length, void *client_data) { return reinterpret_cast(client_data) ->lengthCallback(stream_length); } FLAC__bool FLACParser::eof_callback(const FLAC__StreamDecoder * /* decoder */, void *client_data) { return reinterpret_cast(client_data)->eofCallback(); } FLAC__StreamDecoderWriteStatus FLACParser::write_callback( const FLAC__StreamDecoder * /* decoder */, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) { return reinterpret_cast(client_data) ->writeCallback(frame, buffer); } void FLACParser::metadata_callback(const FLAC__StreamDecoder * /* decoder */, const FLAC__StreamMetadata *metadata, void *client_data) { reinterpret_cast(client_data)->metadataCallback(metadata); } void FLACParser::error_callback(const FLAC__StreamDecoder * /* decoder */, FLAC__StreamDecoderErrorStatus status, void *client_data) { reinterpret_cast(client_data)->errorCallback(status); } // These are the corresponding callbacks with C++ calling conventions FLAC__StreamDecoderReadStatus FLACParser::readCallback(FLAC__byte buffer[], size_t *bytes) { size_t requested = *bytes; ssize_t actual = mDataSource->readAt(mCurrentPos, buffer, requested); if (0 > actual) { *bytes = 0; return FLAC__STREAM_DECODER_READ_STATUS_ABORT; } else if (0 == actual) { *bytes = 0; mEOF = true; return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; } else { assert(actual <= requested); *bytes = actual; mCurrentPos += actual; return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; } } FLAC__StreamDecoderSeekStatus FLACParser::seekCallback( FLAC__uint64 absolute_byte_offset) { mCurrentPos = absolute_byte_offset; mEOF = false; return FLAC__STREAM_DECODER_SEEK_STATUS_OK; } FLAC__StreamDecoderTellStatus FLACParser::tellCallback( FLAC__uint64 *absolute_byte_offset) { *absolute_byte_offset = mCurrentPos; return FLAC__STREAM_DECODER_TELL_STATUS_OK; } FLAC__StreamDecoderLengthStatus FLACParser::lengthCallback( FLAC__uint64 *stream_length) { return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED; } FLAC__bool FLACParser::eofCallback() { return mEOF; } FLAC__StreamDecoderWriteStatus FLACParser::writeCallback( const FLAC__Frame *frame, const FLAC__int32 *const buffer[]) { if (mWriteRequested) { mWriteRequested = false; // FLAC parser doesn't free or realloc buffer until next frame or finish mWriteHeader = frame->header; mWriteBuffer = buffer; mWriteCompleted = true; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } else { return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } } void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) { switch (metadata->type) { case FLAC__METADATA_TYPE_STREAMINFO: if (!mStreamInfoValid) { mStreamInfo = metadata->data.stream_info; mStreamInfoValid = true; } else { break; } break; case FLAC__METADATA_TYPE_SEEKTABLE: mSeekTable = &metadata->data.seek_table; break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: if (!mVorbisCommentsValid) { FLAC__StreamMetadata_VorbisComment vorbisComment = metadata->data.vorbis_comment; for (FLAC__uint32 i = 0; i < vorbisComment.num_comments; ++i) { FLAC__StreamMetadata_VorbisComment_Entry vorbisCommentEntry = vorbisComment.comments[i]; if (vorbisCommentEntry.entry != NULL) { std::string comment( reinterpret_cast(vorbisCommentEntry.entry), vorbisCommentEntry.length); mVorbisComments.push_back(comment); } } mVorbisCommentsValid = true; } else { break; } break; case FLAC__METADATA_TYPE_PICTURE: { const FLAC__StreamMetadata_Picture *parsedPicture = &metadata->data.picture; FlacPicture picture; picture.mimeType.assign(std::string(parsedPicture->mime_type)); picture.description.assign( std::string((char *)parsedPicture->description)); picture.data.assign(parsedPicture->data, parsedPicture->data + parsedPicture->data_length); picture.width = parsedPicture->width; picture.height = parsedPicture->height; picture.depth = parsedPicture->depth; picture.colors = parsedPicture->colors; picture.type = parsedPicture->type; mPictures.push_back(picture); mPicturesValid = true; break; } default: break; } } void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status) { mErrorStatus = status; } // Copy samples from FLAC native 32-bit non-interleaved to // correct bit-depth (non-zero padded), interleaved. // These are candidates for optimization if needed. static void copyToByteArrayBigEndian(int8_t *dst, const int *const *src, unsigned bytesPerSample, unsigned nSamples, unsigned nChannels) { for (unsigned i = 0; i < nSamples; ++i) { for (unsigned c = 0; c < nChannels; ++c) { // point to the first byte of the source address // and then skip the first few bytes (most significant bytes) // depending on the bit depth const int8_t *byteSrc = reinterpret_cast(&src[c][i]) + 4 - bytesPerSample; memcpy(dst, byteSrc, bytesPerSample); dst = dst + bytesPerSample; } } } static void copyToByteArrayLittleEndian(int8_t *dst, const int *const *src, unsigned bytesPerSample, unsigned nSamples, unsigned nChannels) { for (unsigned i = 0; i < nSamples; ++i) { for (unsigned c = 0; c < nChannels; ++c) { // with little endian, the most significant bytes will be at the end // copy the bytes in little endian will remove the most significant byte // so we are good here. memcpy(dst, &(src[c][i]), bytesPerSample); dst = dst + bytesPerSample; } } } static void copyTrespass(int8_t * /* dst */, const int *const * /* src */, unsigned /* bytesPerSample */, unsigned /* nSamples */, unsigned /* nChannels */) { ; } // FLACParser FLACParser::FLACParser(DataSource *source) : mDataSource(source), mCopy(copyTrespass), mDecoder(NULL), mCurrentPos(0LL), mEOF(false), mStreamInfoValid(false), mSeekTable(NULL), firstFrameOffset(0LL), mVorbisCommentsValid(false), mPicturesValid(false), mWriteRequested(false), mWriteCompleted(false), mWriteBuffer(NULL), mErrorStatus((FLAC__StreamDecoderErrorStatus)-1) { memset(&mStreamInfo, 0, sizeof(mStreamInfo)); memset(&mWriteHeader, 0, sizeof(mWriteHeader)); } FLACParser::~FLACParser() { if (mDecoder != NULL) { FLAC__stream_decoder_delete(mDecoder); mDecoder = NULL; } } bool FLACParser::init() { // setup libFLAC parser mDecoder = FLAC__stream_decoder_new(); if (mDecoder == NULL) { // The new should succeed, since probably all it does is a malloc // that always succeeds in Android. But to avoid dependence on the // libFLAC internals, we check and log here. return false; } FLAC__stream_decoder_set_md5_checking(mDecoder, false); FLAC__stream_decoder_set_metadata_ignore_all(mDecoder); FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_STREAMINFO); FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_SEEKTABLE); FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_PICTURE); FLAC__StreamDecoderInitStatus initStatus; initStatus = FLAC__stream_decoder_init_stream( mDecoder, read_callback, seek_callback, tell_callback, length_callback, eof_callback, write_callback, metadata_callback, error_callback, reinterpret_cast(this)); if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) { // A failure here probably indicates a programming error and so is // unlikely to happen. But we check and log here similarly to above. return false; } return true; } bool FLACParser::decodeMetadata() { // parse all metadata if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) { return false; } // store first frame offset FLAC__stream_decoder_get_decode_position(mDecoder, &firstFrameOffset); if (mStreamInfoValid) { // check channel count if (getChannels() == 0 || getChannels() > 8) { return false; } // check bit depth switch (getBitsPerSample()) { case 8: case 16: case 24: case 32: break; default: return false; } // configure the appropriate copy function based on device endianness. if (isBigEndian()) { mCopy = copyToByteArrayBigEndian; } else { mCopy = copyToByteArrayLittleEndian; } } else { return false; } return true; } size_t FLACParser::readBuffer(void *output, size_t output_size) { mWriteRequested = true; mWriteCompleted = false; if (!FLAC__stream_decoder_process_single(mDecoder)) { return -1; } if (!mWriteCompleted) { if (FLAC__stream_decoder_get_state(mDecoder) != FLAC__STREAM_DECODER_END_OF_STREAM) { } return -1; } // verify that block header keeps the promises made by STREAMINFO unsigned blocksize = mWriteHeader.blocksize; if (blocksize == 0 || blocksize > getMaxBlockSize()) { return -1; } if (mWriteHeader.sample_rate != getSampleRate() || mWriteHeader.channels != getChannels() || mWriteHeader.bits_per_sample != getBitsPerSample()) { return -1; } unsigned bytesPerSample = getBitsPerSample() >> 3; size_t bufferSize = blocksize * getChannels() * bytesPerSample; if (bufferSize > output_size) { return -1; } // copy PCM from FLAC write buffer to our media buffer, with interleaving. (*mCopy)(reinterpret_cast(output), mWriteBuffer, bytesPerSample, blocksize, getChannels()); // fill in buffer metadata CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); return bufferSize; } bool FLACParser::getSeekPositions(int64_t timeUs, std::array &result) { if (!mSeekTable) { return false; } unsigned sampleRate = getSampleRate(); int64_t totalSamples = getTotalSamples(); int64_t targetSampleNumber = (timeUs * sampleRate) / 1000000LL; if (targetSampleNumber >= totalSamples) { targetSampleNumber = totalSamples - 1; } FLAC__StreamMetadata_SeekPoint* points = mSeekTable->points; unsigned length = mSeekTable->num_points; for (unsigned i = length; i != 0; i--) { int64_t sampleNumber = points[i - 1].sample_number; if (sampleNumber == -1) { // placeholder continue; } if (sampleNumber <= targetSampleNumber) { result[0] = (sampleNumber * 1000000LL) / sampleRate; result[1] = firstFrameOffset + points[i - 1].stream_offset; if (sampleNumber == targetSampleNumber || i >= length || points[i].sample_number == -1) { // placeholder // exact seek, or no following non-placeholder seek point result[2] = result[0]; result[3] = result[1]; } else { result[2] = (points[i].sample_number * 1000000LL) / sampleRate; result[3] = firstFrameOffset + points[i].stream_offset; } return true; } } result[0] = 0; result[1] = firstFrameOffset; result[2] = 0; result[3] = firstFrameOffset; return true; } namespace { class FuzzDataSource : public DataSource { const uint8_t *data_; size_t size_; public: FuzzDataSource(const uint8_t *data, size_t size) { data_ = data; size_ = size; } ssize_t readAt(off64_t offset, void *const data, size_t size) { if (offset > size_) return -1; size_t remaining = size_ - offset; if (remaining < size) size = remaining; memcpy(data, data_ + offset, size); return size; } }; } // namespace // Fuzz FLAC format and instrument the result as exoplayer JNI would: // https://github.com/google/ExoPlayer/blob/release-v2/extensions/flac/src/main/jni/ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzDataSource source(data, size); FLACParser parser(&source); // Early parsing if (!parser.init() || !parser.decodeMetadata()) return 0; auto streamInfo = parser.getStreamInfo(); // Similar implementation than ExoPlayer int buffer_size = streamInfo.max_blocksize * streamInfo.channels * 2; assert(buffer_size >= 0); // Not expected auto buffer = new uint8_t[buffer_size]; while (parser.readBuffer(buffer, buffer_size) < ((size_t)-1)); delete[] buffer; return 0; } ================================================ FILE: projects/flac/project.yaml ================================================ homepage: "https://xiph.org/flac/" language: c++ primary_contact: "mvanb1@gmail.com" auto_ccs: - "erik.de.castro.lopo@gmail.com" vendor_ccs: - "media-alerts@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 coverage_extra_args: -ignore-filename-regex=/usr/lib/jvm/.* main_repo: 'https://github.com/xiph/flac.git' ================================================ FILE: projects/flask/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y libffi-dev RUN python3 -m pip install --upgrade pip RUN git clone https://github.com/pallets/flask RUN git clone https://github.com/pallets/werkzeug RUN git clone https://github.com/corydolphin/flask-cors RUN git clone --depth=1 https://github.com/google/fuzzing/ RUN pip3 install markupsafe itsdangerous jinja2 COPY build.sh *.py $SRC/ ================================================ FILE: projects/flask/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build Werkzeug from latest cd $SRC/werkzeug pip3 install . # Build flask cd $SRC/flask python3 -m pip install importlib_metadata pip3 install . # Build flask-cors cd $SRC/flask-cors pip3 install requests pip3 install . # Build flask-cors fuzzers cd $SRC/flask-cors compile_python_fuzzer $SRC/cors_fuzz_flask.py # Build flask fuzzers # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done # Copy dictionaries out cp $SRC/fuzzing/dictionaries/http.dict $OUT/fuzz_werkzeug_http.dict ================================================ FILE: projects/flask/cors_fuzz_flask.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse import requests import threading import time import atheris with atheris.instrument_imports(): from flask import Flask from flask_cors import CORS from flask import request app = Flask(__name__) CORS(app) output = "" runs_left = None @app.errorhandler(500) def internal_error(error): print( "Catching exception error from flask. The exception is likely " "printed already right above this message in the log." ) return str(error), 500 @app.route("/") def fuzz_echo(): global output return output def shutdown_server(): func = request.environ.get('werkzeug.server.shutdown') if func is None: raise RuntimeError('Not running with the Werkzeug Server') func() # We use this to force a shutdown of the app. This is to # have a clean exit when a crash is found. @app.route('/shutdown') def shutdown(): shutdown_server() return "Server shutdown" class ServerThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): global app app.run() def TestOneInput(data): global output, runs_left output = data # We use runs_left to ensure proper exit in coverage. if runs_left != None: runs_left -= 1 # 5 may be too much here, as we will cut off some inputs. However, # this is to guarantee exit for now. if runs_left < 5: try: requests.get('http://127.0.0.1:5000/shutdown', timeout=1.02) except Exception: None return try: r = requests.get('http://127.0.0.1:5000', timeout=0.5) if r.status_code == 500: raise Exception(r.text) except requests.exceptions.ConnectionError: None except Exception as e: # Every other exception is raised, but we need to shutdown # the server before raising it. requests.get('http://127.0.0.1:5000/shutdown', timeout=1.02) raise e def get_run_count_if_there(): parser = argparse.ArgumentParser() parser.add_argument("-atheris_runs", required=False, default=None) args, _ = parser.parse_known_args() if args.atheris_runs is None: print("None args") return None print(f"Got a fixed set of runs {args.atheris_runs}") return args.atheris_runs def main(): global runs_left max_runs = get_run_count_if_there() if max_runs is not None: runs_left = int(max_runs) t1 = ServerThread() t1.start() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask/fuzz_json.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys, os with atheris.instrument_imports(): import flask from flask import Flask as _Flask from werkzeug.http import parse_set_header class FuzzFlask(_Flask): testing = True secret_key = "fuzz test key" def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) app = FuzzFlask("flask_test", root_path=os.path.dirname(__file__)) app.config["DEBUG"] = True app.config["TRAP_BAD_REQUEST_ERRORS"] = False @app.route("/json", methods=["POST"]) def post_json(): flask.request.get_json() return None parse_set_header(fdp.ConsumeUnicode(fdp.ConsumeIntInRange(0, 512))) client = app.test_client() try: app.add_url_rule( fdp.ConsumeUnicode(fdp.ConsumeIntInRange(0, 512)), endpoint = "randomendpoint" ) except ValueError: None try: client.post( "/json", data=fdp.ConsumeUnicode(fdp.ConsumeIntInRange(0, 512)), content_type="application/json" ) except (TypeError, UnicodeEncodeError): None def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask/fuzz_werkzeug_formparser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import io import sys with atheris.instrument_imports(): from werkzeug.formparser import FormDataParser from werkzeug.formparser import MultiPartParser def TestOneInput(data): parser = FormDataParser() parser.parse(io.BytesIO(data), "multipart/form-data", 0) parser.parse(io.BytesIO(data), "application/x-url-encoded", 0) parser.parse(io.BytesIO(data), "application/x-www-form-urlencoded", 0) multiparser = MultiPartParser(len(data)) try: multiparser.parse(io.BytesIO(data), b"", len(data)) except ValueError as e: if "Invalid form-data" in str(e): return raise e def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask/fuzz_werkzeug_http.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): import werkzeug.http as whttp def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: whttp.parse_content_range_header(fdp.ConsumeUnicode(100)) whttp.parse_range_header(fdp.ConsumeUnicode(100)) whttp.parse_set_header(fdp.ConsumeUnicode(100)) whttp.parse_etags(fdp.ConsumeUnicode(100)) whttp.parse_if_range_header(fdp.ConsumeUnicode(100)) whttp.parse_dict_header(fdp.ConsumeUnicode(100)) except ValueError as e: if "Bad range provided" in str(e): # https://github.com/pallets/werkzeug/blob/main/src/werkzeug/datastructures.py#L2580 # https://github.com/pallets/werkzeug/blob/main/src/werkzeug/datastructures.py#L2596 pass else: raise e def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask/fuzz_werkzeug_url.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import werkzeug def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: werkzeug.urls.iri_to_uri(fdp.ConsumeUnicode(30)) # except UnicodeEncodeError as e2: return except ValueError as e: if not "IPv6" in str(e): raise e def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pallets/flask language: python main_repo: https://github.com/pallets/flask sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/flask-jwt-extended/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/vimalloc/flask-jwt-extended flask-jwt-extended COPY *.sh *py $SRC/ WORKDIR $SRC/flask-jwt-extended ================================================ FILE: projects/flask-jwt-extended/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/flask-jwt-extended/fuzz_jwt.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import jwt import atheris from flask import Flask from flask import jsonify from flask_jwt_extended import create_access_token from flask_jwt_extended import decode_token from flask_jwt_extended import jwt_required from flask_jwt_extended import JWTManager from flask_jwt_extended import verify_jwt_in_request def get_app(key): """Helper method to get a flask app.""" app = Flask(__name__) app.config["JWT_SECRET_KEY"] = key if key != "" else "randomfuzzkey" app.config["JWT_TOKEN_LOCATION"] = ["query_string"] JWTManager(app) @app.route("/protected", methods=["GET"]) @jwt_required() def access_protected(): return jsonify(foo="bar") return app def test_encodings(data): fdp = atheris.FuzzedDataProvider(data) app = get_app(fdp.ConsumeUnicodeNoSurrogates(64)) with app.test_request_context(): token = create_access_token(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) decoded_token = decode_token(token) def test_get(data): fdp = atheris.FuzzedDataProvider(data) app = get_app(fdp.ConsumeUnicodeNoSurrogates(64)) @app.route("/custom", methods=["GET"]) def custom(): jwt_header, jwt_data = verify_jwt_in_request(optional=fdp.ConsumeBool(), fresh=fdp.ConsumeBool(), refresh=fdp.ConsumeBool()) if fdp.ConsumeBool(): return jsonify(foo=fdp.ConsumeUnicodeNoSurrogates(256)) else: return { fdp.ConsumeUnicodeNoSurrogates(124): fdp.ConsumeUnicodeNoSurrogates(124) } url = "/custom" test_client = app.test_client() with app.test_request_context(): try: token = create_access_token(fdp.ConsumeUnicodeNoSurrogates(256)) except jwt.exceptions.InvalidKeyError: return headers = {"Authorization": "Bearer {}".format(token)} response = test_client.get(url, headers=headers) # Get the json return from /custom response.get_json() def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) if fdp.ConsumeBool(): test_get(data) else: test_encodings(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask-jwt-extended/project.yaml ================================================ homepage: https://github.com/vimalloc/flask-jwt-extended main_repo: https://github.com/vimalloc/flask-jwt-extended language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/flask-restx/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN pip3 install --upgrade pip && pip3 install werkzeug==2.1.2 RUN git clone --depth 1 https://github.com/python-restx/flask-restx flask-restx WORKDIR flask-restx COPY build.sh *.py $SRC/ ================================================ FILE: projects/flask-restx/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed -i "s/werkzeug !=2.0.0/werkzeug ==2.1.2/g" ./requirements/install.pip cd $SRC/flask-restx pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/flask-restx/fuzz_reqparse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import traceback from werkzeug.wrappers import Request import flask from flask_restx.reqparse import RequestParser def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: req = Request.from_values(fdp.ConsumeUnicodeNoSurrogates(1024)) except: # We don't care about errors in werkzeug Request. return app = flask.Flask("fuzz") try: with app.app_context(): parser = RequestParser() parser.add_argument("ex1") parser.add_argument("ex2") # Parse arbitrary req parser.parse_args(req) except Exception as e2: tb = traceback.format_exc() # We don't care about werkzeug errors if "werkzeug" in str(tb): pass else: raise e2 def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask-restx/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/python-restx/flask-restx language: python main_repo: https://github.com/python-restx/flask-restx sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/flask-wtf/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip flask wtforms babel flask_babel RUN git clone https://github.com/wtforms/flask-wtf flask-wtf COPY *.sh *py $SRC/ WORKDIR $SRC/flask-wtf ================================================ FILE: projects/flask-wtf/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/flask-wtf/fuzz_flask_wtf.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from flask import Flask from flask_wtf.csrf import validate_csrf, generate_csrf from flask_wtf.i18n import translations from wtforms import ValidationError def get_app(fdp): """Helper method to get a flask app.""" app = Flask(__name__) key1 = fdp.ConsumeUnicodeNoSurrogates(124) key2 = fdp.ConsumeUnicodeNoSurrogates(124) app.secret_key = key1 if key1 != "" else "random key" app.config["WTF_CSRF_SECRET_KEY"] = key2 if key2 != "" else "random key 2" return app def fuzz_i18n(data): fdp = atheris.FuzzedDataProvider(data) translations.gettext(fdp.ConsumeUnicodeNoSurrogates(124)) translations.ngettext(fdp.ConsumeUnicodeNoSurrogates(124), fdp.ConsumeUnicodeNoSurrogates(124), 2) def fuzz_csrf(data): fdp = atheris.FuzzedDataProvider(data) app = get_app(fdp) with app.test_request_context(): try: validate_csrf( generate_csrf(secret_key=fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)), token_key=fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)))) except ValidationError: pass def TestOneInput(data): fuzz_i18n(data) fuzz_csrf(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/flask-wtf/project.yaml ================================================ homepage: https://github.com/wtforms/flask-wtf/ main_repo: https://github.com/wtforms/flask-wtf/ language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/flatbuffers/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone https://github.com/google/flatbuffers WORKDIR $SRC/ COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/flatbuffers/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build fuzzer only cd $SRC/flatbuffers mkdir build cd build cmake -DOSS_FUZZ:BOOL=ON -G "Unix Makefiles" ../tests/fuzzer make cp ../tests/fuzzer/*.dict $OUT/ cp *.bfbs $OUT/ cp *_fuzzer $OUT/ # Build unit test mkdir $SRC/flatbuffers/build-tests cd $SRC/flatbuffers/build-tests cmake -DFLATBUFFERS_BUILD_FLATC=ON -DFLATBUFFERS_BUILD_TESTS=ON .. make flattests -j$(nproc) ================================================ FILE: projects/flatbuffers/project.yaml ================================================ homepage: "https://github.com/google/flatbuffers" language: c++ primary_contact: "derekbailey@google.com" auto_ccs: - "Adam@adalogics.com" - "vglavnyy@gmail.com" sanitizers: - address - memory - undefined main_repo: 'https://github.com/google/flatbuffers' file_github_issue: True fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/flatbuffers/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir $SRC/flatbuffers/build-tests -j$(nproc) ================================================ FILE: projects/flate2-rs/Dockerfile ================================================ # Copyright 2021 Google LL # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/rust-lang/flate2-rs WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/flate2-rs/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/flate2-rs cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_gz_roundtrip $OUT/fuzz_gz_roundtrip ================================================ FILE: projects/flate2-rs/project.yaml ================================================ homepage: "https://github.com/rust-lang/flate2-rs" main_repo: "https://github.com/rust-lang/flate2-rs" primary_contact: "david@adalogics.com" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "alex@alexcrichton.com" ================================================ FILE: projects/flex/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool m4 \ gettext help2man bison autopoint \ lzip texinfo texlive flex RUN git clone --depth 1 https://github.com/westes/flex flex WORKDIR flex COPY build.sh *.c *.diff *.options $SRC/ ================================================ FILE: projects/flex/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" ./autogen.sh ./configure make V=1 git apply $SRC/flex-patch.diff cd src $CC $CFLAGS -c main.c -DM4=2 -o main.o cd ../ # Remove some object files we dont need. This is needed because we will link to # all othero bject files in the src folder. mv ./src/stage1*.o /tmp/ || true mv ./src/libmain.o /tmp/ || true mv ./src/flex-main.o /tmp/ || true mv ./src/libyywrap.o /tmp/ || true $CC $CFLAGS -c $SRC/fuzz-scanopt.c -I$SRC/flex/src $CC $CFLAGS -c src/scan.c -I$SRC/flex/src $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./fuzz-scanopt.o ./src/*.o -o $OUT/fuzz-scanopt scan.o $CC $CFLAGS -c $SRC/fuzz-main.c -I$SRC/flex/src $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./fuzz-main.o ./src/*.o -o $OUT/fuzz-main scan.o cp $SRC/*.options $OUT/ ================================================ FILE: projects/flex/flex-patch.diff ================================================ diff --git a/src/main.c b/src/main.c index eb2c09f..bab11db 100644 --- a/src/main.c +++ b/src/main.c @@ -38,7 +38,7 @@ #include "tables.h" #include "parse.h" -static char flex_version[] = FLEX_VERSION; +static char flex_version[] ="ran";// FLEX_VERSION; /* declare functions that have forward references */ @@ -144,17 +144,18 @@ int flex_main (int argc, char *argv[]) fflush(stdout); fclose(stdout); } + return 0; + /* while (wait(&child_status) > 0){ if (!WIFEXITED (child_status) || WEXITSTATUS (child_status) != 0){ - /* report an error of a child - */ if( exit_status <= 1 ) exit_status = 2; } } return exit_status - 1; + */ } flexinit (argc, argv); @@ -271,7 +272,7 @@ int flex_main (int argc, char *argv[]) } /* Wrapper around flex_main, so flex_main can be built as a library. */ -int main (int argc, char *argv[]) +int main2 (int argc, char *argv[]) { #if defined(ENABLE_NLS) && ENABLE_NLS #if HAVE_LOCALE_H @@ -293,7 +294,7 @@ void initialize_output_filters(void) output_chain = filter_create_int(NULL, filter_tee_header, env.headerfilename); if ( !(m4 = getenv("M4"))) { - m4 = M4; + m4 = NULL; } filter_create_ext(output_chain, m4, "-P", (char *) 0); filter_create_int(output_chain, filter_fix_linedirs, NULL); ================================================ FILE: projects/flex/fuzz-main.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "flexdef.h" #include "options.h" #include "scanopt.h" char *my_argv[3]; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); my_argv[0] = "/tmp/fakefuzzer"; my_argv[1] = filename; my_argv[2] = NULL; flex_main(2, my_argv); unlink(filename); return 0; } ================================================ FILE: projects/flex/fuzz-main.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/flex/fuzz-scanopt.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "flexdef.h" #include "options.h" #include "scanopt.h" char *my_argv[4]; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 24) { return 0; } char *opt_fuzz = malloc(24); memcpy(opt_fuzz, data, 23); opt_fuzz[23] = 0; data += 23; size -= 23; char *new_str = (char *)malloc(size + 1); if (new_str == NULL) { return 0; } memcpy(new_str, data, size); new_str[size] = '\0'; my_argv[0] = "/tmp/fuzz/"; my_argv[1] = opt_fuzz; my_argv[2] = new_str; my_argv[3] = NULL; scanopt_t sopt; sopt = scanopt_init(flexopts, 3, my_argv, 0); if (!sopt) { free(new_str); free(opt_fuzz); return 0; } int optind; char *arg; scanopt(sopt, &arg, &optind); scanopt_destroy(sopt); free(new_str); free(opt_fuzz); return 0; } ================================================ FILE: projects/flex/project.yaml ================================================ homepage: "https://github.com/westes/flex" main_repo: "https://github.com/westes/flex" language: c vendor_ccs: - "david@adalogics.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/fluent-bit/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make cmake flex bison libssl-dev libyaml-dev RUN git clone --depth 1 https://github.com/fluent/fluent-bit/ fluent-bit # Update the libs in fluent-bit to use the latest patches for optimizing fuzzing workflow RUN cd $SRC/fluent-bit/lib && \ rm -rf ./ctraces && \ git clone --depth 1 https://github.com/fluent/ctraces ctraces && \ rm -rf ./cmetrics && \ git clone --depth 1 https://github.com/fluent/cmetrics WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/fluent-bit/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ find /usr/ -name "libyaml*.so" -exec rm {} \; find /usr/ -name "libyaml-0*" -exec rm {} \; # For fuzz-introspector, cxclude all functions in the fluent-bit/lib/ directory export FUZZ_INTROSPECTOR_CONFIG=$SRC/fuzz_introspector_exclusion.config cat > $FUZZ_INTROSPECTOR_CONFIG < 0xa00000) return NULL;\nreturn malloc(size);}\nstruct msgpack_zone_chunk {/g' ./lib/msgpack-c/src/zone.c fi # Remove the existing build, which makes it more convenient to build # fuzzers with multiple sanitizers using the same working directory. rm -rf ./build mkdir build cd build export CFLAGS="$CFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON" export CXXFLAGS="$CXXFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON" # Plugins enabled/disabled INPUT_PLUGINS="-DFLB_IN_COLLECTD=OFF \ -DFLB_IN_CPU=OFF \ -DFLB_IN_DISK=OFF \ -DFLB_IN_DOCKER=OFF \ -DFLB_IN_EXEC=OFF \ -DFLB_IN_FORWARD=OFF \ -DFLB_IN_HEAD=OFF \ -DFLB_IN_HEALTH=OFF \ -DFLB_IN_KMSG=OFF \ -DFLB_IN_MEM=OFF \ -DFLB_IN_MQTT=OFF \ -DFLB_IN_NETIF=OFF \ -DFLB_IN_PROC=OFF \ -DFLB_IN_RANDOM=OFF \ -DFLB_IN_SERIAL=OFF \ -DFLB_IN_STDIN=OFF \ -DFLB_IN_SYSLOG=OFF \ -DFLB_IN_SYSTEMD=OFF \ -DFLB_IN_TAIL=OFF \ -DFLB_IN_TCP=OFF \ -DFLB_IN_THERMAL=OFF \ -DFLB_IN_WINLOG=OFF" OUTPUT_PLUGINS="-DFLB_OUT_AZURE=OFF \ -DFLB_OUT_BIGQUERY=OFF \ -DFLB_OUT_COUNTER=OFF \ -DFLB_OUT_DATADOG=OFF \ -DFLB_OUT_ES=OFF \ -DFLB_OUT_FILE=OFF \ -DFLB_OUT_FLOWCOUNTER=OFF \ -DFLB_OUT_FORWARD=OFF \ -DFLB_OUT_GELF=OFF \ -DFLB_OUT_HTTP=ON \ -DFLB_OUT_INFLUXDB=OFF \ -DFLB_OUT_KAFKA=OFF \ -DFLB_OUT_KAFKA_REST=OFF \ -DFLB_OUT_LOKI=OFF \ -DFLB_OUT_NATS=OFF \ -DFLB_OUT_NRLOGS=OFF \ -DFLB_OUT_NULL=OFF \ -DFLB_OUT_PGSQL=OFF \ -DFLB_OUT_PLOT=OFF \ -DFLB_OUT_SLACK=OFF \ -DFLB_OUT_SPLUNK=OFF \ -DFLB_OUT_STACKDRIVER=OFF \ -DFLB_OUT_STDOUT=ON \ -DFLB_OUT_SYSLOG=OFF \ -DFLB_OUT_TCP=OFF" MISC_PLUGINS="-DFLB_LUAJIT=OFF \ -DFLB_STREAM_PROCESSOR=OFF" FILTER_PLUGINS="-DFLB_FILTER_ALTER_SIZE=ON \ -DFLB_FILTER_AWS=ON \ -DFLB_FILTER_GREP=ON \ -DFLB_FILTER_KUBERNETES=ON \ -DFLB_FILTER_MODIFY=ON \ -DFLB_FILTER_NEST=ON \ -DFLB_FILTER_PARSER=ON \ -DFLB_FILTER_RECORD_MODIFIER=ON \ -DFLB_FILTER_REWRITE_TAG=ON \ -DFLB_FILTER_THROTTLE=ON" EXTRA_FLAGS="-DFLB_BINARY=OFF \ -DFLB_EXAMPLES=OFF \ -DFLB_METRICS=ON \ -DFLB_DEBUG=ON \ -DMBEDTLS_FATAL_WARNINGS=OFF \ -DFLB_CONFIG_YAML=ON" cmake -DFLB_TESTS_INTERNAL=ON \ -DFLB_TESTS_INTERNAL_FUZZ=ON \ -DFLB_TESTS_OSSFUZZ=ON \ ${EXTRA_FLAGS} \ ${INPUT_PLUGINS} \ ${FILTER_PLUGINS} \ ${MISC_PLUGINS} \ ${OUTPUT_PLUGINS} \ .. if [[ "$SANITIZER" == introspector ]]; then make else make -j$(nproc) fi cp $SRC/fluent-bit/build/bin/*OSSFUZZ ${OUT}/ # Add seeds to config-yaml fuzzer mkdir -p $SRC/config_yaml_seeds cd $SRC/config_yaml_seeds find $SRC/fluent-bit/tests/internal/data/config_format/yaml -name "*.yaml" -exec cp {} . \; zip -rj $OUT/flb-it-fuzz-config_yaml_fuzzer_OSSFUZZ_seed_corpus.zip $SRC/config_yaml_seeds/* ================================================ FILE: projects/fluent-bit/project.yaml ================================================ homepage: "https://github.com/fluent/fluent-bit" primary_contact: "edsiper@gmail.com" language: c++ base_os_version: ubuntu-24-04 auto_ccs: - "david@adalogics.com" - "wppttt@amazon.com" - "zh0512xx@gmail.com" - "leonardo@calyptia.com" main_repo: 'https://github.com/fluent/fluent-bit/' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/fluxcd/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go ENV GOPATH="${GOPATH:-/root/go}" ENV ORG_ROOT="${ORG_ROOT:-${GOPATH}/src/github.com/fluxcd}" RUN mkdir -p "${ORG_ROOT}" # Flux has its components scattered around multiple repositories due to its architecture. # Here we clone all of them. The build process happens as build.sh iterate over each one of them. ARG REPOSITORIES="pkg notification-controller kustomize-controller helm-controller image-reflector-controller source-controller image-automation-controller" RUN for repo in ${REPOSITORIES}; do git clone --depth 1 "https://github.com/fluxcd/${repo}" "${ORG_ROOT}/${repo}"; done COPY build.sh $SRC/ WORKDIR $SRC ================================================ FILE: projects/fluxcd/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This code improves the use of Go Native by: # - Dynamically discovering and building all fuzz tests within the project root path. # - Supporting single (during PR checks) or multiple repositories (oss-fuzz). # - Enabling execution via CI builds and Makefile targets for each repo. GOPATH="${GOPATH:-/root/go}" ORG_ROOT="${ORG_ROOT:-${GOPATH}/src/github.com/fluxcd}" PREBUILD_SCRIPT_PATH="${PREBUILD_SCRIPT_PATH:-tests/fuzz/oss_fuzz_prebuild.sh}" POSTBUILD_SCRIPT_PATH="${POSTBUILD_SCRIPT_PATH:-tests/fuzz/oss_fuzz_postbuild.sh}" # source_prebuild_script sources the prebuild script, which executes project-specific # code and exposes environment variables that are needed during the generic build process. # # Examples of usage may be organising directory structure for embedding # files, downloading artifacts or setting environment variables. function source_prebuild_script(){ if [ -f "${PREBUILD_SCRIPT_PATH}" ]; then # shellcheck source=/dev/null . "${PREBUILD_SCRIPT_PATH}" fi } # source_postbuild_script sources the postbuild script, which executes project-specific # code and unset environment variables that may break follow-up processes. function source_postbuild_script(){ if [ -f "${POSTBUILD_SCRIPT_PATH}" ]; then # shellcheck source=/dev/null . "${POSTBUILD_SCRIPT_PATH}" fi } # go_native_build_all_fuzzers builds all Go Native fuzz tests defined in modules within # the given project dir. # # Args: # project_dir function go_native_build_all_fuzzers(){ local project_path="$1" cd "${project_path}" source_prebuild_script modules=$(find . -mindepth 1 -maxdepth 4 -type f -name 'go.mod' | cut -c 3- | sed 's|/[^/]*$$||' | sort -u | sed 's;/go.mod;;g' | sed 's;go.mod;.;g') for module in ${modules}; do cd "${project_path}/${module}" local test_files test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . || echo "") if [ -z "${test_files}" ]; then continue fi # go-118-fuzz-build is required for each module. go get -u github.com/AdamKorcz/go-118-fuzz-build/testing # The go get command above can affect transient dependencies, may lead # to the go.sym to become out of sync, which would cause build to break. # go mod tidy will only work if the current module has a reference # to the above dependency, so we create one. local pkgName pkgName="$(grep -h '^package ' -- *.go | head -n 1)" if [ -z "${test_files}" ]; then pkgName="package fuzz" fi cat < dep-placeholder.go ${pkgName} import _ "github.com/AdamKorcz/go-118-fuzz-build/testing" EOF # With the reference above, this updates go.sum. go mod tidy # Iterate through all Go Fuzz targets, compiling each into a fuzzer. for file in ${test_files}; do # If the subdir is a module, skip this file, as it will be handled # at the next iteration of the outer loop. if [ -f "$(dirname "${file}")/go.mod" ]; then continue fi targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}") for target_name in ${targets}; do local module_name local fuzzer_name local target_dir # Transform module path into module name (e.g. git/libgit2 to git_libgit2). module_name="${module/\//_}_" # If module equal '._', use empty string instead. module_name="${module/#%._}" # Compose fuzzer name based on the lowercase version of the func names. fuzzer_name="${target_name,,}" # The module name is added after the fuzz prefix, for better discoverability. fuzzer_name="${target_name/fuzz_/fuzz_${module_name}}" target_dir=$(dirname "${file}") echo "Building ${file}.${target_name} into ${fuzzer_name}" compile_native_go_fuzzer "${target_dir}" "${target_name}" "${fuzzer_name}" done done done } function loop_through_org_repositories(){ local repos="" repos="$(find "${ORG_ROOT}" -type d -mindepth 1 -maxdepth 1)" for repo in ${repos}; do go_native_build_all_fuzzers "${repo}" done } function main(){ # If SRC is set to a Flux project, only its fuzzers will be built. if grep -h '^module github.com/fluxcd/' "${SRC}/go.mod"; then echo "Building Go Native fuzzers for ${SRC}" go_native_build_all_fuzzers "${SRC}" exit $? fi echo "Going through all repositories in ${ORG_ROOT}" loop_through_org_repositories } main ================================================ FILE: projects/fluxcd/project.yaml ================================================ homepage: "https://fluxcd.io/" main_repo: "https://github.com/fluxcd/flux2" primary_contact: "cncf-flux-security@lists.cncf.io" auto_ccs : - "hidde@weave.works" - "scott@r6by.com" - "david@adalogics.com" - "adam@adalogics.com" - "max@e13.dev" - "matheuscscp@gmail.com" - "stefan.prodan@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/flyway/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone https://github.com/DataGrip/mongo-jdbc-driver RUN git clone --depth 1 https://github.com/flyway/flyway flyway COPY *.sh *.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/flyway/LocationFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import java.util.regex.PatternSyntaxException; import org.flywaydb.core.api.FlywayException; import org.flywaydb.core.api.Location; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-11 // Heuristic name: jvm-autofuzz-heuristics-11 // Target method: [org.flywaydb.core.api.Location] public (java.lang.String) public class LocationFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { new Location(data.consumeRemainingAsString()); } catch (FlywayException e) { // Known exception } } } ================================================ FILE: projects/flyway/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## # Install mongo-jdbc-dependency required byu flyway cd mongo-jdbc-driver/ git checkout v1.21 ./gradlew clean shadowJar $MVN install:install-file \ -Dfile=../mongo-jdbc-driver/build/libs/mongo-jdbc-standalone-1.21.jar \ -DgroupId=com.github.kornilova203 -DartifactId=mongo-jdbc-driver \ -Dversion=1.21 -Dpackaging=jar -DgeneratePom=true # Buuild flyway cd ../flyway $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True dependency:copy-dependencies -fn JARFILE_LIST= for JARFILE in $(find ./ -name *.jar) do if [[ "$JARFILE" == *"target/"* ]] || [[ "$JARFILE" == *"build/"* ]] || [[ "$JARFILE" == *"dist/"* ]] then if [[ "$JARFILE" != *sources.jar ]] && [[ "$JARFILE" != *javadoc.jar ]] && [[ "$JARFILE" != *tests.jar ]] then cp $JARFILE $OUT/ JARFILE_LIST="$JARFILE_LIST$(basename $JARFILE) " fi fi done curr_dir=$(pwd) rm -rf $OUT/jar_temp mkdir $OUT/jar_temp cd $OUT/jar_temp for JARFILE in $JARFILE_LIST do jar -xf $OUT/$JARFILE done cd $curr_dir BUILD_CLASSPATH=$JAZZER_API_PATH:$OUT/jar_temp RUNTIME_CLASSPATH=\$this_dir/jar_temp:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/flyway/project.yaml ================================================ homepage: https://github.com/flyway/flyway main_repo: https://github.com/flyway/flyway language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/fmt/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN echo "CXX=$CXX" RUN echo "CXXFLAGS=$CXXFLAGS" RUN apt-get update && apt-get install -y cmake ninja-build RUN git clone --depth 1 --branch master \ https://github.com/fmtlib/fmt.git WORKDIR fmt COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/fmt/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #create zip files with initial corpus, taken from version control. #for f in $(ls fuzzers/initial_corpus/) ;do # zip -j -r $OUT/fuzzer_${f}_seed_corpus.zip fuzzers/initial_corpus/$f #done mkdir build cd build # use C++ 14 instead of 17, because even if clang is # bleeding edge, cmake is old in the oss fuzz image. cmake .. \ -GNinja \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_CXX_STANDARD=14 \ -DFMT_DOC=Off \ -DFMT_TEST=On \ -DFMT_SAFE_DURATION_CAST=On \ -DFMT_FUZZ=On \ -DFMT_FUZZ_LINKMAIN=Off \ -DFMT_FUZZ_LDFLAGS=$LIB_FUZZING_ENGINE cmake --build . cp bin/*fuzzer $OUT ================================================ FILE: projects/fmt/project.yaml ================================================ homepage: "https://github.com/fmtlib/fmt" language: c++ primary_contact: "pauldreikossfuzz@gmail.com" auto_ccs: - "victor.zverovich@gmail.com" main_repo: 'https://github.com/fmtlib/fmt.git' ================================================ FILE: projects/fmt/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd build ninja test ================================================ FILE: projects/fontations/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Based on https://google.github.io/oss-fuzz/getting-started/new-project-guide/rust-lang/ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/googlefonts/fontations WORKDIR $SRC/fontations COPY build.sh $SRC/ ================================================ FILE: projects/fontations/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # To test: # export SRC=/tmp # export OUT=/tmp # git clone --depth 1 https://github.com/googlefonts/fontations /tmp/fontations # rm -rf /tmp/{font_srcs,corpus_tmp} # projects/fontations/build.sh CLONE_TMP="$SRC/font_srcs" CORPUS_TMP="$SRC/corpus_tmp" mkdir "$CLONE_TMP" mkdir "$CORPUS_TMP" pushd "$CLONE_TMP" git clone --depth 1 https://github.com/unicode-org/text-rendering-tests.git git clone --depth 1 https://github.com/googlefonts/color-fonts.git git clone --depth 1 https://github.com/harfbuzz/harfbuzz.git for d in text-rendering-tests/fonts color-fonts/fonts harfbuzz/test; do find $d -name '*.[ot]t[fc]' -execdir cp {} ${CORPUS_TMP} \; done popd pushd "$CORPUS_TMP" zip seed_corpus.zip * popd cd $SRC/fontations # Add +nightly after cargo if running locally and getting: error: the option `Z` is only accepted on the nightly compiler cargo fuzz build -O --debug-assertions # Based on zip-rs RELEASE_DIR=target/x86_64-unknown-linux-gnu/release num_fuzzers=0 for fuzzer in $(find $RELEASE_DIR -maxdepth 1 -type f -executable -name 'fuzz_*' -exec basename {} \;); do cp -v "$CORPUS_TMP/seed_corpus.zip" $(basename $fuzzer)_seed_corpus.zip cp -v "$RELEASE_DIR/$fuzzer" $OUT/ num_fuzzers=$((num_fuzzers+1)) done # If we found 0 fuzzers something is very wrong [[ "$num_fuzzers" -gt 0 ]] || { echo "No fuzzers!"; exit 1; } ================================================ FILE: projects/fontations/project.yaml ================================================ homepage: "https://github.com/googlefonts/fontations" language: rust primary_contact: "rsheeter@google.com" auto_ccs: - "drott@google.com" - "grieger@google.com" - "colin.rofls@gmail.com" - "cbrokaw@google.com" - "clupo@google.com" - "behdad.esfahbod@gmail.com" - "qxliu@google.com" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: 'https://github.com/googlefonts/fontations' ================================================ FILE: projects/freeimage/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool wget dos2unix RUN svn checkout https://svn.code.sf.net/p/freeimage/svn/ freeimage-svn WORKDIR $SRC/freeimage-svn/FreeImage/trunk/ RUN wget "https://salsa.debian.org/debian-phototools-team/jxrlib/-/raw/7e12ab1185b347c0edfd893471c055e3ae7830b5/debian/patches/082bb032be1f6c75173bf603252e4f37bfded9fa.patch" --output-document=$SRC/jxrlib_tmpnam.patch COPY run_tests.sh build.sh $SRC/ COPY load_from_memory_fuzzer.cc $SRC/ ================================================ FILE: projects/freeimage/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # b44ExpLogTable.cpp only contains a definition of main(). sed -i 's/Source\/OpenEXR\/IlmImf\/b44ExpLogTable.cpp//' Makefile.srcs sed -i 's/Source\/LibTIFF4\/tif_getimage.c/Source\/LibTIFF4\/tif_getimage.c Source\/LibTIFF4\/tif_hash_set.c/g' ./Makefile.srcs export CXXFLAGS="$CXXFLAGS -std=c++14" # Avoid C++17 build error ( # Avoid tmpnam link error cd Source/LibJXR dos2unix ./image/encode/strenc.c patch -p1 -i $SRC/jxrlib_tmpnam.patch ) make LIBRARIES=-lc++ -j$(nproc) -f Makefile.gnu libfreeimage.a INSTALL_DIR=$PWD cd $SRC $CXX $CXXFLAGS -I${INSTALL_DIR}/ -I${INSTALL_DIR}/Source $LIB_FUZZING_ENGINE \ load_from_memory_fuzzer.cc ${INSTALL_DIR}/libfreeimage.a \ -o $OUT/load_from_memory_fuzzer # Build unit testing when it is not coverage or introspector build # Temporarily skipping testMemIO and testThumbnail because both of them throws ASAN crash of heap overflow if [[ "$SANITIZER" != "introspector" && "$SANITIZER" != "coverage" ]] then cd $SRC/freeimage-svn/FreeImage/trunk/TestAPI sed -i 's#testMemIO#//testMemIO#g' MainTestSuite.cpp sed -i 's#testThumbnail#//testThumbnail#g' MainTestSuite.cpp $CXX $CXXFLAGS -I../Source MainTestSuite.cpp testChannels.cpp testHeaderOnly.cpp testImageType.cpp testJPEG.cpp \ testMPage.cpp testMPageMemory.cpp testMPageStream.cpp testPlugins.cpp testTools.cpp testWrappedBuffer.cpp \ ../libfreeimage.a -fsanitize=$SANITIZER -o testAPI fi ================================================ FILE: projects/freeimage/load_from_memory_fuzzer.cc ================================================ #include #include #include #include #include namespace { // Returns true if the format should be attempted to loaded from memory. bool SafeToLoadFromMemory(FREE_IMAGE_FORMAT fif) { // For now, just load if it is a BMP. Future heuristics may need to be based // on the expected size in different formats for memory regions to avoid OOMs. return fif == FIF_BMP; } } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static bool initialized = false; if (!initialized) { FreeImage_Initialise(); } if (size > 100 * 1000) { return 0; } std::vector fuzzer_data_vector(data, data + size); FIMEMORY* fiMem = FreeImage_OpenMemory( reinterpret_cast(fuzzer_data_vector.data()), fuzzer_data_vector.size()); FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(fiMem, 0); if (SafeToLoadFromMemory(fif)) { FIBITMAP* fiBitmap = FreeImage_LoadFromMemory(fif, fiMem); FreeImage_Unload(fiBitmap); } FreeImage_CloseMemory(fiMem); return 0; } ================================================ FILE: projects/freeimage/project.yaml ================================================ homepage: "http://freeimage.sourceforge.net/" main_repo: 'https://svn.code.sf.net/p/freeimage/svn/' language: c++ primary_contact: "drolon@infonie.fr" sanitizers: - address - undefined labels: load_from_memory_fuzzer: - sundew fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/freeimage/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/freeimage-svn/FreeImage/trunk/TestAPI && ./testAPI ================================================ FILE: projects/freeradius/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y gnupg RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys BE18FC5A41382202 RUN echo "deb http://packages.networkradius.com/extras/ubuntu/focal focal main" > /etc/apt/sources.list.d/networkradius-extras.list RUN apt-get update && apt-get install -y libtalloc-dev libkqueue-dev libunwind-dev libjson-c-dev # OpenSSL 3.0 ARG OPENSSL_VERSION=3.0.15 ARG OPENSSL_HASH=23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533 RUN set -ex \ && curl -s -L -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \ && echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \ && tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \ && cd openssl-${OPENSSL_VERSION} \ && ./Configure linux-x86_64 no-shared no-module --static "$CFLAGS" \ && make build_generated \ && make libcrypto.a \ && make install ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION} RUN git clone --depth 1 https://github.com/FreeRADIUS/freeradius-server.git COPY build.sh $SRC/ # COPY patch.diff $SRC WORKDIR $SRC/freeradius-server ================================================ FILE: projects/freeradius/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ function copy_lib { local fuzzer_path=$1 local lib=$2 cp $(ldd ${fuzzer_path} | grep "${lib}" | awk '{ print $3 }') ${OUT}/lib } mkdir -p $OUT/lib # git apply --ignore-whitespace $SRC/patch.diff # build project ./configure --enable-fuzzer --enable-coverage --enable-address-sanitizer # make tries to compile regular programs as fuzz targets # so -i flag ignores these errors make -i -j$(nproc) make -i install # use shared libraries ldconfig ls ./build/bin/local/fuzzer_* | while read i; do patchelf --set-rpath '$ORIGIN/lib' ${i} copy_lib ${i} libfreeradius copy_lib ${i} talloc copy_lib ${i} kqueue copy_lib ${i} libunwind cp ${i} $OUT/ done cp -r /usr/local/share/freeradius/dictionary $OUT/dict # export FR_DICTIONARY_DIR=/out/dictionary/ # export FR_LIBRARY_PATH=/out/lib/ ================================================ FILE: projects/freeradius/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://freeradius.org" language: c++ primary_contact: "a.cudbardb@gmail.com" auto_ccs: - "adekok@gmail.com" - "p.antoine@catenacyber.fr" - "arthur.chan@adalogics.com" - "david@adalogics.com" - "adam@adalogics.com" main_repo: 'https://github.com/FreeRADIUS/freeradius-server.git' fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/freerdp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # See https://github.com/FreeRDP/FreeRDP/wiki/Compilation # Install Git and base dependences. RUN apt-get update && apt-get install -y devscripts equivs \ build-essential git-core cmake ninja-build pkg-config ccache RUN git clone --depth 1 https://github.com/FreeRDP/FreeRDP.git WORKDIR FreeRDP # Install all dependencies required by the nightly package. RUN mk-build-deps --install --tool 'apt-get --yes --no-remove --no-install-recommends' packaging/deb/freerdp-nightly/control COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/freerdp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Avoid compilation issue due to some undefined references. They are defined in # libc++ and used by Centipede so -lc++ needs to come after centipede's lib. if [[ $FUZZING_ENGINE == centipede ]] then sed -i \ '/$ENV{LIB_FUZZING_ENGINE}/a \ \ \ \ \ \ \ \ -lc++' \ cmake/ConfigOptions.cmake fi case $SANITIZER in address) SANITIZERS_ARGS="-DWITH_SANITIZE_ADDRESS=ON" ;; memory) SANITIZERS_ARGS="-DWITH_SANITIZE_MEMORY=ON" ;; *) SANITIZERS_ARGS="" ;; esac : ${LD:="${CXX}"} : ${LDFLAGS:="${CXXFLAGS}"} # to make sure we link with sanitizer runtime cmake_args=( # clang-15 segfaults on linking binaries when LTO is enabled, # see https://github.com/google/oss-fuzz/pull/10448#issuecomment-1578160436 -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF $SANITIZERS_ARGS -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF # C compiler -DCMAKE_C_COMPILER="${CC}" -DCMAKE_C_FLAGS="${CFLAGS}" # C++ compiler -DCMAKE_CXX_COMPILER="${CXX}" -DCMAKE_CXX_FLAGS="${CXXFLAGS}" # Linker -DCMAKE_LINKER="${LD}" -DCMAKE_EXE_LINKER_FLAGS="${LDFLAGS}" -DCMAKE_MODULE_LINKER_FLAGS="${LDFLAGS}" -DCMAKE_SHARED_LINKER_FLAGS="${LDFLAGS}" ) # Build the project and fuzzers. rm -rf build cmake "${cmake_args[@]}" -S . -B build -G Ninja -C ci/cmake-preloads/config-oss-fuzz.cmake cmake --build build --parallel --target fuzzers for f in $(find build/Testing/ -name 'TestFuzz*' -type f); do cp $f $OUT/ done # Build test mkdir $SRC/FreeRDP/build-test cd $SRC/FreeRDP/build-test cmake -DBUILD_TESTING=True .. make ================================================ FILE: projects/freerdp/project.yaml ================================================ homepage: "https://www.freerdp.com/" main_repo: "https://github.com/FreeRDP/FreeRDP" language: c primary_contact: "team@freerdp.com" auto_ccs: - "freerdpproject@gmail.com" - "estetus@gmail.com" builds_per_day: 4 fuzzing_engines: - afl - centipede - honggfuzz - libfuzzer sanitizers: - address - undefined architectures: - x86_64 ================================================ FILE: projects/freerdp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build-test --output-on-failure ================================================ FILE: projects/freetype2/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y \ autoconf \ cmake \ libtool \ pkg-config \ make \ ninja-build # For run_tests.sh RUN python3 -m pip install meson ninja requests # Get some files for the seed corpus ADD https://github.com/adobe-fonts/adobe-variable-font-prototype/releases/download/1.001/AdobeVFPrototype.otf $SRC/font-corpus/ RUN git clone https://github.com/unicode-org/text-rendering-tests.git && cp text-rendering-tests/fonts/* $SRC/font-corpus RUN git clone --depth 1 https://github.com/freetype/freetype2-testing.git WORKDIR freetype2-testing COPY *.sh $SRC/ ================================================ FILE: projects/freetype2/build.sh ================================================ #!/bin/bash -eux # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Tell CMake what fuzzing engine to link: export CMAKE_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" bash "fuzzing/scripts/build-fuzzers.sh" bash "fuzzing/scripts/prepare-oss-fuzz.sh" # Rename the `legacy' target to `ftfuzzer' for historical reasons: for f in "${OUT}/legacy"*; do mv "${f}" "${f/legacy/ftfuzzer}" done zip -ju "${OUT}/ftfuzzer_seed_corpus.zip" "${SRC}/font-corpus/"* ================================================ FILE: projects/freetype2/project.yaml ================================================ homepage: "https://www.freetype.org/" language: c++ primary_contact: "lemzwerg@gmail.com" auto_ccs: - "lemzwerg@googlemail.com" - "HinTak.Leung@gmail.com" - "ewaldhew@gmail.com" - "apodtele@gmail.com" - "prince.cherusker@gmail.com" - "bungeman@chromium.org" - "thestig@chromium.org" vendor_ccs: - "jkew@mozilla.com" - "jmuizelaar@mozilla.com" - "lsalzman@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/freetype/freetype2-testing.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/freetype2/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd external/freetype2/ python3 tests/scripts/download-test-fonts.py # The tests build with meson so we are forced to rebuild with meson here. # The harnesses are build with Makefiles. meson setup out -Dtests=enabled meson compile -C out meson test -C out ================================================ FILE: projects/fribidi/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y python3-pip pkg-config && \ pip3 install meson==0.54.0 ninja RUN git clone --depth 1 https://github.com/fribidi/fribidi.git WORKDIR fribidi COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/fribidi/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # setup build=$WORK/build # cleanup rm -rf $build mkdir -p $build # Build the library. meson --default-library=static --wrap-mode=nodownload -Ddocs=false \ -Dfuzzer_ldflags="$(echo $LIB_FUZZING_ENGINE)" \ $build \ || (cat build/meson-logs/meson-log.txt && false) # Build the fuzzers. ninja -v -j$(nproc) -C $build bin/fribidi-fuzzer mv $build/bin/fribidi-fuzzer $OUT/ # Archive and copy to $OUT seed corpus if the build succeeded. zip $OUT/fribidi-fuzzer_seed_corpus.zip test/*.{input,reference} test/fuzzing/* ================================================ FILE: projects/fribidi/project.yaml ================================================ homepage: "https://github.com/fribidi/fribidi" language: c primary_contact: "dov.grobgeld@gmail.com" auto_ccs: - "behdad.esfahbod@gmail.com" - "behdad@gnu.org" - "ebrahim@gnu.org" - "dr.khaled.hosny@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory main_repo: 'https://github.com/fribidi/fribidi.git' ================================================ FILE: projects/fribidi/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ meson test -C $WORK/build ================================================ FILE: projects/frr/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y git autoconf automake libtool make \ libreadline-dev texinfo libjson-c-dev pkg-config bison flex python3-pip \ libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev \ libsnmp-dev libcap-dev libelf-dev libpcre3-dev libpcre2-dev \ protobuf-c-compiler libprotobuf-c-dev RUN git clone -b v2.0.0 https://github.com/CESNET/libyang.git RUN git clone --depth 1 --branch fuzz https://github.com/FRRouting/frr RUN git clone --depth 1 https://github.com/qlyoung/corpi RUN git clone --depth 1 https://github.com/pytest-dev/pytest COPY build.sh run_tests.sh $SRC/ WORKDIR $SRC/frr ================================================ FILE: projects/frr/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Inherit system packages to support Indexer building. python3 -m venv --system-site-packages $SRC/venv source $SRC/venv/bin/activate pip3 install pytest function copy_lib { local fuzzer_path=$1 local lib=$2 cp $(ldd ${fuzzer_path} | grep "${lib}" | awk '{ print $3 }') ${OUT}/lib/ || true } mkdir -p $OUT/lib # build dependency ( cd $SRC/libyang mkdir build; cd build cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \ -D CMAKE_BUILD_TYPE:String="Release" .. make -j$(nproc) make install ) # build project export ASAN_OPTIONS=detect_leaks=0 export CFLAGS="${CFLAGS} -DFUZZING_OVERRIDE_LLVMFuzzerTestOneInput" export CXXFLAGS="${CXXFLAGS} -DFUZZING_OVERRIDE_LLVMFuzzerTestOneInput" ./bootstrap.sh ./configure --enable-libfuzzer --enable-static --enable-static-bin --sbindir=$SRC/bin make -j$(nproc) make install cp ./lib/.libs/libfrr.so.0 $OUT/lib/ cp $SRC/bin/bgpd $OUT/ cp $SRC/bin/ospfd $OUT/ cp $SRC/bin/pimd $OUT/ cp $SRC/bin/zebra $OUT/ # build corpus cd $SRC/corpi find . -type d -maxdepth 1 | while read i; do zip -j $OUT/"$i"_seed_corpus.zip "$i"/*; done find $OUT -maxdepth 1 -type f -executable | while read i; do grep "LLVMFuzzerTestOneInput" ${i} > /dev/null 2>&1 || continue patchelf --set-rpath '$ORIGIN/lib' ${i} copy_lib ${i} libpcre2 copy_lib ${i} libyang copy_lib ${i} libelf copy_lib ${i} libjson-c copy_lib ${i} libprotobuf-c done patchelf --remove-needed libpcre2-8.so.0 $OUT/lib/libyang.so.2 ================================================ FILE: projects/frr/project.yaml ================================================ homepage: "https://frrouting.org" language: c++ primary_contact: "security@lists.frrouting.org" auto_ccs: - "qlyoung@qlyoung.net" - "equinox-ossfuzz@diac24.net" - "menotdonald@gmail.com" - "mjs.ietf@gmail.com" - "rwgbsd@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/FRRouting/frr' ================================================ FILE: projects/frr/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # remove broken tests # TODO: Check if these can be fixed # or if they fix themselves over time export TMPDIR=/tmp/frr-tests mkdir /tmp/frr-tests mv tests/bgpd/test_peer_attr.py $TMPDIR/ mv tests/bgpd/test_mp_attr.py $TMPDIR/ mv tests/bgpd/test_mpath.py $TMPDIR/ mv tests/isisd/test_isis_spf.py $TMPDIR/ mv tests/lib/northbound/test_oper_data.py $TMPDIR/ mv tests/lib/test_timer_correctness.py $TMPDIR/ mv tests/lib/test_xref.py $TMPDIR/ mv tests/lib/cli/test_cli.py $TMPDIR/ mv tests/ospf6d/test_lsdb.py $TMPDIR/ mv tests/ospfd/test_ospf_spf.py $TMPDIR/ mv tests/zebra/test_lm_plugin.py $TMPDIR/ source $SRC/venv/bin/activate export ASAN_OPTIONS="detect_leaks=0" # run tests test_output=$(make check) test_exit_code=$? # restore broken tests mv $TMPDIR/test_peer_attr.py tests/bgpd/ mv $TMPDIR/test_mp_attr.py tests/bgpd/ mv $TMPDIR/test_mpath.py tests/bgpd/ mv $TMPDIR/test_isis_spf.py tests/isisd/ mv $TMPDIR/test_oper_data.py tests/lib/northbound/ mv $TMPDIR/test_timer_correctness.py tests/lib/ mv $TMPDIR/test_xref.py tests/lib/ mv $TMPDIR/test_cli.py tests/lib/cli/ mv $TMPDIR/test_lsdb.py tests/ospf6d/ mv $TMPDIR/test_ospf_spf.py tests/ospfd/ mv $TMPDIR/test_lm_plugin.py tests/zebra/ exit $test_exit_code ================================================ FILE: projects/fsnotify/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/fsnotify/fsnotify WORKDIR $SRC/fsnotify COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/fsnotify/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/fsnotify cp $SRC/fuzz_test.go ./ compile_native_go_fuzzer_v2 github.com/fsnotify/fsnotify FuzzInotify FuzzInotify ================================================ FILE: projects/fsnotify/fuzz_test.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package fsnotify import ( "encoding/base64" "errors" "fmt" "os" "path/filepath" "slices" "strings" "testing" ) func FuzzInotify(f *testing.F) { f.Fuzz(func(t *testing.T, op1, op2, op3, op4, op5, op6, op7, op8, op9, op10, op11, op12, op13, op14, op15, op16 uint8, data1, data2, data3, data4, data5, data6, data7, data8 string) { ops := []int{int(op1), int(op2), int(op3), int(op4), int(op5), int(op6), int(op7), int(op8), int(op8), int(op8), int(op9), int(op10), int(op11), int(op12), int(op13), int(op14), int(op15), int(op16)} data := []string{data1, data2, data3, data4, data5, data6, data7, data8} opCounter := 0 dataCounter := 0 createdFiles := make([]string, 0) createdSubDirs := make([]string, 0) createdSubDirs = append(createdSubDirs, ".") tmp := t.TempDir() w := newCollector(t, tmp) w.collect(t) var sb strings.Builder var wantLogger strings.Builder for i := 0; i < 5; i++ { switch ops[opCounter] % 3 { case 0: // Create file t.Log("In case 0") filename, err := getSanitizedName([]byte(data[dataCounter])) dataCounter += 1 if err != nil { continue } parentDir := createdSubDirs[ops[opCounter]%len(createdSubDirs)] opCounter += 1 filename = filepath.Join(parentDir, filename) t.Log("checking if exists...") fi, err := os.Stat(filepath.Join(filepath.Join(tmp, filename))) switch { case errors.Is(err, os.ErrNotExist): sb.WriteString(fmt.Sprintf("CREATE /%s\n", filename)) t.Logf("touching file: %s", filename) case fi.Mode().IsDir(): continue case err == nil: sb.WriteString(fmt.Sprintf("WRITE /%s\n", filename)) t.Logf("touch/writing file: %s", filename) } t.Log("done checking if exists") fuzzTouch(t, tmp, filename) if !slices.Contains(createdFiles, filename) { createdFiles = append(createdFiles, filename) } case 1: // Create and write file t.Log("In case 1") filename, err := getSanitizedName([]byte(data[dataCounter])) dataCounter += 1 if err != nil { continue } t.Log("____have name") parentDir := createdSubDirs[ops[opCounter]%len(createdSubDirs)] opCounter += 1 filename = filepath.Join(parentDir, filename) fileContents := data[dataCounter] dataCounter += 1 var fileExists bool if fi, err := os.Stat(filepath.Join(filepath.Join(tmp, filename))); errors.Is(err, os.ErrNotExist) { fileExists = false } else if fi.Mode().IsDir() { continue } else { fileExists = true } if !slices.Contains(createdFiles, filename) { createdFiles = append(createdFiles, filename) } t.Logf("len of file contents: %d", len(fileContents)) echoAppend(t, fileContents, tmp, filename) if !fileExists { sb.WriteString(fmt.Sprintf("CREATE /%s\n", filename)) t.Logf("CREATE'ing %s", filename) } if len(fileContents) != 0 { t.Logf("Writing %s", filename) sb.WriteString(fmt.Sprintf("WRITE /%s\n", filename)) t.Logf("echo appending file: %s", filename) } case 2: // Create subdir in the watched dir t.Log("In case 2") subDirName, err := getSanitizedName([]byte(data[dataCounter])) dataCounter += 1 if err != nil { continue } t.Log("____have name") // Select a parent dir to create the new subdir in opCounter += 1 parentDir := createdSubDirs[ops[opCounter]%len(createdSubDirs)] if _, err := os.Stat(filepath.Join(filepath.Join(tmp, parentDir, subDirName))); errors.Is(err, os.ErrNotExist) { createdSubDirs = append(createdSubDirs, filepath.Join(parentDir, subDirName)) t.Logf("Creating subdir: %s", filepath.Join(parentDir, subDirName)) mkdir(t, tmp, parentDir, subDirName) sb.WriteString(fmt.Sprintf("CREATE /%s\n", filepath.Join(parentDir, subDirName))) if err := w.w.Add(filepath.Join(tmp, parentDir, subDirName)); err != nil { t.Fatal(err) } } } } evs := w.stop(t) s := sb.String() fmt.Println(wantLogger.String()) cmpEvents(t, tmp, evs, newEvents(t, s)) return }) } func getSanitizedName(data []byte) (string, error) { b64Name := base64.URLEncoding.EncodeToString(data) nameWoSlashes := strings.Replace(b64Name, "/", "", -1) if len(nameWoSlashes) == 0 { return "", errors.New("Too short name") } sanitizedName := filepath.Clean(nameWoSlashes) if len(sanitizedName) > 60 { sanitizedName = sanitizedName[:60] } return sanitizedName, nil } // touch but without fatal'ing if it could not create the file // error means that the touch did not create a file func fuzzTouch(t *testing.T, path ...string) error { t.Helper() if len(path) < 1 { t.Fatalf("touch: path must have at least one element: %s", path) } fp, err := os.Create(join(path...)) if err != nil { return err } err = fp.Close() if err != nil { t.Fatalf("touch(%q): %s", join(path...), err) } if shouldWait(path...) { eventSeparator() } return nil } ================================================ FILE: projects/fsnotify/project.yaml ================================================ homepage: "https://github.com/fsnotify/fsnotify" language: go main_repo: "https://github.com/fsnotify/fsnotify" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/ftfy/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/rspeer/python-ftfy ftfy WORKDIR ftfy COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/ftfy/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/ftfy/fuzz_fix.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): import ftfy def TestInput(data): fdp = atheris.FuzzedDataProvider(data) try: ftfy.fix_text(fdp.ConsumeUnicodeNoSurrogates(100)) plan1 = ftfy.fix_and_explain(fdp.ConsumeUnicodeNoSurrogates(100))[1] ftfy.apply_plan(fdp.ConsumeUnicodeNoSurrogates(100), plan1) ftfy.fix_text_segment(fdp.ConsumeUnicodeNoSurrogates(100)) f = open("temp.txt", "w") f.write(fdp.ConsumeUnicodeNoSurrogates(1000)) f.close() f = open("temp.txt", "r") ftfy.fix_file(f) f.close() ftfy.guess_bytes(fdp.ConsumeBytes(100)) except UnicodeEncodeError as e2: pass except UnicodeError as e: if "Hey wait, this isn't Unicode." not in str(e): raise e def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ftfy/fuzz_format.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): import ftfy.formatting as ftfy import ftfy.fixes as fixes def TestInput(data): if len(data) < 1: return fdp = atheris.FuzzedDataProvider(data) ftfy.character_width(chr(fdp.ConsumeIntInRange(1,1114110))) ftfy.monospaced_width(fdp.ConsumeUnicodeNoSurrogates(1000)) choice = fdp.ConsumeIntInRange(1,3) if choice == 1: ftfy.display_ljust(fdp.ConsumeUnicodeNoSurrogates(1000),fdp.ConsumeIntInRange(1,2000)) if choice == 2: ftfy.display_rjust(fdp.ConsumeUnicodeNoSurrogates(1000),fdp.ConsumeIntInRange(1,2000)) if choice == 3: ftfy.display_center(fdp.ConsumeUnicodeNoSurrogates(1000),fdp.ConsumeIntInRange(1,2000)) fixes.remove_bom(fdp.ConsumeUnicodeNoSurrogates(1000)) def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ftfy/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/rspeer/python-ftfy language: python main_repo: https://github.com/rspeer/python-ftfy sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/fuzzing-puzzles/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool ADD https://raw.githubusercontent.com/llvm-mirror/compiler-rt/master/test/fuzzer/MultipleConstraintsOnSmallInputTest.cpp \ $SRC/fuzzing-puzzles/ WORKDIR fuzzing-puzzles COPY build.sh $SRC/ ================================================ FILE: projects/fuzzing-puzzles/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $CXX $CXXFLAGS $SRC/fuzzing-puzzles/MultipleConstraintsOnSmallInputTest.cpp \ -o $OUT/multiple_constraints_on_small_input_honggfuzz_fuzzer \ $LIB_FUZZING_ENGINE ================================================ FILE: projects/fuzzing-puzzles/project.yaml ================================================ homepage: https://github.com/google/fuzzer-test-suite language: c++ primary_contact: kcc@google.com main_repo: https://github.com/google/fuzzer-test-suite auto_ccs: - "metzman@google.com" - "mmoroz@google.com" sanitizers: - address fuzzing_engines: - honggfuzz disabled: True ================================================ FILE: projects/fuzztest-example/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth=1 https://github.com/google/fuzztest COPY build.sh $SRC/ COPY fuzztest-enable-fuzzers.diff $SRC/ ================================================ FILE: projects/fuzztest-example/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd fuzztest git apply --ignore-space-change --ignore-whitespace $SRC/fuzztest-enable-fuzzers.diff # Compile gfuzztests cd codelab compile_fuzztests.sh ================================================ FILE: projects/fuzztest-example/fuzztest-enable-fuzzers.diff ================================================ diff --git a/codelab/escaping_test.cc b/codelab/escaping_test.cc index 5e5310e..d83901e 100644 --- a/codelab/escaping_test.cc +++ b/codelab/escaping_test.cc @@ -48,20 +48,20 @@ TEST(EscapingTest, UnescapingReplacesEscapeSequences) { // Comment out the following fuzz tests: -// void UnescapingEscapedStringGivesOriginal(std::string_view s) { -// EXPECT_EQ(s, Unescape(Escape(s))); -// } -// FUZZ_TEST(EscapingTest, UnescapingEscapedStringGivesOriginal); +void UnescapingEscapedStringGivesOriginal(std::string_view s) { + EXPECT_EQ(s, Unescape(Escape(s))); +} +FUZZ_TEST(EscapingTest, UnescapingEscapedStringGivesOriginal); -// void EscapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { -// Escape(s); -// } -// FUZZ_TEST(EscapingTest, EscapingAStringNeverTriggersUndefinedBehavior); +void EscapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { + Escape(s); +} +FUZZ_TEST(EscapingTest, EscapingAStringNeverTriggersUndefinedBehavior); -// void UnescapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { -// Unescape(s); -// } -// FUZZ_TEST(EscapingTest, UnescapingAStringNeverTriggersUndefinedBehavior); +void UnescapingAStringNeverTriggersUndefinedBehavior(std::string_view s) { + Unescape(s); +} +FUZZ_TEST(EscapingTest, UnescapingAStringNeverTriggersUndefinedBehavior); } // namespace } // namespace codelab ================================================ FILE: projects/fuzztest-example/project.yaml ================================================ homepage: "https://github.com/google/fuzztest" language: c++ primary_contact: "david@adalogics.com" main_repo: "https://github.com/google/fuzztest" fuzzing_engines: - libfuzzer ================================================ FILE: projects/fuzztest-raksha/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool default-jdk bison m4 \ build-essential\ curl \ doxygen \ flex \ libffi-dev \ libncurses5-dev \ libtool \ libsqlite3-dev \ mcpp \ sqlite \ uuid-runtime \ zlib1g-dev RUN wget https://github.com/bazelbuild/buildtools/releases/download/4.2.5/buildifier-linux-amd64 \ -O /usr/local/bin/buildifier && chmod a+x /usr/local/bin/buildifier RUN git clone https://github.com/google-research/raksha raksha COPY build.sh $SRC/ COPY *.diff $SRC/ ================================================ FILE: projects/fuzztest-raksha/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Extend with oss-fuzz settings. To be upsteamed? cd $SRC/raksha git apply --ignore-space-change --ignore-whitespace $SRC/raksha-fuzztest.diff # Compile gfuzztests export FUZZTEST_TARGET_FOLDER="//src/..." compile_fuzztests.sh ================================================ FILE: projects/fuzztest-raksha/project.yaml ================================================ homepage: "https://github.com/google/fuzztest" language: c++ primary_contact: "david@adalogics.com" main_repo: "https://github.com/google/fuzztest" fuzzing_engines: - libfuzzer ================================================ FILE: projects/fuzztest-raksha/raksha-fuzztest.diff ================================================ diff --git a/WORKSPACE b/WORKSPACE index 73e0e75..33aae53 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -238,12 +238,12 @@ http_archive( ], ) -fuzztest_commit_hash = "4a8253b7299cf1764550054fae55f1b58a65bbaa" +fuzztest_commit_hash = "c8ae15a574068f5ed8cd2944bdb5e56b2a1e9d71" # Fuzztest http_archive( - name = "fuzztest", - sha256 = "72ae2d28323748d2c466396fa47038351ae81bedc50b8a3c6f1de6a9f02cde33", + name = "com_google_fuzztest", + sha256 = "ab7cdadecde55e645cc38dfec7bb9bab9e43ea508c9e13ed2aad884a23020240", strip_prefix = "fuzztest-" + fuzztest_commit_hash, urls = ["https://github.com/google/fuzztest/archive/" + fuzztest_commit_hash + ".zip"], ) diff --git a/src/ir/BUILD b/src/ir/BUILD index d525046..a16cd0f 100644 --- a/src/ir/BUILD +++ b/src/ir/BUILD @@ -206,10 +206,11 @@ cc_test( ":module", ":storage", ":value", - "//src/common/testing:gtest", "//src/common/utils:map_iter", "//src/ir/types", - "@fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", + "//src/common/testing:gtest", ], ) diff --git a/src/ir/datalog/BUILD b/src/ir/datalog/BUILD index 6b3a0c7..f571f31 100644 --- a/src/ir/datalog/BUILD +++ b/src/ir/datalog/BUILD @@ -131,9 +131,10 @@ cc_test( srcs = ["value_test.cc"], deps = [ ":value", - "//src/common/testing:gtest", "@com_google_absl//absl/strings", - "@fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest", + "@com_google_fuzztest//fuzztest:fuzztest_gtest_main", + "//src/common/testing:gtest", ], ) ================================================ FILE: projects/fuzzywuzzy/DiffUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import me.xdrop.diffutils.DiffUtils; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [me.xdrop.diffutils.DiffUtils] public static // me.xdrop.diffutils.structs.MatchingBlock[] getMatchingBlocks(java.lang.String,java.lang.String) public class DiffUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { DiffUtils.getMatchingBlocks( data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); } } ================================================ FILE: projects/fuzzywuzzy/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/xdrop/fuzzywuzzy fuzzywuzzy COPY *.sh *.java $SRC/ WORKDIR $SRC/fuzzywuzzy ================================================ FILE: projects/fuzzywuzzy/FuzzySearchFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import me.xdrop.fuzzywuzzy.FuzzySearch; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [me.xdrop.fuzzywuzzy.FuzzySearch] public static int // weightedRatio(java.lang.String,java.lang.String) public class FuzzySearchFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { FuzzySearch.weightedRatio( data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); } } ================================================ FILE: projects/fuzzywuzzy/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "package/target/fuzzywuzzy-$CURRENT_VERSION.jar" $OUT/fuzzywuzzy.jar cp "build/target/fuzzywuzzy-build-$CURRENT_VERSION.jar" $OUT/fuzzywuzzy-build.jar cp diffutils/target/diffutils-*.jar $OUT/diffutils.jar ALL_JARS="fuzzywuzzy.jar:fuzzywuzzy-build.jar:diffutils.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar --cp=$RUNTIME_CLASSPATH --target_class=$fuzzer_basename --jvm_args="\$mem_settings" \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/fuzzywuzzy/project.yaml ================================================ homepage: https://github.com/xdrop/fuzzywuzzy main_repo: https://github.com/xdrop/fuzzywuzzy language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/fwupd/Dockerfile ================================================ # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y pkg-config zlib1g-dev libffi-dev liblzma-dev libcbor-dev RUN python3 -m pip install -U jinja2 packaging meson ninja RUN git clone --depth 1 https://github.com/fwupd/fwupd.git fwupd WORKDIR . COPY build.sh $SRC/ ================================================ FILE: projects/fwupd/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 fwupd/contrib/ci/oss-fuzz.py ================================================ FILE: projects/fwupd/project.yaml ================================================ homepage: "https://github.com/fwupd/fwupd" language: c primary_contact: "hughsient@gmail.com" main_repo: 'https://github.com/fwupd/fwupd' fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/g-api-auth-httplib2/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN pip3 install --upgrade pip && pip install mock RUN git clone --depth 1 https://github.com/googleapis/google-auth-library-python-httplib2 WORKDIR google-auth-library-python-httplib2 COPY build.sh *.py $SRC/ ================================================ FILE: projects/g-api-auth-httplib2/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-auth-httplib2/fuzz_http.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import six from six.moves import http_client import mock import httplib2 import google_auth_httplib2 # Mocks for fuzzing. Inspired by testing infra. Main difference is we have # added logic to handle the event where the MockHTTP has run out of # responses an appropriate exception is thrown that we catch in the fuzzer. class FuzzMockHttp(object): def __init__(self, responses, headers=None): self.responses = responses self.requests = [] self.headers = headers or {} self.add_certificate = mock.Mock(return_value=None) def request( self, url, method="GET", body=None, headers=None, redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None, ): self.requests.append( (method, url, body, headers, redirections, connection_type) ) if len(self.responses) == 0: raise Exception("FUZZ: No more responses") return self.responses.pop(0) class FuzzMockResponse(object): def __init__(self, status=http_client.OK, data=b""): self.status = status self.data = data def __iter__(self): yield self yield self.data class FuzzMockCredentials(object): def __init__(self, token="token"): self.token = token def apply(self, headers): headers["authorization"] = self.token def before_request(self, request, method, url, headers): self.apply(headers) def refresh(self, request): self.token += "1" def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) mock_credentials = mock.Mock(wraps=FuzzMockCredentials(fdp.ConsumeUnicodeNoSurrogates(10))) if fdp.ConsumeBool() == True: mock_credentials.apply({'authorization': ""}) # Create responses. We need at least two. http_codes = [400, 401, 403, 404, 405, 413, 415, 429, 500, 503, 504] mock_responses = [] for i in range(fdp.ConsumeIntInRange(1, 10)): mock_responses.append( FuzzMockResponse( status = http_codes[fdp.ConsumeIntInRange(0, len(http_codes)-1)], data = fdp.ConsumeBytes(100) ) ) mock_http = FuzzMockHttp(mock_responses) authed_http = google_auth_httplib2.AuthorizedHttp( mock_credentials, http=mock_http ) try: r, d = authed_http.request( "http://localhost:8001", fdp.ConsumeUnicodeNoSurrogates(10), None, None, httplib2.DEFAULT_MAX_REDIRECTS, None ) except Exception as e: if "FUZZ" in str(e): pass else: raise e def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-auth-httplib2/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-auth-library-python-httplib2 language: python main_repo: https://github.com/googleapis/google-auth-library-python-httplib2/ sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-auth-library-python/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/googleapis/google-auth-library-python COPY build.sh *.py $SRC/ WORKDIR google-auth-library-python ================================================ FILE: projects/g-api-auth-library-python/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install -r docs/requirements-docs.txt pip3 install . # Embed certificates and private key too for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data "$PWD/tests/data/privatekey.pem:." --add-data "$PWD/tests/data/public_cert.pem:." done ================================================ FILE: projects/g-api-auth-library-python/fuzz_jwt.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from google.auth import jwt from google.auth import crypt bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) path_to_public_cert = os.path.abspath(os.path.join(bundle_dir, 'public_cert.pem')) if os.path.isfile(path_to_public_cert): with open(path_to_public_cert, "rb") as fh: PUBLIC_CERT_BYTES = fh.read() else: raise Exception("Could not find public cert") @atheris.instrument_func def test_token_decode(data): fdp = atheris.FuzzedDataProvider(data) try: jwt.decode(fdp.ConsumeString(200), certs=PUBLIC_CERT_BYTES) except ValueError: # ValueError is thrown if any failed verification checks pass @atheris.instrument_func def TestOneInput(data): test_token_decode(data) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-auth-library-python/fuzz_jwt_roundtrip.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__))) path_to_public_cert = os.path.abspath(os.path.join(bundle_dir, 'public_cert.pem')) path_to_private_key = os.path.abspath(os.path.join(bundle_dir, 'privatekey.pem')) # We instrument all imports below from google.auth import jwt from google.auth import crypt if os.path.isfile(path_to_private_key): with open(path_to_private_key, "rb") as fh: PRIVATE_KEY_BYTES = fh.read() else: raise Exception("Could not find private key") if os.path.isfile(path_to_public_cert): with open(path_to_public_cert, "rb") as fh: PUBLIC_CERT_BYTES = fh.read() else: raise Exception("Could not find public cert") @atheris.instrument_func def test_roundtrip_unverified(data): fdp = atheris.FuzzedDataProvider(data) signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, "1") to_header = fdp.ConsumeIntInRange(1, 100) if to_header < 50: header = None else: header = { "alg" : fdp.ConsumeString(100), } to_keyid = fdp.ConsumeIntInRange(1, 100) raw_data = fdp.ConsumeString(200) key_id = fdp.ConsumeString(50) if to_keyid < 50 else None encoded = jwt.encode(signer, raw_data, header = header, key_id = key_id) try: _, decoded_data, _, _ = jwt.decode(encoded, PUBLIC_CERT_BYTES) except ValueError as e: return @atheris.instrument_func def TestOneInput(data): test_roundtrip_unverified(data) def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-auth-library-python/project.yaml ================================================ auto_ccs: - saisunder@google.com - stim@google.com - clundin@google.com - sijunliu@google.com fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-auth-library-python language: python main_repo: https://github.com/googleapis/google-auth-library-python primary_contact: kittureddy@google.com sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-pubsub/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip && pip install google-api-core google-cloud-core RUN git clone https://github.com/googleapis/python-pubsub COPY build.sh *.py $SRC/ WORKDIR python-pubsub ================================================ FILE: projects/g-api-pubsub/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-pubsub/fuzz_msg.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import queue import atheris import datetime # We instrument all at the bottom from google.cloud.pubsub_v1.subscriber import message from google.protobuf import timestamp_pb2 from google.pubsub_v1 import types as gapic_types RECEIVED = datetime.datetime(2012, 4, 21, 15, 0, tzinfo=datetime.timezone.utc) PUBLISHED_MICROS = 123456 PUBLISHED = RECEIVED + datetime.timedelta(days=1, microseconds=PUBLISHED_MICROS) PUBLISHED_SECONDS = 1234543 is_once = True def fuzz_exactly_once_delivery_enabled_func(): if is_once: return True return False def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) is_once = fdp.ConsumeBool() gapic_pubsub_message = gapic_types.PubsubMessage( data=data, message_id="message_id", publish_time=timestamp_pb2.Timestamp( seconds=PUBLISHED_SECONDS, nanos=PUBLISHED_MICROS * 1000 ), ordering_key=fdp.ConsumeUnicodeNoSurrogates(20), ) msg = message.Message( message=gapic_pubsub_message._pb, ack_id = fdp.ConsumeUnicodeNoSurrogates(20), delivery_attempt = fdp.ConsumeIntInRange(1, 1000), request_queue=queue.Queue(), exactly_once_delivery_enabled_func = fuzz_exactly_once_delivery_enabled_func ) msg.modify_ack_deadline_with_response(fdp.ConsumeIntInRange(1, 1000)) msg.ack_with_response() msg.nack_with_response() s1 = repr(msg) return msg.ack_id def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-pubsub/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-pubsub language: python main_repo: https://github.com/googleapis/python-pubsub sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-py-api-common-protos/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool zlib1g-dev pkg-config RUN pip3 install --upgrade pip && pip3 install google-api-core RUN git clone --depth 1 --recursive https://github.com/protocolbuffers/protobuf.git RUN git clone --depth 1 https://github.com/googleapis/python-api-common-protos COPY build.sh fuzz_* $SRC/ WORKDIR python-api-common-protos ================================================ FILE: projects/g-api-py-api-common-protos/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build protoc with default options. unset CFLAGS CXXFLAGS mkdir $SRC/protobuf-install/ cd $SRC/protobuf-install/ cmake -Dprotobuf_BUILD_TESTS=OFF $SRC/protobuf make -j$(nproc) make install ldconfig cd $SRC/protobuf/python python3 setup.py build pip3 install . # Compile .proto specs cd $SRC/python-api-common-protos/ for target in quota billing routing log; do protoc --python_out=. --proto_path=. google/api/$target.proto done # Compile fuzzer for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-py-api-common-protos/fuzz_api.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(enable_loader_override=False): import google.api.quota_pb2 import google.api.billing_pb2 import google.api.routing_pb2 import google.api.log_pb2 from google.protobuf.message import DecodeError, EncodeError @atheris.instrument_func def protobuf_roundtrip(proto_target, input_bytes): try: proto_target.ParseFromString(input_bytes) except DecodeError: None try: proto_target.SerializeToString() except EncodeError: None @atheris.instrument_func def TestOneInput(input_bytes): """Test ParseFromString with bytes string""" protobuf_roundtrip(google.api.quota_pb2.QuotaLimit(), input_bytes) protobuf_roundtrip(google.api.billing_pb2.Billing(), input_bytes) protobuf_roundtrip(google.api.routing_pb2.RoutingRule(), input_bytes) protobuf_roundtrip(google.api.log_pb2.LogDescriptor(), input_bytes) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-py-api-common-protos/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-api-common-protos language: python main_repo: https://github.com/googleapis/python-api-common-protos sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/g-api-py-oauthlib/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN pip3 install --upgrade pip && pip3 install mock RUN git clone --depth 1 https://github.com/googleapis/google-auth-library-python-oauthlib WORKDIR google-auth-library-python-oauthlib COPY build.sh *.py $SRC/ ================================================ FILE: projects/g-api-py-oauthlib/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-py-oauthlib/fuzz_config.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import mock import atheris import tempfile import json import mock from google_auth_oauthlib import helpers def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) config_file = tempfile.NamedTemporaryFile(mode="wt") try: payload = json.loads(fdp.ConsumeUnicodeNoSurrogates(1024)) except: return if type(payload) is not dict: return config_file.write(json.dumps(payload)) try: helpers.session_from_client_secrets_file( config_file.name, scopes=mock.sentinel.scopes ) except ValueError as ve: legit_exceptions = [ "Client secrets must be for a web or installed app.", "Client secrets is not in the correct format." ] legit = False for msg in legit_exceptions: if msg in str(ve): legit = True if not legit: raise ve def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-py-oauthlib/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-auth-library-python-oauthlib language: python main_repo: https://github.com/googleapis/google-auth-library-python-oauthlib sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/g-api-python-bigquery-storage/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/googleapis/python-bigquery-storage python-bigquery-storage RUN python3 -m pip install --upgrade pip mock google-api-core google-cloud-core fastavro COPY *.sh *py $SRC/ WORKDIR $SRC/python-bigquery-storage ================================================ FILE: projects/g-api-python-bigquery-storage/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ GRPC_PYTHON_CFLAGS="${CFLAGS}" GRPC_PYTHON_BUILD_SYSTEM_RE2=true GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-python-bigquery-storage/fuzz_avroparser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from google.cloud.bigquery_storage_v1.types import ReadSession from google.protobuf.json_format import Parse def TestOneInput(data): """Fuzzer that creates a random read session and parses the attached avro session. The main point is to ensure none of the parsing routines have insecure calls and that the parsing routines can work with arbitrary ReadSessions. """ fdp = atheris.FuzzedDataProvider(data) try: # Create a random session msg = Parse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize), ReadSession()) except Exception: return avro_parser = _AvroStreamParser(msg) avro_parser.to_dataframe() def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-python-bigquery-storage/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-bigquery-storage language: python main_repo: https://github.com/googleapis/python-bigquery-storage sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/g-api-python-client/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/googleapis/google-api-python-client COPY build.sh *.py $SRC/ WORKDIR google-api-python-client ================================================ FILE: projects/g-api-python-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build flask fuzzers for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-python-client/fuzz_mimeparser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from googleapiclient import mimeparse def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) mimeparse.best_match( ['application/xbel+xml', 'text/xml'], fdp.ConsumeString(200) ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-python-client/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-api-python-client language: python main_repo: https://github.com/googleapis/google-api-python-client sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-python-cloud-core/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/googleapis/python-cloud-core COPY build.sh *.py $SRC/ WORKDIR python-cloud-core ================================================ FILE: projects/g-api-python-cloud-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-python-cloud-core/fuzz_helpers.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import json # We instrument all functions when initiating atheris from google.cloud import _helpers def TestOneInput(data): if len(data) < 100: return fdp = atheris.FuzzedDataProvider(data) try: loaded_data = json.loads(fdp.ConsumeString(300)) success = True except Exception: success = False if success: try: _helpers._ensure_tuple_or_list(loaded_data) except TypeError: pass try: _helpers._bytes_to_unicode(data) except ValueError: pass fdp = atheris.FuzzedDataProvider(data) try: _helpers._time_from_iso8601_time_naive(fdp.ConsumeString(100)) except ValueError: pass fdp = atheris.FuzzedDataProvider(data) try: _helpers._rfc3339_nanos_to_datetime(fdp.ConsumeString(100)) except ValueError: pass fdp = atheris.FuzzedDataProvider(data) try: _helpers._name_from_project_path( fdp.ConsumeString(60), fdp.ConsumeString(60), fdp.ConsumeString(60) ) except ValueError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-python-cloud-core/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-cloud-core language: python main_repo: https://github.com/googleapis/python-cloud-core sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-python-firestore/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip && pip3 install mock RUN git clone https://github.com/googleapis/python-firestore COPY build.sh *.py $SRC/ WORKDIR python-firestore ================================================ FILE: projects/g-api-python-firestore/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-python-firestore/fuzz_test.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import mock import atheris import google.auth.credentials from google.cloud.firestore_v1.query import CollectionGroup from google.cloud.firestore_v1.client import Client def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) credentials = mock.Mock(spec=google.auth.credentials.Credentials) client = Client( project="fuzz_project", credentials = credentials ) try: parent = client.collection(fdp.ConsumeString(100)) except ValueError: return query = CollectionGroup(parent).limit(fdp.ConsumeIntInRange(1, 10)) try: _ = list(query.get_partitions(fdp.ConsumeIntInRange(1, 50))) except ValueError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-python-firestore/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-firestore language: python main_repo: https://github.com/googleapis/python-firestore sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-python-tasks/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && \ apt-get install -y libre2-dev zlib1g-dev libssl-dev RUN python3 -m pip install --upgrade pip && \ python3 -m pip install --upgrade mock RUN python3 -m pip install charset_normalizer RUN git clone --depth 1 https://github.com/googleapis/google-cloud-python $SRC/google-cloud-python WORKDIR $SRC/google-cloud-python/packages/google-cloud-tasks COPY build.sh *.py $SRC/ ================================================ FILE: projects/g-api-python-tasks/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Reinstall grpcio to fix potential build issues python3 -m pip install --force-reinstall --upgrade grpcio GRPC_PYTHON_CFLAGS="${CFLAGS}" \ GRPC_PYTHON_BUILD_SYSTEM_RE2=true \ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true \ GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true \ MAX_JOBS=$(nproc) \ python3 -m pip install -v . --no-binary :all: for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-python-tasks/fuzz_cloudtask_client.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import mock import atheris with atheris.instrument_imports(): from google.auth import credentials as ga_credentials from google.cloud.tasks_v2.services.cloud_tasks import CloudTasksClient from google.cloud.tasks_v2.types import queue from google.cloud.tasks_v2.types import cloudtasks def get_request_queue(fdp, client): request = cloudtasks.GetQueueRequest() request.name = fdp.ConsumeUnicodeNoSurrogates(20) with mock.patch.object(type(client.transport.get_queue), "__call__") as call: call.return_value = queue.Queue() client.get_queue(request) def update_queue(fdp, client): request = cloudtasks.UpdateQueueRequest() with mock.patch.object(type(client.transport.update_queue), "__call__") as call: call.return_value = queue.Queue( name=fdp.ConsumeUnicodeNoSurrogates(20), state=queue.Queue.State.RUNNING, ) response = client.update_queue(request) def delete_queue(fdp, client): request = cloudtasks.DeleteQueueRequest() request.name = fdp.ConsumeUnicodeNoSurrogates(20) with mock.patch.object(type(client.transport.delete_queue), "__call__") as call: call.return_value = None response = client.delete_queue(request) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) client = CloudTasksClient( credentials=ga_credentials.AnonymousCredentials(), ) api_targets = [ get_request_queue, update_queue, delete_queue ] num_of_calls = fdp.ConsumeIntInRange(1, 10) for i in range(num_of_calls): target = api_targets[fdp.ConsumeIntInRange(0, len(api_targets)-1)] target(fdp, client) def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-python-tasks/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-tasks language: python main_repo: https://github.com/googleapis/google-cloud-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/g-api-resource-manager/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && \ apt-get install -y libre2-dev zlib1g-dev libssl-dev RUN python3 -m pip install --upgrade pip && \ python3 -m pip install --upgrade mock RUN git clone --depth 1 https://github.com/googleapis/google-cloud-python $SRC/google-cloud-python WORKDIR $SRC/google-cloud-python/packages/google-cloud-resource-manager COPY build.sh *.py $SRC/ ================================================ FILE: projects/g-api-resource-manager/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ GRPC_PYTHON_CFLAGS="${CFLAGS}" \ GRPC_PYTHON_BUILD_SYSTEM_RE2=true \ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true \ GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true \ MAX_JOBS=$(nproc) \ python3 -m pip install -v . --no-binary :all: for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-resource-manager/fuzz_tag_values_client.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer for google/cloud/resourcemanager_v3/services/tag_values/client.py""" import sys import mock import atheris with atheris.instrument_imports(): from google.auth import credentials as ga_credentials from google.longrunning import operations_pb2 from google.iam.v1 import iam_policy_pb2 from google.iam.v1 import policy_pb2 from google.cloud.resourcemanager_v3.services.tag_values import ( TagValuesAsyncClient, TagValuesClient, pagers, transports, ) from google.cloud.resourcemanager_v3.types import tag_values def test_get_tag_value(fdp, client): if fdp.ConsumeBool(): request = tag_values.GetTagValueRequest() else: request = dict() with mock.patch.object(type(client.transport.get_tag_value), "__call__") as call: call.return_value = tag_values.TagValue( name=fdp.ConsumeUnicodeNoSurrogates(10), parent=fdp.ConsumeUnicodeNoSurrogates(10), short_name=fdp.ConsumeUnicodeNoSurrogates(10), namespaced_name=fdp.ConsumeUnicodeNoSurrogates(10), description=fdp.ConsumeUnicodeNoSurrogates(10), etag=fdp.ConsumeUnicodeNoSurrogates(10), ) response = client.get_tag_value(request) def test_create_tag_value(fdp, client): if fdp.ConsumeBool(): request = tag_values.CreateTagValueRequest() else: request = dict() with mock.patch.object(type(client.transport.create_tag_value), "__call__") as call: call.return_value = operations_pb2.Operation(name=fdp.ConsumeUnicodeNoSurrogates(20)) response = client.create_tag_value(request) def test_update_tag_value(fdp, client): if fdp.ConsumeBool(): request = tag_values.UpdateTagValueRequest() else: request = dict() with mock.patch.object(type(client.transport.update_tag_value), "__call__") as call: call.return_value = operations_pb2.Operation(name=fdp.ConsumeUnicodeNoSurrogates(20)) response = client.update_tag_value(request) def test_delete_tag_value(fdp, client): if fdp.ConsumeBool(): request = tag_values.DeleteTagValueRequest() else: request = dict() with mock.patch.object(type(client.transport.delete_tag_value), "__call__") as call: call.return_value = operations_pb2.Operation(name="operations/spam") response = client.delete_tag_value(request) def test_get_iam_policy(fdp, client): if fdp.ConsumeBool(): request = iam_policy_pb2.GetIamPolicyRequest() else: request = dict() with mock.patch.object(type(client.transport.get_iam_policy), "__call__") as call: call.return_value = policy_pb2.Policy( version=774, etag=fdp.ConsumeBytes(20), ) response = client.get_iam_policy(request) def test_set_iam_policy(fdp, client): if fdp.ConsumeBool(): request = iam_policy_pb2.SetIamPolicyRequest() else: request = dict() with mock.patch.object(type(client.transport.set_iam_policy), "__call__") as call: call.return_value = policy_pb2.Policy( version=774, etag=fdp.ConsumeBytes(20), ) response = client.set_iam_policy(request) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) # Create our client client = TagValuesClient( credentials=ga_credentials.AnonymousCredentials(), transport="grpc", ) # Call a set of operations on the client. Using mocked responses. operations = [ test_get_tag_value, test_create_tag_value, test_update_tag_value, test_delete_tag_value, test_get_iam_policy, test_set_iam_policy ] number_of_calls = 20 for i in range(number_of_calls): target = operations[fdp.ConsumeIntInRange(0, len(operations)-1)] target(fdp, client) def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-resource-manager/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-resource-manager language: python main_repo: https://github.com/googleapis/google-cloud-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-resumable-media-python/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/googleapis/google-resumable-media-python COPY build.sh *.py $SRC/ WORKDIR google-resumable-media-python ================================================ FILE: projects/g-api-resumable-media-python/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-resumable-media-python/fuzz_uploader.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import io # All code is instrumented by calling atheris.instrument_all below from google.resumable_media import _upload def test_simple(data): upload = _upload.SimpleUpload("localhost:8008/index.html") upload._prepare_request(data, None) def test_multipart(data): fdp = atheris.FuzzedDataProvider(data) headers = {"spin": "doctors"} upload = _upload.MultipartUpload( "localhost:8008/index.html", headers=headers, checksum="md5" ) try: upload._prepare_request( fdp.ConsumeBytes(200), {}, fdp.ConsumeString(200) ) except UnicodeEncodeError: pass def _upload_in_flight(data, headers=None, checksum=None): upload = _upload.ResumableUpload( "localhost:8008://heyo", 1024 * 1024, headers=headers, checksum=checksum ) upload._stream = io.BytesIO(data) upload._content_type = "text/plain" upload._total_bytes = len(data) upload._resumable_url = "localhost:8009/test.invalid?upload_id=not-none" return upload def test_checksum(data): fdp = atheris.FuzzedDataProvider(data) for cs in ["md5", "crc32"]: upload = _upload_in_flight(fdp.ConsumeBytes(200), checksum=cs) try: start_byte, payload, _ = _upload.get_next_chunk( upload._stream, fdp.ConsumeIntInRange(1, 250), fdp.ConsumeIntInRange(1, 250) ) except ValueError: pass def TestOneInput(data): test_simple(data) test_multipart(data) test_checksum(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-resumable-media-python/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-resumable-media-python language: python main_repo: https://github.com/googleapis/google-resumable-media-python primary_contact: gorcester@google.com sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-api-secret-manager/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN pip3 install --upgrade pip && pip install google-api-core google-cloud-core mock RUN git clone --depth 1 https://github.com/googleapis/google-cloud-python RUN python3 -m pip install --upgrade pip WORKDIR google-cloud-python COPY build.sh *.py $SRC/ ================================================ FILE: projects/g-api-secret-manager/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd packages/google-cloud-secret-manager/ GRPC_PYTHON_CFLAGS="${CFLAGS}" GRPC_PYTHON_BUILD_SYSTEM_RE2=true GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true python3 -m pip install -v . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-api-secret-manager/fuzz_client.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import mock from google.auth import credentials from google.cloud.secretmanager_v1beta1.services.secret_manager_service import ( SecretManagerServiceAsyncClient, SecretManagerServiceClient, pagers, transports, ) from google.cloud.secretmanager_v1beta1.types import resources, service def test_add_secret_version(client, fdp): """Calls add_secret_version on the client with data from the fuzzer""" # Create the input. if fdp.ConsumeBool(): request = service.AddSecretVersionRequest() try: request.parent = fdp.ConsumeUnicodeNoSurrogates(20) except: request.parent = None else: request = {} parent = None payload = None if fdp.ConsumeBool(): parent = fdp.ConsumeUnicodeNoSurrogates(10) request = None payload = resources.SecretPayload() payload.data = fdp.ConsumeBytes(10) # Mock call within the gRPC stub and fake the request. with mock.patch.object( type(client.transport.add_secret_version), "__call__" ) as call: # Create return value for the call. call.return_value = resources.SecretVersion( name="name_value", state=resources.SecretVersion.State.ENABLED, ) response = client.add_secret_version( request = request, parent = parent, payload = payload ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) # Create a client we can call. client = SecretManagerServiceClient( credentials=credentials.AnonymousCredentials(), transport="grpc", ) test_add_secret_version(client, fdp) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-secret-manager/fuzz_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from google.cloud.secretmanager_v1beta1.services.secret_manager_service import ( SecretManagerServiceClient, ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) SecretManagerServiceClient.parse_secret_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) SecretManagerServiceClient.parse_common_location_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) SecretManagerServiceClient.parse_common_project_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) SecretManagerServiceClient.parse_common_organization_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) SecretManagerServiceClient.parse_common_folder_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) SecretManagerServiceClient.parse_common_billing_account_path(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-api-secret-manager/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-secret-manager language: python main_repo: https://github.com/googleapis/python-secret-manager sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-apis-py-api-core/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/googleapis/python-api-core COPY build.sh *.py $SRC/ WORKDIR python-api-core ================================================ FILE: projects/g-apis-py-api-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build flask fuzzers for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-apis-py-api-core/fuzz_path_template.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from google.api_core import path_template def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) targets = [ "expand", "transcode", "validate" ] target = targets[fdp.ConsumeIntInRange(0, len(targets)-1)] if target == "expand": s1 = fdp.ConsumeString(200) s2 = fdp.ConsumeString(200) try: path_template.expand(s1, s2) except ValueError: # ValueError is raised # https://github.com/googleapis/python-api-core/blob/5b5e77563229687c901d77b5fdecc18168b535e6/google/api_core/path_template.py#L123 pass elif target == "transcode": s1 = fdp.ConsumeString(200) s2 = fdp.ConsumeString(200) s3 = fdp.ConsumeString(200) try: path_template.transcode([{'uri' : s1, 'body' : s2,'method' : s3}]) except ValueError: # ValueError is raised: # https://github.com/googleapis/python-api-core/blob/main/google/api_core/path_template.py#L260 pass elif target == "validate": s1 = fdp.ConsumeString(200) s2 = fdp.ConsumeString(200) path_template.validate(s1, s2) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-apis-py-api-core/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-api-core language: python main_repo: https://github.com/googleapis/python-api-core sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-auth-library-java/.gitignore ================================================ project-parent/google-auth-library-java project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/g-auth-library-java/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/google-auth-library-java RUN git clone --depth 1 https://github.com/googleapis/google-auth-library-java/ $SRC/project-parent/google-auth-library-java COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/g-auth-library-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=google-auth-library-java PROJECT_GROUP_ID=com.google.auth PROJECT_ARTIFACT_ID=google-auth-library MAIN_REPOSITORY=https://github.com/googleapis/google-auth-library-java/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) FUZZ_TARGET_DEPENDENCIES=":google-auth-library-oauth2-http :google-auth-library-credentials :google-auth-library-appengine" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/g-auth-library-java/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test com.google.auth google-auth-library-oauth2-http Fuzzing-SNAPSHOT com.google.auth google-auth-library-credentials Fuzzing-SNAPSHOT com.google.auth google-auth-library-appengine Fuzzing-SNAPSHOT com.google.api-client google-api-client 2.2.0 com.google.cloud google-cloud-storage 1.113.2 maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/g-auth-library-java/project-parent/fuzz-targets/src/test/java/com/example/CredentialsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.google.auth.oauth2.*; import com.google.auth.http.HttpTransportFactory; import com.google.api.client.http.HttpTransport; import com.google.api.client.testing.http.MockHttpTransport; import java.io.ByteArrayInputStream; import java.io.IOException; class CredentialsFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { boolean b = data.consumeBoolean(); MockHttpTransportFactory transportFactory = new MockHttpTransportFactory(); ByteArrayInputStream bais = new ByteArrayInputStream(data.consumeRemainingAsBytes()); try { GoogleCredentials [] credentials = { b ? GoogleCredentials.fromStream(bais) : GoogleCredentials.fromStream(bais, transportFactory), b ? ServiceAccountCredentials.fromStream(bais) : ServiceAccountCredentials.fromStream(bais, transportFactory), b ? ExternalAccountCredentials.fromStream(bais) : ExternalAccountCredentials.fromStream(bais, transportFactory), b ? ExternalAccountAuthorizedUserCredentials.fromStream(bais) : ExternalAccountAuthorizedUserCredentials.fromStream(bais, transportFactory), b ? UserCredentials.fromStream(bais) : UserCredentials.fromStream(bais, transportFactory) }; GoogleCredentials googleCredentials = data.pickValue(credentials); googleCredentials.refreshIfExpired(); googleCredentials.refreshAccessToken(); googleCredentials.getAccessToken(); } catch (IOException expected) { } catch (IllegalArgumentException | NullPointerException | ClassCastException | IllegalStateException ignored) { // Need to catch in order to find more interesting bugs. } } static class MockHttpTransportFactory implements HttpTransportFactory { MockHttpTransport transport = new MockHttpTransport(); @Override public HttpTransport create() { return transport; } } } ================================================ FILE: projects/g-auth-library-java/project-parent/fuzz-targets/src/test/java/com/example/TokenVerifierFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.google.api.client.json.webtoken.JsonWebSignature; import com.google.auth.oauth2.TokenVerifier; import java.security.GeneralSecurityException; class TokenVerifierFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { TokenVerifier tokenVerifier = TokenVerifier.newBuilder().build(); try { JsonWebSignature jsonWebSignature = tokenVerifier.verify(data.consumeRemainingAsString()); jsonWebSignature.verifySignature(); } catch (TokenVerifier.VerificationException | GeneralSecurityException e) { } catch (IllegalArgumentException | NullPointerException e) { // Need to catch in order to find more interesting findings. } } } ================================================ FILE: projects/g-auth-library-java/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom google-auth-library-java fuzz-targets ================================================ FILE: projects/g-auth-library-java/project.yaml ================================================ homepage: "developers.google.com/identity" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/googleapis/google-auth-library-java/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/g-cloud-logging-py/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/googleapis/python-logging gcloud-logging RUN pip3 install --upgrade pip mock WORKDIR gcloud-logging COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/g-cloud-logging-py/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-cloud-logging-py/fuzz_entries.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import google.cloud.logging_v2.entries as entries from google.cloud.logging_v2.client import Client from google.cloud.logging_v2.resource import Resource def create_dummy_log_entry(fdp): return entries.LogEntry( log_name=fdp.ConsumeString(20), labels={ fdp.ConsumeString(10):fdp.ConsumeString(20), fdp.ConsumeString(10):fdp.ConsumeString(20) }, insert_id=fdp.ConsumeString(20), timestamp=fdp.ConsumeString(20), resource=Resource(type="global", labels={}), trace=fdp.ConsumeString(20), span_id=fdp.ConsumeString(20), trace_sampled=fdp.ConsumeBool(), source_location=LogEntrySourceLocation( file=fdp.ConsumeString(20), line=fdp.ConsumeString(20), function=fdp.ConsumeString(20) ), operation=LogEntryOperation( id=fdp.ConsumeString(20), producer=fdp.ConsumeString(20), first=fdp.ConsumeBool(), last=fdp.ConsumeBool() ) ) def TestInput(data): if len(data) < 1: return fdp = atheris.FuzzedDataProvider(data) try: entries._int_or_none(fdp.ConsumeInt(100)) entries.logger_name_from_path(fdp.ConsumeString(100)) entries.logger_name_from_path(fdp.ConsumeString(100),fdp.ConsumeString(50)) log_entry = create_dummy_log_entry(fdp) log_entry.to_api_repr() TextEntry(log_entry).to_api_repr() StructEntry(log_entry).to_api_repr() protobuf_entry = ProtobufEntry(log_entry) protobuf_entry.payload_pb() protobuf_entry.payload_json() protobuf_entry.to_api_repr() except ValueError as e: if "did not match expected pattern" not in str(e): raise e def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-cloud-logging-py/fuzz_handlers.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import logging with atheris.instrument_imports(): import google.cloud.logging_v2.handlers.handlers as handlers import google.cloud.logging_v2.handlers.structured_log as log def TestInput(data): fdp = atheris.FuzzedDataProvider(data) logname = fdp.ConsumeString(100) message = fdp.ConsumeString(100) record = logging.LogRecord( logname, logging.INFO, None, None, message, None, None ) handlers.CloudLoggingFilter._infer_source_location(record) filter = handlers.CloudLoggingFilter(record) handler = log.StructuredLogHandler( labels={ fdp.ConsumeString(10):fdp.ConsumeString(20), fdp.ConsumeString(10):fdp.ConsumeString(20) }, project_id=fdp.ConsumeString(100) ) try: handler.format(record) handlers._format_and_parse_message(record, handler) handlers.setup_logging(handler) except ValueError as e: if "Formatting field not found in record" not in str(e): raise e def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-cloud-logging-py/fuzz_helpers.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import google.cloud.logging_v2._helpers as helpers import google.cloud.logging_v2.handlers._helpers as handlers_helpers def TestInput(data): fdp = atheris.FuzzedDataProvider(data) op = fdp.ConsumeIntInRange(0, 4) if op == 0: helpers._normalize_severity(fdp.ConsumeInt(fdp.ConsumeIntInRange(0, 512))) elif op == 1: helpers._add_defaults_to_filter(fdp.ConsumeUnicodeNoSurrogates(40)) elif op == 2: handlers_helpers._parse_trace_parent(fdp.ConsumeUnicodeNoSurrogates(300)) else: handlers_helpers._parse_xcloud_trace(fdp.ConsumeUnicodeNoSurrogates(300)) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-cloud-logging-py/fuzz_resources.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import mock with atheris.instrument_imports(): from google.cloud.logging_v2.handlers import _monitored_resources global_fdp = None def mock_retrieve_metadata_server(endpoint): """Mock for retrieve_metadata_server""" if global_fdp is None: return None if global_fdp.ConsumeIntInRange(1, 10) < 3: return None return global_fdp.ConsumeUnicodeNoSurrogates(30) def TestInput(data): global global_fdp global_fdp = atheris.FuzzedDataProvider(data) # Mock the metadata server to avoid connections. The # retrieve_metadata_server will return fuzzer-seeded data. patch = mock.patch( "google.cloud.logging_v2.handlers._monitored_resources.retrieve_metadata_server", wraps=mock_retrieve_metadata_server, ) # TODO: randomise relevant environment variables. with patch: _monitored_resources.detect_resource() def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-cloud-logging-py/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-logging language: python main_repo: https://github.com/googleapis/python-logging sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-http-java-client/.gitignore ================================================ project-parent/google-http-java-client project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/g-http-java-client/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/google-http-java-client RUN git clone --depth 1 https://github.com/googleapis/google-http-java-client/ $SRC/project-parent/google-http-java-client COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/g-http-java-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=google-http-java-client PROJECT_GROUP_ID=com.google.http-client PROJECT_ARTIFACT_ID=google-http-client MAIN_REPOSITORY=https://github.com/googleapis/google-http-java-client/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -Denforcer.skip=true -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) FUZZ_TARGET_DEPENDENCIES=":google-http-client :google-http-client-gson" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --jvm_args=\"\$mem_settings\" \ --target_class=com.example.$fuzzer_basename \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/g-http-java-client/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.platform junit-platform-launcher 1.9.2 org.junit.jupiter junit-jupiter-engine 5.9.2 test com.google.http-client google-http-client Fuzzing-SNAPSHOT com.google.http-client google-http-client-gson Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/g-http-java-client/project-parent/fuzz-targets/src/test/java/com/example/JsonObjectParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.io.IOException; import java.io.InputStream; import java.io.ByteArrayInputStream; import java.nio.charset.Charset; import java.lang.IllegalArgumentException; import java.lang.NullPointerException; import com.google.api.client.json.GenericJson; import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.json.JsonObjectParser; class JsonObjectParserFuzzer { static String [] charsetArray = {"ISO-8859-1", "US-ASCII", "UTF-16", "UTF-16BE", "UTF-16LE", "UTF-8"}; @FuzzTest void myFuzzTest(FuzzedDataProvider data) { Charset charset = Charset.forName(data.pickValue(charsetArray)); boolean readLeniency = data.consumeBoolean(); String input = data.consumeRemainingAsString(); try { JsonObjectParser parser = new JsonObjectParser(GsonFactory.builder().setReadLeniency(readLeniency).build()); InputStream inputStream = new ByteArrayInputStream(input.getBytes(charset)); GenericJson json = parser.parseAndClose(inputStream, charset, GenericJson.class); } catch (IOException | IllegalArgumentException | NullPointerException e) { } } } ================================================ FILE: projects/g-http-java-client/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom google-http-java-client fuzz-targets ================================================ FILE: projects/g-http-java-client/project.yaml ================================================ homepage: "https://github.com/googleapis/google-http-java-client/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/googleapis/google-http-java-client/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" ================================================ FILE: projects/g-oauth-java-client/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/googleapis/google-oauth-java-client google-oauth-java-client COPY *.sh *.java $SRC/ WORKDIR $SRC/google-oauth-java-client ================================================ FILE: projects/g-oauth-java-client/OauthSignerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.google.api.client.auth.oauth.OAuthSigner; import com.google.api.client.auth.oauth.OAuthHmacSigner; import com.google.api.client.auth.oauth.OAuthHmacSha256Signer; import com.google.api.client.auth.oauth.OAuthRsaSigner; import java.security.GeneralSecurityException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-2 // Heuristic name: jvm-autofuzz-heuristics-2 // Target method: [com.google.api.client.auth.oauth.OAuthHmacSha256Signer] public java.lang.String computeSignature(java.lang.String) throws java.security.GeneralSecurityException // Target method: [com.google.api.client.auth.oauth.OAuthHmacSigner] public java.lang.String computeSignature(java.lang.String) throws java.security.GeneralSecurityException // Target method: [com.google.api.client.auth.oauth.OAuthRsaSigner] public java.lang.String computeSignature(java.lang.String) throws java.security.GeneralSecurityException public class OauthSignerFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { OAuthSigner obj = null; switch (data.consumeInt(1, 3)) { case 1: obj = new OAuthHmacSigner(); break; case 2: obj = new OAuthHmacSha256Signer(data.consumeString(data.remainingBytes() / 2)); break; case 3: obj = new OAuthRsaSigner(); break; } obj.computeSignature(data.consumeRemainingAsString()); } catch (GeneralSecurityException e1) { // Known exception } } } ================================================ FILE: projects/g-oauth-java-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade cp "./google-oauth-client/target/google-oauth-client-$CURRENT_VERSION.jar" $OUT/oauth.jar ALL_JARS='oauth.jar' # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/g-oauth-java-client/project.yaml ================================================ homepage: https://github.com/googleapis/google-oauth-java-client main_repo: https://github.com/googleapis/google-oauth-java-client language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/g-py-bigquery/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip && \ pip3 install numpy ipython grpcio RUN git clone https://github.com/googleapis/python-bigquery COPY build.sh *.py $SRC/ WORKDIR python-bigquery ================================================ FILE: projects/g-py-bigquery/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build flask fuzzers for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-py-bigquery/fuzz_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import IPython with atheris.instrument_imports(): from google.cloud.bigquery.magics.line_arg_parser.lexer import Lexer from google.cloud.bigquery.magics.line_arg_parser.parser import Parser from google.cloud.bigquery.magics.line_arg_parser.parser import ParseError from google.cloud.bigquery.magics.line_arg_parser.parser import QueryParamsParseError def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) s1 = fdp.ConsumeString(sys.maxsize) tokens = list(Lexer(s1)) if len(tokens) == 0: return lexer = Lexer(s1) parser = Parser(lexer) try: parser.input_line() except ParseError: pass lexer = Lexer(s1) parser = Parser(lexer) try: parser.collection_items() except QueryParamsParseError: pass lexer = Lexer(s1) parser = Parser(lexer) try: parser.dict_items() except QueryParamsParseError: pass def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-py-bigquery/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-bigquery language: python main_repo: https://github.com/googleapis/python-bigquery sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/g-py-crc32c/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/googleapis/python-crc32c COPY build.sh *.py $SRC/ WORKDIR python-crc32c ================================================ FILE: projects/g-py-crc32c/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git submodule update --init --recursive mkdir usr export CRC32C_INSTALL_PREFIX=$(pwd)/usr mkdir google_crc32c/build cd google_crc32c/build cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCRC32C_BUILD_TESTS=no \ -DCRC32C_BUILD_BENCHMARKS=no \ -DBUILD_SHARED_LIBS=yes \ -DCMAKE_INSTALL_PREFIX:PATH=${CRC32C_INSTALL_PREFIX} \ ../ make all install cd ../../ python3 setup.py build_ext \ --include-dirs=$(pwd)/usr/include \ --library-dirs=$(pwd)/usr/lib \ --rpath=$(pwd)/usr/lib pip3 install -e .[testing] # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/g-py-crc32c/fuzz_checksum.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): import google_crc32c def TestOneInput(data): val1 = google_crc32c.value(data) val2 = google_crc32c.Checksum(data)._crc assert val1 == val2 def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/g-py-crc32c/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-crc32c language: python main_repo: https://github.com/googleapis/python-crc32c sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/gast/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN git clone https://github.com/serge-sans-paille/gast gast COPY *.sh *py $SRC/ WORKDIR $SRC/gast ================================================ FILE: projects/gast/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gast/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/serge-sans-paille/gast language: python main_repo: https://github.com/serge-sans-paille/gast sanitizers: - address - undefined vendor_ccs: - david@adalogics.com base_os_version: ubuntu-24-04 ================================================ FILE: projects/gateway/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update \ && apt-get install -y btrfs-progs libbtrfs-dev RUN git clone --depth 1 https://github.com/envoyproxy/gateway.git RUN cd $SRC/gateway && \ GO_VERSION=$(grep -oP '^go \K[0-9]+\.[0-9]+(\.[0-9]+)?' go.mod | head -1) && \ wget https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz && \ mkdir temp-go && \ rm -rf /root/.go/* && \ tar -C temp-go/ -xzf go${GO_VERSION}.linux-amd64.tar.gz && \ mv temp-go/go/* /root/.go/ && \ rm -rf temp-go go${GO_VERSION}.linux-amd64.tar.gz COPY build.sh default.options $SRC/ ================================================ FILE: projects/gateway/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/gateway/test/fuzz/oss_fuzz_build.sh # Copy default.options to all fuzzers in $OUT if they don't have specific options files for fuzzer in "$OUT"/*; do # Skip non-files and files with extensions [[ ! -f "$fuzzer" ]] || [[ "$fuzzer" == *.* ]] && continue fuzzer_name=$(basename "$fuzzer") options_file="$OUT/${fuzzer_name}.options" if [[ ! -f "$options_file" ]] && [[ -f "$SRC/default.options" ]]; then cp "$SRC/default.options" "$options_file" fi done ================================================ FILE: projects/gateway/default.options ================================================ [libfuzzer] # Increase timeout for corpus pruning timeout = 300 ================================================ FILE: projects/gateway/project.yaml ================================================ homepage: "https://gateway.envoyproxy.io/" main_repo: "https://github.com/envoyproxy/gateway.git" primary_contact: "envoy-gateway-security@googlegroups.com" auto_ccs : - "tnareddy@confluent.io" - "sudiptobaral.me@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/gc-iam/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && \ apt-get install -y libre2-dev zlib1g-dev libssl-dev RUN python3 -m pip install --upgrade pip RUN git clone --depth 1 https://github.com/googleapis/google-cloud-python $SRC/google-cloud-python WORKDIR $SRC/google-cloud-python/packages/google-cloud-iam COPY build.sh fuzz_*.py $SRC/ # Ensure all relevant dependencies are installed RUN python3 -m pip install -r requirements.txt || : ================================================ FILE: projects/gc-iam/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies from setup.py python3 -m pip install . # Build and install project (using current CFLAGS, CXXFLAGS). GRPC_PYTHON_CFLAGS="${CFLAGS}" \ GRPC_PYTHON_BUILD_SYSTEM_RE2=true \ GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true \ GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true \ python3 setup.py install for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gc-iam/fuzz_credentials.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import google.cloud.iam_credentials_v1.services.iam_credentials as iam def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) iam.IAMCredentialsClient.service_account_path( fdp.ConsumeString(100), fdp.ConsumeString(100) ) iam.IAMCredentialsClient.parse_service_account_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_service_account_path( "projects/%s/serviceAccounts/%s"%( fdp.ConsumeString(100), fdp.ConsumeString(100) ) ) iam.IAMCredentialsClient.common_billing_account_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_billing_account_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_billing_account_path( "billingAccounts/%s/"%fdp.ConsumeString(100) ) iam.IAMCredentialsClient.common_folder_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_folder_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_folder_path( "folders/%s/"%fdp.ConsumeString(100) ) iam.IAMCredentialsClient.common_organization_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_organization_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_organization_path( "organizations/%s/"%fdp.ConsumeString(100) ) iam.IAMCredentialsClient.common_project_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_project_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_project_path( "projects/%s/"%fdp.ConsumeString(100) ) iam.IAMCredentialsClient.common_location_path( fdp.ConsumeString(100), fdp.ConsumeString(100) ) iam.IAMCredentialsClient.parse_common_location_path(fdp.ConsumeString(100)) iam.IAMCredentialsClient.parse_common_location_path( "projects/%s/locations/%s"%( fdp.ConsumeString(100), fdp.ConsumeString(100) ) ) def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gc-iam/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-iam language: python main_repo: https://github.com/googleapis/google-cloud-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/gcloud-error-py/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/googleapis/python-error-reporting gce WORKDIR gce COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/gcloud-error-py/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install mock pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gcloud-error-py/fuzz_util.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import mock with atheris.instrument_imports(): from google.cloud import error_reporting as error class SampleRequest(object): def __init__(self, url, method, user_agent, referrer, remote_addr): self.url = url self.method = method self.user_agent = user_agent self.referrer = referrer self.remote_addr = remote_addr def TestInput(data): fdp = atheris.FuzzedDataProvider(data) request = SampleRequest( "http://127.0.0.1", "GET" if fdp.ConsumeBool() else "POST", mock.Mock(string=fdp.ConsumeString(100)), fdp.ConsumeString(100), "127.0.0.1" ) error.util.build_flask_context(request) def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gcloud-error-py/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-error-reporting language: python main_repo: https://github.com/googleapis/python-error-reporting sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/gcloud-go/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go LABEL maintainer="codyoss@google.com" RUN git clone https://github.com/googleapis/google-cloud-go COPY build.sh $SRC/ WORKDIR $SRC/google-cloud-go/spanner/ ================================================ FILE: projects/gcloud-go/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer cloud.google.com/go/spanner/spansql FuzzParseQuery fuzz_parse_query ================================================ FILE: projects/gcloud-go/project.yaml ================================================ homepage: "https://github.com/googleapis/google-cloud-go" main_repo: "https://github.com/googleapis/google-cloud-go" primary_contact: "codyoss@google.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/gcp-python-cloud-storage/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip && pip3 install mock RUN git clone https://github.com/googleapis/python-storage COPY build.sh fuzz_fileio.py $SRC/ WORKDIR python-storage ================================================ FILE: projects/gcp-python-cloud-storage/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gcp-python-cloud-storage/fuzz_fileio.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import mock with atheris.instrument_imports(): from google.cloud.storage.fileio import BlobReader global_data = None def TestOneInput(data): global_data = data fdp = atheris.FuzzedDataProvider(data) blob = mock.Mock() def read_fuzz_data(start=0, end=None, **_): return global_data[start:end] blob.download_as_bytes = mock.Mock(side_effect=read_fuzz_data) blob.size = len(data) blob.chunk_size = None download_kwargs = {"if_metageneration_match": 1} reader = BlobReader(blob, **download_kwargs) try: reader.read(fdp.ConsumeIntInRange(0, len(data)*2)) except UnicodeDecodeError: return reader.seek( pos = fdp.ConsumeIntInRange(0, len(data)*2), whence = fdp.ConsumeIntInRange(0, 2) ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gcp-python-cloud-storage/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/googleapis/python-storage language: python main_repo: https://github.com/googleapis/python-storage primary_contact: gorcester@google.com sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/gdal/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && \ apt-get install -y make autoconf automake libtool g++ curl cmake sqlite3 pkg-config RUN git clone --depth 1 https://github.com/OSGeo/gdal gdal RUN cp gdal/fuzzers/build.sh $SRC/ WORKDIR gdal ================================================ FILE: projects/gdal/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://gdal.org" language: c++ primary_contact: "even.rouault@gmail.com" auto_ccs: - "schwehr@gmail.com" - "bishop.dev@gmail.com" - "juergen.fischer@gmail.com" - "athomas@thinkspatial.com.au" - "ari.jolma@gmail.com" - "bjorn.harrtell@gmail.com" - "nyall.dawson@gmail.com" - "uygabel@gmail.com" - "apasotti@gmail.com" architectures: - x86_64 - i386 main_repo: 'https://github.com/OSGeo/gdal' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/gdbm/Dockerfile ================================================ # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get -qq update && \ apt-get install -qq \ build-essential\ git\ autopoint\ automake\ bison\ flex\ libtool\ texinfo\ gettext RUN set -- $(apt-cache policy autoconf | \ sed -n -r -e '/^[[:space:]]+Candidate:[[:space:]]+/{' \ -e s/// \ -e 's/-.*//' \ -e 's/\./ /g' \ -e 'p}'); \ if [ "$2" -ge 71 ]; then \ apt-get install -qq autoconf; \ else \ (cd /usr/src && \ curl -oautoconf-2.71.tar.gz https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz && \ tar xf autoconf-2.71.tar.gz && \ cd autoconf-2.71 && \ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var && \ make install); \ fi RUN git clone --depth 1 https://git.gnu.org.ua/gdbm.git WORKDIR gdbm COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/gdbm/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Bootstrap and configure project ./bootstrap --no-po ./configure --disable-shared --enable-debug --disable-nls # Build project make -j$(nproc) all # Build fuzzer cd fuzz $CC $CFLAGS -c -I.. -I../src -I../tools -ogdbm_fuzzer.o gdbm_fuzzer.c $CXX $CXXFLAGS -ogdbm_fuzzer gdbm_fuzzer.o ../tools/libgdbmapp.a ../src/.libs/libgdbm.a $LIB_FUZZING_ENGINE cp gdbm_fuzzer $OUT cp gdbm_fuzzer.rc $OUT # Create seed PATH=$SRC/gdbm/tools:$PATH sh ./build_seed.sh -C seed zip -rj "$OUT/gdbm_fuzzer_seed_corpus.zip" seed/ ================================================ FILE: projects/gdbm/project.yaml ================================================ homepage: "https://www.gnu.org.ua/software/gdbm" language: c primary_contact: "sergey.poznyakoff@gmail.com" auto_ccs: - "gray@gnu.org" main_repo: "https://git.gnu.org.ua/gdbm.git" ================================================ FILE: projects/gdbm/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Backup testsuite.at for later restore cp tests/testsuite.at tests/testsuite.at.backup # Temporarily disable 3 unit tests that are failing sed -i '/m4_include(\[emptydatum.at\])/d' tests/testsuite.at sed -i '/m4_include(\[dumpload.at\])/d' tests/testsuite.at sed -i '/m4_include(\[coalesce.at\])/d' tests/testsuite.at make check -j$(nproc) # Restore the testsuite.at to pass integrity check of run_tests.sh mv tests/testsuite.at.backup tests/testsuite.at ================================================ FILE: projects/gdk-pixbuf/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y ffmpeg python3-pip gtk-doc-tools libffi-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* RUN pip3 install --disable-pip-version-check --no-cache-dir \ pip==25.1.1 RUN pip3 install --disable-pip-version-check --no-cache-dir \ corpus-replicator \ meson==1.8.2 \ ninja==1.11.1.4 RUN git clone --depth=1 --no-tags https://gitlab.gnome.org/GNOME/gdk-pixbuf.git RUN git clone --depth=1 --branch=2.84.3 https://gitlab.gnome.org/GNOME/glib.git RUN corpus-replicator -o corpus image_gif_gif_ffmpeg.yml image_jpg_jpg_ffmpeg.yml image_png_png_ffmpeg.yml image RUN git clone --depth=1 --no-tags https://github.com/glennrp/libpng.git && \ find $SRC/gdk-pixbuf/tests/ \( -name '*.jpeg' -o -name '*.jpg' -o -name '*.png' \) -exec cp -v '{}' corpus/ ';' && \ find $SRC/libpng -name "*.png" | grep -v crashers | xargs cp -t corpus/ && \ zip -q $SRC/gdk-pixbuf_seed_corpus.zip corpus/* && \ rm -rf libpng corpus ADD https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/png.dict $SRC/png.dict ADD https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/jpeg.dict $SRC/jpeg.dict ADD https://raw.githubusercontent.com/google/fuzzing/master/dictionaries/gif.dict $SRC/gif.dict RUN awk 1 $SRC/*.dict > $SRC/gdk-pixbuf.dict && \ rm -f $SRC/png.dict $SRC/jpeg.dict $SRC/gif.dict WORKDIR $SRC/gdk-pixbuf COPY targets $SRC/fuzz COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/gdk-pixbuf/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PREFIX=$WORK/prefix mkdir -p $PREFIX export PKG_CONFIG="`which pkg-config` --static" export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig export PATH=$PREFIX/bin:$PATH BUILD=$WORK/build rm -rf $WORK/* rm -rf $BUILD mkdir -p $BUILD # Build glib pushd $SRC/glib meson setup \ --prefix=$PREFIX \ --libdir=lib \ --default-library=static \ -Db_lundef=false \ -Doss_fuzz=enabled \ -Dlibmount=disabled \ -Dman-pages=disabled \ -Dsysprof=disabled \ -Dtests=false \ _builddir ninja -C _builddir ninja -C _builddir install popd # Build gdk-pixbuf # TODO: Enable tiff support pushd $SRC/gdk-pixbuf meson setup \ --prefix=$PREFIX \ --libdir=lib \ --default-library=static \ -Dintrospection=disabled \ -Dman=false \ -Ddocumentation=false \ -Dtests=true \ -Dinstalled_tests=false \ -Dthumbnailer=disabled \ -Dglycin=disabled \ -Dbuiltin_loaders='all' \ -Djpeg=enabled \ -Dpng=enabled \ -Dgif=enabled \ -Dothers=enabled \ -Dtiff=disabled \ _builddir ninja -C _builddir ninja -C _builddir install popd mv $SRC/{*.zip,*.dict} $OUT if [ ! -f "${OUT}/gdk-pixbuf_seed_corpus.zip" ]; then echo "missing seed corpus" exit 1 fi if [ ! -f "${OUT}/gdk-pixbuf.dict" ]; then echo "missing dictionary" exit 1 fi PREDEPS_LDFLAGS="-Wl,-Bdynamic -ldl -lm -lc -pthread -lrt -lpthread" DEPS="gmodule-2.0 glib-2.0 gio-2.0 gobject-2.0 gdk-pixbuf-2.0" BUILD_CFLAGS="$CFLAGS `pkg-config --static --cflags $DEPS`" BUILD_LDFLAGS="-Wl,-static `pkg-config --static --libs $DEPS`" fuzzers=$(find $SRC/fuzz/ -name "*_fuzzer.c") for f in $fuzzers; do fuzzer_name=$(basename $f .c) $CC $CFLAGS $BUILD_CFLAGS -c $f -o $WORK/${fuzzer_name}.o $CXX $CXXFLAGS \ $WORK/${fuzzer_name}.o -o $OUT/${fuzzer_name} \ $PREDEPS_LDFLAGS \ $BUILD_LDFLAGS \ $LIB_FUZZING_ENGINE \ -Wl,-Bdynamic ln -sf $OUT/gdk-pixbuf_seed_corpus.zip $OUT/${fuzzer_name}_seed_corpus.zip ln -sf $OUT/gdk-pixbuf.dict $OUT/${fuzzer_name}.dict done ================================================ FILE: projects/gdk-pixbuf/project.yaml ================================================ homepage: https://gitlab.gnome.org/GNOME/gdk-pixbuf/ language: c primary_contact: ebassi@gnome.org sanitizers: - address - undefined main_repo: 'https://gitlab.gnome.org/GNOME/gdk-pixbuf.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/gdk-pixbuf/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Exclude the test case in the slow suite which are always killed because of timeout meson test -C _builddir --no-suite "slow" -j$(nproc) ================================================ FILE: projects/gdk-pixbuf/targets/animation_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 1) { return 0; } GError *error = NULL; GdkPixbuf *pixbuf; GdkPixbufAnimation *anim; char *tmpfile = fuzzer_get_tmpfile(data, size); anim = gdk_pixbuf_animation_new_from_file(tmpfile, &error); if (error != NULL) { g_clear_error(&error); fuzzer_release_tmpfile(tmpfile); return 0; } char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; pixbuf = gdk_pixbuf_animation_get_static_image(anim); if (pixbuf != NULL) { unsigned int rot_amount = ((unsigned int) data[0]) % 4; pixbuf = gdk_pixbuf_rotate_simple(pixbuf, rot_amount * 90); gdk_pixbuf_set_option(pixbuf, buf, buf); gdk_pixbuf_get_pixels(pixbuf); gdk_pixbuf_get_width(pixbuf); gdk_pixbuf_get_height(pixbuf); g_object_unref(pixbuf); } free(buf); g_object_unref(anim); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/gdk-pixbuf/targets/fuzzer_temp_file.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Adapter utility from fuzzer input to a temporary file, for fuzzing APIs that // require a file instead of an input buffer. #ifndef FUZZER_TEMP_FILE_H_ #define FUZZER_TEMP_FILE_H_ #include #include #include #include #include // Pure-C interface for creating and cleaning up temporary files. static char *fuzzer_get_tmpfile(const uint8_t *data, size_t size) { char *filename_buffer = strdup("/tmp/generate_temporary_file.XXXXXX"); if (!filename_buffer) { perror("Failed to allocate file name buffer."); abort(); } const int file_descriptor = mkstemp(filename_buffer); if (file_descriptor < 0) { perror("Failed to make temporary file."); abort(); } FILE *file = fdopen(file_descriptor, "wb"); if (!file) { perror("Failed to open file descriptor."); close(file_descriptor); abort(); } const size_t bytes_written = fwrite(data, sizeof(uint8_t), size, file); if (bytes_written < size) { close(file_descriptor); fprintf(stderr, "Failed to write all bytes to file (%zu out of %zu)", bytes_written, size); abort(); } fclose(file); return filename_buffer; } static void fuzzer_release_tmpfile(char *filename) { if (unlink(filename) != 0) { perror("WARNING: Failed to delete temporary file."); } free(filename); } // C++ RAII object for creating temporary files. #ifdef __cplusplus class FuzzerTemporaryFile { public: FuzzerTemporaryFile(const uint8_t *data, size_t size) : filename_(fuzzer_get_tmpfile(data, size)) {} ~FuzzerTemporaryFile() { fuzzer_release_tmpfile(filename_); } const char *filename() const { return filename_; } private: char *filename_; }; #endif #endif // FUZZER_TEMP_FILE_H_ ================================================ FILE: projects/gdk-pixbuf/targets/pixbuf_cons_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #define WIDTH 10 #define HEIGHT 20 #define ROWSTRIDE (WIDTH * 4) int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (!(size >= WIDTH * HEIGHT * 4)) { return 0; } const gchar *profile; GdkPixbuf *pixbuf, *tmp; GBytes *bytes; bytes = g_bytes_new_static(data, size); pixbuf = g_object_new(GDK_TYPE_PIXBUF, "width", WIDTH, "height", HEIGHT, "rowstride", ROWSTRIDE, "bits-per-sample", 8,"n-channels", 3, "has-alpha", FALSE, "pixel-bytes", bytes, NULL); if (pixbuf == NULL) { return 0; } gdk_pixbuf_scale(pixbuf, pixbuf, 0, 0, gdk_pixbuf_get_width(pixbuf) / 4, gdk_pixbuf_get_height(pixbuf) / 4, 0, 0, 0.5, 0.5, GDK_INTERP_NEAREST); unsigned int rot_amount = ((unsigned int) data[0]) % 4; tmp = gdk_pixbuf_rotate_simple(pixbuf, rot_amount * 90); tmp = gdk_pixbuf_flip(pixbuf, TRUE); tmp = gdk_pixbuf_composite_color_simple(pixbuf, gdk_pixbuf_get_width(pixbuf) / 4, gdk_pixbuf_get_height(pixbuf) / 4, GDK_INTERP_NEAREST, 128, 8, G_MAXUINT32, G_MAXUINT32/2); char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; gdk_pixbuf_set_option(pixbuf, buf, buf); profile = gdk_pixbuf_get_option(pixbuf, buf); tmp = gdk_pixbuf_new_from_data(gdk_pixbuf_get_pixels(pixbuf), GDK_COLORSPACE_RGB, FALSE, gdk_pixbuf_get_bits_per_sample(pixbuf), gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), gdk_pixbuf_get_rowstride(pixbuf), NULL, NULL); tmp = gdk_pixbuf_flip(tmp, TRUE); free(buf); g_object_unref(pixbuf); g_object_unref(tmp); return 0; } ================================================ FILE: projects/gdk-pixbuf/targets/pixbuf_file_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 1) { return 0; } GdkPixbuf *pixbuf, *rotated, *scaled; GError *error = NULL; char *tmpfile = fuzzer_get_tmpfile(data, size); pixbuf = gdk_pixbuf_new_from_file(tmpfile, &error); if (error != NULL) { g_clear_error(&error); fuzzer_release_tmpfile(tmpfile); return 0; } char *buf = (char *) calloc(size + 1, sizeof(char)); memcpy(buf, data, size); buf[size] = '\0'; gdk_pixbuf_get_width(pixbuf); gdk_pixbuf_get_height(pixbuf); gdk_pixbuf_get_bits_per_sample(pixbuf); scaled = gdk_pixbuf_scale_simple(pixbuf, gdk_pixbuf_get_width(pixbuf) / 4, gdk_pixbuf_get_height(pixbuf) / 4, GDK_INTERP_NEAREST); if (scaled) g_object_unref(scaled); unsigned int rot_amount = ((unsigned int) data[0]) % 4; rotated = gdk_pixbuf_rotate_simple(pixbuf, rot_amount * 90); g_object_unref(pixbuf); pixbuf = rotated; gdk_pixbuf_set_option(pixbuf, buf, buf); gdk_pixbuf_get_option(pixbuf, buf); free(buf); g_clear_object(&pixbuf); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/gdk-pixbuf/targets/pixbuf_scale_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 1) { return 0; } GError *error = NULL; GdkPixbuf *pixbuf; char *tmpfile = fuzzer_get_tmpfile(data, size); pixbuf = gdk_pixbuf_new_from_file_at_scale(tmpfile, 1, size, TRUE, &error); if (pixbuf != NULL) { g_clear_object(&pixbuf); } else { g_clear_error(&error); } pixbuf = gdk_pixbuf_new_from_file_at_scale(tmpfile, 1, size, FALSE, &error); if (pixbuf != NULL) { g_clear_object(&pixbuf); } else { g_clear_error(&error); } fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/gdk-pixbuf/targets/stream_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include "fuzzer_temp_file.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { GError *error = NULL; GdkPixbuf *pixbuf; GFile *file; GInputStream *stream; char *tmpfile = fuzzer_get_tmpfile(data, size); file = g_file_new_for_path(tmpfile); stream = (GInputStream *) g_file_read(file, NULL, &error); if (error != NULL) { g_clear_error(&error); g_object_unref(file); fuzzer_release_tmpfile(tmpfile); return 0; } pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, &error); if (pixbuf != NULL) { g_object_unref(pixbuf); } g_clear_error(&error); g_object_unref(stream); g_object_unref(file); fuzzer_release_tmpfile(tmpfile); return 0; } ================================================ FILE: projects/genshi/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/edgewall/genshi genshi COPY *.sh *py $SRC/ WORKDIR $SRC/genshi ================================================ FILE: projects/genshi/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/genshi/fuzz_html.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import genshi from genshi.path import PathSyntaxError from genshi.template.base import TemplateError from genshi.input import ParseError def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) html_raw = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) try: genshi.input.HTML(html_raw) except ( PathSyntaxError, TemplateError, ParseError, ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/genshi/project.yaml ================================================ homepage: https://github.com/edgewall/genshi main_repo: https://github.com/edgewall/genshi language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/geos/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake # fallback to github if main git server is not responding RUN git clone --depth 1 https://git.osgeo.org/gitea/geos/geos.git || git clone --depth 1 https://github.com/libgeos/geos.git COPY run_tests.sh build.sh $SRC/ COPY patch.diff $SRC WORKDIR $SRC/geos RUN git apply ../patch.diff ================================================ FILE: projects/geos/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project mkdir build cd build cmake -DBUILD_SHARED_LIBS=OFF .. make -j$(nproc) cp bin/fuzz* $OUT/ ================================================ FILE: projects/geos/patch.diff ================================================ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3401775c8..70af383b4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,3 +10,4 @@ ################################################################################ add_subdirectory(unit) add_subdirectory(xmltester) +add_subdirectory(fuzz) diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt new file mode 100644 index 000000000..d0bd7a020 --- /dev/null +++ b/tests/fuzz/CMakeLists.txt @@ -0,0 +1,15 @@ +################################################################################ +# Part of CMake configuration for GEOS +# +# Copyright (C) 2018 Mateusz Loskot +# +# This is free software; you can redistribute and/or modify it under +# the terms of the GNU Lesser General Public Licence as published +# by the Free Software Foundation. +# See the COPYING file for more information. +################################################################################ +if(DEFINED ENV{LIB_FUZZING_ENGINE}) + add_executable(fuzz_geo2 fuzz_geo2.c) + target_include_directories(fuzz_geo2 PUBLIC $) + target_link_libraries(fuzz_geo2 geos_c $ENV{LIB_FUZZING_ENGINE}) +endif() diff --git a/tests/fuzz/fuzz_geo2.c b/tests/fuzz/fuzz_geo2.c new file mode 100644 index 000000000..ceee7ea6b --- /dev/null +++ b/tests/fuzz/fuzz_geo2.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "geos_c.h" + +static int initialized = 0; +FILE * flogOut; + +void +notice(const char *fmt, ...) { + va_list ap; + fprintf( flogOut, "NOTICE: "); + va_start (ap, fmt); + vfprintf( flogOut, fmt, ap); + va_end(ap); + fprintf( flogOut, "\n" ); +} + +void +log_and_exit(const char *fmt, ...) { + va_list ap; + fprintf( flogOut, "ERROR: "); + va_start (ap, fmt); + vfprintf( flogOut, fmt, ap); + va_end(ap); + fprintf( flogOut, "\n" ); +} + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + if (initialized == 0) { + flogOut = fopen("/dev/null", "wb"); + initGEOS(notice, log_and_exit); + initialized = 1; + } + size_t sep; + for (sep = 0; sep < Size; sep ++) { + if (Data[sep] == 0) { + break; + } + } + if (sep == Size) { + return 0; + } + GEOSGeometry *g1 = GEOSGeomFromWKT(Data); + + if (g1 != NULL) { + GEOSGeometry *g2 = GEOSGeomFromWKB_buf(Data+sep, Size-sep); + if (g2 != NULL) { + size_t usize; + GEOSGeometry *g3 = GEOSIntersection(g1, g2); + GEOSGeom_destroy(g3); + g3 = GEOSDifference(g1, g2); + GEOSGeom_destroy(g3); + g3 = GEOSUnion(g1, g2); + GEOSGeom_destroy(g3); + unsigned char* uptr = GEOSGeomToWKB_buf(g1, &usize); + free(uptr); + GEOSGeom_destroy(g2); + } + char * r = GEOSGeomToWKT(g1); + free(r); + GEOSGeom_destroy(g1); + } + return 0; +} + ================================================ FILE: projects/geos/project.yaml ================================================ homepage: "https://geos.osgeo.org" language: c++ primary_contact: "mtnclimb@gmail.com" auto_ccs : - "strk@kbt.io" - "lr@pcorp.us" - "p.antoine@catenacyber.fr" sanitizers: - address - undefined main_repo: 'https://git.osgeo.org/gitea/geos/geos.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/geos/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build ================================================ FILE: projects/gfwx/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/guidovranken/gfwx-fuzzers.git gfwx-fuzzers WORKDIR gfwx-fuzzers COPY build.sh $SRC/ ================================================ FILE: projects/gfwx/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [[ $CFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi make cp fuzzer-encoder $OUT/ cp fuzzer-encoder_seed_corpus.zip $OUT/ cp fuzzer-decoder $OUT/ cp fuzzer-decoder_seed_corpus.zip $OUT/ ================================================ FILE: projects/gfwx/project.yaml ================================================ homepage: "http://www.gfwx.org/" language: c++ primary_contact: "fyffe@google.com" main_repo: "https://github.com/kalcutter/gfwx" sanitizers: - address - undefined - memory fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/ghostscript/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf zlibc libtool liblcms2-dev libpng-dev RUN git clone --branch branch-2.2 --single-branch --depth 1 https://github.com/apple/cups.git cups RUN git clone --branch VER-2-14-0 --single-branch --depth 1 https://git.savannah.gnu.org/git/freetype/freetype2.git freetype RUN git clone --single-branch --depth 1 git://git.ghostscript.com/ghostpdl.git ghostpdl RUN mkdir ghostpdl/fuzz COPY pdf_seeds $SRC/pdf_seeds COPY dicts $SRC/dicts WORKDIR ghostpdl COPY *.cc *.options *.h $SRC/ COPY build.sh $SRC/ ================================================ FILE: projects/ghostscript/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build CUPS pushd $SRC/cups # Fix bad line sed -i '2110s/\(\s\)f->value/\1(int)f->value/' cups/ppd-cache.c LSB_BUILD=y ./configure --prefix="$WORK" --libdir="$OUT" --disable-gnutls \ --disable-libusb --with-components=core make clean make install-headers install-libs make -C filter libs install-libs install -m755 cups-config "$WORK"/cups-config popd rm -rf cups/libs || die rm -rf freetype || die rm -rf zlib || die mv $SRC/freetype freetype CUPSCONFIG="$WORK/cups-config" CUPS_CFLAGS=$($CUPSCONFIG --cflags) CUPS_LDFLAGS=$($CUPSCONFIG --ldflags) CUPS_LIBS=$($CUPSCONFIG --image --libs) export CXXFLAGS="$CXXFLAGS $CUPS_CFLAGS" CPPFLAGS="${CPPFLAGS:-} $CUPS_CFLAGS -DPACIFY_VALGRIND" ./autogen.sh \ CUPSCONFIG=$CUPSCONFIG \ --enable-freetype --enable-fontconfig \ --enable-cups --with-ijs --with-jbig2dec \ --with-drivers=pdfwrite,cups,ljet4,laserjet,pxlmono,pxlcolor,pcl3,uniprint,pgmraw,ps2write,png16m,tiffsep1,faxg3,psdcmyk,eps2write,bmpmono,xpswrite make -j$(nproc) libgs fuzzers="gstoraster_fuzzer \ gstoraster_fuzzer_all_colors \ gstoraster_ps_fuzzer \ gstoraster_pdf_fuzzer \ gs_device_pdfwrite_fuzzer \ gs_device_pxlmono_fuzzer \ gs_device_pgmraw_fuzzer \ gs_device_ps2write_fuzzer \ gs_device_png16m_fuzzer \ gs_device_psdcmyk_fuzzer \ gs_device_eps2write_fuzzer \ gs_device_faxg3_fuzzer \ gs_device_bmpmono_fuzzer \ gs_device_xpswrite_fuzzer \ gs_device_pxlcolor_fuzzer \ gs_device_tiffsep1_fuzzer \ gs_device_pdfwrite_opts_fuzzer" for fuzzer in $fuzzers; do $CXX $CXXFLAGS $CUPS_LDFLAGS -std=c++11 -I. -I$SRC \ $SRC/${fuzzer}.cc \ -o "$OUT/${fuzzer}" \ -Wl,-rpath='$ORIGIN' \ $CUPS_LIBS \ $LIB_FUZZING_ENGINE bin/gs.a done # Create PDF seed corpus zip -j "$OUT/gstoraster_pdf_fuzzer_seed_corpus.zip" $SRC/pdf_seeds/* # Create corpus for gstoraster_fuzzer_all_colors. Only use seeds of a few KB in size. mkdir -p "$WORK/all_color_seeds" for f in examples/ridt91.eps examples/snowflak.ps $SRC/pdf_seeds/pdf.pdf; do # Prepend a single byte to seed, because it's used to determine the color # scheme in the gstoraster_fuzzer_all_colors. printf "\x01" | cat - "$f" > tmp_file.txt mv tmp_file.txt $f s=$(sha1sum "$f" | awk '{print $1}') cp "$f" "$WORK/all_color_seeds/$s" done zip -j "$OUT/gstoraster_fuzzer_all_colors_seed_corpus.zip" "$WORK"/all_color_seeds/* # Do the same thing with pdfwrites opt fuzzer, but multiple bytes mkdir -p "$WORK/gs_device_pdfwrite_opts_fuzzer_seeds" for f in examples/ridt91.eps examples/snowflak.ps $SRC/pdf_seeds/pdf.pdf; do # Prepend the number of bytes used for picking options in the opts fuzzer printf "\x01\x01" | cat - "$f" > tmp_file.txt mv tmp_file.txt $f s=$(sha1sum "$f" | awk '{print $1}') cp "$f" "$WORK/gs_device_pdfwrite_opts_fuzzer_seeds/$s" done zip -j "$OUT/gs_device_pdfwrite_opts_fuzzer_seed_corpus.zip" "$WORK"/gs_device_pdfwrite_opts_fuzzer_seeds/* # Create seeds for gstoraster_fuzzer mkdir -p "$WORK/seeds" for f in examples/*.{ps,pdf}; do s=$(sha1sum "$f" | awk '{print $1}') cp "$f" "$WORK/seeds/$s" done # Create corpus for gstoraster_fuzzer zip -j "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$WORK"/seeds/* cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_pdfwrite_fuzzer_seed_corpus.zip" cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_pxlmono_fuzzer_seed_corpus.zip" cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_eps2write_fuzzer_seed_corpus.zip" cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_bmpmono_fuzzer_seed_corpus.zip" cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_xpswrite_fuzzer_seed_corpus.zip" cp "$OUT/gstoraster_fuzzer_seed_corpus.zip" "$OUT/gs_device_pxlcolor_fuzzer_seed_corpus.zip" # Copy out options cp $SRC/*.options $OUT/ # Copy out dictionary fuzzers_with_dict="gstoraster_fuzzer \ gstoraster_fuzzer_all_colors \ gstoraster_pdf_fuzzer \ gs_device_pdfwrite_fuzzer \ gs_device_faxg3_fuzzer \ gs_device_bmpmono_fuzzer \ gs_device_xpswrite_fuzzer" for fuzzer in $fuzzers_with_dict; do cp $SRC/dicts/pdf.dict $OUT/${fuzzer}.dict done cp $SRC/dicts/ps.dict $OUT/gstoraster_ps_fuzzer.dict ================================================ FILE: projects/ghostscript/dicts/pdf.dict ================================================ # # AFL dictionary for PDF # ---------------------- # # This is a pretty big PDF dictionary constructed by Ben by manually reviewing # the spec and combining that with the data pulled out of a corpus of sample # PDFs. # # Contributed by Ben Nagy # "#" "%" "%%" "%%EOF" "%FDF-1.7" "%PDF-1.7" "(" "(/xdp:xdp)" "(\\001)" "(config)" "(datasets)" "(template)" "(xdp:xdp)" ")" "-1" "-1.0" ".." "/" "/#23clipboard" "/.notdef" "/1" "/1.0" "/1.3" "/3D" "/3DA" "/3DAnimationStyle" "/3DB" "/3DD" "/3DI" "/3DLightingScheme" "/3DRenderMode" "/3DV" "/3DView" "/90pv-RKSJ-H" "/A" "/A0" "/A85" "/AA" "/AAIC" "/AAPL" "/ABCDEF+ACaslonPro-Regular" "/ABCDEF+AJensonPro-LtIt" "/ABCDEF+AdobeCorpID-MinionRg" "/ABCDEF+Arial,Bold" "/ABCDEF+BankGothicMdBT" "/ABCDEF+Bauhaus-Heavy" "/ABCDEF+BluesClues" "/ABCDEF+BodegaSans" "/ABCDEF+BodoniMTCondensed" "/ABCDEF+BookAntiqua" "/ABCDEF+CMBX10" "/ABCDEF+CaflischScriptPro-Regular" "/ABCDEF+CityBlueprint" "/ABCDEF+CourierNewPSMT" "/ABCDEF+FixedsysExcelsior2.00" "/ABCDEF+MSTT31854bd45bo188067S00" "/ABCDEF+MinionPro-BoldCnIt" "/ABCDEF+MyriadMM-It_400_300_" "/ABCDEF+Wingdings" "/ABCDEF+ZapfDingbats" "/AC" "/ADBE" "/ADB_DEVICE_DEFAULT_STYLE" "/ADB_DefaultStyle" "/ADB_NO_TRAP_STYLE" "/AE" "/AESV2" "/AGaramond" "/AH" "/AI8DstIndex" "/AI8SrcIndex" "/AIMetaData" "/AIPDFPrivateData1" "/AIS" "/AL" "/AN" "/AP" "/AS" "/ASCII85Decode" "/ASCIIHexDecode" "/ASomewhatLongerName" "/AU" "/Aacute" "/Acc.#20Prod.#202501#20#2F2#20#20" "/Accounts#20payable" "/AccurateScreens" "/Acircumflex" "/AcroForm" "/Action" "/Actual" "/Add" "/Adieresis" "/Adobe" "/Adobe#20PDF#20Library" "/Adobe.PPKLite" "/AdobeCorpID-Acrobat" "/AdobeCorpID-MinionRg" "/AdobePhotoshop" "/Agrave" "/All" "/AllKO" "/AllOn" "/Alt" "/Alternate" "/AlternatePresentations" "/Alternates" "/Amex" "/And" "/Angle" "/Annot" "/Annots" "/AntiAlias" "/AnyOn" "/Apag_PDFX_Checkup" "/App" "/Architecture-Normal" "/Arial" "/Aring" "/Art" "/ArtBox" "/Article" "/Artifact" "/Artwork" "/Ascent" "/Aspect" "/Assistant" "/Atilde" "/AuthEvent" "/Author" "/Avenir-Heavy" "/Avenir-MediumOblique" "/AvgWidth" "/BBox" "/BC" "/BCL" "/BDC" "/BDL" "/BE" "/BFSOL" "/BG" "/BG2" "/BM" "/BMC" "/BS" "/BW" "/Bank" "/BaseEncoding" "/BaseFont" "/BaseState" "/BaseVersion" "/Birch" "/BitsPerComponent" "/BitsPerCoordinate" "/BitsPerFlag" "/BitsPerSample" "/Bl" "/BlCDel" "/BlMiNu" "/Black" "/BlackIs1" "/BlackOP" "/BlackPoint" "/BleedBox" "/Blend" "/Block" "/Blue" "/BluesClues" "/Bookshelf" "/Border" "/Bounds" "/BoxColorInfo" "/Btn" "/BulmerMT-BoldDisplay" "/ByteRange" "/C" "/C0" "/C0_0" "/C1" "/C2W" "/C3" "/CALS_AIS" "/CALS_BM" "/CALS_HT" "/CALS_SMASK" "/CALS_ca" "/CAM" "/CB" "/CC" "/CCH" "/CCITTFaxDecode" "/CD" "/CDL" "/CEN" "/CF" "/CFM" "/CI" "/CIDFontType0" "/CIDFontType0C" "/CIDFontType2" "/CIDInit" "/CIDSet" "/CIDSystemInfo" "/CIDToGIDMap" "/CMV_LabBar" "/CMV_LabControl" "/CMYK" "/CMYK#20#2880,#208,#2034,#200#29" "/CMap" "/CMapName" "/CMapType" "/CMapVersion" "/CO" "/CP" "/CS" "/CS0" "/CT" "/CV" "/CalGray" "/CalRGB" "/CapHeight" "/Caption" "/Caslon540BT-Roman" "/CaslonBT-Bold" "/CaslonBT-BoldItalic" "/Catalog" "/Category" "/Ccedilla" "/CenturySchoolbookBT-Roman" "/Ch" "/Chair" "/Chap" "/Chaparral-Display" "/CharProcs" "/CharSet" "/CheckSum" "/Circle" "/ClarendonBT-Black" "/ClassMap" "/Clearface-Black" "/Clip" "/ClippedText" "/Cn" "/Collection" "/CollectionItem" "/CollectionSchema" "/CollectionSubitem" "/Color" "/ColorBurn" "/ColorDodge" "/ColorMatch" "/ColorSpace" "/ColorTransform" "/ColorType" "/Colorants" "/Colors" "/Columns" "/ComicSansMS,Bold" "/Comment" "/Comments" "/Company" "/Compatibility" "/Compatible" "/Components" "/CompressArt" "/Condensed" "/Configs" "/Consultant" "/ContainerVersion" "/Contents" "/Coords" "/Copy" "/Copy#20center" "/Cor" "/Corner#20surface" "/CosineDot" "/Count" "/Cour" "/Courier" "/Create" "/CreationDate" "/Creator" "/CreatorInfo" "/CreatorVersion" "/CropBox" "/CropFixed" "/CropRect" "/Crypt" "/CryptFilter" "/CryptFilterDecodeParms" "/Cs12" "/Cs3" "/Cyan" "/D" "/DA" "/DCTDecode" "/DIC#202525p*" "/DIS" "/DL" "/DOS" "/DP" "/DR" "/DS" "/DSz" "/DV" "/DW" "/DamagedRowsBeforeError" "/Darken" "/Data" "/Date" "/Decode" "/DecodeParms" "/DefEmbeddedFile" "/Default" "/DefaultCryptFilter" "/DefaultForPrinting" "/DefaultRGB" "/Delete" "/Delta" "/DescendantFonts" "/Descent" "/Description" "/Design" "/Dest" "/DestOutputProfile" "/DestOutputProfileRef" "/Dests" "/DeviceCMYK" "/DeviceGray" "/DeviceN" "/DeviceRGB" "/Difference" "/Differences" "/DigestLocation" "/DigestMethod" "/DigestValue" "/Dimmed" "/Direction" "/DisplayDocTitle" "/Dissolve" "/Div" "/Dm" "/DocMDP" "/DocOpen" "/Document" "/Documents" "/Domain" "/Door" "/DotGain" "/Draw" "/Dt" "/Dur" "/Dynamic#20connector" "/E" "/EF" "/EFF" "/EMC" "/Eacute" "/EarlyChange" "/Ecircumflex" "/Edieresis" "/Editable" "/Egrave" "/EmbedFonts" "/EmbedICCProfile" "/Embedded" "/EmbeddedFile" "/EmbeddedFiles" "/Encode" "/EncodedByteAlign" "/Encoding" "/Encrypt" "/EncryptMetadata" "/EndIndent" "/EndOfBlock" "/EndOfLine" "/Euro" "/Euro.037" "/Event" "/ExData" "/Exchange-Pro" "/Exclude" "/Exclusion" "/Executive" "/Export" "/ExportCrispy" "/ExportState" "/ExtGState" "/Extend" "/Extends" "/ExtensionLevel" "/Extensions" "/F1" "/F1.0" "/F12" "/F13" "/F3" "/F5" "/F6" "/F7" "/F8" "/FB" "/FD" "/FDecodeParms" "/FFilter" "/FICL" "/FM" "/FOV" "/FRM" "/FS" "/FT" "/Facilities" "/Fade" "/False" "/Feature" "/FedEx#20Orange" "/FedEx#20Purple" "/Field" "/Fields" "/Figure" "/File" "/Files" "/Filespec" "/FillIn" "/Filter" "/First" "/FirstChar" "/FirstPage" "/Fit" "/FitB" "/FitBH" "/FitBV" "/FitH" "/FitR" "/FitV" "/FitWindow" "/FixedPrint" "/Flags" "/FlateDecode" "/Fm0" "/Fm4" "/Fo" "/Focoltone#201047" "/Font" "/FontBBox" "/FontDescriptor" "/FontFamily" "/FontFile" "/FontFile2" "/FontMatrix" "/FontName" "/FontStretch" "/FontWeight" "/Form" "/FormEx" "/FormType" "/FreeText" "/FreeTextCallout" "/Frequency" "/FullSave" "/FullScreen" "/Function" "/FunctionType" "/Functions" "/Futura-Bold" "/Futura-CondensedExtraBold" "/G" "/G02" "/GLGR" "/GS0" "/GS1" "/GS2" "/GTS" "/GTS_PDFA1" "/GTS_PDFX" "/GTS_PDFXConformance" "/GTS_PDFXVersion" "/GWG#20Green" "/Gamma" "/Garamond" "/Georgia,Bold" "/GoTo" "/GoTo3DView" "/GoToE" "/GoToR" "/Gold" "/Goudy" "/Gray" "/Green" "/GreymantleMVB" "/GrotesqueMT" "/Group" "/H" "/HDAG_Tools" "/HKana" "/HT" "/HT2" "/Halftone" "/HalftoneName" "/HalftoneType" "/HardLight" "/HeBo" "/Head1" "/Headlamp" "/Height" "/HeiseiMin" "/Helv" "/Helvetica" "/Helvetica-Bold" "/Helvetica-BoldOblique" "/Helvetica-Condensed" "/HelveticaNeue-Black" "/Hide" "/HonMincho-M" "/Horizontal" "/Hue" "/I" "/I0" "/IC" "/ICCBased" "/ICCVersion" "/ID" "/IDS" "/IDTree" "/IEC" "/IF" "/IN" "/ISO32000Registry" "/ISO_PDFE1" "/ISO_PDFEVersion" "/IT" "/ITO" "/ITP" "/IV" "/IX" "/Icircumflex" "/Icon" "/Identity" "/Identity-H" "/IgnEP" "/Illustrator" "/Illustrator8.0" "/Im0" "/Im1" "/Im2" "/Im3" "/Im4" "/Image" "/Image1" "/ImageB" "/ImageC" "/ImageI" "/ImageMask" "/ImageResources" "/ImageType" "/Import" "/ImportData" "/ImpressBT-Regular" "/Index" "/Indexed" "/Info" "/Information#20services" "/Ink" "/InkList" "/InsertPages" "/Insignia" "/IntegerItem" "/Intent" "/Interpolate" "/ItalicAngle" "/ItcKabel-Ultra" "/Item1" "/Item2" "/JBIG2Decode" "/JBIG2Globals" "/JPXDecode" "/JS" "/JT" "/JTC" "/JTF" "/JTFile" "/JTM" "/JavaScript" "/JobTicketContents" "/Justify" "/Keywords" "/Kids" "/L" "/L1" "/L1a" "/L1b" "/L2R" "/L50188" "/LBody" "/LI" "/LL" "/LLE" "/LLO" "/LS" "/LSP" "/LZW" "/LZWDecode" "/Lab" "/Lang" "/Last" "/LastChar" "/LastItem" "/LastModified" "/Lateral#20file" "/Launch" "/Layout" "/Lbl" "/Leading" "/Legal" "/Length" "/Length1" "/Length2" "/Length3" "/LetterspaceFlags" "/Lighten" "/Limits" "/Line" "/LineDimension" "/LineHeight" "/Linear" "/Linearized" "/Link" "/Locked" "/LogoGreen" "/LrTb" "/Lslash" "/Luminosity" "/M" "/MB" "/MC" "/MC0" "/MCD" "/MCID" "/MCR" "/MD5" "/MH" "/MIT" "/MK" "/MMType1" "/MP" "/MR" "/MS" "/MUX#20#2F#20DEMUX" "/Mac" "/MacRomanEncoding" "/Magenta" "/Manager" "/MarkInfo" "/Marked" "/MarkedPDF" "/Marker#20board" "/Markup3D" "/Mask" "/Mastercard" "/Matrix" "/Max" "/MaxLen" "/MaxWidth" "/Me" "/Measure" "/MediaBox" "/MetaData" "/Min" "/MinionMM" "/MissingWidth" "/MixedContainer" "/MixingHints" "/ModDate" "/Mode" "/Modify" "/Movie" "/Msg" "/MurrayHillBT-Bold" "/MxGeom" "/MxLaNu" "/MxPts" "/MyriadPro-Black" "/NA" "/NChannel" "/ND" "/NL" "/NM" "/NR" "/Name" "/Name1" "/Named" "/Names" "/NeedsRendering" "/NewCenturySchlbk-Italic" "/NewWindow" "/Next" "/NextPage" "/No" "/NonEFontNoWarn" "/NonStruct" "/None" "/Normal" "/Not" "/NotDefSpecial" "/NumBlock" "/Nums" "/OB" "/OBJR" "/OC" "/OC2" "/OC3" "/OC4" "/OCG" "/OCGs" "/OCL" "/OCMD" "/OCProperties" "/OE" "/OFF" "/OLN" "/ON" "/OOL" "/OPBG" "/OPBS" "/OPI" "/OPM" "/OS" "/OT" "/Oacute" "/Obj" "/ObjStm" "/Ocircumflex" "/Odieresis" "/Ograve" "/Omega" "/OneColumn" "/Online" "/Open" "/OpenAction" "/Operation" "/Opt" "/OptionSet" "/Options" "/Or" "/Orange" "/Order" "/Ordering" "/OriginalLayerName" "/Oslash" "/Otilde" "/Outlines" "/OutputCondition" "/OutputConditionIdentifier" "/OutputIntent" "/OutputIntents" "/Overlay" "/P0" "/P1" "/P2" "/P2,#2300ff007900000000,PANTONE#20151#20C" "/PANTONE" "/PANTONE#20158-5#20CVS" "/PANTONE#20221#20CVU" "/PANTONE#203405#20C" "/PANTONE#20399#20CVC" "/PANTONE#20Blue#20072#20C" "/PANTONE#20Orange#20021#20C" "/PANTONE#20Orange#20021#20CVC" "/PANTONE#20Yellow#20C" "/PC" "/PDFDocEncoding" "/PIX" "/PO" "/PS" "/PUBLISHER" "/PZ" "/Pa0" "/Page" "/PageElement" "/PageLabels" "/PageLayout" "/PageMode" "/PageRange" "/Pages" "/PaintType" "/Palatino,Bold" "/Pale#20Brown.c" "/Panose" "/Paper#20tray" "/Para" "/Params" "/Parent" "/ParentTree" "/ParentTreeNextKey" "/Part" "/Pattern" "/PatternType" "/PcZ" "/Perceptual" "/Perms" "/Pg" "/Pgf" "/PieceInfo" "/PitStop" "/Placement" "/Play" "/Polygon" "/PolygonCloud" "/Popup" "/Position" "/PowerUpPDF" "/PrOut" "/PrRGBGra" "/PrRGBIma" "/Predictor" "/PresSteps" "/PreserveRB" "/Prev" "/PrevPage" "/Preview" "/Print" "/PrintRecord" "/PrintScaling" "/PrintState" "/PrintStyle" "/Printed" "/PrintingOrder" "/Private" "/ProcSet" "/Process" "/ProcessBlue" "/ProcessGreen" "/ProcessRed" "/Producer" "/ProfileCS" "/ProfileName" "/Prop_Build" "/Properties" "/Proportional" "/PubSec" "/Q" "/QuadPoints" "/R1" "/RBGroups" "/RC" "/RD" "/REC" "/REx" "/RF" "/RGB" "/RI" "/RICMYKGra" "/RICMYKIma" "/RICalGra" "/RICalIma" "/RIDefault" "/RIDevNGra" "/RIDevNIma" "/RIRGBGra" "/RIRGBIma" "/RL" "/RM" "/RV" "/Range" "/Rect" "/Red" "/Redact" "/Ref" "/Reference" "/Registry" "/RegistryName" "/RelativeColorimetric" "/Rendition" "/Renditions" "/Requirements" "/ResetForm" "/Resolution" "/Resources" "/ReversedChars" "/RoleMap" "/Root" "/Rotate" "/Round" "/RoundTrip" "/RoundtripVersion" "/Router" "/Rows" "/RunLengthDecode" "/Ryumin" "/SA" "/SBDraft" "/SC" "/SE" "/SFSSL" "/SFTWS" "/SI" "/SL" "/SLA" "/SM" "/SMask" "/SMaskInData" "/SP" "/SPS" "/STL" "/SU" "/SW" "/Saturation" "/SaveAs" "/SaveContents" "/SaveResource" "/SavedBy" "/Scaron" "/Schema" "/Screen" "/Sect" "/SemiCondensed" "/SemiExpanded" "/Separation" "/SeparationInfo" "/SetOCGState" "/SettingsFileName" "/Sh0" "/Sh1" "/Shading" "/ShadingType" "/Shape" "/Sig" "/SigFlags" "/SigRef" "/Signature" "/Signed" "/SinglePage" "/Size" "/SlideShow" "/SoftLight" "/Solid" "/Solidities" "/SomeName" "/Sort" "/Sound" "/Space" "/SpaceAfter" "/SpaceBefore" "/Span" "/SpawnTemplate" "/SpdrArt" "/SpiderInfo" "/Split" "/Spot" "/Spot1" "/Spot2" "/SpotFunction" "/SpotMap" "/St" "/Stamp" "/StandardImageFileData" "/Star" "/Start" "/StartIndent" "/StartResource" "/State" "/StdCF" "/StemH" "/StemV" "/Stm" "/StmF" "/Stop" "/Story" "/StrF" "/StrikeOut" "/StringItem" "/StructElem" "/StructParent" "/StructParents" "/StructTreeRoot" "/Style" "/SubFilter" "/SubType" "/Subdictionary" "/Subform" "/Subj" "/Subject" "/SubmitForm" "/SubmitStandalone" "/SubsetFontsBelow" "/SubsetFontsRatio" "/Supplement" "/Swiss721BT-Black" "/Switch" "/T" "/T1" "/T1_0" "/TB" "/TC" "/TCS" "/TF" "/TID" "/TK" "/TM" "/TO" "/TOC" "/TOCI" "/TOYO#200004pc" "/TP" "/TR" "/TR2" "/TRUMATCH#206-e" "/TS" "/TSV" "/TT" "/TT0" "/TTRefMan" "/TU" "/TV" "/TW" "/TWS" "/TWY" "/Tabs" "/TagSuspect" "/TargetCS" "/Technical" "/Template" "/TemplateInstantiated" "/Templates" "/Text" "/TextAlign" "/TextBox" "/TextIndent" "/The" "/This" "/Thorn" "/Thread" "/Threads" "/Thumb" "/Thumbnail" "/Thumbs" "/Ti" "/TiBI" "/TilingType" "/Times-BoldItalic" "/Times-Roman" "/Title" "/ToUnicode" "/Toggle" "/Trans" "/TransferFunction" "/TransformMethod" "/TransformParams" "/Transparency" "/TrapInfo" "/TrapMagicNumber" "/TrapRegions" "/TrapSet" "/Trapped" "/Trapping" "/TrappingDetails" "/TrappingParameters" "/TrimBox" "/True" "/TrueType" "/TrustedMode" "/TwoColumnLeft" "/Tx" "/Type" "/Type0" "/U3D" "/UA" "/UCR" "/UCR2" "/UIDOffset" "/UR" "/UR3" "/URI" "/URL" "/URLs" "/Uacute" "/Ucircumflex" "/Udieresis" "/Ugrave" "/Univers-BoldExt" "/Unix" "/Unknown" "/Usage" "/UseAttachments" "/UseNone" "/UseOC" "/UseOutlines" "/UseThumbs" "/UsedCMYK" "/UserProperties" "/UserUnit" "/V2" "/VA" "/VE" "/VP" "/Verdana,Bold" "/Version" "/Vertical" "/VeryLastItem" "/View" "/ViewerPreferences" "/Visa" "/Visible" "/Volume" "/W2" "/WAI" "/WAN" "/WMode" "/WP" "/WarnockPro-BoldIt" "/Watermark" "/WebCapture" "/Which" "/WhiteBG" "/WhitePoint" "/Widget" "/Width" "/Widths" "/Win" "/WinAnsiEncoding" "/Window" "/Windows" "/Work#20surface" "/Workbook" "/Worksheet" "/WritingMode" "/X" "/X1" "/XFA" "/XHeight" "/XML" "/XN" "/XObject" "/XRef" "/XRefStm" "/XStep" "/XUID" "/XYZ" "/Y" "/YStep" "/Yacute" "/Ydieresis" "/Yellow" "/Z" "/Z7KNXbN" "/ZaDb" "/ZapfDingbats" "/Zcaron" "/Zoom" "/_No_paragraph_style_" "/a1" "/acute" "/adbe.pkcs7.detached" "/ampersand" "/apple" "/approxequal" "/asciicircum" "/asciitilde" "/asterisk" "/at" "/audio#2Fmpeg" "/b" "/backslash" "/bar" "/blank" "/braceleft" "/braceright" "/bracketleft" "/bracketright" "/breve" "/brokenbar" "/bullet" "/c108" "/cCompKind" "/cCompQuality" "/cCompression" "/cRes" "/cResolution" "/ca" "/caron" "/cedilla" "/cent" "/circumflex" "/colon" "/comma" "/copyright" "/currency" "/dagger" "/daggerdbl" "/degree" "/deviceNumber" "/dieresis" "/divide" "/dollar" "/dotaccent" "/dotlessi" "/dotlessj" "/eight" "/ellipsis" "/emdash" "/endash" "/equal" "/eth" "/exclam" "/exclamdown" "/f" "/ff" "/ffi" "/ffl" "/fi" "/five" "/fl" "/florin" "/four" "/fraction" "/gCompKind" "/gCompQuality" "/gCompression" "/gRes" "/gResolution" "/germandbls" "/go1" "/grave" "/greater" "/greaterequal" "/guillemotleft" "/guillemotright" "/guilsinglleft" "/guilsinglright" "/hungarumlaut" "/hyphen" "/iacute" "/idieresis" "/igrave" "/infinity" "/integral" "/j" "/k" "/less" "/lessequal" "/logicalnot" "/lozenge" "/lt#20blue" "/mCompKind" "/mCompression" "/mRes" "/mResolution" "/macron" "/minus" "/mu" "/multiply" "/n" "/n0" "/nine" "/notequal" "/ntilde" "/numbersign" "/o" "/ogonek" "/one" "/onehalf" "/onequarter" "/onesuperior" "/op" "/ordfeminine" "/ordmasculine" "/p" "/pageH" "/pageV" "/paragraph" "/parenleft" "/parenright" "/partialdiff" "/pdf" "/pdfx" "/percent" "/period" "/periodcentered" "/perthousand" "/pi" "/plus" "/plusminus" "/pms#208400" "/printX" "/product" "/question" "/questiondown" "/quotedbl" "/quotedblbase" "/quotedblleft" "/quotedblright" "/quoteleft" "/quoteright" "/quotesinglbase" "/quotesingle" "/r" "/radical" "/registered" "/ring" "/s" "/s1" "/sd1" "/sd2" "/section" "/semicolon" "/seven" "/six" "/slash" "/sterling" "/summation" "/thinspace" "/three" "/threequarters" "/threesuperior" "/tilde" "/trademark" "/two" "/twosuperior" "/u" "/underscore" "/v" "/w" "/y1" "/yen" "/yes" "/zero" "0 R" "1" "1.0" "<" "<<" ">" ">>" "Adobe.PPKLite" "Adobe.PubSec" "B*" "BDC" "BI" "BMC" "BT" "BX" "CS" "DP" "Do" "EI" "EMC" "ET" "EX" "Entrust.PPKEF" "ID" "MP" "R" "T*" "TJ" "TL" "Tc" "Td" "Tf" "Tj" "Tm" "Tr" "Ts" "Tw" "W*" "[" "[0.0 0.0 0.0 0.0 0.0 0.0]" "[1 1 1]" "[1.0 -1.0 1.0 -1.0]" "[1.0 -1.0]" "\\" "]" "abs" "adbe.pkcs7.s3" "adbe.pkcs7.s4" "adbe.pkcs7.s5" "add" "and" "atan" "begin" "beginarrangedfont" "beginbfchar" "begincidrange" "begincmap" "begincodespacerange" "beginnotdefchar" "beginnotdefrange" "beginusematrix" "bitshift" "ceiling" "cm" "copy" "cos" "cvi" "cvr" "d0" "d1" "div" "dup" "end" "endarrangedfont" "endbfchar" "endcidrange" "endcmap" "endcodespacerange" "endnotdefchar" "endnotdefrange" "endobj" "endstream" "endusematrix" "eq" "exch" "exp" "f*" "false" "findresource" "floor" "ge" "gs" "gt" "idiv" "if" "ifelse" "index" "le" "ln" "log" "lt" "mod" "mul" "ne" "neg" "not" "null" "obj" "or" "page" "pop" "re" "rg" "ri" "roll" "round" "sin" "sqrt" "startxref" "stream" "sub" "trailer" "true" "truncate" "usecmap" "usefont" "xor" "xref" "{" "}" ================================================ FILE: projects/ghostscript/dicts/ps.dict ================================================ "exch" "pop" "copy" "dup" "index" "roll" "clear" "count" "mark" "cleartomark" "countomark" "add" "div" "sub" "idiv" "mul" "mod" "abs" "neg" "ceiling" "floor" "round" "truncate" "sqrt" "atan" "cos" "sin" "exp" "ln" "log" "rand" "srand" "rrand" "array" "[" "]" "length" "get" "put" "getinterval" "putinterval" "aload" "astore" "copy" "forall" "dict" "length" "maxlength" "begin" "end" "def" "load" "store" "get" "put" "known" "where" "copy" "forall" "errordict" "systemdict" "userdict" "currentdict" "countdictstack" "dictstack" "string" "anchorsearch" "search" "token" "eq" "ne" "ge" "gt" "le" "lt" "and" "not" "or" "xor" "true" "false" "bitshift" "exec" "if" "ifself" "for" "repeat" "loop" "exit" "stop" "stopped" "countexecstack" "quit" "start" "type" "cvlit" "cvx" "xcheck" "executeonly" "noaccess" "readonly" "rcheck" "wcheck" "cvi" "cvn" "cvr" "cvrs" "cvs" "file" "closefile" "read" "write" "readhexstring" "writehexstring" "readstring" "writestring" "readline" "bytesavailable" "flush" "flushfile" "resetfile" "status" "run" "currentfile" "print" "=" "stack" "==" "pstack" "prompt" "echo" "save" "restore" "vmstatus" "bind" "null" "usertime" "version" "gsave" "grestore" "grestoreall" "initgraphics" "setlinewidth" "currentlinewidth" "setlinecap" "currentlinecap" "setlinejoine" "currentlinejoin" "setmiterlimit" "currentmiterlimit" "setdash" "currentdash" "setflat" "currentflat" "setgray" "currentgray" "sethsbcolor" "currenthsbcolor" "setrgbcolor" "currentrgbcolor" "setscreen" "currentscreen" "settransfer" "currenttransfer" "matrix" "initmatrix" "identmatrix2" "defaultmatrix" "currentmatrix" "setmatrix" "translate" "scale" "rotate" "concat" "concatmatrix" "transform" "dtransform" "itransform" "idtransform" "invertmatrix" "newpath" "currentpoint" "moveto" "rmoveto" "lineto" "rlineto" "arc" "arcn" "arcto" "curveto" "rcurveto" "closepath" "flattenpath" "reversepath" "strokepath" "charpath" "clippath" "pathbbox" "pathforall" "initclip" "clip" "eoclip" "erasepage" "fill" "eofill" "stroke" "image" "imagemask" "showpage" "copypage" "banddevice" "framedevice" "nulldevice" "renderbands" "definefont" "findfont" "scalefont" "makefont" "setfont" "currentfont" "show" "ashow" "widthshow" "awidthshow" "kshow" "stringwidth" "FontDirectory" "standardEncoding" "cachestatus" "setcachedevice" "setcharwidth" "setcachelimit" ================================================ FILE: projects/ghostscript/gs_device_bmpmono_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "bmpmono", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_eps2write_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "eps2write", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_faxg3_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "faxg3", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_pdfwrite_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "pdfwrite", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_pdfwrite_opts_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 2) { return 0; } int color_scheme = ((int)data[0] % 63); int do_interpolation = ((int)data[1] % 2); data += 2; size -= 2; fuzz_gs_device(data, size, color_scheme, "pdfwrite", "/dev/null", do_interpolation); return 0; } ================================================ FILE: projects/ghostscript/gs_device_pgmraw_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "pgmraw", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_png16m_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "png16m", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_ps2write_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "ps2write", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_psdcmyk_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "psdcmyk", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_pxlcolor_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "pxlcolor", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_pxlmono_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "pxlmono", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_tiffsep1_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d.tiff", getpid()); fuzz_gs_device(data, size, 1, "tiffsep1", filename, 0); return 0; } ================================================ FILE: projects/ghostscript/gs_device_xpswrite_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { fuzz_gs_device(data, size, 1, "xpswrite", "/dev/null", 0); return 0; } ================================================ FILE: projects/ghostscript/gs_fuzzlib.h ================================================ /* # Copyright 2019 The Chromium OS Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include #include static const unsigned char *g_data; static size_t g_size; int fuzz_gs_device( const unsigned char *buf, size_t size, int color_scheme, const char *device_target, const char *output_file, int do_interpolation ); #define min(x, y) ((x) < (y) ? (x) : (y)) static int gs_stdin(void *inst, char *buf, int len) { size_t to_copy = min(len, g_size); to_copy = min(INT_MAX, to_copy); memcpy(buf, g_data, to_copy); g_data += to_copy; g_size -= to_copy; return to_copy; } static int gs_stdnull(void *inst, const char *buf, int len) { /* Just discard everything. */ return len; } int gs_to_raster_fuzz( const unsigned char *buf, size_t size, int color_scheme ) { return fuzz_gs_device(buf, size, color_scheme, "cups", "/dev/null", 0); } int fuzz_gs_device( const unsigned char *buf, size_t size, int color_scheme, const char *device_target, const char *output_file, int do_interpolation ) { int ret; void *gs = NULL; char color_space[50]; char gs_device[50]; char gs_o[100]; char opt_interpolation[50]; /* * We are expecting color_scheme to be in the [0:62] interval. * This corresponds to the color schemes defined here: * https://github.com/ArtifexSoftware/ghostpdl/blob/8c97d5adce0040ac38a1fb4d7954499c65f582ff/cups/libs/cups/raster.h#L102 */ sprintf(color_space, "-dcupsColorSpace=%d", color_scheme); sprintf(gs_device, "-sDEVICE=%s", device_target); sprintf(gs_o, "-sOutputFile=%s", output_file); if (do_interpolation) { sprintf(opt_interpolation, "-dDOINTERPOLATE"); } else { sprintf(opt_interpolation, "-dNOINTERPOLATE"); } /* Mostly stolen from cups-filters gstoraster. */ char *args[] = { "gs", "-K1048576", "-r200x200", "-sBandListStorage=memory", "-dMaxBitmap=0", "-dBufferSpace=450k", "-dMediaPosition=1", color_space, "-dQUIET", "-dSAFER", "-dNOPAUSE", "-dBATCH", opt_interpolation, "-dNOMEDIAATTRS", "-sstdout=%%stderr", gs_o, gs_device, "-_", }; int argc = sizeof(args) / sizeof(args[0]); /* Stash buffers globally, for gs_stdin(). */ g_data = buf; g_size = size; ret = gsapi_new_instance(&gs, NULL); if (ret < 0) { fprintf(stderr, "gsapi_new_instance: error %d\n", ret); return ret; } gsapi_set_stdio(gs, gs_stdin, gs_stdnull, gs_stdnull); ret = gsapi_set_arg_encoding(gs, GS_ARG_ENCODING_UTF8); if (ret < 0) { fprintf(stderr, "gsapi_set_arg_encoding: error %d\n", ret); gsapi_delete_instance(gs); return ret; } ret = gsapi_init_with_args(gs, argc, args); if (ret && ret != gs_error_Quit) /* Just keep going, to cleanup. */ fprintf(stderr, "gsapi_init_with_args: error %d\n", ret); ret = gsapi_exit(gs); if (ret < 0 && ret != gs_error_Quit) { fprintf(stderr, "gsapi_exit: error %d\n", ret); return ret; } gsapi_delete_instance(gs); return 0; } ================================================ FILE: projects/ghostscript/gstoraster_fuzzer.cc ================================================ /* # Copyright 2019 The Chromium OS Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Tests RGB color scheme */ gs_to_raster_fuzz(data, size, 1); return 0; } ================================================ FILE: projects/ghostscript/gstoraster_fuzzer_all_colors.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) { return 0; } // Modulo the possibilities: https://github.com/ArtifexSoftware/ghostpdl/blob/8c97d5adce0040ac38a1fb4d7954499c65f582ff/cups/libs/cups/raster.h#L102 // This enables the fuzzer to explore all color schemes int color_scheme = ((int)data[0] % 63); data++; size--; gs_to_raster_fuzz(data, size, color_scheme); return 0; } ================================================ FILE: projects/ghostscript/gstoraster_fuzzer_all_colors.options ================================================ [libfuzzer] max_len = 16834 ================================================ FILE: projects/ghostscript/gstoraster_pdf_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" // Returns 1 if this has a valid PDF header and 0 otherwise static int quick_check_pdf(const uint8_t *data, size_t size) { // PDF checks. Exit early if we don't have a valid PDF signature. if (size < 5) { return 0; } // Check PDF tag. We do this because we want to use seeds if (data[0] != 0x25 || data[1] != 0x50 || data[2] != 0x44 || data[3] != 0x46 || data[4] != 0x2d) { return 0; } return 1; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (quick_check_pdf(data, size) != 1) { return 0; } /* Tests using RGB color scheme */ gs_to_raster_fuzz(data, size, 1); return 0; } ================================================ FILE: projects/ghostscript/gstoraster_ps_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "gs_fuzzlib.h" /* Returns 1 if the data has a PDF header and 0 otherwise */ static int is_pdf(const uint8_t *data, size_t size) { /* Two bytes are needed for the check */ if (size < 2) { return 0; } /* Check for "%P" tag. */ if (data[0] == 0x25 || data[1] == 0x50) { return 1; } return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Avoid PDF files */ if (size == 0 || is_pdf(data, size)) { return 0; } /* * Modulo the possibilities: https://github.com/ArtifexSoftware/ghostpdl/blob/8c97d5adce0040ac38a1fb4d7954499c65f582ff/cups/libs/cups/raster.h#L102 This enables the fuzzer to explore all color schemes */ int color_scheme = ((int)data[0] % 63); data++; size--; gs_to_raster_fuzz(data, size, color_scheme); return 0; } ================================================ FILE: projects/ghostscript/gstoraster_ps_fuzzer.options ================================================ [libfuzzer] max_len = 16834 only_ascii = 1 ================================================ FILE: projects/ghostscript/project.yaml ================================================ homepage: "https://ghostscript.com" language: c++ primary_contact: "skau@google.com" auto_ccs: - "henry.stiles@artifex.com" - "bmgordon@google.com" - "skau@google.com" - "sebastian.rasmussen@artifex.com" - "julians.artifex@gmail.com" - "chris.liddell@artifex.com" - "ken.sharp@artifex.com" - "david@adalogics.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory main_repo: 'git://git.ghostscript.com/ghostpdl.git' fuzzing_engines: - libfuzzer - honggfuzz ================================================ FILE: projects/giflib/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update -y && \ apt-get install -y cmake liblzma-dev libz-dev make ninja-build wget zlib1g-dev RUN git clone --depth=1 https://git.code.sf.net/p/giflib/code $SRC/giflib-code RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git RUN (mkdir LPM && cd LPM && cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release && ninja) COPY *.c *.options build.sh *.h *.cc *.cpp *.proto $SRC/ ================================================ FILE: projects/giflib/ProtoToGif.cpp ================================================ #include "ProtoToGif.h" using namespace gifProtoFuzzer; using namespace std; constexpr unsigned char ProtoConverter::m_sig[]; constexpr unsigned char ProtoConverter::m_ver89a[]; constexpr unsigned char ProtoConverter::m_ver87a[]; string ProtoConverter::gifProtoToString(GifProto const &proto) { visit(proto); return m_output.str(); } void ProtoConverter::visit(GifProto const &gif) { visit(gif.header()); visit(gif.lsd()); if (m_hasGCT) visit(gif.gct()); for (auto const &chunk : gif.chunks()) visit(chunk); visit(gif.trailer()); } void ProtoConverter::visit(Header const &header) { // Signature GIF m_output.write((const char *)m_sig, sizeof(m_sig)); switch (header.ver()) { case Header::ENA: m_output.write((const char *)m_ver89a, sizeof(m_ver89a)); break; case Header::ESA: m_output.write((const char *)m_ver87a, sizeof(m_ver87a)); break; // We simply don't write anything if it's an invalid version // Bytes that follow (LSD) will be interpreted as version case Header::INV: break; } } void ProtoConverter::visit(LogicalScreenDescriptor const &lsd) { writeWord(extractWordFromUInt32(lsd.screenwidth())); writeWord(extractWordFromUInt32(lsd.screenheight())); uint8_t packedByte = extractByteFromUInt32(lsd.packed()); // If MSB of packed byte is 1, GCT follows if (packedByte & 0x80) { m_hasGCT = true; // N: 2^(N+1) colors in GCT m_globalColorExp = packedByte & 0x07; } writeByte(packedByte); writeByte(extractByteFromUInt32(lsd.backgroundcolor())); writeByte(extractByteFromUInt32(lsd.aspectratio())); } void ProtoConverter::visit(GlobalColorTable const &gct) { //[TODO 27/04/2019 VU]: Should it really be exactly the same size? Or do we want some deterministic randomness here? // TODO BS: We never overflow expected table size due to the use of min uint32_t tableSize = min((uint32_t)gct.colors().size(), tableExpToTableSize(m_globalColorExp)); m_output.write(gct.colors().data(), tableSize); } void ProtoConverter::visit(GraphicControlExtension const &gce) { writeByte(0x21); // Extension Introducer writeByte(0xF9); // Graphic Control Label writeByte(4); // Block size uint8_t packedByte = extractByteFromUInt32(gce.packed()); // packed byte writeByte(packedByte); // Delay time is 2 bytes writeWord(extractWordFromUInt32(gce.delaytime())); // Transparent color index is 1 byte writeByte(extractByteFromUInt32(gce.transparentcolorindex())); writeByte(0x0); // Block Terminator } void ProtoConverter::visit(ImageChunk const &chunk) { switch (chunk.chunk_oneof_case()) { case ImageChunk::kBasic: visit(chunk.basic()); break; case ImageChunk::kPlaintext: visit(chunk.plaintext()); break; case ImageChunk::kAppExt: visit(chunk.appext()); break; case ImageChunk::kComExt: visit(chunk.comext()); break; case ImageChunk::CHUNK_ONEOF_NOT_SET: break; } } void ProtoConverter::visit(const BasicChunk &chunk) { // Visit GCExt if necessary if (chunk.has_gcext()) visit(chunk.gcext()); visit(chunk.imdescriptor()); if (m_hasLCT) visit(chunk.lct()); visit(chunk.img()); } void ProtoConverter::visit(LocalColorTable const &lct) { //[TODO 27/04/2019 VU]: Should it really be exactly the same size? Or do we want some deterministic randomness here? // TODO BS: We never overflow expected table size due to the use of min uint32_t tableSize = min((uint32_t)lct.colors().size(), tableExpToTableSize(m_localColorExp)); m_output.write(lct.colors().data(), tableSize); } void ProtoConverter::visit(ImageDescriptor const &descriptor) { // TODO: Remove seperator from proto since it is always 2C writeByte(0x2C); writeWord(extractWordFromUInt32(descriptor.left())); writeWord(extractWordFromUInt32(descriptor.top())); writeWord(extractWordFromUInt32(descriptor.height())); writeWord(extractWordFromUInt32(descriptor.width())); uint8_t packedByte = extractByteFromUInt32(descriptor.packed()); if (packedByte & 0x80) { m_hasLCT = true; m_localColorExp = packedByte & 0x07; } else m_hasLCT = false; } void ProtoConverter::visit(SubBlock const &block) { uint8_t len = extractByteFromUInt32(block.len()); if (len == 0) { writeByte(0x00); } else { // TODO BS: We never overflow expected block size due to the use of min uint32_t write_len = min((uint32_t)len, (uint32_t)block.data().size()); m_output.write(block.data().data(), write_len); } } void ProtoConverter::visit(ImageData const &img) { // TODO: Verify we are writing the image data correctly // LZW writeByte(extractByteFromUInt32(img.lzw())); // Sub-blocks for (auto const &block : img.subs()) visit(block); // NULL sub block signals end of image data writeByte(0x00); } void ProtoConverter::visit(PlainTextExtension const &ptExt) { // Visit GCExt if necessary if (ptExt.has_gcext()) visit(ptExt.gcext()); // First two bytes are 0x21 0x01 writeByte(0x21); writeByte(0x01); // Skip zero bytes writeByte(0x00); for (auto const &block : ptExt.subs()) visit(block); // NULL sub block signals end writeByte(0x00); } void ProtoConverter::visit(CommentExtension const &comExt) { // First two bytes are 0x21 0xFE writeByte(0x21); writeByte(0xFE); // Sub-blocks for (auto const &block : comExt.subs()) visit(block); // NULL sub block signals end of image data writeByte(0x00); } void ProtoConverter::visit(ApplicationExtension const &appExt) { // First two bytes are 0x21 0xFF writeByte(0x21); writeByte(0xFF); // Next, we write "11" decimal or 0x0B writeByte(0x0B); writeLong(appExt.appid()); // We hardcode the auth code to 1.0 or 0x31 0x2E 0x30 writeByte(0x31); writeByte(0x2E); writeByte(0x30); // Sub-blocks for (auto const &block : appExt.subs()) visit(block); // NULL sub block signals end of image data writeByte(0x00); } void ProtoConverter::visit(Trailer const &) { writeByte(0x3B); } // ============================================================= // Utility functions // ============================================================= void ProtoConverter::writeByte(uint8_t x) { m_output.write((char *)&x, sizeof(x)); } void ProtoConverter::writeWord(uint16_t x) { m_output.write((char *)&x, sizeof(x)); } void ProtoConverter::writeInt(uint32_t x) { m_output.write((char *)&x, sizeof(x)); } void ProtoConverter::writeLong(uint64_t x) { m_output.write((char *)&x, sizeof(x)); } uint16_t ProtoConverter::extractWordFromUInt32(uint32_t a) { uint16_t first_byte = (a & 0xFF); uint16_t second_byte = ((a >> 8) & 0xFF) << 8; return first_byte | second_byte; } uint8_t ProtoConverter::extractByteFromUInt32(uint32_t a) { uint8_t byte = a & 0x80; return byte; } /** * Given an exponent, returns the global/local color table size, given by 3*2^(exp+1) * @param tableExp The exponent * @return The actual color table size */ uint32_t ProtoConverter::tableExpToTableSize(uint32_t tableExp) { // 0 <= tableExp <= 7 // 6 <= tableSize <= 768 uint32_t tableSize = 3 * (pow(2, tableExp + 1)); return tableSize; } ================================================ FILE: projects/giflib/ProtoToGif.h ================================================ #include #include #include #include #include "gif_fuzz_proto.pb.h" namespace gifProtoFuzzer { class ProtoConverter { public: std::string gifProtoToString(GifProto const &proto); private: template void visit(google::protobuf::RepeatedPtrField const &_repeated_field); void visit(const GifProto &); void visit(const Header &); void visit(const LogicalScreenDescriptor &); void visit(const GlobalColorTable &); void visit(const ImageChunk &); void visit(const BasicChunk &); void visit(const ImageData &); void visit(const SubBlock &); void visit(const ImageDescriptor &); void visit(const LocalColorTable &); void visit(const GraphicControlExtension &); void visit(const PlainTextExtension &); void visit(const ApplicationExtension &); void visit(const CommentExtension &); void visit(const Trailer &); // Utility functions void writeByte(uint8_t x); void writeWord(uint16_t x); void writeInt(uint32_t x); void writeLong(uint64_t x); static uint16_t extractWordFromUInt32(uint32_t a); static uint8_t extractByteFromUInt32(uint32_t a); static uint32_t tableExpToTableSize(uint32_t tableExp); std::stringstream m_output; bool m_hasGCT = false; bool m_hasLCT = false; uint8_t m_globalColorExp = 0; uint8_t m_localColorExp = 0; static constexpr unsigned char m_sig[] = {0x47, 0x49, 0x46}; static constexpr unsigned char m_ver89a[] = {0x38, 0x39, 0x61}; static constexpr unsigned char m_ver87a[] = {0x38, 0x37, 0x61}; }; } // namespace gifProtoFuzzer ================================================ FILE: projects/giflib/build.sh ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -e SOURCES=(dgif_lib.c egif_lib.c getarg.c gifalloc.c gif_err.c gif_font.c \ gif_hash.c openbsd-reallocarray.c qprintf.c quantize.c) cd $SRC/giflib-code rm -f *.o for file in ${SOURCES[@]}; do name=$(basename $file .c) $CC -c -I . $CFLAGS $file -o $name.o done ar rc libgif.a *.o cd $SRC $CXX $CFLAGS -Wall -c -I giflib-code dgif_target.cc -o dgif_target.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -std=c++11 -I giflib-code dgif_fuzz_common.cc dgif_target.o \ -o $OUT/dgif_target giflib-code/libgif.a $CXX $CXXFLAGS -Wall -c -I giflib-code egif_target.cc -o egif_target.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -std=c++11 -I giflib-code egif_fuzz_common.cc egif_target.o \ -o $OUT/egif_target giflib-code/libgif.a rm -rf genfiles && mkdir genfiles && LPM/external.protobuf/bin/protoc gif_fuzz_proto.proto --cpp_out=genfiles $CXX $CXXFLAGS -DNDEBUG -Wall -c -I giflib-code dgif_protobuf_target.cc -I libprotobuf-mutator/ \ -I genfiles \ -I LPM/external.protobuf/include \ -o dgif_protobuf_target.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -DNDEBUG -std=c++14 -I. -I giflib-code dgif_protobuf_target.o dgif_fuzz_common.cc genfiles/gif_fuzz_proto.pb.cc \ ProtoToGif.cpp \ -I LPM/external.protobuf/include \ -I genfiles \ LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ LPM/src/libprotobuf-mutator.a \ -Wl,--start-group LPM/external.protobuf/lib/lib*.a -Wl,--end-group \ -o $OUT/dgif_protobuf_target giflib-code/libgif.a # Place dict and config in OUT wget -O $OUT/gif.dict \ https://raw.githubusercontent.com/mirrorer/afl/master/dictionaries/gif.dict \ &> /dev/null cp $SRC/*.options $OUT/ find $SRC/giflib-code -iname "*.gif" -exec \ zip -ujq $OUT/dgif_target_seed_corpus.zip "{}" \; ================================================ FILE: projects/giflib/dgif_fuzz_common.cc ================================================ #include "dgif_fuzz_common.h" #include using namespace std; extern "C" void PrintGifError(int ErrorCode); int stub_input_reader(GifFileType *gifFileType, GifByteType *gifByteType, int len) { struct gifUserData *gud = (struct gifUserData *)gifFileType->UserData; if (gud->gifLen == 0) return 0; int read_len = (len > gud->gifLen ? gud->gifLen : len); memcpy(gifByteType, gud->gifData, read_len); gud->gifData += read_len; gud->gifLen -= read_len; return read_len; } int fuzz_dgif(const uint8_t *Data, size_t Size) { GifFileType *GifFile; int Error; uint8_t *gifData = (uint8_t *)malloc(Size); memcpy(gifData, Data, Size); struct gifUserData gUData = {Size, gifData}; GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error); if (GifFile != NULL) { DGifSlurp(GifFile); DGifCloseFile(GifFile, &Error); } free(gifData); return 0; } int fuzz_dgif_extended(const uint8_t *Data, size_t Size) { GifFileType *GifFile; int Error; uint8_t *gifData = (uint8_t *)malloc(Size); memcpy(gifData, Data, Size); struct gifUserData gUData = {Size, gifData}; GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error); if (GifFile == NULL) { free(gifData); return 0; } if (DGifSlurp(GifFile) != GIF_OK) { DGifCloseFile(GifFile, &Error); free(gifData); return 0; } GraphicsControlBlock gcb; for (int i = 0; i < GifFile->ImageCount; i++) { DGifSavedExtensionToGCB(GifFile, i, &gcb); } const ColorMapObject *cmap = GifFile->SColorMap; if (cmap) { DGifSavedExtensionToGCB(GifFile, 0, &gcb); } DGifCloseFile(GifFile, &Error); free(gifData); return 0; } static Color8888 gifColorToColor8888(const GifColorType &color) { return ARGB_TO_COLOR8888(0xff, color.Red, color.Green, color.Blue); } static bool willBeCleared(const GraphicsControlBlock &gcb) { return gcb.DisposalMode == DISPOSE_BACKGROUND || gcb.DisposalMode == DISPOSE_PREVIOUS; } static long getDelayMs(GraphicsControlBlock &gcb) { return gcb.DelayTime * 10; } int fuzz_dgif_ala_android(const uint8_t *Data, size_t Size) { GifFileType *GifFile; int Error; uint8_t *gifData = (uint8_t *)malloc(Size); memcpy(gifData, Data, Size); struct gifUserData gUData = {Size, gifData}; GifFile = DGifOpen((void *)&gUData, stub_input_reader, &Error); if (GifFile == NULL) { free(gifData); return 0; } if (DGifSlurp(GifFile) != GIF_OK) { PrintGifError(GifFile->Error); DGifCloseFile(GifFile, &Error); free(gifData); return 0; } long durationMs = 0; int lastUnclearedFrame = -1; bool *preservedFrames = new bool[GifFile->ImageCount]; int *restoringFrames = new int[GifFile->ImageCount]; int loopCount = 0; Color8888 bgColor = 0; GraphicsControlBlock gcb; for (int i = 0; i < GifFile->ImageCount; i++) { const SavedImage &image = GifFile->SavedImages[i]; // find the loop extension pair for (int j = 0; (j + 1) < image.ExtensionBlockCount; j++) { ExtensionBlock *eb1 = image.ExtensionBlocks + j; ExtensionBlock *eb2 = image.ExtensionBlocks + j + 1; if (eb1->Function == APPLICATION_EXT_FUNC_CODE // look for "NETSCAPE2.0" app extension && eb1->ByteCount == 11 && !memcmp((const char *)(eb1->Bytes), "NETSCAPE2.0", 11) // verify extension contents and get loop count && eb2->Function == CONTINUE_EXT_FUNC_CODE && eb2->ByteCount == 3 && eb2->Bytes[0] == 1) { loopCount = (int)(eb2->Bytes[2] << 8) + (int)(eb2->Bytes[1]); } } DGifSavedExtensionToGCB(GifFile, i, &gcb); // timing durationMs += getDelayMs(gcb); // preserve logic preservedFrames[i] = false; restoringFrames[i] = -1; if (gcb.DisposalMode == DISPOSE_PREVIOUS && lastUnclearedFrame >= 0) { preservedFrames[lastUnclearedFrame] = true; restoringFrames[i] = lastUnclearedFrame; } if (!willBeCleared(gcb)) { lastUnclearedFrame = i; } // Draw // assert(y+8 <= Image->ImageDesc.Height); // assert(x+8*strlen(legend) <= Image->ImageDesc.Width); int imgHeight = GifFile->SavedImages[i].ImageDesc.Height; int imgWidth = GifFile->SavedImages[i].ImageDesc.Width; // TODO: Source x,y, string, and color from fuzzer input int x = 0; int y = 0; int strLen = 6; if (y + 8 <= imgHeight && x + 8 * strLen <= imgWidth) GifDrawText8x8(&GifFile->SavedImages[i], 0, 0, "legend", 42); } #if GIF_DEBUG ALOGD("FrameSequence_gif created with size %d %d, frames %d dur %ld", GifFile->SWidth, GifFile->SHeight, GifFile->ImageCount, durationMs); for (int i = 0; i < GifFile->ImageCount; i++) { DGifSavedExtensionToGCB(GifFile, i, &gcb); ALOGD(" Frame %d - must preserve %d, restore point %d, trans color %d", i, preservedFrames[i], restoringFrames[i], gcb.TransparentColor); } #endif const ColorMapObject *cmap = GifFile->SColorMap; if (cmap) { // calculate bg color GraphicsControlBlock gcb; DGifSavedExtensionToGCB(GifFile, 0, &gcb); if (gcb.TransparentColor == NO_TRANSPARENT_COLOR && GifFile->SBackGroundColor < cmap->ColorCount) { bgColor = gifColorToColor8888(cmap->Colors[GifFile->SBackGroundColor]); } } DGifCloseFile(GifFile, &Error); free(gifData); delete[] preservedFrames; delete[] restoringFrames; return 0; } ================================================ FILE: projects/giflib/dgif_fuzz_common.h ================================================ #include "gif_lib.h" #include #include #include #define ARGB_TO_COLOR8888(a, r, g, b) \ ((a) << 24 | (b) << 16 | (g) << 8 | (r)) typedef uint32_t Color8888; struct gifUserData { size_t gifLen; uint8_t *gifData; }; int stub_input_reader(GifFileType *gifFileType, GifByteType *gifByteType, int len); int fuzz_dgif(const uint8_t *Data, size_t Size); int fuzz_dgif_extended(const uint8_t *Data, size_t Size); int fuzz_dgif_ala_android(const uint8_t *Data, size_t Size); ================================================ FILE: projects/giflib/dgif_protobuf_target.cc ================================================ #include #include #include #include #include #include #include "dgif_fuzz_common.h" #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" #include "ProtoToGif.h" using namespace gifProtoFuzzer; DEFINE_PROTO_FUZZER(const GifProto &gif_proto) { // Instantiate ProtoConverter object ProtoConverter converter; std::string gifRawData = converter.gifProtoToString(gif_proto); if (const char *dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate a GIF from proto: // PROTO_FUZZER_DUMP_PATH=x.gif ./fuzzer proto-input std::ofstream of(dump_path); of.write(gifRawData.data(), gifRawData.size()); } fuzz_dgif_extended((const uint8_t *)gifRawData.data(), gifRawData.size()); } ================================================ FILE: projects/giflib/dgif_target.cc ================================================ #include #include #include #include "dgif_fuzz_common.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return fuzz_dgif_extended(Data, Size); } ================================================ FILE: projects/giflib/dgif_target.options ================================================ [libfuzzer] dict = gif.dict ================================================ FILE: projects/giflib/egif_fuzz_common.cc ================================================ #include "egif_fuzz_common.h" #define GIF_IMAGE_WIDTH 100 // This is rgb byte stream length per horizontal line = GIF_IMAGE_WIDTH * 3 #define GIF_IMAGE_LINE 300 extern "C" void PrintGifError(int ErrorCode); int stub_output_writer(GifFileType *gifFileType, const uint8_t *buf, int len) { struct gifUserData *gud = (struct gifUserData *)gifFileType->UserData; if (gud == NULL || gud->gifData == NULL || len == 0) return 0; if (gud->allocatedSize < (gud->gifLen + len)) { // Reallocate gifFileType int newSize = (gud->gifLen + len) * 2; uint8_t *oldGud = gud->gifData; gud->gifData = (uint8_t *)realloc(oldGud, newSize); // Assert when realloc fails. assert(gud->gifData != NULL); gud->allocatedSize = newSize; } memcpy(gud->gifData + gud->gifLen, buf, len); gud->gifLen += len; return len; } // RGB to GIF converter static bool rgb_to_gif(const uint8_t *data, size_t size) { // Bail if total size is not a multiple of GIF_IMAGE_LINE (see below) // Keep a fixed width e.g., GIF_IMAGE_WIDTH // size/3 = GIF_IMAGE_WIDTH * height // height = size/GIF_IMAGE_LINE // Extract height int height = size / GIF_IMAGE_LINE; // GifByteType is unsigned char (raw byte) // mem holds the raw RGB byte stream for the entire image GifByteType *mem = (GifByteType *)malloc(sizeof(GifByteType) * height * GIF_IMAGE_WIDTH * 3); if (!mem) return false; // Copy RGB data to mem memcpy(mem, data, size); GifByteType *red_buf = mem; GifByteType *green_buf = mem + (GIF_IMAGE_WIDTH * height); GifByteType *blue_buf = mem + (GIF_IMAGE_WIDTH * height * 2); // ColorMapObject *GifMakeMapObject(int ColorCount, GifColorType *ColorMap) // Allocate storage for a color map object with the given number of RGB triplet slots. // If the second argument is non-NULL, initialize the color table portion of // the new map from it. Returns NULL if memory is exhausted or if the size is // not a power of 2 <= 256. // TODO: Fuzz color map size (has to be a power of 2 less than equal to 256) // TODO: Fuzz color table initialization int color_map_size = 256; ColorMapObject *output_color_map = GifMakeMapObject(color_map_size, NULL); if (!output_color_map) { free(mem); return false; } // gif output will be written to output_buf size_t out_size = sizeof(GifByteType) * GIF_IMAGE_WIDTH * height; GifByteType *output_buf = (GifByteType *)malloc(out_size); if (!output_buf) { GifFreeMapObject(output_color_map); free(mem); return false; } if (GifQuantizeBuffer(GIF_IMAGE_WIDTH, height, &color_map_size, red_buf, green_buf, blue_buf, output_buf, output_color_map->Colors) == GIF_ERROR) { GifFreeMapObject(output_color_map); free(output_buf); free(mem); return false; } // Now that raw RGB data has been quantized, we no longer need it. free(mem); GifFileType *GifFile; int Error; // We start with 1024, but resize dynamically // see stub_output_writer uint8_t *gifData = (uint8_t *)malloc(1024); struct gifUserData gUData = {0, 1024, gifData}; /* GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *ErrorCode) * Description: * Open a new GIF file using the given userPtr (in binary mode, if under Windows). * writeFunc is a function pointer that writes to output gif file. * If any error occurs, NULL is returned and the ErrorCode is set. */ GifFile = EGifOpen((void *)&gUData, stub_output_writer, &Error); if (GifFile == NULL) { PrintGifError(GifFile->Error); GifFreeMapObject(output_color_map); free(output_buf); free(gUData.gifData); return false; } /* void EGifSetGifVersion(GifFileType *GifFile, bool gif89) * Description: * Set the GIF type, to GIF89 if the argument is true and GIF87 if it is false. * The default type is GIF87. This function may be called after the GifFile * record is allocated but before EGifPutScreenDesc(). */ EGifSetGifVersion(GifFile, false); /* int EGifPutScreenDesc(GifFileType *GifFile, * const int GifWidth, const GifHeight, * const int GifColorRes, const int GifBackGround, * ColorMapObject *GifColorMap) * * Update the GifFile Screen parameters, in GifFile structure and in the real file. * If error occurs, returns GIF_ERROR (see gif_lib.h), otherwise GIF_OK. * This routine should be called immediately after the GIF file was opened. */ if (EGifPutScreenDesc(GifFile, GIF_IMAGE_WIDTH, height, color_map_size, 0, output_color_map) == GIF_ERROR) { PrintGifError(GifFile->Error); GifFreeMapObject(output_color_map); free(output_buf); EGifCloseFile(GifFile, &Error); free(gUData.gifData); return false; } /* int EGifPutImageDesc(GifFileType *GifFile, const int GifLeft, const int GifTop, * const int GifWidth, const GifHeight, const bool GifInterlace, ColorMapObject *GifColorMap) * Description * Update GifFile Image parameters, in GifFile structure and in the real file. * if error occurs returns GIF_ERROR (see gif_lib.h), otherwise GIF_OK. * This routine should be called each time a new image must be dumped to the file. */ if (EGifPutImageDesc(GifFile, 0, 0, GIF_IMAGE_WIDTH, height, false, NULL) == GIF_ERROR) { PrintGifError(GifFile->Error); GifFreeMapObject(output_color_map); free(output_buf); EGifCloseFile(GifFile, &Error); free(gUData.gifData); return false; } GifByteType *output_bufp = output_buf; for (int i = 0; i < height; i++) { /* int EGifPutLine(GifFileType *GifFile, PixelType *GifLine, int GifLineLen) * Description: * Dumps a block of pixels out to the GIF file. The slab can be of any length. * More than that, this routine may be interleaved with EGifPutPixel(), * until all pixels have been sent. * Returns GIF_ERROR if something went wrong, GIF_OK otherwise. */ if (EGifPutLine(GifFile, output_bufp, GIF_IMAGE_WIDTH) == GIF_ERROR) { PrintGifError(GifFile->Error); GifFreeMapObject(output_color_map); free(output_buf); EGifCloseFile(GifFile, &Error); free(gUData.gifData); return false; } output_bufp += GIF_IMAGE_WIDTH; } /* void GifFreeMapObject(ColorMapObject *Object) * Description * Free the storage occupied by a ColorMapObject that is no longer needed. */ GifFreeMapObject(output_color_map); free(output_buf); EGifCloseFile(GifFile, &Error); free(gUData.gifData); return true; } int fuzz_egif(const uint8_t *Data, size_t Size) { // We treat fuzzed data as a raw RGB stream for a picture // with a fixed width of GIF_IMAGE_WIDTH. // Since we need 3 color bytes per pixel (RGB), height = size/GIF_IMAGE_LINE // where GIF_IMAGE_LINE = GIF_IMAGE_WIDTH * 3 // For integral height, we need Size to be a multiple of GIF_IMAGE_LINE if ((Size == 0) || ((Size % GIF_IMAGE_LINE) != 0)) return 0; bool status = rgb_to_gif(Data, Size); return 0; } ================================================ FILE: projects/giflib/egif_fuzz_common.h ================================================ #include "gif_lib.h" #include "assert.h" #include #include #include struct gifUserData { size_t gifLen; size_t allocatedSize; uint8_t *gifData; }; extern "C" int GifQuantizeBuffer(unsigned int Width, unsigned int Height, int *ColorMapSize, GifByteType * RedInput, GifByteType * GreenInput, GifByteType * BlueInput, GifByteType * OutputBuffer, GifColorType * OutputColorMap); int stub_output_writer(GifFileType *gifFileType, GifByteType *gifByteType, int len); int fuzz_egif(const uint8_t *Data, size_t Size); ================================================ FILE: projects/giflib/egif_target.cc ================================================ #include #include #include #include "egif_fuzz_common.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { return fuzz_egif(Data, Size); } ================================================ FILE: projects/giflib/gif_fuzz_proto.proto ================================================ syntax = "proto2"; // Proto description of the gif format. // Refer to: https://www.fileformat.info/format/gif/egff.htm // https://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp // TODO: Verify if this is correct message LogicalScreenDescriptor { required uint32 ScreenWidth = 1; required uint32 ScreenHeight= 2; required uint32 Packed = 3; required uint32 BackgroundColor = 4; required uint32 AspectRatio = 5; } message GlobalColorTable { required bytes colors = 1; } message ImageDescriptor { required uint32 Seperator =1; required uint32 Left =2; required uint32 Top = 3; required uint32 Width = 4; required uint32 Height = 5; required uint32 Packed = 6; } message GraphicControlExtension { required uint32 Packed = 1; required uint32 DelayTime = 2; required uint32 transparentColorIndex = 3; } message PlainTextExtension { repeated SubBlock subs = 1; optional GraphicControlExtension gcExt = 2; } message LocalColorTable { required bytes colors = 1; } message SubBlock { required uint32 len = 1; required bytes data = 2; } message ImageData { required uint32 lzw = 1; repeated SubBlock subs = 2; } message BasicChunk { required ImageDescriptor imDescriptor =1; required LocalColorTable lct = 2; required ImageData img = 3; optional GraphicControlExtension gcExt = 4; } message ApplicationExtension { required fixed64 appid = 1; repeated SubBlock subs = 2; } message CommentExtension { repeated SubBlock subs = 1; } message Header { enum Version { ENA = 1; ESA = 2; INV = 3; } required Version ver = 1; } message Trailer {} message ImageChunk { oneof chunk_oneof { BasicChunk basic = 1; PlainTextExtension plaintext = 2; ApplicationExtension appExt = 3; CommentExtension comExt = 4; } } message GifProto { required Header header = 1; required LogicalScreenDescriptor lsd = 2; // Instead of making GCT optional here, we condition its visit on LSD's packed byte // in the converter required GlobalColorTable gct = 3; repeated ImageChunk chunks = 4; required Trailer trailer = 5; } package gifProtoFuzzer; ================================================ FILE: projects/giflib/project.yaml ================================================ homepage: "http://giflib.sourceforge.net/" main_repo: "https://git.code.sf.net/p/giflib/code" language: c++ primary_contact: "esr@thyrsus.com" auto_ccs: - "vincent.ulitzsch@live.de" - "bshas3@gmail.com" fuzzing_engines: - afl - honggfuzz - libfuzzer coverage_extra_args: -ignore-filename-regex=.*/LPM/.* ================================================ FILE: projects/gimli/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/gimli-rs/gimli gimli RUN git clone --depth 1 https://github.com/gimli-rs/gimli-libfuzzer-corpora $SRC/gimli/fuzz/corpus WORKDIR gimli COPY build.sh $SRC/ ================================================ FILE: projects/gimli/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cargo fuzz build -O cargo fuzz list | while read i; do cp fuzz/target/x86_64-unknown-linux-gnu/release/$i $OUT/ if [ -d "$SRC/gimli/fuzz/corpus/${i}" ]; then zip -rj "$OUT/${i}_seed_corpus.zip" "$SRC/gimli/fuzz/corpus/${i}" fi done ================================================ FILE: projects/gimli/project.yaml ================================================ homepage: "https://github.com/gimli-rs/gimli" language: rust primary_contact: "philipjcraig@gmail.com" main_repo: "https://github.com/gimli-rs/gimli" sanitizers: - address fuzzing_engines: - libfuzzer vendor_ccs: - maxnair.dev@gmail.com ================================================ FILE: projects/git/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install --no-install-recommends -y \ cvs cvsps gettext libcgi-pm-perl libcurl4-gnutls-dev \ libdbd-sqlite3-perl liberror-perl libexpat1-dev libhttp-date-perl \ libio-pty-perl libmailtools-perl libpcre2-dev libpcre3-dev libsvn-perl \ perl-modules libyaml-perl libz-dev python subversion tcl unzip \ asciidoc docbook-xsl xmlto libssl-dev zip RUN git clone --depth 1 https://github.com/git/git git RUN git clone --depth 1 https://github.com/madler/zlib WORKDIR $SRC/git COPY run_tests.sh build.sh $SRC/ # This is to fix Fuzz Introspector build by using LLVM old pass manager # re https://github.com/ossf/fuzz-introspector/issues/305 ENV OLD_LLVMPASS=1 ================================================ FILE: projects/git/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build zlib pushd "$SRC/zlib" ./configure --static --prefix="$WORK" make -j$(nproc) CFLAGS="$CFLAGS -fPIC" make install popd export ZLIB_PATH=$WORK # Enable a timeout for lockfiles rather than exit immediately. This is to # overcome in case multiple processes try to lock a file around the same # time. sed -i 's/hold_lock_file_for_update_timeout(lk, path, flags, 0);/hold_lock_file_for_update_timeout(lk, path, flags, 5000);/g' lockfile.h # Override GITLIBS to exclude common-main.o. The fuzzing engine (libFuzzer or AFL) # provides its own main() that calls LLVMFuzzerTestOneInput(). # For AFL, we also need --whole-archive to force include the AFL driver's main(). if [ "${FUZZING_ENGINE:-}" = "afl" ]; then FUZZING_ENGINE_FLAGS="-Wl,--whole-archive $LIB_FUZZING_ENGINE -Wl,--no-whole-archive" else FUZZING_ENGINE_FLAGS="$LIB_FUZZING_ENGINE" fi # build fuzzers make -j$(nproc) CC=$CC CXX=$CXX CFLAGS="$CFLAGS" \ FUZZ_CXXFLAGS="$CXXFLAGS" \ LIB_FUZZING_ENGINE="$FUZZING_ENGINE_FLAGS" \ GITLIBS=libgit.a fuzz-all FUZZERS="" FUZZERS="$FUZZERS fuzz-commit-graph" FUZZERS="$FUZZERS fuzz-config" FUZZERS="$FUZZERS fuzz-credential-from-url-gently" FUZZERS="$FUZZERS fuzz-date" FUZZERS="$FUZZERS fuzz-pack-headers" FUZZERS="$FUZZERS fuzz-pack-idx" FUZZERS="$FUZZERS fuzz-parse-attr-line" FUZZERS="$FUZZERS fuzz-url-decode-mem" # copy fuzzers for fuzzer in $FUZZERS ; do cp oss-fuzz/$fuzzer $OUT done for fuzzer in $FUZZERS ; do cat >$OUT/$fuzzer.options << EOF [libfuzzer] detect_leaks = 0 EOF done ================================================ FILE: projects/git/project.yaml ================================================ homepage: "https://git-scm.com" language: c++ primary_contact: "steadmon@google.com" auto_ccs: - "git-fuzz-reports@google.com" - "emilyshaffer@google.com" - "jonathantanmy@google.com" - "jrn@google.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" main_repo: 'https://github.com/git/git' # Disable honggfuzz due to undiagnosed build failures fuzzing_engines: - libfuzzer - afl ================================================ FILE: projects/git/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make test -j$(nproc) ================================================ FILE: projects/gitdb/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/gitpython-developers/gitdb gitdb COPY *.sh *py $SRC/ WORKDIR $SRC/gitdb ================================================ FILE: projects/gitdb/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gitdb/fuzz_gitdb.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzzer for several modules in gitdb. We keep it in one fuzzer for ease of development """ import sys import atheris import zlib from gitdb import ( DecompressMemMapReader, LooseObjectDB, MemoryDB ) from gitdb.pack import ( PackFile ) from gitdb.exc import ParseError def fuzz_decompression_map_reader(data): """Targets gitdb/stream.py#DecompressMemMapReader""" fdp = atheris.FuzzedDataProvider(data) zdata = zlib.compress(data) test_reader = DecompressMemMapReader(zdata, True) try: bytes_read = test_reader.read(fdp.ConsumeIntInRange(0, 10000)) except ValueError: # Ignore these as they're uninteresting return def fuzz_loose_obj_db(data): """Targets gitdb/db/loose.py""" path = "/tmp/loosedb.db" with open(path, "wb") as f: f.write(data) if not os.path.isfile(path): return ldb = LooseObjectDB(path) if ldb.size() != 0: mdb = MemoryDB() mdb.stream_copy(mdb.sha_iter(), ldb) for sha1 in ldb.sha_iter(): ldb.info(sha1) ldb.stream(sha1) def fuzz_pack_file(data): """Targets code in gitdb/pack.py""" # Ensure we have enough data for a packet if len(data) < 100: return path = "/tmp/packfile.idx" with open(path, "wb") as f: f.write(data) if not os.path.isfile(path): return pack_file = PackFile(path) try: pack_file.version() except ParseError: return if pack_file.size() <= 0: return for obj in pack_file.stream_iter(): info = pack_file.info(obj.pack_offset) def TestOneInput(data): fuzz_decompression_map_reader(data) fuzz_loose_obj_db(data) fuzz_pack_file(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gitdb/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/gitpython-developers/gitdb language: python main_repo: https://github.com/gitpython-developers/gitdb sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/gitea/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/go-gitea/gitea COPY build.sh $SRC/ WORKDIR $SRC/gitea ================================================ FILE: projects/gitea/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer code.gitea.io/gitea/tests/fuzz FuzzMarkdownRenderRaw fuzz_markdown_render_raw gofuzz compile_native_go_fuzzer code.gitea.io/gitea/tests/fuzz FuzzMarkupPostProcess fuzz_markup_post_process gofuzz ================================================ FILE: projects/gitea/project.yaml ================================================ homepage: "https://github.com/go-gitea/gitea" primary_contact: "security@gitea.io" auto_ccs : - "adam@adalogics.com" - "xiaolunwen@gmail.com" - "lauris@nix.lv" - "techknowlogick@gitea.io" - "sapk@sapk.fr" - "zeripath@gmail.com" - "john.olheiser@gmail.com" - "the6543dev@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/go-gitea/gitea" ================================================ FILE: projects/github_scarecrow/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install requests RUN git clone --depth 1 https://github.com/Alan32Liu/github-scarecrow.git $SRC/github-scarecrow WORKDIR $SRC/github-scarecrow RUN git clone --depth 1 https://github.com/google/oss-fuzz RUN cd oss-fuzz/infra/experimental/SystemSan && make COPY shell_injection_poc_fuzzer.py fakelib.py build.sh $SRC/ ================================================ FILE: projects/github_scarecrow/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_python_fuzzer ../shell_injection_poc_fuzzer.py ================================================ FILE: projects/github_scarecrow/fakelib.py ================================================ #!/usr/bin/env python # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ RAN_ONCE = False def do_something(data): global RAN_ONCE if not RAN_ONCE: RAN_ONCE = True if not data: return if data[0]: print('hello') else: print('bye') ================================================ FILE: projects/github_scarecrow/project.yaml ================================================ fuzzing_engines: - libfuzzer # dummy homepage: 'https://github.com/Alan32Liu/github-scarecrow' primary_contact: 'donggeliu@google.com' language: python sanitizers: - address main_repo: 'https://github.com/Alan32Liu/github-scarecrow' file_github_issue: True auto_ccs: - 'gongh@google.com' ================================================ FILE: projects/github_scarecrow/shell_injection_poc_fuzzer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import os # To trick atheris import fakelib def TestOneInput(data): fakelib.do_something(data) if not data: return if not data[0]: return if any(0 == c for c in data): return try: os.system(data) except ValueError as e: print(e) return return def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gitoxide/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/Byron/gitoxide.git gitoxide RUN rustup update nightly WORKDIR gitoxide RUN rustup component add rust-src COPY build.sh $SRC/ ================================================ FILE: projects/gitoxide/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -eox pipefail export CARGO_BUILD_TARGET_DIR=$WORK/shared_cache FUZZ_CRATE_DIRS=$(find . -type d -name fuzz -exec dirname $(readlink -f {}) \;) for CRATE_DIR in ${FUZZ_CRATE_DIRS[@]}; do echo "Building crate: $CRATE_DIR" cd $CRATE_DIR cargo +nightly fuzz build -O --debug-assertions FUZZ_TARGET_OUTPUT_DIR=$CARGO_BUILD_TARGET_DIR/x86_64-unknown-linux-gnu/release for f in fuzz/fuzz_targets/*.rs do FUZZ_TARGET_NAME=$(basename ${f%.*}) CRATE_NAME=$(basename $CRATE_DIR) OUT_FUZZER_NAME=$OUT/$CRATE_NAME-$FUZZ_TARGET_NAME cp $FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT_FUZZER_NAME FUZZ_CORPUS_BUILDER=./fuzz/fuzz_targets/${FUZZ_TARGET_NAME}_corpus_builder.sh if test -f "$FUZZ_CORPUS_BUILDER"; then $FUZZ_CORPUS_BUILDER $SRC/gitoxide ${OUT_FUZZER_NAME}_seed_corpus.zip fi FUZZ_DICT=./fuzz/fuzz_targets/${FUZZ_TARGET_NAME}.dict if test -f "$FUZZ_DICT"; then cp $FUZZ_DICT ${OUT_FUZZER_NAME}.dict fi done done ================================================ FILE: projects/gitoxide/project.yaml ================================================ homepage: "https://crates.io/crates/gitoxide" language: rust primary_contact: "byronimo@gmail.com" auto_ccs: - "nathaniel.brough@gmail.com" - "eliahkagan@gmail.com" main_repo: "https://github.com/GitoxideLabs/gitoxide" file_github_issue: true sanitizers: - address fuzzing_engines: - libfuzzer coverage_extra_args: > -ignore-filename-regex=.*/rustc/.* ================================================ FILE: projects/gitpython/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/gitpython-developers/gitpython gitpython RUN $SRC/gitpython/fuzzing/oss-fuzz-scripts/container-environment-bootstrap.sh COPY *.sh $SRC/ WORKDIR $SRC/gitpython ================================================ FILE: projects/gitpython/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ . "$SRC/gitpython/fuzzing/oss-fuzz-scripts/build.sh" ================================================ FILE: projects/gitpython/project.yaml ================================================ homepage: "https://github.com/gitpython-developers/gitpython" language: python primary_contact: "byronimo@gmail.com" auto_ccs: - "david.js.lakin@gmail.com" - "eliahkagan@gmail.com" main_repo: "https://github.com/gitpython-developers/gitpython" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/glaze/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/stephenberry/glaze WORKDIR glaze COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/glaze/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ fuzzing/ossfuzz.sh ================================================ FILE: projects/glaze/project.yaml ================================================ homepage: "https://github.com/stephenberry/glaze" language: c++ primary_contact: "pauldreikossfuzz@gmail.com" auto_ccs: - "stephenberry.developer@gmail.com" main_repo: "https://github.com/stephenberry/glaze.git" file_github_issue: true ================================================ FILE: projects/glaze/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd build ASAN_OPTIONS=detect_leaks=0 ctest -C Release -j$(nproc) --output-on-failure ================================================ FILE: projects/glib/0001-deflate-Zero-initialise-the-prev-and-window-buffers.patch ================================================ From 73aa394ed2e45876945ae90d1e2fd0fb0dfb84b7 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 1 Dec 2025 19:16:55 +0000 Subject: [PATCH] deflate: Zero-initialise the prev and window buffers This is the combination of patches: - https://github.com/chromium/chromium/blob/main/third_party/zlib/patches/0003-uninitializedjump.patch - https://github.com/chromium/chromium/blob/main/third_party/zlib/patches/0007-zero-init-deflate-window.patch - https://github.com/chromium/chromium/blob/main/third_party/zlib/patches/0017-deflate-move-zmemzero-after-null-check.patch authored by Adenilson Cavalcanti, Hans Wennborg and pedro martelletto for Chromium. They needed to be combined and re-rolled as a patch to avoid having to apply all the other Chromium zlib patches so they would apply properly. They fix some msan errors from deflate which have been reported to zlib upstream but not fixed yet. See the original patches for details. Also clear the `head` and `pending_buf` buffers similarly (my own changes). --- deflate.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/deflate.c b/deflate.c index 012ea81..e626727 100644 --- a/deflate.c +++ b/deflate.c @@ -503,6 +503,16 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, deflateEnd (strm); return Z_MEM_ERROR; } + /* Avoid use of unitialized values in the window, see crbug.com/1137613 and + * crbug.com/1144420 */ + zmemzero(s->window, s->w_size * (2 * sizeof(Byte))); + /* Avoid use of uninitialized value, see: + * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11360 + */ + zmemzero(s->prev, s->w_size * sizeof(Pos)); + /* Same for the other buffers */ + zmemzero(s->head, s->hash_size * sizeof(Pos)); + zmemzero(s->pending_buf, s->lit_bufsize * LIT_BUFS); #ifdef LIT_MEM s->d_buf = (ushf *)(s->pending_buf + (s->lit_bufsize << 1)); s->l_buf = s->pending_buf + (s->lit_bufsize << 2); -- 2.51.1 ================================================ FILE: projects/glib/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf automake libtool pkg-config python3-pip RUN unset CFLAGS CXXFLAGS && pip3 install -U meson ninja packaging RUN git clone --depth 1 --branch v1.3.1 --no-tags https://github.com/madler/zlib.git RUN git clone --depth 1 --no-tags https://gitlab.gnome.org/GNOME/glib WORKDIR glib COPY build.sh $SRC/ COPY 0001-deflate-Zero-initialise-the-prev-and-window-buffers.patch $SRC/ ================================================ FILE: projects/glib/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PREFIX=$WORK/prefix mkdir -p $PREFIX export PKG_CONFIG="`which pkg-config` --static" export PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig export PATH=$PREFIX/bin:$PATH BUILD=$WORK/build rm -rf $WORK/* rm -rf $BUILD mkdir -p $BUILD # Build zlib locally so it definitely has fsanitize support # Apply some patches from Chromium to fix known msan issues # which are not yet fixed upstream. pushd $SRC/zlib patch -p1 < $SRC/0001-deflate-Zero-initialise-the-prev-and-window-buffers.patch mkdir build && cd build CFLAGS=-fPIC ../configure --static --prefix=$PREFIX make install -j$(nproc) popd # Build GLib itself meson $BUILD \ -Doss_fuzz=enabled \ -Db_lundef=false \ --prefix=$PREFIX \ --libdir=lib \ -Ddefault_library=static \ -Dlibmount=disabled ninja -C $BUILD find $BUILD/fuzzing -maxdepth 1 -executable -type f -exec cp "{}" $OUT \; find fuzzing -type f -name "*.dict" -exec cp "{}" $OUT \; for CORPUS in $(find fuzzing -type f -name "*.corpus"); do BASENAME=${CORPUS##*/} zip $OUT/${BASENAME%%.*}_seed_corpus.zip . -ws -r -i@$CORPUS done ================================================ FILE: projects/glib/project.yaml ================================================ homepage: "https://gitlab.gnome.org/GNOME/glib/" language: c++ primary_contact: "bugzilla@tecnocode.co.uk" auto_ccs: - philip.withnall@gmail.com - mwl458@gmail.com - iain@orangesquash.org.uk - slomo@coaxion.net - trevi55@gmail.com - mcatanza@redhat.com - tcullum@redhat.com sanitizers: - address - memory - undefined help_url: https://gitlab.gnome.org/GNOME/glib/tree/master/fuzzing#how-to-reproduce-oss-fuzz-bugs-locally main_repo: 'https://gitlab.gnome.org/GNOME/glib' ================================================ FILE: projects/globaleaks-whistleblowing-software/project.yaml ================================================ homepage: "https://www.globaleaks.org/" language: python primary_contact: "giovanni.pellerano@globaleaks.org" main_repo: 'https://github.com/globaleaks/globaleaks-whistleblowing-software.git' ================================================ FILE: projects/glog/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/google/glog COPY run_tests.sh build.sh $SRC/ WORKDIR $SRC/glog ================================================ FILE: projects/glog/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake .. -DWITH_FUZZING=ossfuzz -DBUILD_SHARED_LIBS=OFF make -j$(nproc) cp fuzz_* $OUT/ ================================================ FILE: projects/glog/project.yaml ================================================ homepage: "https://github.com/google/glog" language: c++ primary_contact: "sergiu.deitsch@gmail.com" auto_ccs : - "p.antoine@catenacyber.fr" main_repo: 'https://github.com/google/glog' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/glog/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build -E "stacktrace|symbolize|includes_logging|includes_vlog_is_on|includes_raw_logging" ================================================ FILE: projects/glom/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/mahmoud/glom COPY build.sh *.py $SRC/ WORKDIR glom ================================================ FILE: projects/glom/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/glom/fuzz_core.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import glom import json def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) val = {'d': {'e': ['f']}} try: glom.core.glom(val, glom.core.Inspect(fdp.ConsumeUnicodeNoSurrogates(64))) except glom.GlomError: pass try: glom.core.glom( val, glom.core.Coalesce(fdp.ConsumeUnicodeNoSurrogates(32), fdp.ConsumeUnicodeNoSurrogates(32), fdp.ConsumeUnicodeNoSurrogates(32))) except glom.GlomError: pass # Create a random dictionary. In this case if any # error happens during random dict creation we just # exit. try: json_dict = json.loads(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 512))) except Exception: return if not isinstance(json_dict, dict): return # Use random dict as input to glom try: glom.core.glom(json_dict, fdp.ConsumeString(30)) except glom.GlomError: pass try: spec = glom.T['a']['b']['c'] glom.core.glom(json_dict, spec) except glom.GlomError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/glom/fuzz_glom.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import glom import json def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) val = {'d': {'e': ['f']}} try: glom.core.glom(val, fdp.ConsumeString(30)) except glom.core.PathAccessError: pass # Create a random dictionary. In this case if any # error happens during random dict creation we just # exit. try: json_dict = json.loads(fdp.ConsumeString(100)) except Exception: return if not isinstance(json_dict, dict): return # Use random dict as input to glom try: glom.core.glom(json_dict, fdp.ConsumeString(30)) except glom.core.PathAccessError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/glom/fuzz_matching.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import glom import json def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) spec = glom.matching.Match([{ 'fuzz1': str, 'fuzz2': str, 'fuzz3': int, 'fuzz4': dict }]) # Create a random object using json try: json_val = json.loads(fdp.ConsumeString(sys.maxsize)) except Exception: return try: glom.glom(json_val, spec) except glom.GlomError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/glom/fuzz_mutation.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import glom import json def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: glom.mutation.delete({'a': [{ 'f': 'z' }, {'ff', 'zz'}]}, fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024))) except (glom.GlomError, ValueError): pass # Create a random object using json try: json_val = json.loads(fdp.ConsumeString(fdp.ConsumeIntInRange(0, 1024))) except Exception: return try: glom.mutation.delete(json_val, 'a.1.b.2.c') except (glom.GlomError, ValueError, TypeError): pass try: glom.mutation.delete(json_val, fdp.ConsumeUnicodeNoSurrogates(64)) except (glom.GlomError, ValueError, TypeError): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/glom/fuzz_reduction.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys import glom import json def test_flatten(data): fdp = atheris.FuzzedDataProvider(data) list_of_lists = [] for idx in range(fdp.ConsumeIntInRange(1, 1000)): list_of_lists.append( fdp.ConsumeIntListInRange(fdp.ConsumeIntInRange(1, 100), -100000, 10000)) glom.reduction.flatten(list_of_lists) def test_merge(data): fdp = atheris.FuzzedDataProvider(data) list_of_dicts = [] for idx in range(fdp.ConsumeIntInRange(1, 1000)): tmp_dict = {} tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) tmp_dict[fdp.ConsumeUnicodeNoSurrogates( 12)] = fdp.ConsumeUnicodeNoSurrogates(12) list_of_dicts.append(tmp_dict) glom.reduction.merge(list_of_dicts) def TestOneInput(data): test_flatten(data) test_merge(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/glom/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/mahmoud/glom language: python main_repo: https://github.com/mahmoud/glom sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/glslang/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y python-is-python3 build-essential \ autoconf automake libtool pkg-config RUN git clone https://github.com/khronosgroup/glslang glslang COPY *_fuzzer.cc *.sh $SRC/ WORKDIR $SRC/glslang ================================================ FILE: projects/glslang/build.sh ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir -p build cd build cmake -DCMAKE_BUILD_TYPE=Release \ -DGLSLANG_TESTS=ON \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DENABLE_OPT=0 ../ make V=1 -j$(nproc) install $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/compile_fuzzer.cc \ -DENABLE_HLSL -DENABLE_OPT=0 -DGLSLANG_OSINCLUDE_UNIX \ -I/src/glslang/glslang/Include/ -I/src/glslang/glslang/.. \ -I/src/glslang/build/include -I/src/glslang/SPIRV/.. \ ./glslang/libglslang.a ./SPIRV/libSPIRV.a \ ./glslang/libglslang-default-resource-limits.a \ -lpthread ./glslang/libMachineIndependent.a \ ./glslang/OSDependent/Unix/libOSDependent.a \ ./glslang/libGenericCodeGen.a \ -o $OUT/compile_fuzzer ================================================ FILE: projects/glslang/compile_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "glslang/Public/ResourceLimits.h" #include "glslang/Public/ShaderLang.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { glslang::InitializeProcess(); EShMessages controls; glslang::TShader shader(EShLangVertex); const char *dataPtr = (const char*)data; const int dataSize = (const int)size; shader.setStringsWithLengths(&dataPtr, &dataSize, 1); shader.setEntryPoint("ep"); // Parse the shader shader.parse(GetDefaultResources(), 100, false, controls); glslang::FinalizeProcess(); return 0; } ================================================ FILE: projects/glslang/project.yaml ================================================ homepage: "https://github.com/khronosgroup/glslang" main_repo: "https://github.com/khronosgroup/glslang" language: c++ sanitizers: - address vendor_ccs: - david@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/glslang/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd build make test ================================================ FILE: projects/gluon/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/ProtonMail/gluon.git RUN go install github.com/AdamKorcz/go-118-fuzz-build@latest COPY build.sh $SRC/ WORKDIR $SRC/gluon ================================================ FILE: projects/gluon/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer github.com/ProtonMail/gluon/imap FuzzNewParsedMessage fuzz_new_parsed_message compile_native_go_fuzzer github.com/ProtonMail/gluon/rfc5322 FuzzParseAddress fuzz_parse_address compile_native_go_fuzzer github.com/ProtonMail/gluon/rfc5322 FuzzRFC5322 fuzz_rfc5322 compile_native_go_fuzzer github.com/ProtonMail/gluon/rfc822 FuzzParseDec fuzz_parse_dec ================================================ FILE: projects/gluon/project.yaml ================================================ homepage: "https://proton.me" language: go primary_contact: "security@proton.me" auto_ccs: - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/ProtonMail/gluon" ================================================ FILE: projects/gnucobol/project.yaml ================================================ homepage: "https://www.gnu.org/software/gnucobol/" language: c primary_contact: "simonsobisch@gmail.com" auto_ccs: - "simonsobisch@gnu.org" sanitizers: - address - memory: experimental: True - undefined architectures: - x86_64 - i386 # 'https://svn.code.sf.net/p/gnucobol/code/trunk' is the "next big version" (unstable), # code installed in OS package managers is found in 3.x branch main_repo: 'https://svn.code.sf.net/p/gnucobol/code/branches/gnucobol-3.x' ================================================ FILE: projects/gnupg/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf libtool bzip2 bison flex gettext pkg-config RUN wget http://ftp.de.debian.org/debian/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ apt install -y ./automake_1.16.5-1.3_all.deb RUN git clone --depth 1 git://git.gnupg.org/libgpg-error.git libgpg-error RUN git clone --depth 1 git://git.gnupg.org/libgcrypt.git libgcrypt RUN git clone --depth 1 git://git.gnupg.org/libassuan.git libassuan RUN git clone --depth 1 git://git.gnupg.org/libksba.git libksba RUN git clone --depth 1 git://git.gnupg.org/npth.git npth # Build dependencies once in the Docker image RUN cd libgpg-error && ./autogen.sh && \ ./configure --enable-static --disable-shared --disable-doc --disable-tests CFLAGS="-O0" && \ make -j$(nproc) && make install RUN cd libgcrypt && ./autogen.sh && \ ./configure --enable-static --disable-shared --disable-doc --disable-tests --disable-asm CFLAGS="-O0" && \ make -j$(nproc) && make install RUN cd libassuan && ./autogen.sh && \ ./configure --enable-static --disable-shared --disable-doc CFLAGS="-O0" && \ make -j$(nproc) && make install RUN cd libksba && ./autogen.sh && \ ./configure --enable-static --disable-shared --disable-doc CFLAGS="-O0" && \ make -j$(nproc) && make install RUN cd npth && ./autogen.sh && \ ./configure --enable-static --disable-shared CFLAGS="-O0" && \ make -j$(nproc) && make install RUN git clone --depth 1 git://git.gnupg.org/gnupg.git $SRC/gnupg WORKDIR $SRC/gnupg COPY fuzz_* $SRC/ COPY fuzzer_stubs.c $SRC/ COPY build.sh $SRC/ # This is to fix Fuzz Introspector build by using LLVM old pass manager # re https://github.com/ossf/fuzz-introspector/issues/305 ENV OLD_LLVMPASS 1 ================================================ FILE: projects/gnupg/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Dependencies are already built in the Docker image cd /src/gnupg ./autogen.sh ./configure --enable-maintainer-mode --disable-doc --disable-tests --disable-nls \ --disable-sqlite --disable-gnutls --disable-ldap --disable-card-support \ CFLAGS="$CFLAGS" CXXFLAGS="$CXXFLAGS" # Generate built sources first (status-codes.h, audit-events.h, etc.) make -j$(nproc) -C common audit-events.h status-codes.h make -j$(nproc) -C regexp _unicode_mapping.c # Build only needed components make -j$(nproc) -C common libcommon.a libcommonpth.a libgpgrl.a make -j$(nproc) -C regexp libregexp.a make -j$(nproc) -C kbx libkeybox.a # Build g10 - just build the gpg program which compiles all needed objects make -j$(nproc) -C g10 gpg # Create a library archive from all the compiled objects, excluding gpg.o which has main() mkdir -p g10/.libs find g10 -name '*.o' -type f ! -name 'gpg.o' ! -name 't-*.o' | xargs ar cru g10/.libs/libgpg.a ranlib g10/.libs/libgpg.a # Build fuzzers cd /src/gnupg # Compile the fuzzer stubs that provide opt and glo_ctrl $CC $CFLAGS -I. -Icommon -Ig10 -c /src/fuzzer_stubs.c -o fuzzer_stubs.o for fuzzer in fuzz_decrypt fuzz_import fuzz_list fuzz_verify; do [ -f /src/${fuzzer}.c ] || continue $CC $CFLAGS -I. -Icommon -Ig10 -c /src/${fuzzer}.c -o ${fuzzer}.o $CXX $CXXFLAGS fuzzer_stubs.o ${fuzzer}.o \ g10/.libs/libgpg.a \ kbx/libkeybox.a \ common/libcommonpth.a \ regexp/libregexp.a \ common/libgpgrl.a \ $LIB_FUZZING_ENGINE \ -lgcrypt -lgpg-error -lassuan -lksba -lnpth -lutil \ -o $OUT/${fuzzer} done cp /src/*.options $OUT/ 2>/dev/null || true ================================================ FILE: projects/gnupg/fuzz_decrypt.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "config.h" #include "gpg.h" #include "../common/types.h" #include "../common/iobuf.h" #include "keydb.h" #include "keyedit.h" #include "../common/util.h" #include "main.h" #include "trustdb.h" #include #include #include #include #include static bool initialized = false; ctrl_t ctrlGlobal; int fd; char *filename; //hack not to include gpg.c which has main function extern int g10_errors_seen; extern int assert_signer_true; extern int assert_pubkey_algo_false; void g10_exit( int rc ) { gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); gcry_control (GCRYCTL_TERM_SECMEM ); /* Don't exit in fuzzer - just return to allow fuzzing to continue */ (void)rc; return; } static void gpg_deinit_default_ctrl (ctrl_t ctrl) { #ifdef USE_TOFU tofu_closedbs (ctrl); #endif gpg_dirmngr_deinit_session_data (ctrl); keydb_release (ctrl->cached_getkey_kdb); } static void my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) { return; } static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag) { if (typeflag == FTW_F){ unlink(fpath); } return 0; } static void rmrfdir(char *path) { ftw(path, unlink_cb, 16); if (rmdir(path) != 0) { printf("failed rmdir, errno=%d\n", errno); } } // 65kb should be enough ;-) #define MAX_LEN 0x10000 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (! initialized) { ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal)); if (!ctrlGlobal) { exit(1); } //deletes previous tmp dir and (re)create it as a ramfs //system("umount /tmp/fuzzdirdecrypt"); rmrfdir("/tmp/fuzzdirdecrypt"); mkdir("/tmp/fuzzdirdecrypt", 0700); //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirdecrypt"); filename=strdup("/tmp/fuzzdirdecrypt/fuzz.gpg"); if (!filename) { free(ctrlGlobal); return 0; } fd = open("/tmp/fuzzdirdecrypt/fuzz.gpg", O_RDWR | O_CREAT, 0600); if (fd == -1) { free(ctrlGlobal); free(filename); return 0; } gnupg_set_homedir("/tmp/fuzzdirdecrypt/"); if (keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT) != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); return 0; } if (setup_trustdb (1, NULL) != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); return 0; } //populate /tmp/fuzzdirdecrypt/ as homedir ~/.gnupg strlist_t sl = NULL; public_key_list (ctrlGlobal, sl, 0, 0); free_strlist(sl); //no output for stderr log_set_file("/dev/null"); gcry_set_log_handler (my_gcry_logger, NULL); //gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG); //overwrite output file //opt.batch = 1; //opt.answer_yes = 1; initialized = true; } memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; if (Size > MAX_LEN) { // limit maximum size to avoid long computing times Size = MAX_LEN; } if (ftruncate(fd, Size) == -1) { return 0; } if (lseek (fd, 0, SEEK_SET) < 0) { return 0; } if (write (fd, Data, Size) != Size) { return 0; } decrypt_messages(ctrlGlobal, 1, &filename); gpg_deinit_default_ctrl (ctrlGlobal); memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; decrypt_message(ctrlGlobal, filename, NULL); gpg_deinit_default_ctrl (ctrlGlobal); return 0; } ================================================ FILE: projects/gnupg/fuzz_decrypt.options ================================================ [libfuzzer] close_fd_mask = 1 ================================================ FILE: projects/gnupg/fuzz_import.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "config.h" #include "gpg.h" #include "../common/types.h" #include "../common/iobuf.h" #include "keydb.h" #include "keyedit.h" #include "../common/util.h" #include "main.h" #include "options.h" #include "trustdb.h" #include #include #include #include #include // 8kb should be enough ;-) #define MAX_LEN 0x2000 static bool initialized = false; ctrl_t ctrlGlobal; int fd; char *filename; //hack not to include gpg.c which has main function extern int g10_errors_seen; extern int assert_signer_true; extern int assert_pubkey_algo_false; void g10_exit( int rc ) { gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); gcry_control (GCRYCTL_TERM_SECMEM ); /* Don't exit in fuzzer - just return to allow fuzzing to continue */ (void)rc; return; } static void gpg_deinit_default_ctrl (ctrl_t ctrl) { #ifdef USE_TOFU tofu_closedbs (ctrl); #endif gpg_dirmngr_deinit_session_data (ctrl); keydb_release (ctrl->cached_getkey_kdb); } static void my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) { return; } static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag) { if (typeflag == FTW_F){ unlink(fpath); } return 0; } static void rmrfdir(char *path) { ftw(path, unlink_cb, 16); if (rmdir(path) != 0) { printf("failed rmdir, errno=%d\n", errno); } } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (! initialized) { ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal)); if (!ctrlGlobal) { exit(1); } //deletes previous tmp dir and (re)create it as a ramfs //system("umount /tmp/fuzzdirimport"); rmrfdir("/tmp/fuzzdirimport"); if (mkdir("/tmp/fuzzdirimport", 0700) < 0) { printf("failed mkdir, errno=%d\n", errno); if (errno != EEXIST) { return 0; } } //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirimport"); filename=strdup("/tmp/fuzzdirimport/fuzz.gpg"); if (!filename) { free(ctrlGlobal); return 0; } fd = open(filename, O_RDWR | O_CREAT, 0666); if (fd == -1) { free(filename); free(ctrlGlobal); printf("failed open, errno=%d\n", errno); return 0; } gnupg_set_homedir("/tmp/fuzzdirimport/"); gpg_error_t gpgerr = keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT); if (gpgerr != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); printf("failed keydb_add_resource, errno=%d\n", gpgerr); return 0; } gpgerr = setup_trustdb (1, NULL); if (gpgerr != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); printf("failed setup_trustdb, errno=%d\n", gpgerr); return 0; } //populate /tmp/fuzzdirimport/ as homedir ~/.gnupg strlist_t sl = NULL; public_key_list (ctrlGlobal, sl, 0, 0); free_strlist(sl); //no output for stderr log_set_file("/dev/null"); gcry_set_log_handler (my_gcry_logger, NULL); //gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG); initialized = true; } memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; if (Size > MAX_LEN) { // limit maximum size to avoid long computing times Size = MAX_LEN; } if (ftruncate(fd, Size) == -1) { return 0; } if (lseek (fd, 0, SEEK_SET) < 0) { return 0; } if (write (fd, Data, Size) != Size) { return 0; } import_keys (ctrlGlobal, &filename, 1, NULL, IMPORT_REPAIR_KEYS, 0, NULL); gpg_deinit_default_ctrl (ctrlGlobal); /*memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; PKT_public_key pk; get_pubkey_fromfile (ctrlGlobal, &pk, filename); release_public_key_parts (&pk); gpg_deinit_default_ctrl (ctrlGlobal);*/ return 0; } ================================================ FILE: projects/gnupg/fuzz_list.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "config.h" #include "gpg.h" #include "../common/types.h" #include "../common/iobuf.h" #include "keydb.h" #include "keyedit.h" #include "../common/util.h" #include "main.h" #include "trustdb.h" #include #include #include #include #include static bool initialized = false; ctrl_t ctrlGlobal; int fd; char *filename; //hack not to include gpg.c which has main function extern int g10_errors_seen; extern int assert_signer_true; extern int assert_pubkey_algo_false; void g10_exit( int rc ) { gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); gcry_control (GCRYCTL_TERM_SECMEM ); /* Don't exit in fuzzer - just return to allow fuzzing to continue */ (void)rc; return; } static void gpg_deinit_default_ctrl (ctrl_t ctrl) { #ifdef USE_TOFU tofu_closedbs (ctrl); #endif gpg_dirmngr_deinit_session_data (ctrl); keydb_release (ctrl->cached_getkey_kdb); } static void my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) { return; } static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag) { if (typeflag == FTW_F){ unlink(fpath); } return 0; } static void rmrfdir(char *path) { ftw(path, unlink_cb, 16); if (rmdir(path) != 0) { printf("failed rmdir, errno=%d\n", errno); } } // 65kb should be enough ;-) #define MAX_LEN 0x10000 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { IOBUF a; armor_filter_context_t *afx = NULL; if (! initialized) { ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal)); if (!ctrlGlobal) { exit(1); } //deletes previous tmp dir and (re)create it as a ramfs //system("umount /tmp/fuzzdirlist"); rmrfdir("/tmp/fuzzdirlist"); if (mkdir("/tmp/fuzzdirlist", 0700) < 0) { printf("failed mkdir, errno=%d\n", errno); if (errno != EEXIST) { return 0; } } //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirlist"); filename=strdup("/tmp/fuzzdirlist/fuzz.gpg"); if (!filename) { free(ctrlGlobal); return 0; } fd = open(filename, O_RDWR | O_CREAT, 0666); if (fd == -1) { free(filename); free(ctrlGlobal); printf("failed open, errno=%d\n", errno); return 0; } gnupg_set_homedir("/tmp/fuzzdirlist/"); gpg_error_t gpgerr = keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT); if (gpgerr != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); printf("failed keydb_add_resource, errno=%d\n", gpgerr); return 0; } gpgerr = setup_trustdb (1, NULL); if (gpgerr != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); printf("failed setup_trustdb, errno=%d\n", gpgerr); return 0; } //populate /tmp/fuzzdirlist/ as homedir ~/.gnupg strlist_t sl = NULL; public_key_list (ctrlGlobal, sl, 0, 0); free_strlist(sl); //no output for stderr log_set_file("/dev/null"); gcry_set_log_handler (my_gcry_logger, NULL); //gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG); //opt.list_packets=1; // Disable packet listing during fuzzing to avoid output flooding //set_packet_list_mode(1); initialized = true; } if (Size > MAX_LEN) { // limit maximum size to avoid long computing times return 0; } memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; if (ftruncate(fd, Size) == -1) { return 0; } if (lseek (fd, 0, SEEK_SET) < 0) { return 0; } if (write (fd, Data, Size) != Size) { return 0; } a = iobuf_open(filename); if( !a ) { printf("failed iobuf_open\n"); return 0; } if( use_armor_filter( a ) ) { afx = new_armor_context (); push_armor_filter (afx, a); } proc_packets (ctrlGlobal, NULL, a ); iobuf_close(a); release_armor_context (afx); gpg_deinit_default_ctrl (ctrlGlobal); return 0; } ================================================ FILE: projects/gnupg/fuzz_list.options ================================================ [libfuzzer] close_fd_mask = 1 ================================================ FILE: projects/gnupg/fuzz_verify.c ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "config.h" #include "gpg.h" #include "../common/types.h" #include "../common/iobuf.h" #include "keydb.h" #include "keyedit.h" #include "../common/util.h" #include "main.h" #include "trustdb.h" #include #include #include #include #include static bool initialized = false; ctrl_t ctrlGlobal; int fd; char *filename; //hack not to include gpg.c which has main function extern int g10_errors_seen; extern int assert_signer_true; extern int assert_pubkey_algo_false; void g10_exit( int rc ) { gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE); gcry_control (GCRYCTL_TERM_SECMEM ); /* Don't exit in fuzzer - just return to allow fuzzing to continue */ (void)rc; return; } static void gpg_deinit_default_ctrl (ctrl_t ctrl) { #ifdef USE_TOFU tofu_closedbs (ctrl); #endif gpg_dirmngr_deinit_session_data (ctrl); keydb_release (ctrl->cached_getkey_kdb); } static void my_gcry_logger (void *dummy, int level, const char *format, va_list arg_ptr) { return; } static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag) { if (typeflag == FTW_F){ unlink(fpath); } return 0; } static void rmrfdir(char *path) { ftw(path, unlink_cb, 16); if (rmdir(path) != 0) { printf("failed rmdir, errno=%d\n", errno); } } int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (! initialized) { ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal)); if (!ctrlGlobal) { exit(1); } //deletes previous tmp dir and (re)create it as a ramfs //system("umount /tmp/fuzzdirverify"); rmrfdir("/tmp/fuzzdirverify"); mkdir("/tmp/fuzzdirverify/", 0700); //system("mount -t tmpfs -o size=64M tmpfs /tmp/fuzzdirverify"); filename=strdup("/tmp/fuzzdirverify/fuzz.gpg"); if (!filename) { free(ctrlGlobal); return 0; } fd = open("/tmp/fuzzdirverify/fuzz.gpg", O_RDWR | O_CREAT, 0600); if (fd == -1) { free(ctrlGlobal); free(filename); return 0; } gnupg_set_homedir("/tmp/fuzzdirverify/"); if (keydb_add_resource ("pubring" EXTSEP_S GPGEXT_GPG, KEYDB_RESOURCE_FLAG_DEFAULT) != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); return 0; } if (setup_trustdb (1, NULL) != GPG_ERR_NO_ERROR) { free(filename); free(ctrlGlobal); close(fd); return 0; } //populate /tmp/fuzzdirverify/ as homedir ~/.gnupg strlist_t sl = NULL; public_key_list (ctrlGlobal, sl, 0, 0); free_strlist(sl); //no output for stderr log_set_file("/dev/null"); gcry_set_log_handler (my_gcry_logger, NULL); //gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG); initialized = true; } memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; if (ftruncate(fd, Size) == -1) { return 0; } if (lseek (fd, 0, SEEK_SET) < 0) { return 0; } if (write (fd, Data, Size) != Size) { return 0; } verify_signatures(ctrlGlobal, 1, &filename); gpg_deinit_default_ctrl (ctrlGlobal); memset(ctrlGlobal, 0, sizeof(*ctrlGlobal)); ctrlGlobal->magic = SERVER_CONTROL_MAGIC; verify_files(ctrlGlobal, 1, &filename); gpg_deinit_default_ctrl (ctrlGlobal); return 0; } ================================================ FILE: projects/gnupg/fuzzer_stubs.c ================================================ /* Copyright 2025 Google LLC. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* Stub definitions for fuzzer linking */ #define INCLUDED_BY_MAIN_MODULE 1 #include "config.h" #include "gpg.h" #include "main.h" #include "options.h" /* These are needed but gpg.c is excluded */ int g10_errors_seen = 0; int assert_signer_true = 0; int assert_pubkey_algo_false = 0; ================================================ FILE: projects/gnupg/fuzzgnupg.diff ================================================ diff --git a/configure.ac b/configure.ac index fea504e..131595e 100644 --- a/configure.ac +++ b/configure.ac @@ -989,6 +989,18 @@ if test x"$use_tofu" = xyes ; then *** $tmp]]) fi fi + +# TODO choose when to build fuzzing with option ? +AC_CHECK_LIB(FuzzingEngine, main, + [ LIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" + have_fuzz=yes + ]) +AC_SUBST(LIB_FUZZING_ENGINE) +AC_CHECK_PROG(HAVE_CLANGXX, clang++, 1) +AM_CONDITIONAL(HAVE_LIB_FUZZING_ENGINE, [test "$have_fuzz" = yes -a "$HAVE_CLANGXX" = 1]) + + + if test "$have_sqlite" != "yes"; then build_keyboxd=no fi @@ -2151,6 +2163,7 @@ tests/migrations/Makefile tests/tpm2dtests/Makefile tests/gpgme/Makefile tests/pkits/Makefile +tests/fuzz/Makefile g10/gpg.w32-manifest tools/gpg-connect-agent.w32-manifest tools/gpgconf.w32-manifest diff --git a/g10/Makefile.am b/g10/Makefile.am index eb23573b7..785ac2b4b 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -47,6 +47,7 @@ endif # NB: We use noinst_ for gpg and gpgv so that we can install them with # the install-hook target under the name gpg2/gpgv2. noinst_PROGRAMS = gpg +noinst_LIBRARIES = libgpg.a if !HAVE_W32CE_SYSTEM noinst_PROGRAMS += gpgv endif @@ -164,6 +165,9 @@ gpg_sources = server.c \ gpg_SOURCES = gpg.c \ keyedit.c keyedit.h \ $(gpg_sources) +libgpg_a_SOURCES = keyedit.c keyedit.h \ + $(gpg_sources) + gpgv_SOURCES = gpgv.c \ $(common_source) \ diff --git a/g10/armor.c b/g10/armor.c index eb2d28bca..594f5bd2d 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -313,7 +313,9 @@ static void invalid_armor(void) { write_status(STATUS_BADARMOR); +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION g10_exit(1); /* stop here */ +#endif } diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h index c0f1e0cec..52652a0e0 100644 --- a/g10/call-dirmngr.h +++ b/g10/call-dirmngr.h @@ -19,6 +19,8 @@ #ifndef GNUPG_G10_CALL_DIRMNGR_H #define GNUPG_G10_CALL_DIRMNGR_H +#include "options.h" + void gpg_dirmngr_deinit_session_data (ctrl_t ctrl); gpg_error_t gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver); diff --git a/g10/compress-bz2.c b/g10/compress-bz2.c index 45aa40dfc..1a74a89d7 100644 --- a/g10/compress-bz2.c +++ b/g10/compress-bz2.c @@ -155,8 +155,15 @@ do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs, (unsigned)bzs->avail_in, (unsigned)bzs->avail_out, zrc); if( zrc == BZ_STREAM_END ) rc = -1; /* eof */ - else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR ) - log_fatal("bz2lib inflate problem: rc=%d\n", zrc ); + else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR ) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + log_error("bz2lib inflate problem: rc=%d\n", zrc ); + rc = GPG_ERR_BAD_DATA; + break; +#else + log_fatal("bz2lib inflate problem: rc=%d\n", zrc ); +#endif + } else if (zrc == BZ_OK && eofseen && !bzs->avail_in && bzs->avail_out > 0) { diff --git a/g10/compress.c b/g10/compress.c index e7a6f2b11..9a9ab5460 100644 --- a/g10/compress.c +++ b/g10/compress.c @@ -204,10 +204,19 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs, if( zrc == Z_STREAM_END ) rc = -1; /* eof */ else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + rc = -1; + zrc = Z_BUF_ERROR; + if( zs->msg ) + log_error("zlib inflate problem: %s\n", zs->msg ); + else + log_error("zlib inflate problem: rc=%d\n", zrc ); +#else if( zs->msg ) log_fatal("zlib inflate problem: %s\n", zs->msg ); else log_fatal("zlib inflate problem: rc=%d\n", zrc ); +#endif } } while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR && !leave); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index bb05eabb7..638d895d0 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -806,7 +806,12 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos, * the uncompressing layer - in some error cases it just loops * and spits out 0xff bytes. */ log_error ("%s: garbled packet detected\n", iobuf_where (inp)); +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + rc = gpg_error (GPG_ERR_INV_PACKET); + goto leave; +#else g10_exit (2); +#endif } if (out && pkttype) diff --git a/g10/plaintext.c b/g10/plaintext.c index 3e169d93f..aa83ffbe0 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -617,10 +617,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2, if (!fp) { +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + errno = ENOENT; + rc = gpg_error_from_syserror (); + goto leave; +#else if (opt.verbose) log_info (_("reading stdin ...\n")); fp = iobuf_open (NULL); log_assert (fp); +#endif } do_hash (md, md2, fp, textmode); iobuf_close (fp); diff --git a/g10/sig-check.c b/g10/sig-check.c index 8dd18b2e2..9f5db89f9 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -783,8 +783,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) { gcry_md_hd_t md; - if (gcry_md_open (&md, sig->digest_algo, 0)) - BUG (); + rc = gcry_md_open (&md, sig->digest_algo, 0); + if (rc) + return rc; hash_public_key(md,pk); /* Note: check_signature only checks that the signature is good. It does not fail if the key is revoked. */ diff --git a/tests/Makefile.am b/tests/Makefile.am index f29b68a53..e788c9916 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,7 +24,13 @@ else tpm2dtests = endif -SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) . +SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) + +if MAINTAINER_MODE +SUBDIRS += fuzz +endif + +SUBDIRS += . GPGSM = ../sm/gpgsm diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am new file mode 100644 index 000000000..eb2216d3e --- /dev/null +++ b/tests/fuzz/Makefile.am @@ -0,0 +1,84 @@ +# Makefile.am - For tests/fuzz +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GnuPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# Process this file with automake to create Makefile.in + + +# Programs required before we can run these tests. +required_pgms = ../../g10/gpg$(EXEEXT) + + +# Force linking with clang++ even if we have pure C fuzzing targets +CCLD = clang++ +AM_LDFLAGS = -stdlib=libc++ + +AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/g10 +include $(top_srcdir)/am/cmacros.am + +noinst_PROGRAMS = fuzz_verify fuzz_import fuzz_decrypt fuzz_list + +fuzz_verify_SOURCES = fuzz_verify.c + +fuzz_verify_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE) \ + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBICONV) $(resource_objs) $(extra_sys_libs) + +fuzz_verify_DEPENDENCIES = fuzz_verify_seed_corpus.zip + +fuzz_verify_seed_corpus.zip: + cd .. && zip -r fuzz/fuzz_verify_seed_corpus.zip openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* openpgp/samplemsgs/* + +fuzz_import_SOURCES = fuzz_import.c + +fuzz_import_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBICONV) $(resource_objs) $(extra_sys_libs) + +fuzz_import_DEPENDENCIES = fuzz_import_seed_corpus.zip + +fuzz_import_seed_corpus.zip: + cd .. && zip -r fuzz/fuzz_import_seed_corpus.zip openpgp/samplekeys/* openpgp/key-selection/* openpgp/*.asc openpgp/trust-pgp/*.asc openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* + +fuzz_decrypt_SOURCES = fuzz_decrypt.c + +fuzz_decrypt_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ + $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ + $(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBICONV) $(resource_objs) $(extra_sys_libs) + +fuzz_decrypt_DEPENDENCIES = fuzz_decrypt_seed_corpus.zip + +fuzz_decrypt_seed_corpus.zip: + cd .. && zip -r fuzz/fuzz_decrypt_seed_corpus.zip openpgp/tofu/conflicting/* openpgp/tofu/cross-sigs/* openpgp/samplemsgs/* + +fuzz_list_SOURCES = fuzz_list.c + +fuzz_list_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\ +$(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \ +$(LIBASSUAN_LIBS) $(NPTH_LIBS) $(GPG_ERROR_LIBS) \ +$(LIBICONV) $(resource_objs) $(extra_sys_libs) + +fuzz_list_DEPENDENCIES = fuzz_list_seed_corpus.zip + +fuzz_list_seed_corpus.zip: + cd .. && zip -r fuzz/fuzz_list_seed_corpus.zip openpgp/ + +# We need to depend on a couple of programs so that the tests don't +# start before all programs are built. +all-local: $(required_pgms) ================================================ FILE: projects/gnupg/project.yaml ================================================ homepage: "https://www.gnupg.org" language: c++ primary_contact: "p.antoine@catenacyber.fr" main_repo: 'git://git.gnupg.org/gnupg.git' fuzzing_engines: - libfuzzer - honggfuzz ================================================ FILE: projects/gnutls/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ make \ pkg-config \ autoconf \ automake \ autogen \ autopoint \ libtool \ gperf \ bison \ texinfo \ curl \ gettext \ gengetopt \ wget \ python \ mercurial \ gtk-doc-tools \ libtasn1-bin \ lzip ENV GNULIB_TOOL $SRC/gnulib/gnulib-tool RUN git clone --depth=500 git://git.savannah.gnu.org/gnulib.git RUN wget -qO- https://ftp.gnu.org/gnu/libunistring/libunistring-latest.tar.gz | tar xz && mv libunistring-* libunistring RUN wget -qO- https://ftp.gnu.org/gnu/libidn/libidn2-latest.tar.gz | tar xz && mv libidn2-* libidn2 RUN wget -qO- https://ftp.gnu.org/gnu/gmp/gmp-6.3.0.tar.gz | tar xz && mv gmp-* gmp RUN wget -qO- https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.20.0.tar.gz | tar xz && mv libtasn1-* libtasn1 RUN git clone --depth=1 https://git.lysator.liu.se/nettle/nettle.git --branch=nettle_3.10.1_release_20241230 # Try twice in case of network issues. RUN git clone --depth=1 --recursive https://gitlab.com/gnutls/gnutls.git || git clone --depth=1 --recursive https://gitlab.com/gnutls/gnutls.git WORKDIR gnutls COPY build.sh $SRC/ ================================================ FILE: projects/gnutls/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export DEPS_PATH=$SRC/deps export PKG_CONFIG_PATH=$DEPS_PATH/lib64/pkgconfig:$DEPS_PATH/lib/pkgconfig export CPPFLAGS="-I$DEPS_PATH/include" export LDFLAGS="-L$DEPS_PATH/lib -L$DEPS_PATH/lib64" export GNULIB_SRCDIR=$SRC/gnulib # gnutls requires autoconf 2.71 minimum which is not available in the Ubuntu 20 base image # Skip this step if a newer base image is used if grep -q -F "20.04" /etc/os-release ; then cd /tmp wget https://archive.ubuntu.com/ubuntu/pool/main/a/autoconf/autoconf_2.71-2_all.deb # Ensure file is not modified or corrupted before install if echo "96b528889794c4134015a63c75050f93d8aecdf5e3f2a20993c1433f4c61b80e autoconf_2.71-2_all.deb" | sha256sum --check --status ; then # Install but use G option to prevent downgrade in case this is dpkg -i -G /tmp/autoconf_2.71-2_all.deb fi fi cd "$SRC"/libunistring ASAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --prefix="$DEPS_PATH" make -j"$(nproc)" make install cd "$SRC"/libidn2 ASAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --disable-doc --disable-gcc-warnings --prefix="$DEPS_PATH" make -j"$(nproc)" make install # always disable assembly in GMP to avoid issues due to SIGILL # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3119 # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3159 GMP_CONFIGURE_FLAGS="--disable-assembly --disable-fat" cd "$SRC"/gmp ASAN_OPTIONS=detect_leaks=0 \ ./configure --disable-shared --prefix="$DEPS_PATH" $GMP_CONFIGURE_FLAGS make -j"$(nproc)" make install cd $SRC/libtasn1 ./configure --disable-gcc-warnings --disable-gtk-doc --disable-gtk-doc-pdf --disable-doc \ --disable-shared --enable-static --prefix="$DEPS_PATH" make -j"$(nproc)" make install NETTLE_CONFIGURE_FLAGS="--disable-assembler" # Temporarily disalbe asm to work around error "undefined reference to [...]" if [[ $CFLAGS = *sanitize=memory* ]]; then NETTLE_CONFIGURE_FLAGS="--disable-assembler --disable-fat" fi cd "$SRC"/nettle bash .bootstrap ASAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --disable-documentation --prefix="$DEPS_PATH" $NETTLE_CONFIGURE_FLAGS ( make -j"$(nproc)" || make -j"$(nproc)" ) && make install if test $? != 0; then echo "Failed to compile nettle" exit 1 fi GNUTLS_CONFIGURE_FLAGS="" if [[ $CFLAGS = *sanitize=memory* ]]; then GNUTLS_CONFIGURE_FLAGS="--disable-hardware-acceleration" fi cd "$SRC"/gnutls ./bootstrap ASAN_OPTIONS=detect_leaks=0 LIBS="-lunistring" CXXFLAGS="$CXXFLAGS -L$DEPS_PATH/lib" \ ./configure --enable-fuzzer-target --disable-gcc-warnings --enable-static --disable-shared --disable-doc --disable-tests \ --disable-tools --disable-cxx --disable-maintainer-mode --disable-libdane --without-p11-kit \ --disable-full-test-suite $GNUTLS_CONFIGURE_FLAGS # Do not use the syscall interface for randomness in oss-fuzz, it seems # to confuse memory sanitizer. sed -i 's|include |include \n#undef SYS_getrandom|' lib/nettle/sysrng-linux.c make -j"$(nproc)" -C gl make -j"$(nproc)" -C lib cd fuzz make oss-fuzz find . -name '*_fuzzer' -exec cp -v '{}' "$OUT" ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' "$OUT" ';' find . -name '*_fuzzer.options' -exec cp -v '{}' "$OUT" ';' for dir in *_fuzzer.in; do fuzzer=$(basename "$dir" .in) zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/" done ================================================ FILE: projects/gnutls/project.yaml ================================================ homepage: "https://www.gnutls.org" language: c++ primary_contact: "daiki.ueno@gmail.com" auto_ccs: - "rockdaboot@gmail.com" - "nisse@lysator.liu.se" - "anderjuaristi.cictg@gmail.com" - "dbaryshkov@gmail.com" - "zfridric@redhat.com" sanitizers: - address - memory - undefined main_repo: 'https://gitlab.com/gnutls/gnutls.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/go-attestation/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/go-attestation RUN wget https://go.dev/dl/go1.24.6.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.24.6.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.24.6.linux-amd64.tar.gz WORKDIR go-attestation COPY build.sh $SRC/ ================================================ FILE: projects/go-attestation/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/google/go-attestation/attest FuzzParseEventLog \ parse_event_log_fuzzer compile_go_fuzzer github.com/google/go-attestation/attest FuzzParseAKPublic \ parse_ak_public_fuzzer compile_go_fuzzer github.com/google/go-attestation/attest FuzzParseAKPublic \ parse_ak_public_fuzzer compile_go_fuzzer github.com/google/go-attestation/attest FuzzParseEKCertificate \ parse_ek_certificate_fuzzer ================================================ FILE: projects/go-attestation/project.yaml ================================================ homepage: "https://github.com/google/go-attestation" primary_contact: "bweeks@google.com" auto_ccs: - "ericchiang@google.com" - "jsonp@google.com" fuzzing_engines: - libfuzzer sanitizers: - address language: go main_repo: 'https://github.com/google/go-attestation' file_github_issue: True ================================================ FILE: projects/go-cmp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/go-cmp WORKDIR go-cmp COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-cmp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./cmp/ go mod tidy printf "package cmp\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy compile_native_go_fuzzer github.com/google/go-cmp/cmp FuzzDiff FuzzDiff ================================================ FILE: projects/go-cmp/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package cmp import ( "testing" ) func FuzzDiff(f *testing.F) { f.Fuzz(func(t *testing.T, data1, data2 []byte) { _ = Diff(data1, data2) }) } ================================================ FILE: projects/go-cmp/project.yaml ================================================ homepage: "https://github.com/google/go-cmp/cmp" language: go main_repo: "https://github.com/google/go-cmp/cmp" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-coap/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/plgd-dev/go-coap.git RUN go install github.com/AdamKorcz/go-118-fuzz-build@latest COPY build.sh $SRC/ WORKDIR $SRC/go-coap ================================================ FILE: projects/go-coap/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer $(pwd)/udp/coder FuzzDecode fuzz_decode_udp compile_native_go_fuzzer $(pwd)/tcp/coder FuzzDecode fuzz_decode_tcp compile_native_go_fuzzer $(pwd)/message FuzzUnmarshalData fuzz_unmarshal_data compile_native_go_fuzzer $(pwd)/message/codes FuzzUnmarshalJSON fuzz_unmarshal_json ================================================ FILE: projects/go-coap/project.yaml ================================================ homepage: "https://plgd.dev" language: go primary_contact: "daniel.adam@plgd.dev" auto_ccs: - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/plgd-dev/go-coap" ================================================ FILE: projects/go-containerregistry/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/go-containerregistry WORKDIR $SRC/go-containerregistry COPY build.sh fuzz.go $SRC/ ================================================ FILE: projects/go-containerregistry/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz.go $SRC/go-containerregistry/pkg/name/ compile_go_fuzzer github.com/google/go-containerregistry/pkg/name FuzzParseReference fuzz_parse_reference ================================================ FILE: projects/go-containerregistry/fuzz.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package name func FuzzParseReference(data []byte) int { _, _ = ParseReference(string(data)) return 1 } ================================================ FILE: projects/go-containerregistry/project.yaml ================================================ homepage: "https://github.com/google/go-containerregistry" language: go primary_contact: "jason@chainguard.dev" main_repo: "https://github.com/google/go-containerregistry" auto_ccs: - "go-containerregistry@chainguard.dev" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-coredns/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 ENV GO111MODULE=on RUN git clone --depth 1 https://github.com/coredns/coredns $GOPATH/src/github.com/coredns/coredns COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/go-coredns/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Same as usual except for added -tags gofuzz. cd $GOPATH/src/github.com/coredns/coredns #make ls plugin/*/fuzz.go | while read target do fuzzed_plugin=`echo $target | cut -d'/' -f 2` compile_go_fuzzer github.com/coredns/coredns/plugin/$fuzzed_plugin Fuzz fuzz_plugin_$fuzzed_plugin gofuzz done compile_go_fuzzer github.com/coredns/coredns/test Fuzz fuzz_core gofuzz ================================================ FILE: projects/go-coredns/project.yaml ================================================ homepage: "https://coredns.io" primary_contact: "security@coredns.io" main_repo: 'https://github.com/coredns/coredns.git' auto_ccs : - "miek@miek.nl" - "p.antoine@catenacyber.fr" - "yong.tang.github@gmail.com" - "ville@vesilehto.fi" language: go fuzzing_engines: - libfuzzer sanitizers: - address base_os_version: ubuntu-24-04 ================================================ FILE: projects/go-dhcp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/insomniacslk/dhcp.git RUN go install github.com/AdamKorcz/go-118-fuzz-build@latest COPY build.sh $SRC/ WORKDIR $SRC/dhcp ================================================ FILE: projects/go-dhcp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing go get github.com/stretchr/testify/assert@v1.6.1 sed -i '58s/^/\/\//g' dhcpv6/dhcpv6_test.go compile_native_go_fuzzer github.com/insomniacslk/dhcp/dhcpv4 FuzzDHCPv4 fuzz_DHCPv4 compile_native_go_fuzzer github.com/insomniacslk/dhcp/dhcpv6 FuzzDHCPv6 fuzz_DHCPv6 compile_native_go_fuzzer github.com/insomniacslk/dhcp/rfc1035label FuzzLabel fuzz_Label ================================================ FILE: projects/go-dhcp/project.yaml ================================================ homepage: "https://github.com/insomniacslk/dhcp" language: go primary_contact: "insomniac@slackware.it" auto_ccs: - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/insomniacslk/dhcp.git" ================================================ FILE: projects/go-dns/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #FROM gcr.io/oss-fuzz-base/base-builder-go FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/miekg/dns.git RUN wget https://go.dev/dl/go1.24.6.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.24.6.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.24.6.linux-amd64.tar.gz COPY build.sh $SRC/ WORKDIR $SRC/dns ================================================ FILE: projects/go-dns/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Same as usual except for added -tags fuzz. compile_go_fuzzer github.com/miekg/dns FuzzNewRR fuzz_newrr fuzz compile_go_fuzzer github.com/miekg/dns Fuzz fuzz_msg_unpack fuzz ================================================ FILE: projects/go-dns/project.yaml ================================================ homepage: "https://github.com/miekg/dns" primary_contact: "miek@miek.nl" auto_ccs: - "me+google@tomthorogood.co.uk" - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/miekg/dns" ================================================ FILE: projects/go-ethereum/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --single-branch --depth=1 https://github.com/ethereum/go-ethereum $GOPATH/src/github.com/ethereum/go-ethereum RUN (cd $GOPATH/src/github.com/ethereum/go-ethereum && go mod download) RUN cp $GOPATH/src/github.com/ethereum/go-ethereum/oss-fuzz.sh $SRC/build.sh # Enable this for easier local testing / repro #ADD build.sh $SRC/build.sh WORKDIR $SRC/ ================================================ FILE: projects/go-ethereum/project.yaml ================================================ homepage: "https://github.com/ethereum/go-ethereum" primary_contact: "peter@ethereum.org" auto_ccs : - "fjl@ethereum.org" - "martin.swende@ethereum.org" - "marius.vanderwijden@ethereum.org" - "garyrong@ethereum.org" - "zsfelfoldi@ethereum.org" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/ethereum/go-ethereum' ================================================ FILE: projects/go-git/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go ENV GOPATH="${GOPATH:-/root/go}" ENV ORG_ROOT="${GOPATH}/src/github.com/go-git" RUN mkdir -p "${ORG_ROOT}" # The fuzzed components are scattered around multiple repositories. # Here we clone all of them and cache their go dependencies. # The build process happens as build.sh iterate over each one of them. ARG REPOSITORIES="go-git go-billy" RUN for repo in ${REPOSITORIES}; do \ git clone --depth 1 "https://github.com/go-git/${repo}" "${ORG_ROOT}/${repo}"; \ cd "${ORG_ROOT}/${repo}"; \ go mod download; \ cd -; \ done # Install go imports as the import section needs to reflect some of the changes # made by build.sh. RUN go install golang.org/x/tools/cmd/goimports@latest COPY build.sh $SRC/ WORKDIR $SRC ================================================ FILE: projects/go-git/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This code improves the use of Go Native by: # - Dynamically discovering and building all fuzz tests within the project root path. # - Supporting single (during PR checks) or multiple repositories (oss-fuzz). # - Enabling execution via CI builds and Makefile targets for each repo. GOPATH="${GOPATH:-/root/go}" ORG_ROOT="${ORG_ROOT:-${GOPATH}/src/github.com/go-git}" PREBUILD_SCRIPT_PATH="${PREBUILD_SCRIPT_PATH:-tests/fuzz/oss_fuzz_prebuild.sh}" POSTBUILD_SCRIPT_PATH="${POSTBUILD_SCRIPT_PATH:-tests/fuzz/oss_fuzz_postbuild.sh}" # source_prebuild_script sources the prebuild script, which executes project-specific # code and exposes environment variables that are needed during the generic build process. # # Examples of usage may be organising directory structure for embedding # files, downloading artifacts or setting environment variables. function source_prebuild_script(){ if [ -f "${PREBUILD_SCRIPT_PATH}" ]; then # shellcheck source=/dev/null . "${PREBUILD_SCRIPT_PATH}" fi } # source_postbuild_script sources the postbuild script, which executes project-specific # code and unset environment variables that may break follow-up processes. function source_postbuild_script(){ if [ -f "${POSTBUILD_SCRIPT_PATH}" ]; then # shellcheck source=/dev/null . "${POSTBUILD_SCRIPT_PATH}" fi } # go_native_build_all_fuzzers builds all Go Native fuzz tests defined in modules within # the given project dir. # # Args: # project_dir function go_native_build_all_fuzzers(){ local project_path="$1" cd "${project_path}" source_prebuild_script modules=$(find . -mindepth 1 -maxdepth 4 -type f -name 'go.mod' | cut -c 3- | sed 's|/[^/]*$$||' | sort -u | sed 's;/go.mod;;g' | sed 's;go.mod;.;g') for module in ${modules}; do cd "${project_path}/${module}" local test_files test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . || echo "") if [ -z "${test_files}" ]; then continue fi # go-118-fuzz-build is required for each module. go get -u github.com/AdamKorcz/go-118-fuzz-build/testing # The go get command above can affect transient dependencies, may lead # to the go.sym to become out of sync, which would cause build to break. # go mod tidy will only work if the current module has a reference # to the above dependency, so we create one. local pkgName pkgName="$(grep -h '^package ' -- *.go | head -n 1)" if [ -z "${test_files}" ]; then pkgName="package fuzz" fi cat < dep-placeholder.go ${pkgName} import _ "github.com/AdamKorcz/go-118-fuzz-build/testing" EOF # With the reference above, this updates go.sum. go mod tidy # Iterate through all Go Fuzz targets, compiling each into a fuzzer. for file in ${test_files}; do # If the subdir is a module, skip this file, as it will be handled # at the next iteration of the outer loop. if [ -f "$(dirname "${file}")/go.mod" ]; then continue fi # Remove all funcs that are not Fuzz tests. Some were resulting # in errors due to referring to other test files. # # Suite based tests funcs were also failing with the error: # cannot use t (variable of type ...) as *"testing".T value in argument to suite.Run # # As those are not needed for fuzzing purposes they are removed. sed -i '/^func Fuzz/!{/^func /,/^}/d}' "${file}" # Remove global declarations and any comments. sed -i '/^\(var\|const\)\b/d; /^\s*\/\//d; /^\s*\/\*/,/\*\//d' "${file}" # Remove structs which may be referring to subtypes from other test files. sed -i '/^type .* struct {/,/^}/d' "${file}" # Ensure the file is still properly formatted. go fmt "${file}" goimports -w "${file}" targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}") for target_name in ${targets}; do local module_name local fuzzer_name local target_dir # Transform module path into module name (e.g. git/libgit2 to git_libgit2). module_name="${module/\//_}_" # If module equal '._', use empty string instead. module_name="${module/#%._}" # Compose fuzzer name based on the lowercase version of the func names. fuzzer_name="${target_name,,}" # The module name is added after the fuzz prefix, for better discoverability. fuzzer_name="${target_name/fuzz_/fuzz_${module_name}}" target_dir=$(dirname "${file}") echo "Building ${file}.${target_name} into ${fuzzer_name}" cat "${file}" compile_native_go_fuzzer "${target_dir}" "${target_name}" "${fuzzer_name}" done done done } function loop_through_org_repositories(){ local repos="" repos="$(find "${ORG_ROOT}" -type d -mindepth 1 -maxdepth 1)" for repo in ${repos}; do go_native_build_all_fuzzers "${repo}" done } function main(){ if grep -h '^module github.com/go-git/' "${SRC}/go.mod"; then echo "Building Go Native fuzzers for ${SRC}" go_native_build_all_fuzzers "${SRC}" exit $? fi echo "Going through all repositories in ${ORG_ROOT}" loop_through_org_repositories } main ================================================ FILE: projects/go-git/project.yaml ================================================ homepage: "https://github.com/go-git/go-git" language: go primary_contact: "go-git-security@googlegroups.com" auto_ccs: - "paulo.gomes.uk@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/go-git/go-git" ================================================ FILE: projects/go-humanize/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/dustin/go-humanize WORKDIR $SRC/go-humanize COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-humanize/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./ go mod tidy printf "package humanize\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy echo building compile_native_go_fuzzer github.com/dustin/go-humanize FuzzParseBytes FuzzParseBytes ================================================ FILE: projects/go-humanize/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package humanize import ( "testing" ) func FuzzParseBytes(f *testing.F) { f.Fuzz(func(t *testing.T, data string) { _, _ = ParseBytes(data) }) } ================================================ FILE: projects/go-humanize/project.yaml ================================================ homepage: "https://github.com/dustin/go-humanize" language: go main_repo: "https://github.com/dustin/go-humanize" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-json-iterator/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone https://github.com/json-iterator/go json-iterator COPY fuzz_json.go $SRC/json-iterator/ COPY build.sh $SRC/ WORKDIR $SRC/json-iterator/ ================================================ FILE: projects/go-json-iterator/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/json-iterator/go Fuzz fuzz_json ================================================ FILE: projects/go-json-iterator/fuzz_json.go ================================================ // Copyright 2015 go-fuzz project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE. // Modified from original file https://github.com/dvyukov/go-fuzz-corpus/blob/master/json/json.go package jsoniter import ( "encoding/json" "fmt" "reflect" ) func Fuzz(data []byte) int { score := 0 for _, ctor := range []func() interface{}{ //func() interface{} { return nil }, func() interface{} { return new([]interface{}) }, func() interface{} { m := map[string]string{}; return &m }, func() interface{} { m := map[string]interface{}{}; return &m }, func() interface{} { return new(S) }, } { v := ctor() if ConfigCompatibleWithStandardLibrary.Unmarshal(data, v) != nil { continue } score = 1 vj := ctor() err := json.Unmarshal(data, vj) if err != nil { panic(err) } if !reflect.DeepEqual(v, vj) { fmt.Printf("v0: %#v\n", v) fmt.Printf("v1: %#v\n", vj) panic("not equal") } data1, err := ConfigCompatibleWithStandardLibrary.Marshal(v) if err != nil { panic(err) } v1 := ctor() if ConfigCompatibleWithStandardLibrary.Unmarshal(data1, v1) != nil { continue } if !reflect.DeepEqual(v, v1) { fmt.Printf("v0: %#v\n", v) fmt.Printf("v1: %#v\n", v1) panic("not equal") } } return score } type S struct { A int `json:",omitempty"` B string `json:"B1,omitempty"` C float64 D bool E uint8 F []byte G interface{} H map[string]interface{} I map[string]string J []interface{} K []string L S1 M *S1 N *int O **int // P json.RawMessage Q Marshaller R int `json:"-"` S int `json:",string"` } type S1 struct { A int B string } type Marshaller struct { v string } func (m *Marshaller) MarshalJSON() ([]byte, error) { return ConfigCompatibleWithStandardLibrary.Marshal(m.v) } func (m *Marshaller) UnmarshalJSON(data []byte) error { return ConfigCompatibleWithStandardLibrary.Unmarshal(data, &m.v) } ================================================ FILE: projects/go-json-iterator/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://jsoniter.com" main_repo: "https://github.com/json-iterator/go" primary_contact: "taowen@gmail.com" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-ldap/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/go-ldap/ldap.git RUN go install github.com/AdamKorcz/go-118-fuzz-build@latest COPY build.sh $SRC/ WORKDIR $SRC/ldap ================================================ FILE: projects/go-ldap/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing compile_native_go_fuzzer github.com/go-ldap/ldap FuzzParseDN fuzz_parse_dn compile_native_go_fuzzer github.com/go-ldap/ldap FuzzDecodeEscapedSymbols fuzz_decode_escaped_symbols compile_native_go_fuzzer github.com/go-ldap/ldap FuzzEscapeDN fuzz_escape_dn ================================================ FILE: projects/go-ldap/project.yaml ================================================ homepage: "https://github.com/go-ldap/ldap" language: go primary_contact: "cp@lumen.sh" auto_ccs: - "johnweldon4@gmail.com" - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/go-ldap/ldap" ================================================ FILE: projects/go-ole/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/go-ole/go-ole WORKDIR $SRC/go-ole COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-ole/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./ go mod tidy printf "package ole\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy compile_native_go_fuzzer github.com/go-ole/go-ole FuzzGUID FuzzGUID ================================================ FILE: projects/go-ole/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package ole import ( "testing" ) func FuzzGUID(f *testing.F) { f.Fuzz(func(t *testing.T, data string) { g := NewGUID(data) _ = g.String() }) } ================================================ FILE: projects/go-ole/project.yaml ================================================ homepage: "https://github.com/go-ole/go-ole" language: go main_repo: "https://github.com/go-ole/go-ole" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-pprof/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/pprof WORKDIR $SRC/pprof COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-pprof/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/fuzz_test.go $SRC/pprof/profile/ compile_native_go_fuzzer_v2 github.com/google/pprof/profile FuzzParseData FuzzParseData ================================================ FILE: projects/go-pprof/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package profile import ( "testing" ) func FuzzParseData(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { ParseData(data) }) } ================================================ FILE: projects/go-pprof/project.yaml ================================================ homepage: "https://github.com/google/pprof" language: go main_repo: "https://github.com/google/pprof" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-readline/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/chzyer/readline WORKDIR readline COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-readline/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go mod tidy printf "package readline\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > ./register.go go mod tidy cp $SRC/fuzz_test.go ./ compile_native_go_fuzzer github.com/chzyer/readline FuzzReadline FuzzReadline ================================================ FILE: projects/go-readline/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package readline import ( "testing" ) func FuzzReadline(f *testing.F) { f.Fuzz(func(t *testing.T, line string) { rl, err := New(line) if err != nil { return } defer rl.Close() for { _, err := rl.Readline() if err != nil { // io.EOF break } } }) } ================================================ FILE: projects/go-readline/project.yaml ================================================ homepage: "https://github.com/chzyer/readline" language: go main_repo: "https://github.com/chzyer/readline" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-redis/Dockerfile ================================================ # Copyright 2021 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/redis/go-redis redis COPY build.sh $SRC/ WORKDIR $SRC/redis ================================================ FILE: projects/go-redis/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. compile_go_fuzzer github.com/redis/go-redis/v9/fuzz Fuzz fuzz gofuzz ================================================ FILE: projects/go-redis/project.yaml ================================================ homepage: "https://github.com/redis/go-redis" main_repo: "https://github.com/redis/go-redis" primary_contact: "vladimir.webdev@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-sftp/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/pkg/sftp COPY build.sh $SRC/ WORKDIR $SRC/sftp ================================================ FILE: projects/go-sftp/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer . Fuzz fuzz_sftp ================================================ FILE: projects/go-sftp/project.yaml ================================================ homepage: "https://github.com/pkg/sftp" primary_contact: "nicola.murino@gmail.com" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/pkg/sftp' ================================================ FILE: projects/go-shlex/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/shlex WORKDIR $SRC/shlex COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-shlex/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./ go mod tidy compile_native_go_fuzzer_v2 github.com/google/shlex FuzzLexer FuzzLexer ================================================ FILE: projects/go-shlex/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package shlex import ( "bytes" "io" "testing" ) func FuzzLexer(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { l := NewLexer(bytes.NewReader(data)) for { _, err := l.Next() if err == io.EOF { return } } }) } ================================================ FILE: projects/go-shlex/project.yaml ================================================ homepage: "https://github.com/google/shlex" language: go main_repo: "https://github.com/google/shlex" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/go-snappy/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/golang/snappy COPY build.sh $SRC/ COPY fuzz.go $SRC/snappy WORKDIR $SRC/snappy ================================================ FILE: projects/go-snappy/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer . FuzzRoundTrip fuzz_roundtrip gofuzz compile_go_fuzzer . FuzzDecode fuzz_decode gofuzz ================================================ FILE: projects/go-snappy/fuzz.go ================================================ // +build gofuzz package snappy import ( "bytes" ) func FuzzRoundTrip(data []byte) int { if len(data) > 1234567 { return 0 } encoded := Encode(nil, data) decoded, err := Decode(nil, encoded) if err != nil { panic("Error decoding snappy-encoded") } if !bytes.Equal(data, decoded) { panic("Different result on roundtrip encode/decode") } return 1 } func FuzzDecode(data []byte) int { if n, _ := DecodedLen(data); n > 1234567 { return 0 } _, err := Decode(nil, data) if err != nil { return 0 } return 1 } ================================================ FILE: projects/go-snappy/project.yaml ================================================ homepage: "https://github.com/golang/snappy" primary_contact: "nigeltao@golang.org" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/golang/snappy' disabled: true ================================================ FILE: projects/go-sqlite3/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 http://github.com/mattn/go-sqlite3 $GOPATH/src/github.com/mattn/go-sqlite3 COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/go-sqlite3/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $GOPATH/src/github.com/mattn/go-sqlite3 compile_go_fuzzer github.com/mattn/go-sqlite3/_example/fuzz FuzzOpenExec fuzz_open_exec # generate corpus go run _example/simple/simple.go echo -n -e "select id, name from foo\x00" > simple.fuzc cat foo.db >> simple.fuzc zip -r $OUT/fuzz_open_exec_seed_corpus.zip simple.fuzc ================================================ FILE: projects/go-sqlite3/project.yaml ================================================ homepage: "http://mattn.github.io/go-sqlite3/" primary_contact: "mattn.jp@gmail.com" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/mattn/go-sqlite3/' ================================================ FILE: projects/go-toml/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 --single-branch --branch v2 https://github.com/pelletier/go-toml go-toml COPY build.sh $SRC/ WORKDIR $SRC/go-toml ================================================ FILE: projects/go-toml/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir -p $OUT/benchmark cp benchmark/benchmark.toml $OUT/benchmark/benchmark.toml compile_go_fuzzer github.com/pelletier/go-toml/v2/ossfuzz FuzzToml fuzz_toml gofuzz ================================================ FILE: projects/go-toml/project.yaml ================================================ homepage: "https://github.com/pelletier/go-toml" language: go main_repo: "https://github.com/pelletier/go-toml" primary_contact: "pelletier.thomas@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - maxnair.dev@gmail.com file_github_issue: true ================================================ FILE: projects/go-yaml/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/go-yaml/yaml WORKDIR yaml COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/go-yaml/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./ go mod tidy printf "package yaml\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy compile_native_go_fuzzer gopkg.in/yaml.v3 FuzzDecode FuzzDecode ================================================ FILE: projects/go-yaml/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package yaml import ( "bytes" "testing" ) type FuzzType struct { field1 string Field2 string field3 []byte Field4 []byte } func FuzzDecode(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { d := NewDecoder(bytes.NewReader(data)) d.Decode(&FuzzType{}) }) } ================================================ FILE: projects/go-yaml/project.yaml ================================================ homepage: "https://github.com/go-yaml/yaml" language: go main_repo: "https://github.com/go-yaml/yaml" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/gobgp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/osrg/gobgp.git COPY build.sh $SRC/ WORKDIR $SRC/gobgp ================================================ FILE: projects/gobgp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing sed -i '/func BenchmarkNormalizeFlowSpecOpValues(/,/^}/ s/^/\/\//' pkg/packet/bgp/bgp_test.go compile_native_go_fuzzer $PWD/pkg/packet/rtr FuzzParseRTR fuzz_parse_rtr compile_native_go_fuzzer $PWD/pkg/packet/bmp FuzzParseBMPMessage fuzz_parse_bmp_message compile_native_go_fuzzer $PWD/pkg/packet/bgp FuzzParseBGPMessage fuzz_parse_bgp_message compile_native_go_fuzzer $PWD/pkg/packet/bgp FuzzParseLargeCommunity fuzz_parse_large_community compile_native_go_fuzzer $PWD/pkg/packet/bgp FuzzParseFlowSpecComponents fuzz_parse_flow_spec_components compile_native_go_fuzzer $PWD/pkg/packet/mrt FuzzMRT fuzz_mrt compile_native_go_fuzzer $PWD/pkg/zebra FuzzZapi fuzz_zapi ================================================ FILE: projects/gobgp/project.yaml ================================================ homepage: "https://osrg.github.io/gobgp" language: go primary_contact: "fujita.tomonori@gmail.com" auto_ccs: - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/osrg/gobgp" ================================================ FILE: projects/gogo-protobuf/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/gogo/protobuf WORKDIR $SRC/protobuf COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/gogo-protobuf/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir fuzzing cp $SRC/fuzz_test.go ./fuzzing/ cd fuzzing go mod tidy printf "package fuzzing\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy echo building compile_native_go_fuzzer github.com/gogo/protobuf/fuzzing FuzzProtoUnmarshal FuzzProtoUnmarshal ================================================ FILE: projects/gogo-protobuf/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package fuzzing import ( "testing" "github.com/gogo/protobuf/proto" tpb "github.com/gogo/protobuf/proto/proto3_proto" ) func FuzzProtoUnmarshal(f *testing.F) { f.Fuzz(func(t *testing.T, raw []byte) { var msgBlackhole = new(tpb.Message) proto.Unmarshal(raw, msgBlackhole) }) } ================================================ FILE: projects/gogo-protobuf/project.yaml ================================================ homepage: "https://github.com/gogo/protobuf" language: go main_repo: "https://github.com/gogo/protobuf" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/goipp/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/OpenPrinting/goipp.git $SRC/goipp RUN git clone --depth 1 https://github.com/OpenPrinting/fuzzing.git $SRC/fuzzing COPY build.sh $SRC/ WORKDIR $SRC/goipp ================================================ FILE: projects/goipp/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ chmod +x $SRC/fuzzing/projects/goipp/oss_fuzz_build.sh $SRC/fuzzing/projects/goipp/oss_fuzz_build.sh ================================================ FILE: projects/goipp/project.yaml ================================================ homepage: "https://github.com/OpenPrinting/goipp" main_repo: "https://github.com/OpenPrinting/goipp" primary_contact: "mdimad005@gmail.com" auto_ccs: - "till.kamppeter@gmail.com" - "ossfuzz@iosifache.me" - "jiongchiyu@gmail.com" - "pzz@apevzner.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/golang/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus golang RUN git clone --depth 1 https://github.com/golang/go RUN git clone --depth 1 https://github.com/golang/net RUN git clone --depth 1 https://github.com/golang/image RUN git clone --depth 1 https://github.com/golang/crypto RUN git clone --depth 1 https://github.com/golang/text RUN git clone --depth=1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=november-backup RUN wget https://go.dev/dl/go1.24.3.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.24.3.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ COPY build.sh text_fuzzer.go \ math_big_fuzzer.go \ fuzz_tar_reader.go \ fuzz_tar_reader.options \ regexp_fuzzer.go \ language_fuzzer.go \ unicode_fuzzer.go \ x509_fuzzer.go \ ecdsa_fuzzer.go \ dsa_fuzzer.go \ aes_fuzzer.go \ h2c_fuzzer.go \ fuzz_x_h2c.options \ elf_fuzzer.go \ tiff_fuzzer.go \ fuzz_tiff_decode.options \ openpgp_fuzzer.go \ webp_fuzzer.go \ fuzz_webp_decode.options \ filepath_fuzzer.go \ strings_fuzzer.go \ multipart_fuzzer.go \ encoding_fuzzer.go \ glob_fuzzer.options $SRC/ WORKDIR $SRC/golang ================================================ FILE: projects/golang/aes_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package aes import ( "crypto/aes" "runtime" "strings" ) func catchPanics() { if r := recover(); r != nil { var err string switch r.(type) { case string: err = r.(string) case runtime.Error: err = r.(runtime.Error).Error() case error: err = r.(error).Error() } if strings.Contains(err, "not full block") { return } else if strings.Contains(err, "invalid buffer overlap") { return } else { panic(err) } } } func FuzzAesCipherDecrypt(data []byte) int { if len(data) < 5 { return 0 } keyIndex := int(data[0]) lenIn := int(data[1]) if lenIn < aes.BlockSize { return 0 } data = data[2:] if (keyIndex + 5) > len(data) { return 0 } key := data[:keyIndex] c, err := aes.NewCipher(key) if err != nil { return 0 } dst := make([]byte, lenIn) src := data[keyIndex+1:] defer catchPanics() c.Decrypt(dst, src) return 1 } func FuzzAesCipherEncrypt(data []byte) int { if len(data) < 5 { return 0 } keyIndex := int(data[0]) lenIn := int(data[1]) data = data[2:] if (keyIndex + 5) > len(data) { return 0 } key := data[:keyIndex] c, err := aes.NewCipher(key) if err != nil { return 0 } dst := make([]byte, lenIn) src := data[keyIndex+1:] defer catchPanics() c.Encrypt(dst, src) return 1 } ================================================ FILE: projects/golang/build.sh ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Temporarily disable coverage build in OSS-Fuzz's CI if [ -n "${OSS_FUZZ_CI-}" ] then if [ "${SANITIZER}" = 'coverage' ] then exit 0 fi fi export GOTOOLCHAIN="local" export FUZZ_ROOT="github.com/dvyukov/go-fuzz-corpus" cd $SRC/go-118-fuzz-build go build . mv go-118-fuzz-build /root/go/bin/ cd $SRC/text cp $SRC/unicode_fuzzer.go ./encoding/unicode/ find . -name "*_test.go" ! -name 'fuzz_test.go' -type f -exec rm -f {} + compile_go_fuzzer golang.org/x/text/encoding/unicode FuzzUnicodeTransform fuzz_unicode_transform function setup_golang_fuzzers() { cd $SRC/golang # These two directories cause build issues and are not used by oss-fuzz. # They can be removed: rm -r sqlparser rm -r parser mkdir $SRC/golang/math && cp $SRC/math_big_fuzzer.go $SRC/golang/math/ mkdir $SRC/golang/text && cp $SRC/text_fuzzer.go $SRC/golang/text/ cp $SRC/language_fuzzer.go $SRC/golang/text/ mkdir -p $SRC/golang/crypto/x509 cp $SRC/x509_fuzzer.go $SRC/golang/crypto/x509/ mkdir -p $SRC/golang/crypto/ecdsa cp $SRC/ecdsa_fuzzer.go ./crypto/ecdsa/ mkdir -p $SRC/golang/crypto/dsa cp $SRC/dsa_fuzzer.go ./crypto/dsa/ mkdir -p $SRC/golang/crypto/aes cp $SRC/aes_fuzzer.go ./crypto/aes/ mkdir $SRC/golang/fp cp $SRC/filepath_fuzzer.go $SRC/golang/fp/ cp $SRC/strings_fuzzer.go $SRC/golang/strings/ cp $SRC/multipart_fuzzer.go $SRC/golang/multipart/main.go mkdir $SRC/golang/encoding && cp $SRC/encoding_fuzzer.go $SRC/golang/encoding/ go mod init "github.com/dvyukov/go-fuzz-corpus" mkdir fuzzingdep printf "package fuzzingdep\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > fuzzingdep/register.go go mod edit -replace github.com/AdamKorcz/go-118-fuzz-build="$SRC"/go-118-fuzz-build go mod tidy } function compile_fuzzers() { # version is used as suffix for the binaries version=$1 compile_go_fuzzer $FUZZ_ROOT/encoding FuzzEncoding fuzz_encoding$version compile_go_fuzzer $FUZZ_ROOT/strings FuzzStringsSplit fuzz_strings_split$version compile_go_fuzzer $FUZZ_ROOT/fp FuzzFpGlob glob_fuzzer$version if [ "${version}" != '_latest_master' ] then compile_go_fuzzer $FUZZ_ROOT/crypto/ecdsa FuzzEcdsaSign FuzzEcdsaSign$version compile_native_go_fuzzer $FUZZ_ROOT/crypto/ecdsa FuzzEcdsaVerify FuzzEcdsaVerify$version compile_native_go_fuzzer $FUZZ_ROOT/crypto/dsa FuzzDsaSign FuzzDsaSign$version compile_native_go_fuzzer $FUZZ_ROOT/crypto/dsa FuzzDsaVerify FuzzDsaVerify$version fi compile_go_fuzzer $FUZZ_ROOT/crypto/x509 FuzzParseCert fuzz_parse_cert$version compile_go_fuzzer $FUZZ_ROOT/crypto/x509 FuzzPemDecrypt fuzz_pem_decrypt$version compile_go_fuzzer $FUZZ_ROOT/crypto/aes FuzzAesCipherDecrypt fuzz_aes_cipher_decrypt$version compile_go_fuzzer $FUZZ_ROOT/crypto/aes FuzzAesCipherEncrypt fuzz_aes_cipher_encrypt$version compile_go_fuzzer $FUZZ_ROOT/text FuzzAcceptLanguage accept_language_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/text FuzzMultipleParsers fuzz_multiple_parsers$version compile_go_fuzzer $FUZZ_ROOT/text FuzzCurrency currency_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/math FuzzFloatSetString fuzz_float_set_string$version compile_go_fuzzer $FUZZ_ROOT/math FuzzBigGobdecode fuzz_big_gobdecode$version compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp1 big_cmp_fuzzer1$version compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp2 big_cmp_fuzzer2$version compile_go_fuzzer $FUZZ_ROOT/math FuzzRatSetString big_rat_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/math FuzzFloat64SpecialCases fuzz_float64_special_cases$version compile_go_fuzzer $FUZZ_ROOT/asn1 Fuzz asn_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/csv Fuzz csv_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/elliptic Fuzz elliptic_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/flate Fuzz flate_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/fmt Fuzz fmt_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/gzip Fuzz gzip_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/httpreq Fuzz httpreq_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/jpeg Fuzz jpeg_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/json Fuzz json_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/lzw Fuzz lzw_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/mime Fuzz mime_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/multipart Fuzz multipart_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/png Fuzz png_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/tar Fuzz tar_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/time Fuzz time_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/xml Fuzz xml_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/zip Fuzz zip_fuzzer$version compile_go_fuzzer $FUZZ_ROOT/zlib Fuzz zlib_fuzzer$version zip $OUT/fuzz_pem_decrypt${version}_seed_corpus.zip $SRC/go/src/crypto/x509/testdata/* zip $OUT/fuzz_parse_cert${version}_seed_corpus.zip $SRC/go/src/crypto/x509/testdata/* } # Build fuzzers with Go 1.18 setup_golang_fuzzers compile_fuzzers "" cd $SRC/go/src/regexp cp $SRC/regexp_fuzzer.go ./ go mod init regexpPackage go mod tidy find . -name "*_test.go" ! -name 'fuzz_test.go' -type f -exec rm -f {} + compile_go_fuzzer regexpPackage FuzzCompile fuzz_regexp_compile compile_go_fuzzer regexpPackage FuzzCompilePOSIX fuzz_compile_posix compile_go_fuzzer regexpPackage FuzzReplaceAll fuzz_replace_all compile_go_fuzzer regexpPackage FuzzFindMatchApis fuzz_find_match_apis #cd $SRC/go/src/archive/tar #go mod init tarPackage #go mod tidy #find . -name "*_test.go" ! -name 'fuzz_test.go' -type f -exec rm -f {} + #go get github.com/AdamKorcz/go-118-fuzz-build/testingtypes #go get github.com/AdamKorcz/go-118-fuzz-build/utils #compile_native_go_fuzzer tarPackage FuzzReader fuzz_std_lib_tar_reader #zip $OUT/fuzz_std_lib_tar_reader_seed_corpus.zip $SRC/go/src/archive/tar/testdata/*.tar cp $SRC/h2c_fuzzer.go $SRC/net/http2/h2c/ cd $SRC/net/http2/h2c go mod tidy compile_go_fuzzer . FuzzH2c fuzz_x_h2c mv $SRC/fuzz_x_h2c.options $OUT/ cp $SRC/openpgp_fuzzer.go $SRC/crypto/openpgp/packet cd $SRC/crypto/openpgp/packet go mod tidy compile_go_fuzzer . FuzzOpenpgpRead fuzz_openpgp_read cd $SRC/image/webp cp $SRC/webp_fuzzer.go ./ compile_go_fuzzer . FuzzWebpDecode fuzz_webp_decode zip $OUT/fuzz_webp_decode_seed_corpus.zip $SRC/image/testdata/*.webp cd $SRC/image/tiff cp $SRC/tiff_fuzzer.go ./ compile_go_fuzzer . FuzzTiffDecode fuzz_tiff_decode cp $SRC/fuzz_tiff_decode.options $OUT/ zip $OUT/fuzz_tiff_decode_seed_corpus.zip $SRC/image/testdata/*.tiff cd $SRC/go/src/archive/tar cp $SRC/fuzz_tar_reader.go ./ rm ./*_test.go #compile_go_fuzzer tarPackage FuzzTarReader fuzz_tar_reader #mv $SRC/fuzz_tar_reader.options $OUT/ #zip $OUT/fuzz_tar_reader_seed_corpus.zip $SRC/go/src/archive/tar/testdata/*.tar #cd $SRC/go/src/archive/zip #go mod init zipPackage #go mod tidy #find . -name "*_test.go" ! -name 'fuzz_test.go' -type f -exec rm -f {} + #go get github.com/AdamKorcz/go-118-fuzz-build/testingtypes #go get github.com/AdamKorcz/go-118-fuzz-build/utils #compile_native_go_fuzzer zipPackage FuzzReader fuzz_std_lib_zip_reader #zip $OUT/fuzz_std_lib_zip_reader_seed_corpus.zip $SRC/go/src/archive/zip/testdata/*.zip cd $SRC/go/src/internal/saferio go mod init saferioPackage go mod tidy cd $SRC/go/src/internal/zstd go mod init zstdPackage go mod tidy cd $SRC/go/src/image/png go mod init pngPackage go get github.com/AdamKorcz/go-118-fuzz-build/testing go mod edit -replace github.com/AdamKorcz/go-118-fuzz-build="$SRC"/go-118-fuzz-build compile_native_go_fuzzer pngPackage FuzzDecode fuzz_png_decode zip $OUT/fuzz_png_decode_seed_corpus.zip ./testdata/*.png cd $SRC/go/src/compress/gzip go mod init gzipPackage go mod tidy find . -name "*_test.go" ! -name 'fuzz_test.go' -type f -exec rm -f {} + go get github.com/AdamKorcz/go-118-fuzz-build/testing go mod edit -replace github.com/AdamKorcz/go-118-fuzz-build="$SRC"/go-118-fuzz-build compile_native_go_fuzzer gzipPackage FuzzReader fuzz_std_lib_gzip_reader zip $OUT/fuzz_std_lib_gzip_reader_seed_corpus.zip $SRC/go/src/compress/gzip/testdata/* # golangs build from source currently breaks. cd $SRC/go/src/html go mod init htmlPackage go mod tidy go get github.com/AdamKorcz/go-118-fuzz-build/testing go mod edit -replace github.com/AdamKorcz/go-118-fuzz-build="$SRC"/go-118-fuzz-build compile_native_go_fuzzer htmlPackage FuzzEscapeUnescape fuzz_html_escape_unescape # Install latest Go from master branch and build fuzzers again cd $SRC rm -r go rm -r golang git clone --depth 1 https://github.com/golang/go git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus $SRC/golang cd $SRC/go/src # delete failing test rm ./cmd/cgo/internal/testsanitizers/msan_test.go # These tests are currently broken so let's remove them rm ./cmd/go/internal/modfetch/codehost/git_test.go rm ./cmd/go/internal/vcweb/vcstest/vcstest_test.go GOMEMLIMIT=2048MiB ./all.bash ls /src/go/bin export GOROOT="/src/go" export PATH=/src/go/bin:$PATH # build fuzzers setup_golang_fuzzers compile_fuzzers "_latest_master" # options files cp $SRC/glob_fuzzer.options $OUT/ cp $SRC/glob_fuzzer.options $OUT/glob_fuzzer_latest_master.options ================================================ FILE: projects/golang/dsa_fuzzer.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package dsa import ( "bytes" "crypto/dsa" "math/big" "testing" ) func FuzzDsaVerify(f *testing.F) { f.Fuzz(func(t *testing.T, data1, data2, data3 []byte, s1, s2 string, s uint8) { bi1, ok := new(big.Int).SetString(s1, 16) bi2, ok2 := new(big.Int).SetString(s2, 16) if !ok || !ok2 { return } var priv dsa.PrivateKey params := &priv.Parameters sizes := []dsa.ParameterSizes{ dsa.L1024N160, dsa.L2048N224, dsa.L2048N256, dsa.L3072N256, } err := dsa.GenerateParameters(params, bytes.NewReader(data1), sizes[int(s)%len(sizes)]) if err != nil { return } err = dsa.GenerateKey(&priv, bytes.NewReader(data2)) if err != nil { return } dsa.Verify(&priv.PublicKey, data3, bi1, bi2) }) } func FuzzDsaSign(f *testing.F) { f.Fuzz(func(t *testing.T, data1, data2, data3, data4 []byte, s uint8) { var priv dsa.PrivateKey params := &priv.Parameters sizes := []dsa.ParameterSizes{ dsa.L1024N160, dsa.L2048N224, dsa.L2048N256, dsa.L3072N256, } err := dsa.GenerateParameters(params, bytes.NewReader(data1), sizes[int(s)%len(sizes)]) if err != nil { return } err = dsa.GenerateKey(&priv, bytes.NewReader(data2)) if err != nil { return } dsa.Sign(bytes.NewReader(data3), &priv, data4) }) } ================================================ FILE: projects/golang/ecdsa_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package ecdsa import ( "bytes" "crypto/ecdsa" "crypto/elliptic" "testing" ) func FuzzEcdsaSign(data []byte) int { if len(data) < 5 { return 0 } c := []elliptic.Curve{ elliptic.P256(), elliptic.P224(), elliptic.P384(), elliptic.P521(), } cIndex := int(data[0] % 4) firstRandReaderLen := int(data[1]) data = data[2:] if (firstRandReaderLen + 3) > len(data) { return 0 } randReader := bytes.NewReader(data[:firstRandReaderLen]) priv, err := ecdsa.GenerateKey(c[cIndex], randReader) if err != nil { return 0 } _, _, _ = ecdsa.Sign(randReader, priv, data[firstRandReaderLen+1:]) return 1 } func FuzzEcdsaVerify(f *testing.F) { f.Fuzz(func(t *testing.T, rand1, rand2, sig []byte, cIndex uint8) { cs := []elliptic.Curve{ elliptic.P256(), elliptic.P224(), elliptic.P384(), elliptic.P521(), } c := int(cIndex) % len(cs) randReader := bytes.NewReader(rand1) priv, err := ecdsa.GenerateKey(cs[c], randReader) if err != nil { return } pub := priv.Public() ecdsa.VerifyASN1(pub.(*ecdsa.PublicKey), rand2, sig) }) } ================================================ FILE: projects/golang/elf_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package elf import ( "os" ) func FuzzElfOpen(data []byte) int { defer os.Remove("tmpFile") f, err := os.Create("tmpFile") if err != nil { return 0 } defer f.Close() _, err = f.Write(data) if err != nil { return 0 } _, err = Open("tmpFile") if err != nil { return 0 } return 1 } ================================================ FILE: projects/golang/encoding_fuzzer.go ================================================ package encoding import ( "bytes" "encoding/base32" "encoding/base64" "encoding/gob" "encoding/json" "encoding/xml" fuzz "github.com/AdaLogics/go-fuzz-headers" ) func FuzzEncoding(data []byte) int { f := fuzz.NewConsumer(data) decType, err := f.GetInt() if err != nil { return 0 } b1, err := f.GetBytes() if err != nil { return 0 } switch decType % 5 { case 0: e, err := f.GetString() if err != nil || len(e) != 32 { return 0 } enc := base32.NewEncoding(e) d := base32.NewDecoder(enc, bytes.NewReader(b1)) dbuf := make([]byte, enc.DecodedLen(len(e))) _, _ = d.Read(dbuf) case 1: e, err := f.GetString() if err != nil || len(e) != 64 { return 0 } for i := 0; i < len(e); i++ { if e[i] == '\n' || e[i] == '\r' { return 0 } } enc := base64.NewEncoding(e) d := base64.NewDecoder(enc, bytes.NewReader(b1)) dbuf := make([]byte, enc.DecodedLen(len(e))) _, _ = d.Read(dbuf) case 2: b2, err := f.GetBytes() if err != nil { return 0 } d := gob.NewDecoder(bytes.NewReader(b1)) _ = d.Decode(b2) case 3: b2, err := f.GetBytes() if err != nil { return 0 } d := json.NewDecoder(bytes.NewReader(b1)) _ = d.Decode(b2) case 4: d := xml.NewDecoder(bytes.NewReader(b1)) _, _ = d.Token() } return 1 } ================================================ FILE: projects/golang/filepath_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package fp import ( "path/filepath" ) func FuzzFpGlob(data []byte) int { _, _ = filepath.Glob(string(data)) return 1 } ================================================ FILE: projects/golang/fuzz_tar_reader.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package tar import ( "bytes" "io" ) func FuzzTarReader(data []byte) int { r := bytes.NewReader(data) tarReader := NewReader(r) for { _, err := tarReader.Next() if err == io.EOF { break } if err != nil { return 0 } } return 1 } ================================================ FILE: projects/golang/fuzz_tar_reader.options ================================================ [libfuzzer] max_len = 1500000 len_control = 0 ================================================ FILE: projects/golang/fuzz_tiff_decode.options ================================================ [libfuzzer] max_len = 1500000 len_control = 0 rss_limit_mb=6000 ================================================ FILE: projects/golang/fuzz_webp_decode.options ================================================ [libfuzzer] timeout = 120 ================================================ FILE: projects/golang/fuzz_x_h2c.options ================================================ [libfuzzer] max_len = 1600000 len_control = 0 ================================================ FILE: projects/golang/glob_fuzzer.options ================================================ [libfuzzer] max_len = 1500000 len_control = 0 ================================================ FILE: projects/golang/h2c_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package h2c import ( "bufio" "bytes" "context" "fmt" "golang.org/x/net/http2" "io/ioutil" "net" "net/http" "net/textproto" "net/url" "runtime" "strings" ) type FakeHttpWriter struct { HeaderStatus int Payload []byte } func (f *FakeHttpWriter) Header() http.Header { return http.Header{} } func (f *FakeHttpWriter) Write(body []byte) (int, error) { f.Payload = body return len(body), nil } func (f *FakeHttpWriter) WriteHeader(status int) { f.HeaderStatus = status } func (f *FakeHttpWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { r1 := bytes.NewReader([]byte{}) r2 := bufio.NewReader(r1) w := bufio.NewWriter(ioutil.Discard) rw := bufio.NewReadWriter(r2, w) return nil, rw, nil } // We ignore these panics, as they don't represent real bugs. func catchPanics() { if r := recover(); r != nil { var err string switch r.(type) { case string: err = r.(string) case runtime.Error: err = r.(runtime.Error).Error() case error: err = r.(error).Error() } // Very hacky for now, but it rids us of a lot of instantiation if strings.Contains(err, "invalid memory address or nil pointer dereference") { return } else { panic(err) } } } func FuzzH2c(data []byte) int { if len(data) < 10 { return 0 } headerMap := make(map[string][]string) headerMap[textproto.CanonicalMIMEHeaderKey("Upgrade")] = []string{"h2c"} headerMap[textproto.CanonicalMIMEHeaderKey("Connection")] = []string{"HTTP2-Settings"} headerMap[textproto.CanonicalMIMEHeaderKey("HTTP2-Settings")] = []string{""} handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello world") }) h2s := &http2.Server{ // ... } h := NewHandler(handler, h2s) w := &FakeHttpWriter{} r, err := http.NewRequestWithContext(context.Background(), "PUT", "nil", bytes.NewReader(data)) if err != nil { return -1 } r.Header = headerMap u, err := url.Parse("http://localhost:8001") if err != nil { return 0 } r.URL = u defer catchPanics() h.ServeHTTP(w, r) return 1 } ================================================ FILE: projects/golang/language_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package fuzztext import ( "golang.org/x/text/currency" "golang.org/x/text/language" "golang.org/x/text/unicode/cldr" ) func FuzzMultipleParsers(data []byte) int { if len(data) < 2 { return 0 } parser_type := int(data[0]) data = data[1:] switch parser_type % 7 { case 0: _, _ = language.ParseExtension(string(data)) case 1: _, _ = language.ParseBase(string(data)) case 2: _, _ = language.ParseScript(string(data)) case 3: _, _ = language.ParseRegion(string(data)) case 4: _, _ = language.ParseVariant(string(data)) case 5: _, _ = cldr.ParseDraft(string(data)) case 6: _, _ = currency.ParseISO(string(data)) } return 1 } ================================================ FILE: projects/golang/math_big_fuzzer.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package mathfuzzer import ( "fmt" fuzz "github.com/AdaLogics/go-fuzz-headers" "math" "math/big" "strconv" "strings" ) func FuzzBigIntCmp1(data []byte) int { if !isDivisibleBy(len(data), 2) { return -1 } i1 := new(big.Int) i2 := new(big.Int) half := len(data) / 2 halfOne := data[:half] halfTwo := data[half:] i1.SetBytes(halfOne) i2.SetBytes(halfTwo) i1.Cmp(i2) return 1 } func FuzzBigIntCmp2(data []byte) int { if !isDivisibleBy(len(data), 2) { return -1 } x, y := new(big.Int), new(big.Int) half := len(data) / 2 if err := x.UnmarshalText(data[:half]); err != nil { return 0 } if err := y.UnmarshalText(data[half:]); err != nil { return 0 } x.Cmp(y) return 1 } func FuzzRatSetString(data []byte) int { _, _ = new(big.Rat).SetString(string(data)) return 1 } func FuzzFloatSetString(data []byte) int { f := fuzz.NewConsumer(data) f64, err := f.GetFloat64() if err != nil { return 0 } if math.IsNaN(f64) { return 0 } s, err := f.GetString() if err != nil { return 0 } fl := big.NewFloat(f64) fl.SetString(s) return 1 } func FuzzBigGobdecode(data []byte) int { f := fuzz.NewConsumer(data) buf, err := f.GetBytes() if err != nil { return 0 } target, err := f.GetInt() if err != nil { return 0 } switch target % 2 { case 0: i, err := f.GetInt() if err != nil { return 0 } bi := big.NewInt(int64(i)) bi.GobDecode(buf) case 1: i1, err := f.GetInt() if err != nil { return 0 } i2, err := f.GetInt() if err != nil { return 0 } if int64(i2) == 0 { return 0 } r := big.NewRat(int64(i1), int64(i2)) r.GobDecode(buf) } return 1 } func isDivisibleBy(n int, divisibleby int) bool { return (n % divisibleby) == 0 } func FuzzFloat64SpecialCases(data []byte) int { input := string(data) if strings.HasPrefix(input, "long:") { input = input[len("long:"):] } r, ok := new(big.Rat).SetString(input) if !ok { return 0 } f, exact := r.Float64() // 1. Check string -> Rat -> float64 conversions are // consistent with strconv.ParseFloat. // Skip this check if the input uses "a/b" rational syntax. if !strings.Contains(input, "/") { e, _ := strconv.ParseFloat(input, 64) // Careful: negative Rats too small for // float64 become -0, but Rat obviously cannot // preserve the sign from SetString("-0"). switch { case math.Float64bits(e) == math.Float64bits(f): // Ok: bitwise equal. case f == 0 && r.Num().BitLen() == 0: // Ok: Rat(0) is equivalent to both +/- float64(0). default: return 0 panic(fmt.Sprintf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g\n", input, e, e, f, f, f-e)) } } if !isFiniteFuzz(f) { return 0 } // 2. Check f is best approximation to r. if !checkIsBestApprox64Fuzz(f, r) { // Append context information. panic(fmt.Sprintf("(input was %q\n)", input)) } // 3. Check f->R->f roundtrip is non-lossy. checkNonLossyRoundtrip64Fuzz(f) // 4. Check exactness using slow algorithm. if wasExact := new(big.Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact { fmt.Println(input) panic(fmt.Sprintf("Rat.SetString(%q).Float64().exact = %t, want %t\n", input, exact, wasExact)) } return 1 } func checkNonLossyRoundtrip64Fuzz(f float64) { if !isFiniteFuzz(f) { return } r := new(big.Rat).SetFloat64(f) if r == nil { panic(fmt.Sprintf("Rat.SetFloat64(%g (%b)) == nil\n", f, f)) } f2, exact := r.Float64() if f != f2 || !exact { panic(fmt.Sprintf("Rat.SetFloat64(%g).Float64() = %g (%b), %v, want %g (%b), %v; delta = %b\n", f, f2, f2, exact, f, f, true, f2-f)) } } func isFiniteFuzz(f float64) bool { return math.Abs(f) <= math.MaxFloat64 } func checkIsBestApprox64Fuzz(f float64, r *big.Rat) bool { if math.Abs(f) >= math.MaxFloat64 { // Cannot check +Inf, -Inf, nor the float next to them (MaxFloat64). // But we have tests for these special cases. return true } // r must be strictly between f0 and f1, the floats bracketing f. f0 := math.Nextafter(f, math.Inf(-1)) f1 := math.Nextafter(f, math.Inf(+1)) // For f to be correct, r must be closer to f than to f0 or f1. df := deltaFuzz(r, f) df0 := deltaFuzz(r, f0) df1 := deltaFuzz(r, f1) if df.Cmp(df0) > 0 { panic(fmt.Sprintf("Rat(%v).Float64() = %g (%b), but previous float64 %g (%b) is closer", r, f, f, f0, f0)) } if df.Cmp(df1) > 0 { panic(fmt.Sprintf("Rat(%v).Float64() = %g (%b), but next float64 %g (%b) is closer", r, f, f, f1, f1)) } if df.Cmp(df0) == 0 && !isEven64Fuzz(f) { panic(fmt.Sprintf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f0, f0)) } if df.Cmp(df1) == 0 && !isEven64Fuzz(f) { panic(fmt.Sprintf("Rat(%v).Float64() = %g (%b); halfway should have rounded to %g (%b) instead", r, f, f, f1, f1)) } return true } func deltaFuzz(r *big.Rat, f float64) *big.Rat { d := new(big.Rat).Sub(r, new(big.Rat).SetFloat64(f)) return d.Abs(d) } func isEven64Fuzz(f float64) bool { return math.Float64bits(f)&1 == 0 } ================================================ FILE: projects/golang/multipart_fuzzer.go ================================================ // Copyright 2015 go-fuzz project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. package multipart import ( "bytes" "fmt" "io" "io/ioutil" "mime/multipart" "net/textproto" "runtime" "github.com/dvyukov/go-fuzz-corpus/fuzz" ) type Part struct { hdr textproto.MIMEHeader data []byte } func Fuzz(data []byte) int { defer func() { if r := recover(); r != nil { } runtime.GC() }() const boundary = "dfhjksd23f43242f43fv4b4g2g2g23vf2" { r := multipart.NewReader(bytes.NewReader(data), boundary) f, err := r.ReadForm(1 << 20) if err == nil { f.RemoveAll() } } fmt.Println("Creating multipart reader") r := multipart.NewReader(bytes.NewReader(data), boundary) fmt.Println("Reading") var parts []Part for { p, err := r.NextPart() if err == io.EOF { break } if err != nil { return 0 } p.FileName() p.FormName() pdata, err := ioutil.ReadAll(p) if err != nil { return 0 } p.Close() // The parser is loose here. // If data contains \n followed by boundary (but without \r), // it parses it as part body. However, when it serializes it back, // it writes \r\n followed by boundary, which becomes new part separator. if bytes.Contains(pdata, []byte(boundary)) { continue } parts = append(parts, Part{p.Header, pdata}) } if len(parts) == 0 { return 0 } fmt.Println("Creating new writer") buf := new(bytes.Buffer) w := multipart.NewWriter(buf) w.SetBoundary(boundary) fmt.Println("Writing data") for _, p := range parts { pw, err := w.CreatePart(p.hdr) if err != nil { panic(err) } n, err := pw.Write(p.data) if err != nil { panic(err) } if n != len(p.data) { panic("partial write") } } w.Close() fmt.Println("Time to compare") data1 := buf.Bytes() r1 := multipart.NewReader(buf, boundary) var parts1 []Part for { p, err := r1.NextPart() if err == io.EOF { break } if err != nil { fmt.Printf("parts0: %+v\n", parts) fmt.Printf("data0: %q\n", data) fmt.Printf("data1: %q\n", data1) panic(err) } p.FileName() p.FormName() pdata, err := ioutil.ReadAll(p) if err != nil { panic(err) } p.Close() parts1 = append(parts1, Part{p.Header, pdata}) } fmt.Println("Performing deep equal") if !fuzz.DeepEqual(parts, parts1) { fmt.Printf("parts0: %+v\n", parts) fmt.Printf("parts1: %+v\n", parts1) fmt.Printf("data0: %q\n", data) fmt.Printf("data1: %q\n", data1) panic("data has changed") } return 1 } ================================================ FILE: projects/golang/openpgp_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package packet import ( "bytes" ) func FuzzOpenpgpRead(data []byte) int { _, _ = Read(bytes.NewReader(data)) return 1 } ================================================ FILE: projects/golang/project.yaml ================================================ homepage: "https://golang.org/" main_repo: "https://github.com/golang/go" primary_contact: "security@golang.org" auto_ccs: - "bracewell@google.com" - "dneil@google.com" - "nealpatel@google.com" - "rsc@google.com" - "Adam@adalogics.com" language: go sanitizers: - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/golang/regexp_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package regexp func FuzzCompile(data []byte) int { _, _ = Compile(string(data)) return 1 } func FuzzCompilePOSIX(data []byte) int { _, _ = CompilePOSIX(string(data)) return 1 } func FuzzReplaceAll(data []byte) int { if len(data) < 5 { return 0 } chunk1Len := int(data[0]) chunk2Len := int(data[1]) if chunk2Len <= chunk1Len || chunk1Len < 3 || len(data) < (chunk2Len+2) { return 0 } chunk1 := data[2:chunk1Len] chunk2 := data[chunk1Len+1 : chunk2Len] chunk3 := data[chunk2Len+1:] re, err := Compile(string(chunk1)) if err != nil { return 0 } _ = re.ReplaceAll(chunk2, chunk3) return 1 } func FuzzFindMatchApis(data []byte) int { if len(data) < 5 { return 0 } callType := int(data[0]) chunk1Len := int(data[1]) data = data[2:] if chunk1Len+2 >= len(data) { return 0 } reString := string(data[:chunk1Len]) apiPayload := data[chunk1Len+1:] re, err := Compile(reString) if err != nil { return 0 } switch callType % 6 { case 0: _ = re.FindIndex(apiPayload) case 1: _ = re.FindString(string(apiPayload)) case 2: _ = re.FindStringIndex(string(apiPayload)) case 3: _ = re.FindSubmatch(apiPayload) case 4: _ = re.MatchString(string(apiPayload)) case 5: _ = re.Match(apiPayload) } return 1 } ================================================ FILE: projects/golang/strings_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package strings import ( fuzz "github.com/AdaLogics/go-fuzz-headers" "strings" ) func FuzzStringsSplit(data []byte) int { f := fuzz.NewConsumer(data) str1, err := f.GetString() if err != nil { return 0 } str2, err := f.GetString() if err != nil { return 0 } _ = strings.Split(str1, str2) return 1 } ================================================ FILE: projects/golang/text_fuzzer.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package fuzztext import ( "golang.org/x/text/currency" "golang.org/x/text/language" ) func FuzzAcceptLanguage(data []byte) int { _, _, _ = language.ParseAcceptLanguage(string(data)) return 1 } func FuzzCurrency(data []byte) int { // Create tag t, err := language.Parse(string(data)) if err != nil { return 0 } _, _ = currency.FromTag(t) return 1 } ================================================ FILE: projects/golang/tiff_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package tiff import ( "bytes" "runtime" ) func FuzzTiffDecode(data []byte) int { defer func() { if r := recover(); r != nil { } runtime.GC() }() config, err := DecodeConfig(bytes.NewReader(data)) if err != nil || config.Width > 16384 || config.Height > 16384 { return 1 } _, _ = Decode(bytes.NewReader(data)) return 1 } ================================================ FILE: projects/golang/unicode_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package unicode import ( fuzz "github.com/AdaLogics/go-fuzz-headers" "golang.org/x/text/encoding/charmap" ) var ( utf16LEIB = UTF16(LittleEndian, IgnoreBOM) // UTF-16LE (atypical interpretation) utf16LEUB = UTF16(LittleEndian, UseBOM) // UTF-16, LE utf16LEEB = UTF16(LittleEndian, ExpectBOM) // UTF-16, LE, Expect utf16BEIB = UTF16(BigEndian, IgnoreBOM) // UTF-16BE (atypical interpretation) utf16BEUB = UTF16(BigEndian, UseBOM) // UTF-16 default utf16BEEB = UTF16(BigEndian, ExpectBOM) // UTF-16 Expect ) func FuzzUnicodeTransform(data []byte) int { f := fuzz.NewConsumer(data) sizeDest, err := f.GetInt() if err != nil { return 0 } b, err := f.GetBytes() if err != nil { return 0 } b2 := make([]byte, sizeDest) decoderType, err := f.GetInt() if err != nil { return 0 } boo, err := f.GetBool() if err != nil { return 0 } switch decoderType % 10 { case 0: utf16LEIB.NewDecoder().Transform(b2, b, boo) case 1: utf16LEUB.NewDecoder().Transform(b2, b, boo) case 2: utf16LEEB.NewDecoder().Transform(b2, b, boo) case 3: utf16BEIB.NewDecoder().Transform(b2, b, boo) case 4: utf16BEUB.NewDecoder().Transform(b2, b, boo) case 5: utf16BEEB.NewDecoder().Transform(b2, b, boo) case 6: UTF8.NewDecoder().Transform(b2, b, boo) case 7: UTF8BOM.NewDecoder().Transform(b2, b, boo) case 8: tr := UTF8BOM.NewEncoder() tr.Reset() tr.Transform(b2, b, boo) case 9: tr := BOMOverride(charmap.CodePage437.NewDecoder()) tr.Reset() tr.Transform(b2, b, boo) } return 1 } ================================================ FILE: projects/golang/webp_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package webp import ( "bytes" ) func FuzzWebpDecode(data []byte) int { conf, err := DecodeConfig(bytes.NewReader(data)) if err != nil { return 0 } totalSize := conf.Width * conf.Height if totalSize > 1e6 { return 0 } _, _ = Decode(bytes.NewReader(data)) return 1 } ================================================ FILE: projects/golang/x509_fuzzer.go ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package x509 import ( "crypto/x509" "encoding/pem" ) func FuzzParseCert(data []byte) int { if len(data) < 2 { return 1 } plural := int(data[0])%2 == 0 data = data[1:] if plural { _, _ = x509.ParseCertificates(data) } else { _, _ = x509.ParseCertificate(data) } return 1 } func FuzzPemDecrypt(data []byte) int { if len(data) < 6 { return 0 } pemDataLen := int(data[0]) if (pemDataLen + 5) > len(data) { return 0 } data = data[1:] pemData := data[:pemDataLen] password := data[pemDataLen+1:] block, _ := pem.Decode(pemData) if block == nil { return 0 } _, _ = x509.DecryptPEMBlock(block, password) return 1 } ================================================ FILE: projects/golang-appengine/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/golang/appengine WORKDIR $SRC/appengine COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/golang-appengine/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./v2/blobstore/ cd $SRC/appengine/v2 go mod tidy printf "package appengine\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > register.go go mod tidy compile_native_go_fuzzer google.golang.org/appengine/v2/blobstore FuzzParseUpload FuzzParseUpload ================================================ FILE: projects/golang-appengine/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package blobstore import ( "bytes" "net/http" "testing" fuzz "github.com/AdaLogics/go-fuzz-headers" ) func FuzzParseUpload(f *testing.F) { f.Fuzz(func(t *testing.T, body, headers []byte) { r, err := http.NewRequest("POST", "", bytes.NewReader(body)) if err != nil { return } ff := fuzz.NewConsumer(headers) h := make(map[string][]string, 0) ff.FuzzMap(&h) if len(h) == 0 { return } _, ok := h["Content-Type"] if !ok { hSlice := make([]string, 0) err := ff.CreateSlice(&hSlice) if err != nil { return } h["Content-Type"] = hSlice } r.Header = h ParseUpload(r) }) } ================================================ FILE: projects/golang-appengine/project.yaml ================================================ homepage: "https://github.com/golang/appengine" language: go main_repo: "https://github.com/golang/appengine" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/golang-protobuf/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://go.googlesource.com/protobuf $GOPATH/src/google.golang.org/protobuf COPY build.sh $SRC/ WORKDIR $GOPATH/src/google.golang.org/protobuf ================================================ FILE: projects/golang-protobuf/build.sh ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. . internal/fuzz/oss-fuzz-build.sh ================================================ FILE: projects/golang-protobuf/project.yaml ================================================ homepage: "https://github.com/protocolbuffers/protobuf-go" main_repo: "https://github.com/protocolbuffers/protobuf-go" primary_contact: "stapelberg@google.com" auto_ccs: - "lassefolger@google.com" - "stapelberg@google.com" - "dneil@google.com" sanitizers: - address fuzzing_engines: - libfuzzer language: go ================================================ FILE: projects/gonids/372f9bd.diff ================================================ From 372f9bdd0a914945296123b51df92eed4ece3df6 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 11 Nov 2021 19:58:23 -0500 Subject: [PATCH] [release-branch.go1.17] reflect: keep pointer in aggregate-typed args live in Call When register ABI is used, reflect.Value.Call prepares the call arguments in a memory representation of the argument registers. It has special handling to keep the pointers in arguments live. Currently, this handles pointer-typed arguments. But when an argument is an aggregate-type that contains pointers and passed in registers, it currently doesn't keep the pointers live. Do so in this CL. Fixes #49961 Change-Id: I9264a8767e2a2c48573f6047144759b845dcf480 --- diff --git a/src/internal/abi/abi.go b/src/internal/abi/abi.go index aaff9ce..aa5083a 100644 --- a/src/internal/abi/abi.go +++ b/src/internal/abi/abi.go @@ -33,6 +33,24 @@ ReturnIsPtr IntArgRegBitmap } +func (r *RegArgs) Dump() { + print("Ints:") + for _, x := range r.Ints { + print(" ", x) + } + println() + print("Floats:") + for _, x := range r.Floats { + print(" ", x) + } + println() + print("Ptrs:") + for _, x := range r.Ptrs { + print(" ", x) + } + println() +} + // IntArgRegBitmap is a bitmap large enough to hold one bit per // integer argument/return register. type IntArgRegBitmap [(IntArgRegs + 7) / 8]uint8 diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index eac27e8..6f350af 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -6270,6 +6270,29 @@ *CallGC = false } +func TestCallArgLive(t *testing.T) { + type T struct{ X, Y *string } // pointerful aggregate + + F := func(t T) { *t.X = "ok" } + + // In reflect.Value.Call, trigger a garbage collection in reflect.call + // between marshaling argument and the actual call. + *CallGC = true + + x := new(string) + runtime.SetFinalizer(x, func(p *string) { + if *p != "ok" { + t.Errorf("x dead prematurely") + } + }) + v := T{x, nil} + + ValueOf(F).Call([]Value{ValueOf(v)}) + + // Stop garbage collecting during reflect.call. + *CallGC = false +} + func TestMakeFuncStackCopy(t *testing.T) { target := func(in []Value) []Value { runtime.GC() diff --git a/src/reflect/value.go b/src/reflect/value.go index 6f878eb..520dc69 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -352,7 +352,7 @@ return v.call("CallSlice", in) } -var callGC bool // for testing; see TestCallMethodJump +var callGC bool // for testing; see TestCallMethodJump and TestCallArgLive const debugReflectCall = false @@ -509,12 +509,16 @@ // Copy values to "integer registers." if v.flag&flagIndir != 0 { offset := add(v.ptr, st.offset, "precomputed value offset") - memmove(unsafe.Pointer(®Args.Ints[st.ireg]), offset, st.size) - } else { if st.kind == abiStepPointer { // Duplicate this pointer in the pointer area of the // register space. Otherwise, there's the potential for // this to be the last reference to v.ptr. + regArgs.Ptrs[st.ireg] = *(*unsafe.Pointer)(offset) + } + memmove(unsafe.Pointer(®Args.Ints[st.ireg]), offset, st.size) + } else { + if st.kind == abiStepPointer { + // See the comment in abiStepPointer case above. regArgs.Ptrs[st.ireg] = v.ptr } regArgs.Ints[st.ireg] = uintptr(v.ptr) @@ -539,6 +543,15 @@ // Mark pointers in registers for the return path. regArgs.ReturnIsPtr = abi.outRegPtrs + if debugReflectCall { + regArgs.Dump() + } + + // For testing; see TestCallArgLive. + if callGC { + runtime.GC() + } + // Call. call(frametype, fn, stackArgs, uint32(frametype.size), uint32(abi.retOffset), uint32(frameSize), ®Args) ================================================ FILE: projects/gonids/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/google/gonids ADD https://rules.emergingthreats.net/open/suricata/emerging.rules.zip emerging.rules.zip COPY build.sh $SRC/ COPY *.diff $SRC/ WORKDIR $SRC/gonids ================================================ FILE: projects/gonids/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/google/gonids FuzzParseRule fuzz_parserule cd $SRC unzip emerging.rules.zip cd rules i=0 mkdir corpus # quit output for commands set +x cat *.rules | while read l; do echo $l > corpus/$i.rule; i=$((i+1)); done set -x zip -q -r $OUT/fuzz_parserule_seed_corpus.zip corpus ================================================ FILE: projects/gonids/project.yaml ================================================ homepage: "https://github.com/google/gonids" primary_contact: "duane.security@gmail.com" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/google/gonids' file_github_issue: True ================================================ FILE: projects/gopacket/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone https://github.com/google/gopacket.git COPY build.sh $SRC/ WORKDIR $SRC/gopacket ================================================ FILE: projects/gopacket/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/google/gopacket/layers FuzzLayer fuzz_layers ================================================ FILE: projects/gopacket/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/google/gopacket" primary_contact: "gconnell@google.com" auto_ccs : - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/google/gopacket' file_github_issue: True ================================================ FILE: projects/gopsutil/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/shirou/gopsutil WORKDIR $SRC/gopsutil COPY build.sh fuzz_test.go $SRC/ ================================================ FILE: projects/gopsutil/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz_test.go ./process/ go mod tidy printf "package process\nimport _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\"\n" > ./process/register.go go mod tidy compile_native_go_fuzzer github.com/shirou/gopsutil/v4/process FuzzTest FuzzTest ================================================ FILE: projects/gopsutil/fuzz_test.go ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package process import ( "context" "os" "path/filepath" "testing" ) func init() { os.Setenv("HOST_PROC", ".") } func FuzzTest(f *testing.F) { f.Fuzz(func(t *testing.T, data []byte) { p := &Process{Pid: int32(1)} if len(data) < 5 { return } err := os.Mkdir("1", 0750) if err != nil { panic(err) } defer os.RemoveAll("1") file := filepath.Join(".", "1", "limits") err = os.WriteFile(file, data, 0666) if err != nil { panic(err) } p.RlimitUsageWithContext(context.Background(), true) }) } ================================================ FILE: projects/gopsutil/project.yaml ================================================ homepage: "https://github.com/shirou/gopsutil" language: go main_repo: "https://github.com/shirou/gopsutil" auto_ccs: - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/gosnmp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/gosnmp/gosnmp.git COPY build.sh $SRC/ WORKDIR $SRC/gosnmp ================================================ FILE: projects/gosnmp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go get github.com/AdamKorcz/go-118-fuzz-build/testing sed -i '5,6d' marshal_test.go sed -i '/func BenchmarkSendOneRequest(/,/^}/ s/^/\/\//' marshal_test.go compile_native_go_fuzzer github.com/gosnmp/gosnmp FuzzUnmarshal fuzz_unmarshal marshal ================================================ FILE: projects/gosnmp/project.yaml ================================================ homepage: "https://github.com/gosnmp/gosnmp" language: go primary_contact: "tim.rots@protonmail.ch" auto_ccs: - "superq@gmail.com" - "ajsinghyadav00@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/gosnmp/gosnmp" ================================================ FILE: projects/gpac/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y build-essential pkg-config libz-dev RUN git clone https://github.com/gpac/gpac && cd gpac && git submodule update --init --remote --recursive COPY build.sh $SRC/ WORKDIR $SRC/gpac ================================================ FILE: projects/gpac/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./configure --static-build --extra-cflags="${CFLAGS}" --extra-ldflags="${CFLAGS}" make fuzzers=$(find $SRC/gpac/testsuite/oss-fuzzers -name "fuzz_*.c") for f in $fuzzers; do fuzzerName=$(basename $f .c) echo "Building fuzzer $fuzzerName" $CC $CFLAGS -I./include -I./ -DGPAC_HAVE_CONFIG_H -c $f $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzerName.o -o $OUT/$fuzzerName \ ./bin/gcc/libgpac_static.a \ -lm -lz -lpthread -lssl -lcrypto -DGPAC_HAVE_CONFIG_H if [ -d "$SRC/gpac/testsuite/oss-fuzzers/${fuzzerName}_corpus" ]; then zip -j $OUT/${fuzzerName}_seed_corpus.zip $SRC/gpac/testsuite/oss-fuzzers/${fuzzerName}_corpus/* fi done ================================================ FILE: projects/gpac/project.yaml ================================================ homepage: "https://gpac.io" main_repo: "https://github.com/gpac/gpac" primary_contact: "project.gpac@gmail.com" language: c auto_ccs: - "david@adalogics.com" ================================================ FILE: projects/gprof2dot/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/jrfonseca/gprof2dot gprof2dot COPY *.sh *py $SRC/ WORKDIR $SRC/gprof2dot ================================================ FILE: projects/gprof2dot/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gprof2dot/fuzz_profile.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1 # Imports by the generated code import gprof2dot def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) funcName = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) # Class target. try: profile = gprof2dot.Profile() profile.getFunctionIds(funcName) except ( gprof2dot.XmlTokenMismatch, gprof2dot.UndefinedEvent, gprof2dot.ParseError, ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gprof2dot/project.yaml ================================================ homepage: https://github.com/jrfonseca/gprof2dot main_repo: https://github.com/jrfonseca/gprof2dot language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/gpsd/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y scons python3-distutils RUN git clone --depth 1 https://gitlab.com/gpsd/gpsd RUN git clone --depth 1 https://github.com/adalogics/ada-fuzzers RUN cp $SRC/ada-fuzzers/projects/gpsd/build.sh $SRC/ && \ cp -r $SRC/ada-fuzzers/projects/gpsd/fuzzer $SRC/gpsd/fuzzer && \ cp -r $SRC/ada-fuzzers/projects/gpsd/corp $SRC/gpsd/corp WORKDIR $SRC/gpsd/ ================================================ FILE: projects/gpsd/project.yaml ================================================ homepage: "https://gpsd.io" language: c primary_contact: "gem@rellim.com" auto_ccs: - "arthur.chan@adalogics.com" - "david@adalogics.com" - "adam@adalogics.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory main_repo: 'https://gitlab.com/gpsd/gpsd' ================================================ FILE: projects/graphicsmagick/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Needed tools RUN apt-get update && \ apt-get install -y \ mercurial \ autoconf \ autopoint \ cmake \ libtool \ nasm \ pkg-config \ po4a \ ninja-build \ libgflags-dev \ yasm # Due to libtiff requirements, build requires autoconf 2.71 (or later) RUN curl -LO https://mirrors.edge.kernel.org/ubuntu/pool/main/a/autoconf/autoconf_2.72-3.1ubuntu1_all.deb && \ apt install ./autoconf_2.72-3.1ubuntu1_all.deb # Due to libxml2 requirements, build requires automake 1.16.3 (or later) RUN curl -LO https://mirrors.edge.kernel.org/ubuntu/pool/main/a/automake-1.17/automake_1.17-4ubuntu1_all.deb && \ apt install ./automake_1.17-4ubuntu1_all.deb # GraphicsMagick RUN hg clone --time -b default https://foss.heptapod.net/graphicsmagick/graphicsmagick graphicsmagick || \ hg clone --time -b default https://foss.heptapod.net/graphicsmagick/graphicsmagick graphicsmagick || \ hg clone --time -b default https://foss.heptapod.net/graphicsmagick/graphicsmagick graphicsmagick # Libtiff RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff # h.265 codec implementation needed by libheif RUN git clone --depth 1 https://github.com/strukturag/libde265 || \ printf "https://github.com/strukturag/libde265 is not available!\n" # x265 HEVC Encoder needed by libheif # https://bitbucket.org/multicoreware/x265_git/src/stable/ # https://bitbucket.org/multicoreware/x265_git/src/master/ RUN git clone --depth 1 https://bitbucket.org/multicoreware/x265_git/src/stable/ x265 || \ printf "https://bitbucket.org/multicoreware/x265_git/src/stable/ is not available!\n" # AV1 Codec Library needed by libheif RUN git clone --depth 1 https://aomedia.googlesource.com/aom aom || \ printf "https://aomedia.googlesource.com/aom is not available!\n" # AVC (OpenH264) Codec Library needed by libheif RUN git clone --depth 1 https://github.com/cisco/openh264 openh264 # JPEG 2000 (OpenJPEG) Library needed by libheif RUN git clone --depth 1 https://github.com/uclouvain/openjpeg openjpeg # Libheif RUN git clone --depth 1 https://github.com/strukturag/libheif # WebP RUN git clone --depth 1 https://github.com/webmproject/libwebp # Zlib RUN git clone --depth 1 https://github.com/madler/zlib # XZ RUN git clone --depth 1 https://github.com/tukaani-project/xz # Zstd RUN git clone --depth 1 https://github.com/facebook/zstd # libjpeg-turbo RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo # Freetype RUN git clone --depth 1 https://github.com/freetype/freetype # Libpng RUN git clone --depth 1 https://github.com/pnggroup/libpng # Little-CMS RUN git clone --depth 1 https://github.com/mm2/Little-CMS # Bzip2 RUN git clone --depth 1 https://gitlab.com/federicomenaquintero/bzip2.git # Jasper RUN git clone --depth 1 https://github.com/jasper-software/jasper # Libxml2 (fall back to github mirror if gitlab.gnome.org is overloaded) RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git || \ git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git || \ git clone --depth 1 https://github.com/GNOME/libxml2 # Libjxl RUN git clone --depth 1 https://github.com/libjxl/libjxl.git # Libzip RUN git clone --depth 1 https://github.com/nih-at/libzip.git # Libjxl sub-repositories # Borrowed from projects/libjxl/Dockerfile RUN git -C libjxl submodule update --init --recommend-shallow \ third_party/brotli \ third_party/highway \ third_party/libjpeg-turbo \ third_party/skcms # JBIG-kit RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit # does not support shallow # libwmf RUN git clone --depth 1 https://github.com/caolanm/libwmf.git # vvdec RUN git clone --depth 1 https://github.com/fraunhoferhhi/vvdec.git # vvenc RUN git clone --depth 1 https://github.com/fraunhoferhhi/vvenc.git # x264 RUN git clone --depth 1 https://code.videolan.org/videolan/x264.git # OpenJPH RUN git clone --depth 1 https://github.com/aous72/OpenJPH.git # Build! WORKDIR $SRC/graphicsmagick COPY build.sh $SRC/ ================================================ FILE: projects/graphicsmagick/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./fuzzing/oss-fuzz-build.sh ================================================ FILE: projects/graphicsmagick/project.yaml ================================================ homepage: "http://www.graphicsmagick.org/" main_repo: "https://foss.heptapod.net/graphicsmagick/graphicsmagick" language: c++ primary_contact: "bobjfriesenhahn@gmail.com" auto_ccs: - troyjp@gmail.com - alex.gaynor@gmail.com - paul.l.kehrer@gmail.com sanitizers: - address - memory - undefined architectures: - x86_64 - i386 fuzzing_engines: - libfuzzer - honggfuzz - afl ================================================ FILE: projects/graphql-java/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/graphql-java/graphql-java graphql-java COPY *.sh *.java $SRC/ WORKDIR $SRC/graphql-java ================================================ FILE: projects/graphql-java/GraphqlFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import graphql.GraphQL; import graphql.GraphQLException; import graphql.schema.GraphQLSchema; import graphql.schema.idl.RuntimeWiring; import graphql.schema.idl.SchemaGenerator; import graphql.schema.idl.SchemaParser; import graphql.schema.idl.TypeDefinitionRegistry; public class GraphqlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { GraphQLSchema graphQLSchema; SchemaParser schemaParser = new SchemaParser(); SchemaGenerator schemaGenerator = new SchemaGenerator(); try { if (data.consumeBoolean()) { TypeDefinitionRegistry registry = schemaParser.parse(data.consumeString(data.remainingBytes() / 2)); graphQLSchema = schemaGenerator.makeExecutableSchema( registry, RuntimeWiring.newRuntimeWiring().build()); } else { graphQLSchema = schemaGenerator.createdMockedSchema(data.consumeString(data.remainingBytes() / 2)); } GraphQL.newGraphQL(graphQLSchema).build().execute(data.consumeRemainingAsString()); } catch (GraphQLException | ClassCastException e) { // Known exception } } } ================================================ FILE: projects/graphql-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## # Retrieve JDK-17 wget https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz -O openjdk-17.tar.gz tar -zxf openjdk-17.tar.gz rm -f openjdk-17.tar.gz cp -r jdk-17 $OUT/ JAVA_HOME=$OUT/jdk-17 PATH=$JAVA_HOME/bin:$PATH # Add task for copy dependency jars echo " task copyToLib(type: Copy) { into \"\${buildDir}/dependencies\" from configurations.runtimeClasspath }" >> ./build.gradle # Gradle build with gradle wrapper rm -rf $HOME/.gradle/caches/ ./gradlew clean build shadowJar copyToLib -x test -x javadoc -x sources ./gradlew --stop cp "./build/libs/$(basename ./build/tmp/jar/*.jar)" $OUT/graphql-java.jar ALL_JARS="graphql-java.jar" # Copy dependency jars for JARFILE in $(ls ./build/dependencies/*.jar) do cp $JARFILE $OUT/ ALL_JARS=$ALL_JARS" $(basename $JARFILE)" done # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/graphql-java/project.yaml ================================================ homepage: https://github.com/graphql-java/graphql-java main_repo: https://github.com/graphql-java/graphql-java language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/greenmail/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/greenmail-mail-test/greenmail.git greenmail RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.4/bin/mvn COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/greenmail ================================================ FILE: projects/greenmail/UserManagerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium; import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.ServerSetup; import com.icegreen.greenmail.user.GreenMailUser; import com.icegreen.greenmail.user.UserManager; import com.icegreen.greenmail.user.UserException; public class UserManagerFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { GreenMail greenMail = new GreenMail(ServerSetup.ALL); String email = data.consumeString(240); String login = data.consumeString(240); String pwd = data.consumeRemainingAsString(); try { UserManager userManger = greenMail.getUserManager(); userManger.createUser(email, login, pwd); GreenMailUser greenMailUser = userManger.getUser(login); if (!greenMailUser.getLogin().equals(login)) { throw new FuzzerSecurityIssueMedium("User is not created"); } if (!userManger.test(login, pwd)) { throw new FuzzerSecurityIssueMedium("Loggin is not possible!"); } userManger.deleteUser(greenMailUser); } catch (UserException e) { } } } ================================================ FILE: projects/greenmail/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 -Djdk.version=15" $MVN clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) cp ./greenmail-core/target/greenmail-$CURRENT_VERSION.jar $OUT/greenmail-core.jar ALL_JARS="greenmail-core.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/greenmail/project.yaml ================================================ homepage: "https://github.com/greenmail-mail-test/greenmail" language: jvm main_repo: "https://github.com/greenmail-mail-test/greenmail.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/grok/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --recursive --depth 1 https://github.com/GrokImageCompression/grok.git grok RUN git clone --depth 1 https://github.com/GrokImageCompression/grok-test-data.git grok-data WORKDIR grok COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/grok/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Configure Test Data Path export GRK_DATA_ROOT=$SRC/grok-data # Build grok core code and unit test mkdir build cd build cmake .. -DGRK_BUILD_CODEC=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=ON make clean -s make -j$(nproc) -s cd .. ./tests/fuzzers/build_google_oss_fuzzers.sh ./tests/fuzzers/build_seed_corpus.sh ================================================ FILE: projects/grok/project.yaml ================================================ homepage: "https://github.com/GrokImageCompression/grok" primary_contact: "boxerab@gmail.com" language: c++ fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/GrokImageCompression/grok.git' ================================================ FILE: projects/grok/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable allocator problem and leak problem for unit testing export ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1" ctest --test-dir build ================================================ FILE: projects/groovy/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone https://github.com/apache/groovy.git COPY *.diff $SRC/ RUN cd groovy && tr -d '\015' < $SRC/add-shadow-to-test.diff | git apply COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/groovy ================================================ FILE: projects/groovy/DurationFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import groovy.time.*; public class DurationFuzzer { int years[] = null; int months[] = null; int days[] = null; int hours[] = null; int minutes[] = null; int seconds[] = null; int millis[] = null; public DurationFuzzer(FuzzedDataProvider data) { years=new int[] { data.consumeInt(), data.consumeInt() }; months=new int[] { data.consumeInt(), data.consumeInt() }; days=new int[] { data.consumeInt(), data.consumeInt() }; hours=new int[] { data.consumeInt(), data.consumeInt() }; minutes=new int[] { data.consumeInt(), data.consumeInt() }; seconds=new int[] { data.consumeInt(), data.consumeInt() }; millis=new int[] { data.consumeInt(), data.consumeInt() }; } void runTest(BaseDuration duration1, BaseDuration duration2) { duration1.getAgo(); duration1.compareTo(duration2); duration1.getHours(); duration1.getMillis(); duration1.getMinutes(); duration1.getMonths(); duration1.getSeconds(); duration1.getYears(); duration1.toString(); duration1.getFrom(); duration1.getFrom().getNow(); duration1.getFrom().getToday(); duration1.toMilliseconds(); } void runTest(Duration duration1, Duration duration2) { runTest((BaseDuration)duration1, duration2); duration1.minus(duration2); duration1.plus(duration2); } void runTest(TimeDuration duration1, TimeDuration duration2) { runTest((BaseDuration)duration1, duration2); duration1.minus(duration2); duration1.plus(duration2); } void runTest(DatumDependentDuration duration1, DatumDependentDuration duration2) { runTest((BaseDuration)duration1, duration2); duration1.minus(duration2); duration1.plus(duration2); } void runTest(DatumDependentDuration duration1, TimeDatumDependentDuration duration2) { runTest((BaseDuration)duration1, duration2); duration1.plus(duration2); } void runTest(FuzzedDataProvider data) { runTest(new Duration(days[0], hours[0], minutes[0], seconds[0], millis[0]), new Duration(days[1], hours[1], minutes[1], seconds[1], millis[1])); runTest(new TimeDuration(days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDuration(days[1], hours[1], minutes[1], seconds[1], millis[1])); runTest(new DatumDependentDuration(years[0], months[0],days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDuration(days[1], hours[1], minutes[1], seconds[1], millis[1])); runTest(new DatumDependentDuration(years[0], months[0],days[0], hours[0], minutes[0], seconds[0], millis[0]), new TimeDatumDependentDuration(years[1], months[1], days[1], hours[1], minutes[1], seconds[1], millis[1])); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { DurationFuzzer testClosure = new DurationFuzzer(data); testClosure.runTest(data); } } ================================================ FILE: projects/groovy/TestFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium; import groovy.test.*; import junit.framework.AssertionFailedError; import static groovy.test.GroovyAssert.shouldFail; import java.util.Arrays; import groovy.lang.*; class MyObject { boolean a, b; MyObject(boolean a, boolean b) { this.a = a; this.b = b; } public boolean equals(Object anotherObject) { MyObject other = (MyObject) anotherObject; if (a != other.a) { return false; } if (b != other.b) { return false; } return true; } } class MyClosure extends Closure { boolean shouldFail; MyClosure(FuzzedDataProvider data) { super(null); shouldFail = data.consumeBoolean(); } public Object doCall(Object args) { if (shouldFail) { Object x = null; x.hashCode(); } return null; } } public class TestFuzzer extends GroovyTestCase { public TestFuzzer(FuzzedDataProvider data) { } MyObject getObject(FuzzedDataProvider data) { return new MyObject(data.consumeBoolean(), data.consumeBoolean()); } MyClosure getClosure(FuzzedDataProvider data) { return new MyClosure(data); } void printPos() { try { throw new Exception(); } catch (Exception e) { e.printStackTrace(System.out); } } void assertLengthArrayTest(FuzzedDataProvider data) { var n = data.consumeInt(); var intArray = new int[] { data.consumeInt(), data.consumeInt() }; boolean wasEqual; boolean equal = (n == intArray.length); try { assertLength(n, intArray); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertLength mismatch not detected"); } } void assertLengthArrayTestTwo(FuzzedDataProvider data) { var length = data.consumeInt(); var intArray = new int[data.consumeInt(1, 10)]; boolean wasEqual; boolean equal = (length == intArray.length); try { assertLength(length, intArray); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertLength mismatch not detected"); } } void assertLengthCharTest(FuzzedDataProvider data) { var n = data.consumeInt(); var charArray = new char[] { data.consumeChar(), data.consumeChar() }; boolean wasEqual; boolean equal = (n == charArray.length); try { assertLength(n, charArray); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertLength mismatch not detected"); } } void assertLengthObjectTest(FuzzedDataProvider data) { var length = data.consumeInt(); var objectArray = new MyObject[] { getObject(data), getObject(data) }; boolean wasEqual; boolean equal = (length == objectArray.length); try { assertLength(length, objectArray); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertObjectLength mismatch not detected"); } } void assertEqualsStringTest(FuzzedDataProvider data) { var actual = data.consumeString(1000); var expected = data.consumeString(1000); boolean wasEqual; boolean equal = (actual.equals(expected)); try { assertEquals(actual, expected); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertEqual mismatch not detected"); } } void assertEqualsObjectWithMessageTest(FuzzedDataProvider data) { var message = data.consumeString(100); var actual = getObject(data); var expected = getObject(data); boolean wasEqual; boolean equal = (actual.equals(expected)); try { assertEquals(message, actual, expected); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("Object mismatch not detected."); } } void assertEqualsObjectTest(FuzzedDataProvider data) { var actual = getObject(data); var expected = getObject(data); boolean wasEqual; boolean equal = (actual.equals(expected)); try { assertEquals(actual, expected); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("Object mismatch not detected."); } } void assertObjectEqualsTest(FuzzedDataProvider data) { var expected = getObject(data); var actual = getObject(data); boolean wasEqual; boolean equal = (expected.equals(actual)); try { assertEquals(expected, actual); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertEquals mismatch not detected"); } } void assertObjectArrayEqualsTest(FuzzedDataProvider data) { var expected = new MyObject[] { getObject(data), getObject(data) }; var actual = new MyObject[] { getObject(data), getObject(data) }; boolean wasEqual; boolean equal = (Arrays.equals(expected, actual)); try { assertArrayEquals(expected, actual); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertObjectArrayEquals mismatch not detected"); } } void assertInspectTest(FuzzedDataProvider data) { var value = getObject(data); var expected = data.consumeString(100); boolean wasEqual; boolean equal = (value.toString() == expected); try { assertInspect(value, expected); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertInspect mismatch not detected"); } } void shouldFailTest(FuzzedDataProvider data) { MyClosure c = new MyClosure(data); boolean hasFailed; try { shouldFail(c); hasFailed = true; } catch (AssertionError er) { hasFailed = false; } if (c.shouldFail != hasFailed) { throw new FuzzerSecurityIssueMedium("failure not detected"); } } void shouldFailClassCLosureTest(FuzzedDataProvider data) { MyClosure c = new MyClosure(data); boolean hasFailed; try { shouldFail(NullPointerException.class, c); hasFailed = true; } catch (AssertionError er) { hasFailed = false; } if (c.shouldFail != hasFailed) { throw new FuzzerSecurityIssueMedium("failure not detected"); } } void shouldFailWithCauseTest(FuzzedDataProvider data) { MyClosure c = new MyClosure(data); boolean hasFailed; try { shouldFailWithCause(NullPointerException.class, c); hasFailed = true; } catch (AssertionError er) { hasFailed = false; } if (c.shouldFail != hasFailed) { throw new FuzzerSecurityIssueMedium("failure not detected"); } } void shouldFailStringTest(FuzzedDataProvider data) { try { shouldFail(data.consumeString(1000)); } catch (AssertionError er) { } } void assertToStringTest(FuzzedDataProvider data) { var value = getObject(data); var expected = data.consumeString(100); boolean wasEqual; boolean equal = (value.toString() == expected); try { assertToString(value, expected); wasEqual = true; } catch (AssertionFailedError er) { wasEqual = false; } if (equal != wasEqual) { throw new FuzzerSecurityIssueMedium("assertToString mismatch not detected"); } } void runFuzzerTest(FuzzedDataProvider data) { assertObjectArrayEqualsTest(data); assertObjectEqualsTest(data); try { assertContains(data.consumeChar(), new char[] { data.consumeChar(), data.consumeChar() }); } catch (AssertionFailedError er) { /* documented ignore */ } try { assertContains(data.consumeInt(), new int[] { data.consumeInt(), data.consumeInt() }); } catch (AssertionFailedError er) { /* documented ignore */ } assertEqualsObjectWithMessageTest(data); assertEqualsObjectTest(data); assertEqualsStringTest(data); assertInspectTest(data); assertLengthCharTest(data); assertLengthArrayTest(data); assertLengthArrayTestTwo(data); assertLengthObjectTest(data); assertToStringTest(data); try { fixEOLs(data.consumeString(1000)); } catch (AssertionFailedError er) { /* documented ignore */ } try { getMethodName(); } catch (AssertionFailedError er) { /* documented ignore */ } try { getName(); } catch (AssertionFailedError er) { /* documented ignore */ } try { getTestClassName(); } catch (AssertionFailedError er) { /* documented ignore */ } try { notYetImplemented(getObject(data)); } catch (Exception er) { /* documented ignore */ } try { assertScript(data.consumeString(1000)); } catch (Exception er) { /* documented ignore */ } try { notYetImplemented(); } catch (AssertionError er) { /* documented ignore */ } shouldFailTest(data); shouldFailStringTest(data); try { shouldFail(NullPointerException.class, data.consumeString(100)); } catch (AssertionError er) { /* documented ignore */ } shouldFailClassCLosureTest(data); shouldFailWithCauseTest(data); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { TestFuzzer testClosure = new TestFuzzer(data); testClosure.runFuzzerTest(data); } } ================================================ FILE: projects/groovy/add-shadow-to-test.diff ================================================ diff --git a/subprojects/groovy-test/build.gradle b/subprojects/groovy-test/build.gradle index 655944cb0b..604a54a9da 100644 --- a/subprojects/groovy-test/build.gradle +++ b/subprojects/groovy-test/build.gradle @@ -17,6 +17,7 @@ * under the License. */ plugins { + id 'com.github.johnrengelman.shadow' version '7.1.2' id 'org.apache.groovy-library' } ================================================ FILE: projects/groovy/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ALL_JARS="" pushd "${SRC}/groovy" ./gradlew shadowJar --info JAR_PATH=$(find ./build/libs/ -name "groovy-*.jar" | head -n 1) if [[ -f $JAR_PATH ]]; then cp -v "$JAR_PATH" "$OUT/groovy.jar" ALL_JARS="${ALL_JARS} groovy.jar" else echo "Error: No JAR file found in ./build/libs/" exit 1 fi if ls ./subprojects/groovy-test/build/libs/groovy-test-*-SNAPSHOT-all.jar 1> /dev/null 2>&1; then cp -v ./subprojects/groovy-test/build/libs/groovy-test-*-SNAPSHOT-all.jar "$OUT/groovy-test.jar" ALL_JARS="${ALL_JARS} groovy-test.jar" else echo "Error: ./subprojects/groovy-test/build/libs/groovy-test-*-SNAPSHOT-all.jar not found" exit 1 fi popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java cp $SRC/*.class $OUT/ for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/groovy/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://groovy-lang.org/ language: jvm main_repo: https://github.com/apache/groovy.git sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/grpc-gateway/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go ENV GO111MODULE on RUN git clone https://github.com/grpc-ecosystem/grpc-gateway COPY build.sh $SRC/ WORKDIR $SRC/grpc-gateway ================================================ FILE: projects/grpc-gateway/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule Fuzz fuzz gofuzz ================================================ FILE: projects/grpc-gateway/project.yaml ================================================ homepage: "https://github.com/grpc-ecosystem/grpc-gateway" primary_contact: "grpc-gateway-maintainers@googlegroups.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/grpc-ecosystem/grpc-gateway' ================================================ FILE: projects/grpc-go/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone https://github.com/grpc/grpc-go RUN git clone --depth 1 https://github.com/grpc/grpc-go $GOPATH/src/google.golang.org/grpc COPY build.sh fuzz_*.go $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/grpc-go/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/fuzz*.go $GOPATH/src/google.golang.org/grpc/examples/ # seems needed to build the targets with the golang modules... cd $GOPATH/src/google.golang.org/grpc/examples/ compile_go_fuzzer google.golang.org/grpc/examples FuzzHelloClient fuzz_helloclient compile_go_fuzzer google.golang.org/grpc/examples FuzzHelloServer fuzz_helloserver ================================================ FILE: projects/grpc-go/fuzz_hello.go ================================================ package grpc_hello_fuzz import ( "context" "log" "net" "time" "google.golang.org/grpc" pb "google.golang.org/grpc/examples/helloworld/helloworld" ) var initialized = 0 type server struct { pb.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { log.Printf("Received: %v", in.GetName()) return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil } func FuzzHelloServer(data []byte) int { if initialized == 0 { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Printf("failed to listen: %v\n", err) return 0 } s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) // start server as a separate goroutine go func() { if err := s.Serve(lis); err != nil { log.Printf("failed to serve: %v\n", err) } }() initialized = 1 } conn, err := net.Dial("tcp", "localhost:50051") if err != nil { log.Printf("failed to dial: %v\n", err) return 0 } conn.Write(data) response := make([]byte, 1+len(data)) n, err := conn.Read(response) conn.Close() if err != nil || n == 0 { return 0 } return 1 } var fuzzdata []byte func FuzzHelloClient(data []byte) int { if len(data) == 0 { return 0 } if initialized == 0 { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Printf("failed to listen: %v\n", err) return 0 } go func() { for { conn, err := lis.Accept() if err != nil { log.Printf("did not accept: %v", err) break } conn.SetDeadline(time.Now().Add(time.Millisecond * 100)) request := make([]byte, 24) n, err := conn.Read(request) if err != nil || n == 0 { log.Printf("did not read: %v", err) conn.Close() break } n, err = conn.Write(fuzzdata) if err != nil || n == 0 { log.Printf("did not write: %v", err) } conn.Close() } }() initialized = 1 } fuzzdata = data // Set up a connection to the server. ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*10) defer cancel() conn, err := grpc.DialContext(ctx, "localhost:50051", grpc.WithInsecure(), grpc.WithBlock()) if err != nil { return 0 } defer conn.Close() c := pb.NewGreeterClient(conn) // Contact the server and print out its response. r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "world"}) if err != nil { return 0 } r.GetMessage() return 1 } ================================================ FILE: projects/grpc-go/project.yaml ================================================ homepage: "https://grpc.io/" primary_contact: "menghanl@google.com" auto_ccs: - "dfawley@google.com" - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/grpc/grpc-go' ================================================ FILE: projects/grpc-httpjson-transcoding/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Todo: unpin to support llvm 22 FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04@sha256:d34b94e3cf868e49d2928c76ddba41fd4154907a1a381b3a263fafffb7c3dce0 MAINTAINER nareddyt@google.com RUN apt-get update && apt-get install python3 -y RUN git clone https://github.com/grpc-ecosystem/grpc-httpjson-transcoding.git WORKDIR $SRC/grpc-httpjson-transcoding/ COPY build.sh $SRC/ ================================================ FILE: projects/grpc-httpjson-transcoding/build.sh ================================================ #!/bin/bash -eu # # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This project uses bazel rules_fuzzing. bazel_build_fuzz_tests ================================================ FILE: projects/grpc-httpjson-transcoding/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding" main_repo: "https://github.com/grpc-ecosystem/grpc-httpjson-transcoding.git" language: c++ primary_contact: "nareddyt@google.com" auto_ccs: - "yangshuo@google.com" - "taoxuy@google.com" - "qiwzhang@google.com" - "justinmp@google.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory ================================================ FILE: projects/grpc-py/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt install python3-dev libssl-dev libre2-dev -y RUN git clone https://github.com/grpc/grpc grpc && \ cd grpc && \ git submodule update --init WORKDIR grpc COPY build.sh *.py $SRC/ ================================================ FILE: projects/grpc-py/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install --upgrade pip pip3 install -r ./requirements.txt GRPC_PYTHON_CFLAGS="${CFLAGS}" GRPC_PYTHON_BUILD_SYSTEM_RE2=true GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=true GRPC_PYTHON_BUILD_SYSTEM_ZLIB=true pip3 install -v . # Install grpcio_status cd src/python/grpcio_status pip3 install . cd $SRC/grpc/examples/python/helloworld for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data helloworld_pb2.py:. --add-data helloworld_pb2_grpc.py:. done ================================================ FILE: projects/grpc-py/fuzz_server.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Fuzz grpc server using the Greeter example""" import os import sys import time import grpc from google.protobuf import any_pb2 from google.rpc import status_pb2 from grpc_status import rpc_status import socket import atheris import threading import argparse from concurrent.futures import ThreadPoolExecutor from google.protobuf.internal import builder as _builder # Extract path of fuzzer so we can include protobuf modules if getattr(sys, 'frozen', False): app_path = os.path.dirname(sys.executable) elif __file__: app_path = os.path.dirname(__file__) else: raise Exception("Could not extract path needed to import loop.py") sys.path.append(app_path) import helloworld_pb2 import helloworld_pb2_grpc runs_left = None server = None # Simple server class FuzzGreeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): print("In server") return helloworld_pb2.HelloReply(message='Hello from fuzz server, %s!' % request.name) def serve() -> None: """Starts fuzz server""" global server server = grpc.server(ThreadPoolExecutor(max_workers=1)) helloworld_pb2_grpc.add_GreeterServicer_to_server(FuzzGreeter(), server) server.add_insecure_port('[::]:50051') server.start() #server.wait_for_termination() return @atheris.instrument_func def TestInput(input_bytes): """Send fuzzing input to the server""" global runs_left global server if runs_left != None: runs_left = runs_left - 1 if runs_left <= 2: server.stop() return time.sleep(0.02) try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect(("localhost", 50051)) s.sendall(input_bytes) data = s.recv(1024) except OSError: # We don't want to report network errors return # Hit the rpc_status too fdp = atheris.FuzzedDataProvider(input_bytes) try: rich_status = status_pb2.Status( code=fdp.ConsumeIntInRange(1,30000), message=fdp.ConsumeUnicodeNoSurrogates(60) ) rpc_status.to_status(rich_status) except ValueError: pass return def get_run_count_if_there(): """Ensure proper exit for coverage builds""" parser = argparse.ArgumentParser() parser.add_argument("-atheris_runs", required=False, default=None) args, _ = parser.parse_known_args() if args.atheris_runs is None: print("None args") return None print(f"Got a fixed set of runs {args.atheris_runs}") return args.atheris_runs def main(): global runs_left max_runs = get_run_count_if_there() if max_runs is not None: runs_left = int(max_runs) # Launch a grpc server serve() # Start fuzzing atheris.instrument_all() atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/grpc-py/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/grpc/grpc primary_contact: "j.belleville.richard@gmail.com" language: python main_repo: https://github.com/grpc/grpc sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/grpc-swift/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-swift # specific to project RUN apt-get update && apt-get install -y zlib1g-dev RUN git clone --depth 1 https://github.com/grpc/grpc-swift COPY build.sh $SRC WORKDIR $SRC/grpc-swift ================================================ FILE: projects/grpc-swift/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ . precompile_swift # build project cd FuzzTesting swift build -c debug $SWIFTFLAGS ( cd .build/debug/ find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-debug; done ) swift build -c release $SWIFTFLAGS ( cd .build/release/ find . -maxdepth 1 -type f -name "*Fuzzer" -executable | while read i; do cp $i $OUT/"$i"-release; done ) ================================================ FILE: projects/grpc-swift/project.yaml ================================================ homepage: "https://github.com/grpc/grpc-swift" language: swift primary_contact: "gbarnett@apple.com" auto_ccs : - "lukasa@apple.com" - "pp_adams@apple.com" - "p.antoine@catenacyber.fr" fuzzing_engines: - libfuzzer sanitizers: - address - thread main_repo: 'https://github.com/grpc/grpc-swift' ================================================ FILE: projects/gson/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget openjdk-17-jdk RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/gson gson WORKDIR gson COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/gson/FuzzParse.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.*; import com.google.gson.*; public class FuzzParse { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JsonParser.parseString(data.consumeRemainingAsString()); } catch (JsonParseException expected) { } } } ================================================ FILE: projects/gson/FuzzReader.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.*; import com.google.gson.*; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; public class FuzzReader { public static void fuzzerTestOneInput(FuzzedDataProvider data) { TypeAdapter adapter = new Gson().getAdapter(JsonElement.class); boolean lenient = data.consumeBoolean(); JsonReader reader = new JsonReader(new StringReader(data.consumeRemainingAsString())); reader.setLenient(lenient); try { while (reader.peek() != JsonToken.END_DOCUMENT) { adapter.read(reader); } } catch (JsonParseException | IllegalStateException | NumberFormatException | IOException expected) { } } } ================================================ FILE: projects/gson/FuzzStreamParser.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.*; import com.google.gson.*; public class FuzzStreamParser { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JsonStreamParser parser = new JsonStreamParser(data.consumeRemainingAsString()); JsonElement element; while (parser.hasNext() == true) { // We do not catch NoSuchElementException here as we // have just checked an element exists. element = parser.next(); } } catch (JsonParseException expected) { } } } ================================================ FILE: projects/gson/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export JAVA_HOME="$OUT/open-jdk-17" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-17-openjdk-amd64/" "$JAVA_HOME" # Skip ProGuard because it is only needed for tests (which are skipped as well) and # because it would fail since `jmods` JDK folder is removed from this Docker image MAVEN_ARGS="-DskipTests -Dproguard.skip" # Only build 'gson' Maven module cd gson $MVN --batch-mode --update-snapshots package ${MAVEN_ARGS} cd .. find ./gson -name "gson-*.jar" -exec mv {} $OUT/gson.jar \; ALL_JARS="gson.jar" BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name 'Fuzz*.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-17/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-17/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/gson/project.yaml ================================================ homepage: "https://github.com/google/gson" language: jvm primary_contact: "emcmanus@google.com" main_repo: "https://github.com/google/gson" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address file_github_issue: True ================================================ FILE: projects/gss-ntlmssp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ autoconf \ docbook-xsl \ gettext \ libkrb5-dev \ libtool \ libunistring-dev \ libxml2-utils \ make \ xsltproc \ zlib1g-dev RUN git clone --depth 1 https://github.com/gssapi/gss-ntlmssp COPY *.sh $SRC/ COPY fuzzing/ $SRC/gss-ntlmssp/fuzzing/ WORKDIR $SRC/gss-ntlmssp/ ================================================ FILE: projects/gss-ntlmssp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ autoreconf -f -i ./configure --disable-shared --enable-static --without-wbclient make -j$(nproc) pushd fuzzing/ make fuzzer cp fuzz-accept-sec-context $OUT/ cp fuzz-accept-sec-context.dict $OUT/ popd ================================================ FILE: projects/gss-ntlmssp/fuzzing/Makefile ================================================ all: fuzzer fuzzer: $(CC) $(CFLAGS) $(EXTCFLAGS) -I../include -I../src -c fuzz-accept-sec-context.c $(CXX) $(CFLAGS) -o fuzz-accept-sec-context fuzz-accept-sec-context.o ../.libs/gssntlmssp.a $(LIB_FUZZING_ENGINE) -lssl -lcrypto -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lunistring -lz ================================================ FILE: projects/gss-ntlmssp/fuzzing/fuzz-accept-sec-context.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include "gss_ntlmssp.h" extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { OM_uint32 maj_stat, min_stat; gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_name_t client_name = GSS_C_NO_NAME; gss_cred_id_t deleg_cred = GSS_C_NO_CREDENTIAL; /* Each fuzz input contains multiple tokens preceded by a length field. * Process them in turn with gss_accept_sec_context while * GSS_S_CONTINUE_NEEDED is set */ do { unsigned short token_length; gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; if (Size < sizeof(token_length)) break; token_length = *(unsigned short *)Data; Data += sizeof(token_length); Size -= sizeof(token_length); if (token_length == 0 || token_length > Size) break; input_token.length = token_length; input_token.value = malloc(token_length); memcpy(input_token.value, Data, token_length); Data += token_length; Size -= token_length; maj_stat = gssntlm_accept_sec_context( &min_stat, &ctx, GSS_C_NO_CREDENTIAL, /* server_creds */ &input_token, GSS_C_NO_CHANNEL_BINDINGS, /* input_bindings */ &client_name, NULL, /* mech_type */ &output_token, NULL, /* ret_flags */ NULL, /* time */ &deleg_cred ); gss_release_buffer(&min_stat, &input_token); gss_release_buffer(&min_stat, &output_token); } while(maj_stat == GSS_S_CONTINUE_NEEDED); gss_release_name(&min_stat, &client_name); gss_release_cred(&min_stat, &deleg_cred); gss_delete_sec_context(&min_stat, &ctx, GSS_C_NO_BUFFER); return 0; } ================================================ FILE: projects/gss-ntlmssp/fuzzing/fuzz-accept-sec-context.dict ================================================ "BAR\\foo" "foo@BAR" "foo\\@bar.example.com" "foo\\@bar.example.com@BAR" "\\foo@bar.example.com" "BAR\\foo@bar.example.com" "BAR@dom\\foo@bar.example.com" ================================================ FILE: projects/gss-ntlmssp/project.yaml ================================================ homepage: "https://github.com/gssapi/gss-ntlmssp" language: c primary_contact: "ssorce@redhat.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: "https://github.com/gssapi/gss-ntlmssp" ================================================ FILE: projects/gss-ntlmssp/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### make check ================================================ FILE: projects/gstreamer/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y make autoconf automake libtool build-essential pkg-config bison flex patchelf RUN pip3 install --disable-pip-version-check --no-cache-dir \ pip==25.1.1 RUN pip3 install --disable-pip-version-check --no-cache-dir \ corpus-replicator \ meson==1.8.2 \ ninja==1.11.1.4 RUN git clone --depth 1 https://gitlab.xiph.org/xiph/vorbis.git vorbis RUN git clone --depth 1 https://gitlab.xiph.org/xiph/ogg.git ogg RUN git clone --depth 1 https://gitlab.xiph.org/xiph/theora.git theora # Checkout repository RUN git clone --depth 1 --recursive https://gitlab.freedesktop.org/gstreamer/gstreamer.git gstreamer WORKDIR gstreamer COPY build.sh $SRC/ ================================================ FILE: projects/gstreamer/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # gstreamer requires autoconf 2.71 minimum which is not available in the Ubuntu 20 base image # Skip this step if a newer base image is used if grep -q -F "20.04" /etc/os-release ; then cd /tmp wget https://archive.ubuntu.com/ubuntu/pool/main/a/autoconf/autoconf_2.71-2_all.deb # Ensure file is not modified or corrupted before install if echo "96b528889794c4134015a63c75050f93d8aecdf5e3f2a20993c1433f4c61b80e autoconf_2.71-2_all.deb" | sha256sum --check --status ; then # Install but use G option to prevent downgrade in case this is dpkg -i -G /tmp/autoconf_2.71-2_all.deb fi fi $SRC/gstreamer/ci/fuzzing/build-oss-fuzz.sh ================================================ FILE: projects/gstreamer/project.yaml ================================================ homepage: "https://gstreamer.freedesktop.org/" language: c++ primary_contact: "gstreamer-security@lists.freedesktop.org" auto_ccs: - "bilboed@bilboed.com" - "tim@centricular.com" - "slomo@coaxion.net" - "mduponchelle1@gmail.com" - "saunierthibault@gmail.com" - "ystreet00@gmail.com" - "thaytan@noraisin.net" - "adam@adalogics.com" - "arthur.chan@adalogics.com" - "david@adalogics.com" main_repo: 'https://gitlab.freedesktop.org/gstreamer/gstreamer.git' fuzzing_engines: - honggfuzz - libfuzzer ================================================ FILE: projects/guava/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/guava COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/guava ================================================ FILE: projects/guava/HashingFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.hash.HashCode; import com.google.common.hash.Hasher; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; import java.lang.IllegalStateException; public class HashingFuzzer { public static class HashInputData { public HashInputData(FuzzedDataProvider fuzzedDataProvider) { m_bool = fuzzedDataProvider.consumeBoolean(); m_bytes = fuzzedDataProvider.consumeBytes(2); m_char = fuzzedDataProvider.consumeChar(); m_double = fuzzedDataProvider.consumeDouble(); m_float = fuzzedDataProvider.consumeFloat(); m_int = fuzzedDataProvider.consumeInt(); m_long = fuzzedDataProvider.consumeLong(); m_short = fuzzedDataProvider.consumeShort(); m_string = fuzzedDataProvider.consumeRemainingAsString(); } public boolean getBoolean() { return m_bool; } public byte getByte() { return (m_bytes.length > 0) ? m_bytes[0] : (byte)m_int; } public byte[] getBytes() { return m_bytes; } public char getChar() { return m_char; } public double getDouble() { return m_double; } public float getFloat() { return m_float; } public int getInt() { return m_int; } public long getLong() { return m_long; } public short getShort() { return m_short; } public String getString() { return m_string; } private boolean m_bool; private byte m_bytes[]; private char m_char; private double m_double; private float m_float; private int m_int; private long m_long; private short m_short; private String m_string; } private static void testHashCode(HashCode hc) { try { hc.bits(); try { int i = hc.asInt(); HashCode.fromInt(i); } catch (IllegalStateException ise) { /* documented, ignore */ } try { long l = hc.asLong(); HashCode.fromLong(l); } catch (IllegalStateException ise) { /* documented, ignore */ } hc.padToLong(); byte[] bytes = hc.asBytes(); hc.writeBytesTo(bytes,0,bytes.length); HashCode.fromBytes(bytes); String s = hc.toString(); HashCode.fromString(s); hc.hashCode(); } catch (IllegalArgumentException e) { /* ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } private static void testHash(HashFunction hash, HashInputData hashInputData) { HashCode hc = null; try { Hasher h = hash.newHasher(); h.putBoolean(hashInputData.getBoolean()); h.putByte(hashInputData.getByte()); h.putBytes(hashInputData.getBytes()); h.putChar(hashInputData.getChar()); h.putDouble(hashInputData.getDouble()); h.putFloat(hashInputData.getFloat()); h.putInt(hashInputData.getInt()); h.putLong(hashInputData.getLong()); h.putShort(hashInputData.getShort()); h.putUnencodedChars(hashInputData.getString()); hc = h.hash(); } catch (IllegalArgumentException e) { /* ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } if (hc != null) { testHashCode(hc); } /* * fromString documents it accepts only well-formated input, * but doesn't document what it does when ill-formated input * is provided. Feed it some fuzz data and find out. */ try { HashCode.fromString(hashInputData.getString()); } catch (IllegalArgumentException e) { /* ignore */ } catch(Exception e) { e.printStackTrace(System.out); throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { // Choose realistic and valid minimumBits value; this is normally not controlled by the user int minimumBits = fuzzedDataProvider.consumeInt(1, 8192); int seed = fuzzedDataProvider.consumeInt(); int k0 = fuzzedDataProvider.consumeInt(); int k1 = fuzzedDataProvider.consumeInt(); HashInputData hashInputData = new HashInputData(fuzzedDataProvider); /* * testHash handles exceptions itself, so this try-block * only catches exceptions thrown by Hashing's "factory" * functions, none of which is documented to throw * exceptions. */ try { testHash(Hashing.adler32(), hashInputData); testHash(Hashing.crc32(), hashInputData); testHash(Hashing.crc32c(), hashInputData); testHash(Hashing.farmHashFingerprint64(), hashInputData); testHash(Hashing.goodFastHash(minimumBits), hashInputData); testHash(Hashing.murmur3_128(), hashInputData); testHash(Hashing.murmur3_128(seed), hashInputData); testHash(Hashing.murmur3_32(), hashInputData); testHash(Hashing.murmur3_32(seed), hashInputData); testHash(Hashing.md5(), hashInputData); testHash(Hashing.sha1(), hashInputData); testHash(Hashing.sha256(), hashInputData); testHash(Hashing.sha384(), hashInputData); testHash(Hashing.sha512(), hashInputData); testHash(Hashing.sipHash24(), hashInputData); testHash(Hashing.sipHash24(k0, k1), hashInputData); } catch (IllegalArgumentException e) { /* ignore */ } catch (Exception e) { e.printStackTrace(System.out); throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/guava/HostAndPortFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.net.HostAndPort; import java.lang.IllegalArgumentException; public class HostAndPortFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { HostAndPort hap = HostAndPort.fromString(data.consumeRemainingAsString()); } catch (IllegalArgumentException e) { /* documented to be thrown, ignore */ } catch (Exception e) { e.printStackTrace(System.out); throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/guava/HostSpecifierFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.net.HostSpecifier; import java.text.ParseException; public class HostSpecifierFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { HostSpecifier hs = HostSpecifier.from(data.consumeRemainingAsString()); /* * hs.toString() is a valid string, as otherwise the * HostSpecifier.from() invocation to initialize hs * would have thrown an exception. */ if (! HostSpecifier.isValid(hs.toString())) { throw new FuzzerSecurityIssueLow("toString() generated a poor host specifier"); } hs.hashCode(); } catch (ParseException e) { /* documented to be thrown, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/guava/InetAddressesFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.net.InetAddresses; import java.lang.IllegalArgumentException; import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.UnknownHostException; public class InetAddressesFuzzer { private static void testInet6ApiSpecificMethods(InetAddress inaddr) { Inet6Address inet6 = null; if ((inaddr != null) && (inaddr instanceof Inet6Address)) { inet6 = (Inet6Address)inaddr; } if (inet6 != null) { try { InetAddresses.getEmbeddedIPv4ClientAddress(inet6); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } try { InetAddresses.TeredoInfo teredoInfo = InetAddresses.getTeredoInfo(inet6); teredoInfo.getServer(); teredoInfo.getClient(); teredoInfo.getPort(); teredoInfo.getFlags(); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } try { InetAddresses.getCoercedIPv4Address(inet6); } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { InetAddress in6 = null; InetAddress in4 = null; try { in6 = InetAddresses.fromLittleEndianByteArray(data.consumeBytes(16)); in4 = InetAddresses.fromLittleEndianByteArray(data.consumeBytes(4)); } catch (UnknownHostException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } testInet6ApiSpecificMethods(in6); String value = data.consumeRemainingAsString(); InetAddress addr = null, uriAddr = null; try { uriAddr = InetAddresses.forUriString(value); addr = InetAddresses.forString(value); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } /* * These don't throw exceptions. */ try { InetAddresses.isInetAddress(value); InetAddresses.isUriInetAddress(value); InetAddresses.isMappedIPv4Address(value); InetAddresses.isMappedIPv4Address(value); } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } if (addr != null) { /* * These don't throw exceptions, either, but need a valid * InetAddress instance. */ try { InetAddresses.toUriString(addr); InetAddresses.toAddrString(addr); InetAddresses.coerceToInteger(addr); } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } try { InetAddresses.increment(addr); InetAddresses.decrement(addr); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } try { InetAddresses.fromIPv6BigInteger(InetAddresses.toBigInteger(addr)); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } try { InetAddresses.fromIPv4BigInteger(InetAddresses.toBigInteger(addr)); } catch (IllegalArgumentException e) { /* documented, ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } } ================================================ FILE: projects/guava/InternetDomainNameFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.net.InternetDomainName; import java.lang.IllegalArgumentException; import java.lang.IllegalStateException; public class InternetDomainNameFuzzer { private static void testAccessorMethods(InternetDomainName idn) { idn.parts(); idn.isPublicSuffix(); idn.hasPublicSuffix(); idn.publicSuffix(); idn.isUnderPublicSuffix(); idn.isTopPrivateDomain(); try { idn.topPrivateDomain(); } catch(IllegalStateException e) { /* documented, ignore */ } idn.isRegistrySuffix(); idn.hasRegistrySuffix(); idn.registrySuffix(); idn.isUnderRegistrySuffix(); idn.isTopDomainUnderRegistrySuffix(); try { idn.topDomainUnderRegistrySuffix(); } catch(IllegalStateException e) { /* documented, ignore */ } idn.hasParent(); try { idn.parent(); } catch(IllegalStateException e) { /* documented, ignore */ } idn.hashCode(); } public static void testChild(InternetDomainName idn, String leftParts) { try { idn.child(leftParts); } catch(IllegalArgumentException e) { /* documented, ignore */ } catch(NullPointerException e) { /* documented, ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider dataProvider) { try { InternetDomainName idn; try { idn = InternetDomainName.from(dataProvider.consumeString(dataProvider.remainingBytes())); } catch (IllegalArgumentException e) { /* * documented to be thrown, ignore */ return; } testAccessorMethods(idn); testChild(idn, dataProvider.consumeString(dataProvider.remainingBytes())); } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/guava/MediaTypeFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import com.google.common.net.MediaType; import java.lang.IllegalArgumentException; public class MediaTypeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String value = data.consumeRemainingAsString(); try { MediaType.create(value, value); MediaType.parse(value).type(); MediaType.create(value, value).withParameter(value, value); } catch (IllegalArgumentException e) { } } } ================================================ FILE: projects/guava/UrlEscapersFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.base.Charsets; import com.google.common.escape.Escaper; import com.google.common.net.PercentEscaper; import com.google.common.net.UrlEscapers; import java.lang.IllegalArgumentException; import java.net.URLDecoder; public class UrlEscapersFuzzer { /* * These constants are private members copy-pasted from * com.google.common.net.UrlEscapers. */ static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*"; static final String URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS = "-._~" // Unreserved characters. + "!$'()*,;&=" // The subdelim characters (excluding '+'). + "@:"; // The gendelim characters permitted in paths. private static boolean containsUnsafeCharacters(String string, String additionalSafeChars) { String safe = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /* * The percent character is always safe. */ safe += "%"; safe += additionalSafeChars; for (int i = 0; i < string.length(); ++i) { if (safe.indexOf(string.charAt(i)) < 0) { return true; } } return false; } public static void testUrlEscaper(Escaper escaper, String additionalSafeChars, String sample, boolean plusIsSpace) { String encoded = escaper.escape(sample); if (containsUnsafeCharacters(encoded, additionalSafeChars)) { throw new FuzzerSecurityIssueMedium("unsafe character was not escaped"); } String percentEncoded = encoded.replace("+", (plusIsSpace ? "%20" : "%2B")); String decoded = URLDecoder.decode(percentEncoded, Charsets.UTF_8); if (!decoded.equals(sample)) { throw new FuzzerSecurityIssueLow("escaped sequence not being decoded as expected"); } } private static void testPercentEncoderConstructor(String safe, boolean plusIsSpace) { try { new PercentEscaper(safe, plusIsSpace); } catch (IllegalArgumentException e) { /* documented, ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { boolean plusIsSpace = data.consumeBoolean(); String value = data.consumeRemainingAsString(); testPercentEncoderConstructor(value, plusIsSpace); testUrlEscaper(new PercentEscaper("", plusIsSpace), (plusIsSpace ? "+" : ""), value, plusIsSpace); testUrlEscaper(UrlEscapers.urlFormParameterEscaper(), URL_FORM_PARAMETER_OTHER_SAFE_CHARS + "+", value, true); testUrlEscaper(UrlEscapers.urlFragmentEscaper(), URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS + "+/?", value, false); testUrlEscaper(UrlEscapers.urlPathSegmentEscaper(), URL_PATH_OTHER_SAFE_CHARS_LACKING_PLUS + "+", value, false); } catch (IllegalArgumentException e) { /* ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/guava/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN install $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "guava/target/guava-$CURRENT_VERSION.jar" "$OUT/guava.jar" ALL_JARS="guava.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac -cp $BUILD_CLASSPATH ${SRC}/*.java install ${SRC}/*.class ${OUT}/ for fuzzer in $(find $SRC -name '*Fuzzer.java' -maxdepth 1); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/guava/project.yaml ================================================ homepage: "https://github.com/google/guava" language: jvm main_repo: "https://github.com/google/guava.git" fuzzing_engines: - libfuzzer sanitizers: - address primary_contact: "emcmanus@google.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/guetzli/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool libpng-dev pkg-config curl RUN mkdir afl-testcases RUN cd afl-testcases/ && curl https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz | tar -xz RUN zip guetzli_fuzzer_seed_corpus.zip afl-testcases/jpeg/full/images/* afl-testcases/jpeg_turbo/full/images/* $SRC/libjpeg-turbo/testimages/ RUN git clone --depth=1 https://github.com/google/guetzli guetzli WORKDIR guetzli COPY build.sh $SRC/ ================================================ FILE: projects/guetzli/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make guetzli_static $CXX $CXXFLAGS -std=c++11 -I. fuzz_target.cc $LIB_FUZZING_ENGINE \ -o $OUT/guetzli_fuzzer bin/Release/libguetzli_static.a cp $SRC/guetzli_fuzzer_seed_corpus.zip $OUT/ ================================================ FILE: projects/guetzli/project.yaml ================================================ homepage: "https://github.com/google/guetzli" language: c++ primary_contact: "robryk@google.com" auto_ccs: - "szabadka@google.com" sanitizers: - address - memory - undefined main_repo: 'https://github.com/google/guetzli' file_github_issue: True ================================================ FILE: projects/guice/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/guice COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/guice ================================================ FILE: projects/guice/InjectorFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.google.inject.*; import com.google.inject.internal.Annotations; import com.google.inject.internal.InternalFlags; import com.google.inject.matcher.Matchers; import com.google.inject.name.Named; import com.google.inject.CreationException; import com.google.inject.name.Names; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static com.google.inject.name.Names.named; import com.google.inject.ConfigurationException; import java.lang.annotation.Retention; import java.util.*; public class InjectorFuzzer { @Retention(RUNTIME) @BindingAnnotation @interface NumericValue {} @Retention(RUNTIME) @BindingAnnotation @interface EnumValue {} @Retention(RUNTIME) @BindingAnnotation @interface ClassName {} public enum Bar { TEE, BAZ, BOB } public static void fuzzerTestOneInput(FuzzedDataProvider data) { String value = data.consumeRemainingAsString(); try { Injector injector = Guice.createInjector( new AbstractModule() { @Override protected void configure() { bindConstant().annotatedWith(NumericValue.class).to(value); bindConstant().annotatedWith(EnumValue.class).to(value); bindConstant().annotatedWith(ClassName.class).to(value); } }); DummyClass foo = injector.getInstance(DummyClass.class); } catch (CreationException | ConfigurationException e) { } } public static class DummyClass { @Inject @EnumValue Bar enumField; @Inject @ClassName Class classField; @Inject @NumericValue Byte byteField; } } ================================================ FILE: projects/guice/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cat > patch.diff <<- EOM --- a/pom.xml 2022-05-05 09:49:53.028735612 +0200 +++ b/pom.xml 2022-05-05 09:49:30.445695122 +0200 @@ -120,7 +120,7 @@ | The last stable release version id, used for generating API diffs between released versions --> 7.0.0 - false + true true EOM git apply patch.diff cd core cat > patch2.diff <<- EOM --- a/pom.xml 2022-05-05 13:32:09.413975213 +0200 +++ b/pom.xml 2022-05-05 13:33:53.389402985 +0200 @@ -68,6 +68,24 @@ + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + jar-with-dependencies + + + + + + EOM git apply patch2.diff cd .. MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "core/target/guice-$CURRENT_VERSION-jar-with-dependencies.jar" "$OUT/guice.jar" ALL_JARS="guice.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --disabled_hooks=\"com.code_intelligence.jazzer.sanitizers.ReflectiveCall\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/guice/project.yaml ================================================ homepage: "https://github.com/google/guice" language: jvm main_repo: "https://github.com/google/guice.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/gunicorn/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/benoitc/gunicorn WORKDIR gunicorn COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/gunicorn/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install --upgrade pip pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/gunicorn/fuzz_util.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from gunicorn import util from gunicorn.errors import AppImportError def TestInput(data): fdp = atheris.FuzzedDataProvider(data) util.is_ipv6(fdp.ConsumeString(100)) util.warn(fdp.ConsumeString(100)) util.split_request_uri(fdp.ConsumeString(100)) try: util.parse_address(fdp.ConsumeString(100)) except RuntimeError as e: if "is not a valid port number." not in str(e): raise e try: util.http_date(fdp.ConsumeInt(50)) except OSError as e: if "Value too large for defined data type" not in str(e): raise e except (OverflowError,ValueError) as e: if "out of range" not in str(e): raise e try: util.to_bytestring(fdp.ConsumeString(100)) util.to_bytestring(fdp.ConsumeString(100),'ascii') except UnicodeEncodeError as e: if "codec can't encode character" not in str(e): raise e try: util.import_app(fdp.ConsumeString(100)) except (ValueError,ImportError,AppImportError) as e: error_list = [ "Empty module name", "No module", "Failed to parse", "Function reference", "literal values", "attribute name", "find attribute", "takes", "inner", "find application object", "callable" ] expected_error = False for error in error_list: if error in str(e): expected_error = True if not expected_error: raise e def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/gunicorn/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/benoitc/gunicorn language: python main_repo: https://github.com/benoitc/gunicorn sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/gwt/.gitignore ================================================ project-parent/gwt project-parent/tools project-parent/fuzz-targets/target project-parent/fuzz-targets/.cifuzz-corpus project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/gwt/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/json.dict $SRC/JsonArrayFuzzer.dict && \ cp fuzzing/dictionaries/json.dict $SRC/JsonObjectFuzzer.dict && \ cp fuzzing/dictionaries/js.dict $SRC/JsParserFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JsonArrayFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -j $SRC/JsonObjectFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/gwt RUN rm -rf $SRC/project-parent/tools RUN apt update && apt install -y openjdk-11-jdk RUN git clone --depth 1 https://github.com/gwtproject/gwt/ $SRC/project-parent/gwt RUN git clone --depth 1 https://github.com/gwtproject/tools/ $SRC/project-parent/tools COPY build.sh $SRC/ COPY pom.xml $SRC/project-parent/gwt WORKDIR $SRC/ ================================================ FILE: projects/gwt/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=gwt PROJECT_GROUP_ID=org.gwtproject PROJECT_ARTIFACT_ID=gwt-dev MAIN_REPOSITORY=https://github.com/gwtproject/gwt/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -Denforcer.skip=true -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT # build tools for gwt git -C tools pull || git clone https://github.com/gwtproject/tools/ tools set_project_version_in_fuzz_targets_dependency #install mvn -pl $PROJECT install -DskipTests mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT export JAVA_HOME="$OUT/open-jdk-11" mkdir -p $JAVA_HOME rsync -aL --copy-links --exclude=blacklisted.certs --exclude=*.zip "/usr/lib/jvm/java-11-openjdk-amd64/" "$JAVA_HOME" set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # dependency:build-classpath won't work for ant generated jars cp $SRC/project-parent/gwt/build/lib/gwt-dev.jar $OUT/ cp $SRC/project-parent/gwt/build/lib/gwt-user.jar $OUT/ ALL_JARS="gwt-dev.jar gwt-user.jar" # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes:$(echo $ALL_JARS | xargs printf -- "$OUT/%s:")" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent/fuzz-targets -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi this_dir=\$(dirname \"\$0\") JAVA_HOME=\"\$this_dir/open-jdk-11/\" \ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/gwt/pom.xml ================================================ 4.0.0 org.gwtproject gwt 1 gwt gwt 1.8 1.8 1.8 org.apache.maven.plugins maven-antrun-plugin 3.1.0 generate-jars install run ${project.basedir}/src/test/resources ================================================ FILE: projects/gwt/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 1.8 1.8 1.8 com.code-intelligence jazzer-junit 0.19.0 org.junit.platform junit-platform-launcher 1.9.2 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.gwtproject gwt-user 1.0 system ${basedir}/../gwt/build/lib/gwt-user.jar org.gwtproject gwt-dev 1.0 system ${basedir}/../gwt/build/lib/gwt-dev.jar maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/gwt/project-parent/fuzz-targets/src/test/java/com/example/JsParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.io.IOException; import java.io.StringReader; import com.google.gwt.dev.js.ast.JsBlock; import com.google.gwt.dev.js.ast.JsProgram; import com.google.gwt.dev.js.JsParser; import com.google.gwt.dev.js.JsParserException; import com.google.gwt.dev.js.ast.JsRootScope; import com.google.gwt.dev.jjs.SourceInfo; import com.google.gwt.dev.jjs.SourceOrigin; class JsParserFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { StringReader sr = new StringReader(data.consumeRemainingAsString()); try { JsProgram program = new JsProgram(); SourceInfo rootSourceInfo = program.createSourceInfo(1, data.consumeString(100)); JsBlock block = program.getGlobalBlock(); JsParser.parse(SourceOrigin.UNKNOWN, JsRootScope.INSTANCE, sr); JsParser.parseInto(rootSourceInfo, program.getScope(), block, sr); } catch (IOException | JsParserException e) { } catch (RuntimeException e) { // Need to catch this error in order to reach deeper states. } } } ================================================ FILE: projects/gwt/project-parent/fuzz-targets/src/test/java/com/example/JsonFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import java.io.IOException; import java.io.StringReader; import com.google.gwt.dev.json.JsonObject; import com.google.gwt.dev.json.JsonArray; import com.google.gwt.dev.json.JsonException; class JsonFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { StringReader sr = new StringReader(data.consumeRemainingAsString()); try { JsonObject.parse(sr); JsonArray.parse(sr); } catch (JsonException | IOException e) { } } } ================================================ FILE: projects/gwt/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom gwt fuzz-targets ================================================ FILE: projects/gwt/project.yaml ================================================ homepage: "https://www.gwtproject.org/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/gwtproject/gwt/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" run_tests: False ================================================ FILE: projects/h11/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/python-hyper/h11 h11 COPY *.sh *py $SRC/ WORKDIR $SRC/h11 ================================================ FILE: projects/h11/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/h11/fuzz_h11.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import h11 def fuzz_headers(data): fdp = atheris.FuzzedDataProvider(data) fuzz_headers = [(fdp.ConsumeBytes(32), fdp.ConsumeBytes(1024)), (fdp.ConsumeBytes(32), fdp.ConsumeBytes(1024))] try: normalized_headers = h11._headers.normalize_and_validate(fuzz_headers) get_comma_header(normalized_headers, b'connection') set_comma_header(normalized_headers, fdp.ConsumeBytes(64)) except (h11._util.ProtocolError): pass try: h11._headers.has_expect_100_continue( h11._events.Request(method='GET', target='/', headers=fuzz_headers, http_version='1.0')) except (h11._util.ProtocolError): pass def fuzz_receivebuffer(data): fdp = atheris.FuzzedDataProvider(data) rec_buf = h11._receivebuffer.ReceiveBuffer() for i in range(5): rec_buf += fdp.ConsumeBytes(124) rec_buf.maybe_extract_at_most(fdp.ConsumeIntInRange(1, 100)) rec_buf.maybe_extract_next_line() rec_buf.maybe_extract_lines() def fuzz_connection(data): fdp = atheris.FuzzedDataProvider(data) conn = h11.Connection(our_role=h11.CLIENT) event = h11.Request( method="GET", target="/get", headers=[("Host", "127.0.0.1"), ("Connection", "close")], ) conn.send(event) conn.send(h11.EndOfMessage()) conn.next_event() conn.receive_data(fdp.ConsumeBytes(1024)) try: event2 = h11.Request( method=fdp.ConsumeUnicodeNoSurrogates(5), target=fdp.ConsumeUnicodeNoSurrogates(124), headers=[(fdp.ConsumeUnicodeNoSurrogates(5), fdp.ConsumeUnicodeNoSurrogates(124)), (fdp.ConsumeUnicodeNoSurrogates(124), fdp.ConsumeUnicodeNoSurrogates(124))], ) conn.send(event2) conn.send(h11.EndOfMessage()) conn.next_event() conn.receive_data(fdp.ConsumeBytes(1024)) except (h11._util.ProtocolError): pass def TestOneInput(data): fuzz_headers(data) fuzz_receivebuffer(data) fuzz_connection(data) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/h11/project.yaml ================================================ homepage: https://github.com/python-hyper/h11 main_repo: https://github.com/python-hyper/h11 language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/h2database/CsvReadBackFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; import org.h2.tools.Csv; import org.h2.tools.SimpleResultSet; public class CsvReadBackFuzzer { static class TableContent { private static boolean contains(String haystack[], String needle, int n) { while (n-- > 0) { if (haystack[n].equals(needle)) { return true; } } return false; } public TableContent(FuzzedDataProvider fuzzedDataProvider) { m_columnCount = fuzzedDataProvider.consumeInt(1,4); m_rowCount = fuzzedDataProvider.consumeInt(1,100); m_headers = new String[getColumnCount()]; m_content = new String[getRowCount()][getColumnCount()]; for (int column = 0; column < getColumnCount(); ++column) { m_headers[column] = "C_" + column; } for (int row = 0; row < getRowCount(); ++row) { for (int column = 0; column < getColumnCount(); ++column) { if (row == 0) { m_content[row][column] = fuzzedDataProvider.consumeAsciiString(8); } else { m_content[row][column] = fuzzedDataProvider.consumeRemainingAsAsciiString(); } } } } public SimpleResultSet simpleResultSet() { SimpleResultSet rs = new SimpleResultSet(); for (int column = 0; column < getColumnCount(); ++column) { /* * VARCHAR(255) might be insufficient */ rs.addColumn(columnHeader(column), Types.VARCHAR, 255, 0); } for (int row = 0; row < getRowCount(); ++row) { rs.addRow(getRow(row)); } return rs; } public String columnHeader(int column) { return m_headers[column]; } public int getColumnCount() { return m_columnCount; } public int getRowCount() { return m_rowCount; } public Object[] getRow(int row) { return m_content[row]; } public String getCell(int row, int column) { return m_content[row][column]; } int m_columnCount; int m_rowCount; String m_headers[]; String m_content[][]; }; public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { TableContent data = new TableContent(fuzzedDataProvider); ByteArrayOutputStream outStream = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(outStream); try { new Csv().write(writer, data.simpleResultSet()); } catch (SQLException ex) { /* documented, ignore */ return; } ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray()); InputStreamReader reader = new InputStreamReader(inStream); ResultSet resultSet = null; try { resultSet = new Csv().read(reader, null); } catch (IOException e) { return; } try { ResultSetMetaData meta = resultSet.getMetaData(); if (meta.getColumnCount() != data.getColumnCount()) { throw new FuzzerSecurityIssueLow("Column Count Mismatch"); } for (int column = 0; column < meta.getColumnCount(); ++column) { String have = meta.getColumnLabel(column + 1); String want = data.columnHeader(column); if ( ! have.equals(want) ) { System.out.println("\'" + have + "\' != \'" + want + "\'"); throw new FuzzerSecurityIssueLow("Column Label Mismatch"); } } int row = 0; while (resultSet.next()) { for (int column = 0; column < meta.getColumnCount(); ++column) { String have = resultSet.getString(column + 1); String want = data.getCell(row, column); if ( ! have.equals( want ) ) { System.out.println("\'" + have + "\' != \'" + want + "\'"); throw new FuzzerSecurityIssueLow("Cell Value Mismatch"); } } ++row; } if (row != data.getRowCount()) { throw new FuzzerSecurityIssueLow("Row Count Mismatch"); } resultSet.close(); } catch (SQLException ex) { /* documented, but shouldn't happen on our well-known input */ ex.printStackTrace(System.out); throw new FuzzerSecurityIssueLow("SQLException??"); } } } ================================================ FILE: projects/h2database/CsvReadFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; import org.h2.tools.Csv; public class CsvReadFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { ByteArrayInputStream inStream = new ByteArrayInputStream(fuzzedDataProvider.consumeRemainingAsBytes()); InputStreamReader reader = new InputStreamReader(inStream); try { new Csv().read(reader, null); } catch (IOException e) { /* ignore */ } catch (Exception e) { throw new FuzzerSecurityIssueLow("Undocumented Exception"); } } } ================================================ FILE: projects/h2database/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/h2database/h2database.git COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/h2database ================================================ FILE: projects/h2database/ServerLoginFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.h2.tools.Server; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.PreparedStatement; public class ServerLoginFuzzer extends TestServer { ServerLoginFuzzer(String password, boolean verbose) throws SQLException { super(password, verbose); } public String getTestName() { return getClass().getSimpleName(); } static void testOneInput(String fuzzyString, boolean verbose) { ServerLoginFuzzer server; try { server = new ServerLoginFuzzer("", verbose); } catch (SQLException ex) { ex.printStackTrace(System.out); return; } try { server.getConnection(fuzzyString); } catch (SQLException ex) { /* ignore failed login attempts */ server.diagnostic("failed to get a connection"); } if ( ! server.isRunning() ) { throw new FuzzerSecurityIssueHigh("Login attempt caused Server to crash"); } try { server.stop(); } catch (SQLException ex) { throw new FuzzerSecurityIssueHigh("Why can't we shutdown the server?"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString(), false); } } ================================================ FILE: projects/h2database/ShellFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.h2.tools.Shell; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class ShellFuzzer extends TestServer { ShellFuzzer(boolean verbose) throws SQLException { super("myH2DBPassword", verbose); } public String getTestName() { return getClass().getSimpleName(); } static void testOneInput(String fuzzyString, boolean verbose) { SqlStatementFuzzer server; try { server = new SqlStatementFuzzer(verbose); } catch (SQLException ex) { ex.printStackTrace(System.out); return; } try { Shell shell = new Shell(); shell.setErr(new PrintStream(new ByteArrayOutputStream())); shell.setOut(new PrintStream(new ByteArrayOutputStream())); shell.runTool(new String[]{"-url", server.getConnectionURL(), "-password", server.getDatabasePassword(), "-sql", fuzzyString}); } catch (SQLException ex) { /* ignore */ } catch (Exception ex) { server.diagnostic("unexpected exception on the client side..."); } if ( ! server.isRunning() ) { throw new FuzzerSecurityIssueHigh("Shell caused server crash"); } try { server.stop(); } catch (SQLException ex) { throw new FuzzerSecurityIssueHigh("Why can't we shutdown the server?"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString(), false); } } ================================================ FILE: projects/h2database/SqlPreparedStatementFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.h2.tools.Server; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class SqlPreparedStatementFuzzer extends TestServer { SqlPreparedStatementFuzzer(boolean verbose) throws SQLException { super("myH2DBPassword", verbose); } public String getTestName() { return getClass().getSimpleName(); } static void testOneInput(String fuzzyString, boolean verbose) { SqlStatementFuzzer server; try { server = new SqlStatementFuzzer(verbose); } catch (SQLException ex) { ex.printStackTrace(System.out); return; } try { Connection connection = server.getConnection(); connection.createStatement().executeUpdate("DROP TABLE IF EXISTS t; CREATE TABLE t (x VARCHAR(255));"); PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO t(x) VALUES(?)"); preparedStatement.setString(1, fuzzyString); preparedStatement.executeUpdate(); server.diagnostic("insert performed"); } catch (SQLException ex) { /* ignore */ server.diagnostic("insert not executed"); server.diagnostic(ex); } if ( ! server.isRunning() ) { throw new FuzzerSecurityIssueHigh("SQL Statement caused server crash"); } try { server.stop(); } catch (SQLException ex) { throw new FuzzerSecurityIssueHigh("Why can't we shutdown the server?"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString(), false); } } ================================================ FILE: projects/h2database/SqlStatementFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.h2.tools.Server; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class SqlStatementFuzzer extends TestServer { SqlStatementFuzzer(boolean verbose) throws SQLException { super("myH2DBPassword", verbose); } public String getTestName() { return getClass().getSimpleName(); } static void testOneInput(String fuzzyString, boolean verbose) { SqlStatementFuzzer server; try { server = new SqlStatementFuzzer(verbose); } catch (SQLException ex) { ex.printStackTrace(System.out); return; } try { Connection connection = server.getConnection(); connection.createStatement().executeUpdate(fuzzyString); server.diagnostic("statement executed"); } catch (SQLException ex) { /* ignore */ server.diagnostic("statement not executed"); server.diagnostic(ex); } if ( ! server.isRunning() ) { throw new FuzzerSecurityIssueHigh("SQL Statement caused server crash"); } try { server.stop(); } catch (SQLException ex) { throw new FuzzerSecurityIssueHigh("Why can't we shutdown the server?"); } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString(), false); } } ================================================ FILE: projects/h2database/TestServer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.h2.tools.Server; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.PreparedStatement; public class TestServer { private static String g_shutdownPassword = "ServerShutdownPassword"; // needs to be non-empty string private Server m_server = null; private boolean m_verbose; private String m_password; String getDatabasePassword() { return m_password; } void diagnostic(String message) { if (m_verbose) { System.out.println(message); } } void diagnostic(Exception ex) { if (m_verbose) { ex.printStackTrace(System.out); } } TestServer(String password, boolean verbose) throws SQLException { m_verbose = verbose; m_password = password; String args[] = new String[]{ "-tcpPassword", g_shutdownPassword, "-ifNotExists", "-tcpDaemon" }; m_server = Server.createTcpServer(args).start(); diagnostic("Server started"); try { // passwords default to empty string/null setPassword("", password); } catch (SQLException ex) { setPassword(password, password); } } String getConnectionURL() { return "jdbc:h2:" + m_server.getURL() + "/~/" + getTestName() + ";"; } Connection getConnection() throws SQLException { return getConnection("PASSWORD=" + getDatabasePassword() + ";"); } Connection getConnection(String options) throws SQLException { Connection connection = DriverManager.getConnection(getConnectionURL() + options, null, null); DatabaseMetaData metaData = connection.getMetaData(); diagnostic("Connected to " + metaData.getDatabaseProductName() + "-" + metaData.getDatabaseProductVersion() + " via " + metaData.getURL()); return connection; } void setPassword(String oldPassword, String newPassword) throws SQLException { Connection connection = getConnection("PASSWORD=" + oldPassword); PreparedStatement statement = connection.prepareStatement("SET PASSWORD ?"); statement.setString(1, newPassword); statement.executeUpdate(); diagnostic("Password reset."); } boolean isRunning() { return m_server.isRunning(true); } void stop() throws SQLException { m_server.shutdownTcpServer(m_server.getURL(), g_shutdownPassword, true, true); m_server.stop(); diagnostic("Server stopped"); } public String getTestName() { return getClass().getSimpleName(); } } ================================================ FILE: projects/h2database/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd h2 MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/h2-$CURRENT_VERSION.jar" "$OUT/h2.jar" popd ALL_JARS="h2.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH $SRC/*.java cp $SRC/*.class $OUT/ # generate jazzer start script for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) #javac -cp $SRC:$BUILD_CLASSPATH $fuzzer #cp $SRC/$fuzzer_basename.class $OUT/ #for member_class in $(find $SRC -maxdepth 1 -name "$fuzzer_basename\$*.class"); do # cp $member_class $OUT/ #done # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --disabled_hooks=\"com.code_intelligence.jazzer.sanitizers.SqlInjection\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/h2database/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://h2database.com/" language: jvm main_repo: "https://github.com/h2database/h2database.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/h2o/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev RUN git clone https://github.com/h2o/h2o WORKDIR h2o COPY build.sh $SRC/ COPY *.options $SRC/ ================================================ FILE: projects/h2o/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd $SRC/h2o cmake -DBUILD_FUZZER=ON -DOSS_FUZZ=ON -DOPENSSL_USE_STATIC_LIBS=TRUE . make cp ./h2o-fuzzer-* $OUT/ zip -jr $OUT/h2o-fuzzer-http1_seed_corpus.zip $SRC/h2o/fuzz/http1-corpus zip -jr $OUT/h2o-fuzzer-http2_seed_corpus.zip $SRC/h2o/fuzz/http2-corpus zip -jr $OUT/h2o-fuzzer-http3_seed_corpus.zip $SRC/h2o/fuzz/http3-corpus zip -jr $OUT/h2o-fuzzer-url_seed_corpus.zip $SRC/h2o/fuzz/url-corpus cp $SRC/*.options $SRC/h2o/fuzz/*.dict $OUT/ popd ================================================ FILE: projects/h2o/h2o-fuzzer-http1.options ================================================ [libfuzzer] close_fd_mask = 3 max_len = 16384 dict = http.dict ================================================ FILE: projects/h2o/h2o-fuzzer-http2.options ================================================ [libfuzzer] close_fd_mask = 3 max_len = 16384 dict = http.dict ================================================ FILE: projects/h2o/h2o-fuzzer-http3.options ================================================ [libfuzzer] close_fd_mask = 3 max_len = 16384 dict = http.dict ================================================ FILE: projects/h2o/h2o-fuzzer-url.options ================================================ [libfuzzer] close_fd_mask = 3 ================================================ FILE: projects/h2o/project.yaml ================================================ homepage: "https://github.com/h2o/h2o" language: c++ primary_contact: "jonathan.foote@gmail.com" sanitizers: - address - undefined auto_ccs: - "frederik.deweerdt@gmail.com" - "kazuhooku@gmail.com" - "i.nagata110@gmail.com" - "hfujita@fastly.com" - "security@fastly.com" - "mtakayama@fastly.com" - "gfuji@fastly.com" - "nalramli@fastly.com" - "ethompson@fastly.com" main_repo: 'https://github.com/h2o/h2o' ================================================ FILE: projects/h3/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool \ pkg-config RUN git clone --depth 1 https://github.com/uber/h3 WORKDIR h3 COPY *.sh $SRC/ ================================================ FILE: projects/h3/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake -DBUILD_TESTING=ON .. make -j$(nproc) all H3_BASE=/src/h3/ for fuzzer in $(find $H3_BASE/src/apps/fuzzers -name '*.c'); do fuzzer_basename=$(basename -s .c $fuzzer) # H3_USE_LIBFUZZER is needed so that H3 does not try to build its own # implementation of `main` $CC $CFLAGS -DH3_PREFIX="" \ -DH3_USE_LIBFUZZER=1 \ -I$H3_BASE/src/apps/applib/include \ -I$H3_BASE/src/h3lib/include \ -I$H3_BASE/build/src/h3lib/include \ -o $fuzzer_basename.o \ -c $fuzzer $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -rdynamic \ $fuzzer_basename.o \ -o $OUT/$fuzzer_basename \ lib/libh3.a done ================================================ FILE: projects/h3/project.yaml ================================================ homepage: "https://github.com/uber/h3" language: c primary_contact: "isaacnf0x@gmail.com" auto_ccs: - "Adam@adalogics.com" - "h3-dev@googlegroups.com" - "isv.damocles@gmail.com" - "ajfriend@gmail.com" - "nick.rabinowitz@gmail.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/uber/h3' ================================================ FILE: projects/h3/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd build make test ================================================ FILE: projects/h5py/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y pkg-config libhdf5-dev RUN pip3 install --upgrade pip Cython numpy RUN git clone https://github.com/h5py/h5py h5py COPY *.sh *py $SRC/ WORKDIR $SRC/h5py ================================================ FILE: projects/h5py/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/h5py/fuzz_h5f.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import h5py from h5py import h5f, h5p def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) image = fdp.ConsumeUnicodeNoSurrogates(sys.maxsize) fapl = h5p.create(h5py.h5p.FILE_ACCESS) fapl.set_fapl_core() try: fapl.set_file_image(image) except ValueError: return except TypeError: return fid = h5f.open("/tmp/tmpf.h5p", h5py.h5f.ACC_RDONLY, fapl=fapl) f = h5py.File(fid) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/h5py/project.yaml ================================================ base_os_version: ubuntu-24-04 fuzzing_engines: - libfuzzer homepage: https://github.com/h5py/h5py language: python main_repo: https://github.com/h5py/h5py sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/hadoop/.gitignore ================================================ project-parent/hadoop project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/hadoop/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/hadoop RUN git clone --depth 1 https://github.com/apache/hadoop/ $SRC/project-parent/hadoop COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/hadoop/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=hadoop PROJECT_GROUP_ID=org.apache.hadoop PROJECT_ARTIFACT_ID=hadoop MAIN_REPOSITORY=https://github.com/apache/hadoop/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) FUZZ_TARGET_DEPENDENCIES=":hadoop-common" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/hadoop/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.apache.hadoop hadoop-common Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/hadoop/project-parent/fuzz-targets/src/test/java/com/example/FileUtilFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.hadoop.fs.*; import java.io.*; import java.util.concurrent.ExecutionException; class FileUtilFuzzer { static String currentDir = new File("").getAbsolutePath(); @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { boolean b = data.consumeBoolean(); byte[] b1 = data.consumeBytes(5000); byte[] b2 = data.consumeRemainingAsBytes(); FileUtil.unZip(new ByteArrayInputStream(b1), new File(currentDir)); FileUtil.unTar(new ByteArrayInputStream(b2), new File(currentDir), b); } catch (IOException | ExecutionException | InterruptedException e) { } } } ================================================ FILE: projects/hadoop/project-parent/fuzz-targets/src/test/java/com/example/JavaSerializationFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.apache.hadoop.io.serializer.*; import org.apache.hadoop.io.DataInputBuffer; import org.apache.hadoop.io.DataOutputBuffer; import java.io.IOException; class JavaSerializationFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { String s = data.consumeString(5000); String d = data.consumeRemainingAsString(); Serialization ser = new JavaSerialization(); try { Serializer serializer = ser.getSerializer(String.class); DataOutputBuffer dob = new DataOutputBuffer(); serializer.open(dob); serializer.serialize(s); serializer.close(); Deserializer deserializer = ser.getDeserializer(String.class); DataInputBuffer dib = new DataInputBuffer(); dib.reset(d.getBytes(), d.length()); deserializer.open(dib); deserializer.deserialize(null); deserializer.close(); } catch (IOException e) { } catch (ClassCastException | ArrayIndexOutOfBoundsException | NegativeArraySizeException | NullPointerException e) { // Need to catch in order to find more interesting findings. } } } ================================================ FILE: projects/hadoop/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom hadoop fuzz-targets ================================================ FILE: projects/hadoop/project.yaml ================================================ homepage: "https://hadoop.apache.org/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/apache/hadoop/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/halide/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y ninja-build lsb-core software-properties-common zlib1g-dev RUN pip3 install -U cmake RUN git clone --depth 1 --branch llvmorg-15.0.0 https://github.com/llvm/llvm-project.git $SRC/llvm-project RUN git clone --depth 1 https://github.com/halide/Halide.git halide WORKDIR halide COPY build.sh $SRC/ ================================================ FILE: projects/halide/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set euox pipefail export LDFLAGS="-fuse-ld=lld" declare -A LLVM_SANITIZER=( ["address"]="Address" ["undefined"]="Undefined" ["memory"]="Memory" ) if [[ -v LLVM_SANITIZER[$SANITIZER] ]]; then LLVM_SANITIZER_FLAG="-DLLVM_USE_SANITIZER=${LLVM_SANITIZER[$SANITIZER]}" else LLVM_SANITIZER_FLAG="" fi cmake -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_TARGETS_TO_BUILD="X86" \ $LLVM_SANITIZER_FLAG \ -DLLVM_ENABLE_TERMINFO=OFF \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DLLVM_ENABLE_EH=OFF \ -DLLVM_ENABLE_RTTI=OFF \ -DLLVM_BUILD_32_BITS=OFF \ -DLLVM_INCLUDE_BENCHMARKS=OFF \ -DLLVM_INCLUDE_EXAMPLES=OFF \ -DLLVM_INCLUDE_TESTS=OFF \ -DCMAKE_INSTALL_MODE=ABS_SYMLINK \ -S $SRC/llvm-project/llvm -B $WORK/llvm-build cmake --build $WORK/llvm-build -j$(nproc) cmake --install $WORK/llvm-build --prefix $WORK/llvm-install # Cleanup space so github runners don't run out of disk space. rm -rf $WORK/llvm-build $SRC/llvm-project export LLVM_DIR=$WORK/llvm-install cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release \ -DTARGET_WEBASSEMBLY=OFF \ -DWITH_TUTORIALS=OFF \ -DWITH_UTILS=OFF \ -DWITH_PYTHON_BINDINGS=OFF \ -DWITH_TESTS=ON \ -DWITH_TEST_AUTO_SCHEDULE=OFF \ -DWITH_TEST_CORRECTNESS=OFF \ -DWITH_TEST_ERROR=OFF \ -DWITH_TEST_WARNING=OFF \ -DWITH_TEST_PERFORMANCE=OFF \ -DWITH_TEST_RUNTIME=OFF \ -DWITH_TEST_GENERATOR=OFF \ -DWITH_TEST_FUZZ=ON \ -DBUILD_SHARED_LIBS=OFF cmake --build ./build --target build_fuzz -j$(nproc) cp ./build/test/fuzz/fuzz_* $OUT ================================================ FILE: projects/halide/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://halide-lang.org/" language: c++ primary_contact: "srj@google.com" main_repo: "https://github.com/halide/Halide" file_github_issue: false auto_ccs: - alex.reinking@gmail.com - nathaniel.brough@gmail.com fuzzing_engines: - honggfuzz - libfuzzer sanitizers: - address # LLVM isn't building with Undefined sanitizer # - undefined ================================================ FILE: projects/hamcrest/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone https://github.com/hamcrest/JavaHamcrest.git hamcrest COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/hamcrest ================================================ FILE: projects/hamcrest/HamcrestFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import java.util.*; import java.util.regex.*; import javax.xml.xpath.*; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Attr; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import java.util.HashMap; public class HamcrestFuzzer { HashMap hashMap = new HashMap(); HashMap hashMap2 = new HashMap(); public HamcrestFuzzer(FuzzedDataProvider data) { } public void runTest(FuzzedDataProvider data) { hashMap.put(data.consumeString(10), data.consumeString(10)); hashMap2.put(data.consumeString(10), data.consumeString(10)); try { assertThat(data.consumeString(10), containsString(data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10),allOf(startsWith(data.consumeString(10)), containsString(data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap, is(hashMap2)); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap2, is(aMapWithSize(2))); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap2, is(anEmptyMap())); } catch (AssertionError e) { // documented ignore } try { assertThat(Arrays.asList(data.consumeString(10), data.consumeString(10)), hasSize(equalTo(2))); } catch (AssertionError e) { // documented ignore } try { assertThat(new ArrayList() { { add(data.consumeString(10)); add(data.consumeString(10));}}, is(empty())); } catch (AssertionError e) { // documented ignore } try { assertThat(new ArrayList() {{ add(data.consumeString(10)); add(data.consumeString(10));}}, is(emptyCollectionOf(String.class))); } catch (AssertionError e) { // documented ignore } try { assertThat(new ArrayList() {{add(data.consumeString(10));add(data.consumeString(10));}}, is(emptyIterable())); } catch (AssertionError e) { // documented ignore } try { assertThat(new ArrayList() {{add(data.consumeString(10));add(data.consumeString(10));}}, is(emptyIterableOf(String.class))); } catch (AssertionError e) { // documented ignore } try { assertThat(Arrays.asList(data.consumeString(10), data.consumeString(10)),contains(equalTo(data.consumeString(10)), equalTo(data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(Arrays.asList(data.consumeString(10), data.consumeString(10)),containsInAnyOrder(Arrays.asList(equalTo(data.consumeString(10)), equalTo(data.consumeString(10))))); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap, hasEntry(equalTo(data.consumeString(10)), equalTo(data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap, hasKey(equalTo(data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(hashMap, hasValue(data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(in(Arrays.asList(data.consumeString(10), data.consumeString(10))))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), isOneOf(data.consumeString(10), data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(oneOf(data.consumeString(10), data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeDouble(), is(closeTo(data.consumeDouble(), data.consumeDouble()))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeDouble(), is(notANumber())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), comparesEqualTo(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), greaterThan(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), greaterThanOrEqualTo(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), lessThan(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), lessThanOrEqualTo(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), equalToIgnoringCase(data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(emptyString())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(blankString())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeInt(), lessThanOrEqualTo(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), equalToIgnoringCase(data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(emptyOrNullString())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), is(blankOrNullString())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), matchesPattern(data.consumeString(10))); } catch (AssertionError | PatternSyntaxException e) { // documented ignore } try { assertThat(data.consumeString(10),stringContainsInOrder(Arrays.asList(data.consumeString(10), data.consumeString(10)))); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeString(10), hasLength(data.consumeInt())); } catch (AssertionError e) { // documented ignore } try { assertThat(data.consumeBoolean(), hasToString(data.consumeString(10))); } catch (AssertionError e) { // documented ignore } try { assertThat(Integer.class, typeCompatibleWith(Number.class)); } catch (AssertionError e) { // documented ignore } try { DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder(); Document document = documentBuilder.newDocument(); Element root = document.createElement(data.consumeString(10)); document.appendChild(root); Element employee = document.createElement(data.consumeString(10)); root.appendChild(employee); assertThat(root, hasXPath(data.consumeString(10), equalTo(data.consumeString(10)))); } catch (AssertionError | DOMException | IllegalArgumentException | ParserConfigurationException e) { // documented ignore } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { HamcrestFuzzer testClosure = new HamcrestFuzzer(data); testClosure.runTest(data); } } ================================================ FILE: projects/hamcrest/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ALL_JARS="" pushd "${SRC}/hamcrest" ./gradlew jar install -v ./hamcrest/build/libs/hamcrest-*-SNAPSHOT.jar "$OUT/hamcrest.jar" ALL_JARS="${ALL_JARS} hamcrest.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java cp $SRC/*.class $OUT/ for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/hamcrest/project.yaml ================================================ homepage: http://hamcrest.org/ language: jvm main_repo: https://github.com/hamcrest/JavaHamcrest.git fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/haproxy/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make libpcre2-dev zlib1g-dev RUN git clone https://github.com/haproxy/haproxy RUN git clone https://code.vinyl-cache.org/vtest/VTest2 WORKDIR $SRC/haproxy COPY build.sh run_tests.sh $SRC/ COPY fuzz* $SRC/ ================================================ FILE: projects/haproxy/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # export ORIG_CFLAGS=${CFLAGS} cd $SRC/haproxy # Fix some things in the Makefile where there are no options available sed 's/COPTS += $(DEBUG) $(OPTIONS_CFLAGS) $(CFLAGS) $(ADDINC)/COPTS += $(DEBUG) $(OPTIONS_CFLAGS) $(CFLAGS) $(ADDINC) ${ORIG_CFLAGS}/g' -i Makefile sed 's/LDOPTS = $(TARGET_LDFLAGS) $(OPTIONS_LDFLAGS) $(ADDLIB)/LDOPTS = $(TARGET_LDFLAGS) $(OPTIONS_LDFLAGS) $(ADDLIB) ${CXXFLAGS}/g' -i Makefile make TARGET=generic CC=${CC} LD=${CXX} # Make a copy of the main file since it has many global functions we need to declare # We dont want the main function but we need the rest of the stuff in haproxy.c cd /src/haproxy sed 's/int main(int argc/int main2(int argc/g' -i ./src/haproxy.c sed 's/dladdr(main,/dladdr(main2,/g' -i ./src/tools.c sed 's/(void*)main/(void*)main2/g' -i ./src/tools.c SETTINGS="-Iinclude -g -DUSE_POLL -DUSE_TPROXY -DCONFIG_HAPROXY_VERSION=\"\" -DCONFIG_HAPROXY_DATE=\"\"" $CC $CFLAGS $SETTINGS -c -o ./src/haproxy.o ./src/haproxy.c ar cr libhaproxy.a ./src/*.o for fuzzer in hpack_decode cfg_parser; do cp $SRC/fuzz_${fuzzer}.c . $CC $CFLAGS $SETTINGS -c fuzz_${fuzzer}.c -o fuzz_${fuzzer}.o $CXX -g $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_${fuzzer}.o libhaproxy.a -o $OUT/fuzz_${fuzzer} done # build vtest for run_tests.sh cd $SRC/VTest2 make vtest # vtest binary is in $SRC/VTest2/vtest ================================================ FILE: projects/haproxy/fuzz_cfg_parser.c ================================================ /* # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct cfgfile dummy_cfg = { .filename = "fuzzer", .content = (const char *)data, .size = size, }; if (size < 50) return 0; parse_cfg(&dummy_cfg); return 0; } ================================================ FILE: projects/haproxy/fuzz_hpack_decode.c ================================================ /* * # Copyright 2020 Google Inc. * # * # Licensed under the Apache License, Version 2.0 (the "License"); * # you may not use this file except in compliance with the License. * # You may obtain a copy of the License at * # * # http://www.apache.org/licenses/LICENSE-2.0 * # * # Unless required by applicable law or agreed to in writing, software * # distributed under the License is distributed on an "AS IS" BASIS, * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * # See the License for the specific language governing permissions and * # limitations under the License. * # * ################################################################################ * */ #define HPACK_STANDALONE #include #include #include #include #include #include #include #include #include #include #define MAX_RQ_SIZE 65536 #define MAX_HDR_NUM 1000 char hex[MAX_RQ_SIZE*3+3]; // enough for "[ XX]* \0" uint8_t buf[MAX_RQ_SIZE]; char trash_buf[MAX_RQ_SIZE]; char tmp_buf[MAX_RQ_SIZE]; struct buffer tmp = { .area = tmp_buf, .data = 0, .size = sizeof(tmp_buf) }; /* Empty function we dont need - we just need a callback */ void debug_hexdump(FILE *out, const char *pfx, const char *buf, unsigned int baseaddr, int len) { } // These must be included here #include "../src/hpack-huff.c" #include "../src/hpack-tbl.c" #include "../src/hpack-dec.c" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){ char *new_str = (char *)malloc(size+1); struct hpack_dht *dht; struct pool_head pool; int dht_size = 4096; if (new_str == NULL){ return 0; } memcpy(new_str, data, size); new_str[size] = '\0'; struct http_hdr list[MAX_HDR_NUM]; pool.size = dht_size; pool_head_hpack_tbl = &pool; dht = hpack_dht_alloc(); if (dht != NULL) { hpack_decode_frame(dht, new_str, size, list,sizeof(list)/sizeof(list[0]), &tmp); if (dht != NULL) { free(dht); } } free(new_str); return 0; } ================================================ FILE: projects/haproxy/project.yaml ================================================ homepage: "https://github.com/haproxy/haproxy" primary_contact: "adam@adalogics.com" language: c++ auto_ccs: - "david@adalogics.com" - "timwolla@googlemail.com" - "willy@1wt.eu" - "tribuslukas58@gmail.com" - "christopher.faulet@gmail.com" - "vkrasnobaeva@haproxy.com" - "wlallemand@haproxy.com" sanitizers: - address # Bug reports are public by default: view_restrictions: none main_repo: 'https://github.com/haproxy/haproxy' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/haproxy/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/haproxy # These tests fails so remove it. Store them in a temporary directory because # we need to keep same state as prior to running run_tests.sh. mkdir /tmp/saved_tests DISABLED_TEST_DIR=/tmp/saved_tests/ mv reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.vtc ${DISABLED_TEST_DIR} mv reg-tests/http-messaging/http_wait_for_body.vtc ${DISABLED_TEST_DIR} mv reg-tests/stickiness/srvkey-addr.vtc ${DISABLED_TEST_DIR} mv reg-tests/server/cli_set_fqdn.vtc ${DISABLED_TEST_DIR} make unit-tests HAPROXY_PROGRAM=$SRC/haproxy/haproxy VTEST_PROGRAM=$SRC/VTest2/vtest make reg-tests # Restore state mv ${DISABLED_TEST_DIR}/converters_ipmask_concat_strcmp_field_word.vtc reg-tests/http-rules/converters_ipmask_concat_strcmp_field_word.vtc mv ${DISABLED_TEST_DIR}/http_wait_for_body.vtc reg-tests/http-messaging/http_wait_for_body.vtc mv ${DISABLED_TEST_DIR}/srvkey-addr.vtc reg-tests/stickiness/srvkey-addr.vtc mv ${DISABLED_TEST_DIR}/cli_set_fqdn.vtc reg-tests/server/cli_set_fqdn.vtc ================================================ FILE: projects/harfbuzz/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y python3-pip ragel pkg-config && \ pip3 install meson==0.60.0 ninja RUN git clone --depth 1 https://github.com/harfbuzz/harfbuzz.git WORKDIR harfbuzz COPY build.sh $SRC/ ================================================ FILE: projects/harfbuzz/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable: # 1. UBSan vptr since target built with -fno-rtti. export CFLAGS="$CFLAGS -fno-sanitize=vptr -DHB_NO_VISIBILITY" export CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr -DHB_NO_VISIBILITY" # setup build=$WORK/build # cleanup rm -rf $build mkdir -p $build # Build the library. meson --default-library=static --wrap-mode=nodownload \ -Dexperimental_api=true \ -Dfuzzer_ldflags="$(echo $LIB_FUZZING_ENGINE)" \ $build \ || (cat build/meson-logs/meson-log.txt && false) # Build the fuzzers. ninja -v -j$(nproc) -C $build test/fuzzing/hb-{shape,raster,vector,subset,repacker}-fuzzer mv $build/test/fuzzing/hb-{shape,raster,vector,subset,repacker}-fuzzer $OUT/ # Archive and copy to $OUT seed corpus if the build succeeded. mkdir all-fonts for d in \ test/shape/data/in-house/fonts \ test/shape/data/aots/fonts \ test/shape/data/text-rendering-tests/fonts \ test/api/fonts \ test/fuzzing/fonts \ perf/fonts \ ; do cp $d/* all-fonts/ done zip $OUT/hb-shape-fuzzer_seed_corpus.zip all-fonts/* cp $OUT/hb-shape-fuzzer_seed_corpus.zip $OUT/hb-raster-fuzzer_seed_corpus.zip cp $OUT/hb-shape-fuzzer_seed_corpus.zip $OUT/hb-vector-fuzzer_seed_corpus.zip cp $OUT/hb-shape-fuzzer_seed_corpus.zip $OUT/hb-subset-fuzzer_seed_corpus.zip zip $OUT/hb-repacker-fuzzer_seed_corpus.zip ./test/fuzzing/graphs/* ================================================ FILE: projects/harfbuzz/hb-raster-fuzzer.options ================================================ [libfuzzer] timeout = 5 ================================================ FILE: projects/harfbuzz/hb-repacker-fuzzer.options ================================================ [libfuzzer] timeout = 5 ================================================ FILE: projects/harfbuzz/hb-shape-fuzzer.options ================================================ [libfuzzer] timeout = 5 ================================================ FILE: projects/harfbuzz/hb-subset-fuzzer.options ================================================ [libfuzzer] timeout = 5 ================================================ FILE: projects/harfbuzz/hb-vector-fuzzer.options ================================================ [libfuzzer] timeout = 5 ================================================ FILE: projects/harfbuzz/project.yaml ================================================ homepage: "https://github.com/harfbuzz/harfbuzz" language: c++ primary_contact: "harfbuzz-admin@googlegroups.com" auto_ccs: - "behdad.esfahbod@gmail.com" - "ebrahim@gnu.org" - "ebraminio@gmail.com" - "grieger@google.com" - "rsheeter@google.com" - "dr.khaled.hosny@gmail.com" - "jfkthame@gmail.com" - "qxliu@google.com" - "ckitagawa@google.com" - "drott@chromium.org" - "fwang@igalia.com" vendor_ccs: - "jmuizelaar@mozilla.com" - "lsalzman@mozilla.com" - "twsmith@mozilla.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory architectures: - x86_64 - i386 main_repo: 'https://github.com/harfbuzz/harfbuzz.git' ================================================ FILE: projects/hcl/Dockerfile ================================================ # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/hashicorp/hcl COPY build.sh $SRC WORKDIR $SRC/hcl ================================================ FILE: projects/hcl/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FUZZERS_PACKAGE=github.com/hashicorp/hcl/v2 compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/hclsyntax/fuzz FuzzParseTemplate FuzzParseTemplate compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/hclsyntax/fuzz FuzzParseTraversalAbs FuzzParseTraversalAbs compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/hclsyntax/fuzz FuzzParseExpression FuzzParseExpression compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/hclsyntax/fuzz FuzzParseConfig FuzzHclSyntaxParseConfig compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/json/fuzz FuzzParse FuzzParse compile_native_go_fuzzer_v2 $FUZZERS_PACKAGE/hclwrite/fuzz FuzzParseConfig FuzzHclWriteParseConfig zip $OUT/FuzzParseTemplate_seed_corpus.zip $SRC/hcl/hclsyntax/fuzz/testdata/fuzz/FuzzParseTemplate/* zip $OUT/FuzzParseTraversalAbs_seed_corpus.zip $SRC/hcl/hclsyntax/fuzz/testdata/fuzz/FuzzParseTraversalAbs/* zip $OUT/FuzzParseTemplate_seed_corpus.zip $SRC/hcl/hclsyntax/fuzz/testdata/fuzz/FuzzParseTemplate/* zip $OUT/FuzzParseExpression_seed_corpus.zip $SRC/hcl/hclsyntax/fuzz/testdata/fuzz/FuzzParseExpression/* zip $OUT/FuzzParse_seed_corpus.zip $SRC/hcl/json/fuzz/testdata/fuzz/FuzzParse/* zip $OUT/FuzzHclWriteParseConfig_seed_corpus.zip $SRC/hcl/hclsyntax/fuzz/testdata/fuzz/FuzzParseConfig/* ================================================ FILE: projects/hcl/project.yaml ================================================ homepage: "https://github.com/hashicorp/hcl" language: go fuzzing_engines: - libfuzzer sanitizers: - address primary_contact: "security@hashicorp.com" auto_ccs: - jfinnigan@hashicorp.com - kent@hashicorp.com main_repo: 'https://github.com/hashicorp/hcl' ================================================ FILE: projects/hdf5/Dockerfile ================================================ # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool \ pkg-config cmake zlib1g-dev RUN git clone --depth 1 https://github.com/HDFGroup/hdf5 WORKDIR hdf5 COPY build.sh run_tests.sh *.c $SRC/ ================================================ FILE: projects/hdf5/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export LDFLAGS="${CFLAGS}" export CMAKE_C_FLAGS="${CC} ${CFLAGS}" export CMAKE_CXX_FLAGS="${CXX} ${CXXFLAGS}" mkdir build-dir cd build-dir cmake -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE:STRING=Release \ -DBUILD_SHARED_LIBS:BOOL=OFF \ -DBUILD_TESTING:BOOL=OFF \ -DCMAKE_VERBOSE_MAKEFILES:BOOL=ON \ -DHDF5_BUILD_EXAMPLES:BOOL=OFF \ -DHDF5_BUILD_TOOLS:BOOL=OFF \ -DHDF5_ENABLE_SANITIZERS:BOOL=ON \ -DHDF5_ENABLE_Z_LIB_SUPPORT:BOOL=ON \ .. # Make the build verbose for easy logging inspection cmake --build . --verbose --config Release -j$(nproc) cd $SRC/hdf5 $CC $CFLAGS -std=c99 -c \ -I/src/hdf5/src -I/src/hdf5/build-dir/src -I./src/H5FDsubfiling/ \ $SRC/h5_read_fuzzer.c $CXX $CXXFLAGS $LIB_FUZZING_ENGINE h5_read_fuzzer.o ./build-dir/bin/libhdf5.a -lz -o $OUT/h5_read_fuzzer $CC $CFLAGS -std=c99 -c \ -I/src/hdf5/src -I/src/hdf5/build-dir/src -I./src/H5FDsubfiling/ \ $SRC/h5_extended_fuzzer.c $CXX $CXXFLAGS $LIB_FUZZING_ENGINE h5_extended_fuzzer.o ./build-dir/bin/libhdf5.a -lz -o $OUT/h5_extended_fuzzer zip -j $OUT/h5_extended_fuzzer_seed_corpus.zip $SRC/hdf5/test/testfiles/*.h5 # Build test mkdir $SRC/hdf5/build-test cd $SRC/hdf5/build-test cmake -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_TESTING:BOOL=ON .. cmake --build . --verbose --config Release -j$(nproc) ================================================ FILE: projects/hdf5/h5_extended_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "hdf5.h" #include extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); hid_t fuzz_h5_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); if (fuzz_h5_id != H5I_INVALID_HID) { hid_t dataset_id = H5Dopen2(fuzz_h5_id, "dsetname", H5P_DEFAULT); if (dataset_id != H5I_INVALID_HID) { hid_t attribute_id = H5Aopen_name(dataset_id, "theattr"); if (attribute_id != H5I_INVALID_HID) { H5Aclose(attribute_id); } H5Dclose(dataset_id); } H5Fclose(fuzz_h5_id); } return 0; } ================================================ FILE: projects/hdf5/h5_read_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "hdf5.h" #include extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Some old logic with regards to skipping first byte. Leaving it here // to avoid affecting the clusterfuzz-generated corpus. if (size == 0) { return 0; } uint8_t decider = data[0]; size -= 1; data += 1; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); hid_t fuzz_h5_id = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); if (fuzz_h5_id != H5I_INVALID_HID) { H5Fclose(fuzz_h5_id); } return 0; } ================================================ FILE: projects/hdf5/project.yaml ================================================ homepage: "https://www.hdfgroup.org/solutions/hdf5/" main_repo: "https://github.com/HDFGroup/hdf5" language: c primary_contact: "derobins@hdfgroup.org" vendor_ccs: - "Adam@adalogics.com" - "David@adalogics.com" - "jhenderson@hdfgroup.org" - "nfortne2@hdfgroup.org" - "hyoklee@hdfgroup.org" sanitizers: - address - undefined - memory fuzzing_engines: # - afl # Temporarily disabled after a clang-18 bump, to avoid link errors "undefined reference to [...]" - honggfuzz - libfuzzer ================================================ FILE: projects/hdf5/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build-test ================================================ FILE: projects/hdrhistogram/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/HdrHistogram/HdrHistogram.git COPY build.sh $SRC/ COPY LogReaderWriterFuzzer.java $SRC/ WORKDIR $SRC/HdrHistogram ================================================ FILE: projects/hdrhistogram/LogReaderWriterFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.ByteArrayInputStream; import org.HdrHistogram.Histogram; import org.HdrHistogram.EncodableHistogram; import org.HdrHistogram.HistogramLogReader; import java.util.NoSuchElementException; public class LogReaderWriterFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { int numberOfSignificantValueDigits = data.consumeInt(0, 5); byte [] input = data.consumeRemainingAsBytes(); if (input.length == 0) { return; } EncodableHistogram encodeableHistogram = null; Histogram accumulatedHistogram = new Histogram(numberOfSignificantValueDigits); InputStream readerStream = new ByteArrayInputStream(input); HistogramLogReader reader = new HistogramLogReader(readerStream); // Modification to handle exceptions try { while ((encodeableHistogram = reader.nextIntervalHistogram()) != null) { Histogram histogram = (Histogram) encodeableHistogram; histogram.getTotalCount(); accumulatedHistogram.add(histogram); } } catch (NoSuchElementException e) { // Handle exception gracefully; maybe log it or simply ignore } } } ================================================ FILE: projects/hdrhistogram/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Skip the patch that was failing MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS cp HdrHistogram.jar $OUT/HdrHistogram.jar ALL_JARS="HdrHistogram.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/hdrhistogram/project.yaml ================================================ homepage: "https://github.com/HdrHistogram/HdrHistogram.git" language: jvm primary_contact: "gil@azul.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/HdrHistogram/HdrHistogram.git" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/helm/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/helm/helm RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN git clone --depth 1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=november-backup COPY build.sh $SRC/ WORKDIR $SRC/helm ================================================ FILE: projects/helm/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/go-118-fuzz-build go build . mv go-118-fuzz-build /root/go/bin/ cd $SRC $SRC/cncf-fuzzing/projects/helm/build.sh ================================================ FILE: projects/helm/project.yaml ================================================ homepage: "https://helm.sh" main_repo: "https://github.com/helm/helm" primary_contact: "cncf-helm-core-maintainers@lists.cncf.io" auto_ccs : - "adam@adalogics.com" - "david@adalogics.com" - "scott@r6by.com" - "matt.farina@gmail.com" - "marc.khouzam@gmail.com" - "martyintech@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/hermes/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -yqq make autoconf automake libtool wget \ python3 zip libreadline-dev libatomic-ops-dev npm # Building ninja requires PEP 517. RUN pip3 install "pip>=22.3.1" RUN pip3 install meson ninja RUN ln -s /usr/local/bin/ninja /usr/bin/ninja # Install NPM to strip comments RUN npm install -g @prasadrajandran/strip-comments-cli # Add JS dictionaries RUN curl https://raw.githubusercontent.com/chromium/chromium/main/testing/libfuzzer/fuzzers/dicts/javascript_parser_proto.dict > $SRC/hermes.dict && \ curl https://raw.githubusercontent.com/chromium/chromium/main/testing/libfuzzer/fuzzers/dicts/generated/javascript.dict >> $SRC/hermes.dict RUN wget https://github.com/unicode-org/icu/archive/refs/tags/cldr/2021-08-25.tar.gz && \ tar xzvf ./2021-08-25.tar.gz && \ mv ./icu-cldr-2021-08-25/icu4c $SRC/icu RUN git clone https://github.com/facebook/hermes.git && \ git clone --depth 1 https://github.com/tc39/test262 && \ git clone --depth 1 https://github.com/Zon8Research/v8-vulnerabilities && \ git clone --depth 1 https://github.com/v8/v8 # Strip comments from corpus. RUN find hermes/test -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ && \ find hermes/external/esprima/test_fixtures -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ && \ find hermes/external/flowtest/test/flow -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ && \ find test262/test -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ && \ find v8-vulnerabilities/pocs -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ && \ find v8/test/mjsunit -iname '*.js' -exec stripcomments --write --confirm-overwrite '{}' \+ # Process corpora COPY preprocess-corpus.py $SRC/ RUN python preprocess-corpus.py RUN rm $SRC/preprocess-corpus.py # Add unit tests from project directory as seed corpus. RUN find hermes/test -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip && \ # Add tests from test262 as seed corpus. find test262/test -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip && \ # Add V8 PoCs as seed corpus. find v8-vulnerabilities/pocs -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip && \ # Add tests from esprima as seed corpus. find hermes/external/esprima/test_fixtures -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip && \ # Add tests from flow as seed corpus. find hermes/external/flowtest/test/flow -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip && \ # Add tests from v8 as seed corpus. find v8/test/mjsunit -iname '*.js' | zip -@ -q $SRC/hermes_seed_corpus.zip WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/hermes/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Copy seed corpora mv $SRC/hermes_seed_corpus.zip $OUT # Copy dictionary file mv $SRC/hermes.dict $OUT # build ICU for linking statically. cd $SRC/icu/source ./configure --disable-shared --enable-static --disable-layoutex \ --disable-tests --disable-samples --with-data-packaging=static make install -j$(nproc) # Ugly ugly hack to get static linking to work for icu. cd lib ls *.a | xargs -n1 ar x rm *.a ar r libicu.a *.{ao,o} ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicudata.a ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicuuc.a ln -s $PWD/libicu.a /usr/lib/x86_64-linux-gnu/libicui18n.a if [ "${SANITIZER}" = address ] then CONFIGURE_FLAGS="-DHERMES_ENABLE_ADDRESS_SANITIZER=ON" elif [ "${SANITIZER}" = undefined ] then CONFIGURE_FLAGS="-DHERMES_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER=ON" else CONFIGURE_FLAGS="" fi cmake -S "${SRC}/hermes" -B "${OUT}/build" ${CONFIGURE_FLAGS} -DHERMES_USE_STATIC_ICU=ON \ -DBUILD_SHARED_LIBS=OFF -DHERMES_BUILD_SHARED_JSI=OFF \ -DHERMES_FUZZING_FLAG=${LIB_FUZZING_ENGINE} -DHERMES_ENABLE_LIBFUZZER=ON cmake --build "$OUT/build" --target fuzzer-jsi-entry -j 4 cp "${OUT}/build/bin/fuzzer-jsi-entry" "${OUT}" ================================================ FILE: projects/hermes/preprocess-corpus.py ================================================ #!/usr/bin/env python3 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ from pathlib import Path, PosixPath import re import sys import os import fnmatch from typing import List, Set import shutil excluded_CVEs_or_CRBugs = ["CR410030", "CR445267", "CR1150371"] keywords_to_exclude = { "WebAssembly", "Worker", } # v8 runtime functions regex - https://chromium.googlesource.com/v8/v8/+/refs/heads/main/src/runtime/runtime.h v8_runtime_function_pattern = r"%\w+\(" def get_js_files(path: str) -> Set[PosixPath]: path = Path(path) js_files = {x for x in path.glob("**/*.js") if path.is_dir()} if not js_files: print(f"No JS files found in {path}") return js_files if __name__ == "__main__": # Exclude tests marked by Hermes test suite to skip from corpus test262_tests = get_js_files("./test262/test") esprima_tests = get_js_files("./hermes/external/esprima/test_fixtures") flow_tests = get_js_files("./hermes/external/flowtest/test/flow") mjsunit_tests = get_js_files("./v8/test/mjsunit") hermes_skiplist_path = Path("./hermes/utils/testsuite/testsuite_skiplist.py") if not hermes_skiplist_path.is_file(): for file in os.listdir("./hermes"): if fnmatch.fnmatch(file, "testsuite_skiplist.py"): hermes_skiplist_path = Path(file) break shutil.copy(hermes_skiplist_path, "./testsuite_skiplist.py") from testsuite_skiplist import ( SKIP_LIST, PERMANENT_SKIP_LIST, UNSUPPORTED_FEATURES, PERMANENT_UNSUPPORTED_FEATURES, ) # Exclude tests in mjsunit using v8 runtime functions for test in mjsunit_tests.copy(): test_code = test.open().read() if re.search(v8_runtime_function_pattern, test_code): print(f"Removed: {test}") test.unlink() mjsunit_tests.discard(test) # Exclude tests marked explicitly to skip in Hermes test suite tests_to_remove = ( {test_name for test_name in test262_tests if str(test_name) in SKIP_LIST} | {test_name for test_name in esprima_tests if str(test_name) in SKIP_LIST} | {test_name for test_name in flow_tests if str(test_name) in SKIP_LIST} | { test_name for test_name in mjsunit_tests if str(test_name).lstrip("v8/test/") in SKIP_LIST } | { test_name for test_name in test262_tests if str(test_name) in PERMANENT_SKIP_LIST } | { test_name for test_name in esprima_tests if str(test_name) in PERMANENT_SKIP_LIST } | { test_name for test_name in flow_tests if str(test_name) in PERMANENT_SKIP_LIST } | { test_name for test_name in mjsunit_tests if str(test_name).lstrip("v8/test/") in PERMANENT_SKIP_LIST } ) for test in tests_to_remove: print(f"Removed: {test}") test.unlink() test262_tests.discard(test) esprima_tests.discard(test) mjsunit_tests.discard(test) flow_tests.discard(test) # Exclude tests by keywords found in file contents keywords_to_exclude.update(UNSUPPORTED_FEATURES, PERMANENT_UNSUPPORTED_FEATURES) all_tests = test262_tests | esprima_tests | flow_tests | mjsunit_tests for test in all_tests: test_code = test.open().read() for keyword in keywords_to_exclude: if keyword in test_code or keyword in str(test): print(f"Removed: {test}") test.unlink() break # Filter v8 bugs before including in corpus v8_pocs = get_js_files("./v8-vulnerabilities/pocs") for poc in v8_pocs: try: # Exclude specific CVEs or CR bugs if any(f"{id}.js" in str(poc) for id in excluded_CVEs_or_CRBugs): print(f"Removed: {poc}") poc.unlink() continue poc_code = poc.open().read() # Exclude JIT bugs and other bugs using v8 runtime functions if re.search(v8_runtime_function_pattern, poc_code): print(f"Removed: {poc}") poc.unlink() continue # Exclude bugs with features Hermes does not support for keyword in keywords_to_exclude: if keyword in poc_code: print(f"Removed: {poc}") poc.unlink() break except UnicodeDecodeError: # The PoC was likely generated by a fuzzer mutating at the byte level which we can exclude from the corpus pass ================================================ FILE: projects/hermes/project.yaml ================================================ homepage: "https://github.com/facebook/hermes" language: c++ primary_contact: "neildhar@meta.com" auto_ccs: - "hmf@meta.com" - "yaohway@meta.com" - "axxu@meta.com" - "avp@meta.com" - "luigiconiglio@meta.com" - "edq@meta.com" vendor_ccs: - "oss-fuzz@meta.com" sanitizers: - address - undefined main_repo: 'https://github.com/facebook/hermes.git' ================================================ FILE: projects/hibernate-orm/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/hibernate/hibernate-orm.git # # We'll use the hsqldb backend. # RUN curl -o hsqldb-2.7.0.jar "http://www.hsqldb.org/download/hsqldb_270/hsqldb-2.7.0.jar" COPY add-shadow.diff $SRC/ RUN cd ${SRC}/hibernate-orm && tr -d '\015' < $SRC/add-shadow.diff | git apply COPY build.sh ${SRC}/ COPY *.java *.xml ${SRC}/ WORKDIR ${SRC}/hibernate-orm ================================================ FILE: projects/hibernate-orm/PersistentClass.java ================================================ import java.math.BigDecimal; import java.util.Date; import java.sql.Time; import java.sql.Timestamp; public class PersistentClass { private int m_id; private int m_integer; private String m_string; private BigDecimal m_bigDecimal; private long m_long; private short m_short; private byte m_byte; private boolean m_boolean; private Date m_date; private Time m_time; private Timestamp m_timestamp; private SerializableClass m_serializable; public PersistentClass() { } public int getId() { return m_id; } public void setId(int id) { m_id = id; } public int getIntegerMember() { return m_integer; } public void setIntegerMember(int value) { m_integer = value; } public String getStringMember() { return m_string; } public void setStringMember(String value) { m_string = value; } public BigDecimal getBigDecimalMember() { return m_bigDecimal; } public void setBigDecimalMember(BigDecimal bigDecimal) { m_bigDecimal = bigDecimal; } public long getLongMember() { return m_long; } public void setLongMember(long value) { m_long = value; } public short getShortMember() { return m_short; } public void setShortMember(short value) { m_short = value; } public boolean getBooleanMember() { return m_boolean; } public void setBooleanMember(boolean value) { m_boolean = value; } public byte getByteMember() { return m_byte; } public void setByteMember(byte value) { m_byte = value; } public Date getDateMember() { return m_date; } public void setDateMember(Date value) { m_date = value; } public Time getTimeMember() { return m_time; } public void setTimeMember(Time value) { m_time = value; } public Timestamp getTimestampMember() { return m_timestamp; } public void setTimestampMember(Timestamp value) { m_timestamp = value; } public SerializableClass getSerializableClassMember() { return m_serializable; } public void setSerializableClassMember(SerializableClass value) { m_serializable = value; } } ================================================ FILE: projects/hibernate-orm/PersistentClassFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.hibernate.HibernateException; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.Session; import org.hibernate.Session; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; import java.math.BigDecimal; import java.util.Date; import java.util.List; import java.sql.Time; import java.sql.Timestamp; import java.sql.SQLException; public class PersistentClassFuzzer extends TestServer { final private String tableName = "PersistentClassStore"; final private String className = "PersistentClass"; PersistentClass m_persistentClass = null; PersistentClassFuzzer(FuzzedDataProvider fuzzedDataProvider, boolean verbose) { super(verbose); try { dropTable(tableName); } catch(SQLException ex) { ex.printStackTrace(System.out); /* cannot happen? */ } m_persistentClass = new PersistentClass(); m_persistentClass.setIntegerMember(fuzzedDataProvider.consumeInt()); m_persistentClass.setBigDecimalMember(new BigDecimal(fuzzedDataProvider.consumeInt())); m_persistentClass.setShortMember(fuzzedDataProvider.consumeShort()); m_persistentClass.setLongMember(fuzzedDataProvider.consumeLong()); m_persistentClass.setBooleanMember(fuzzedDataProvider.consumeBoolean()); m_persistentClass.setByteMember(fuzzedDataProvider.consumeByte()); m_persistentClass.setDateMember(new Date(fuzzedDataProvider.consumeLong())); m_persistentClass.setTimeMember(new Time(fuzzedDataProvider.consumeLong())); m_persistentClass.setTimestampMember(new Timestamp(fuzzedDataProvider.consumeLong())); m_persistentClass.setSerializableClassMember( new SerializableClass( fuzzedDataProvider.consumeInt(), fuzzedDataProvider.consumeString(8) ) ); m_persistentClass.setStringMember(fuzzedDataProvider.consumeRemainingAsAsciiString()); } boolean persist() { boolean retval; Transaction tx = null; Session session = SessionFactoryBuilder.sessionFactory().openSession(); try { tx = session.beginTransaction(); session.save(m_persistentClass); tx.commit(); retval = true; } catch (HibernateException e) { if (tx != null) { tx.rollback(); } retval = false; } finally { session.close(); } return retval; } void restore() { Session session = SessionFactoryBuilder.sessionFactory().openSession(); Transaction tx = null; try { tx = session.beginTransaction(); List allPersistentClasses = session.createQuery("FROM " + className).list(); List persistentClasses = (List)allPersistentClasses; for(PersistentClass pc : persistentClasses) { if (pc.getIntegerMember() != m_persistentClass.getIntegerMember()) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (!pc.getStringMember().equals(m_persistentClass.getStringMember())) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (pc.getBigDecimalMember().compareTo(m_persistentClass.getBigDecimalMember()) != 0) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (pc.getLongMember() != m_persistentClass.getLongMember()) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (pc.getShortMember() != m_persistentClass.getShortMember()) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (pc.getBooleanMember() != m_persistentClass.getBooleanMember()) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (pc.getByteMember() != m_persistentClass.getByteMember()) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (!pc.getDateMember().equals(m_persistentClass.getDateMember())) { throw new FuzzerSecurityIssueHigh("Restore failed for "); } if (!pc.getTimeMember().equals(m_persistentClass.getTimeMember())) { throw new FuzzerSecurityIssueHigh("Restore failed for " tag_open_exclamation="" tag_xml_q="" underscore="_" ================================================ FILE: projects/hoextdown/hoextdown_fuzzer.options ================================================ [libfuzzer] dict = hoextdown.dict ================================================ FILE: projects/hoextdown/project.yaml ================================================ homepage: "https://github.com/kjdev/hoextdown" language: c++ primary_contact: "kjclev@gmail.com" main_repo: 'https://github.com/kjdev/hoextdown.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/hoextdown/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable leak sanitizer export ASAN_OPTIONS="detect_leaks=0" # Run unit test with fuzzer link flag LDFLAGS="-fsanitize=$SANITIZER" make test -j$(nproc) ================================================ FILE: projects/hostap/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y make autoconf automake libtool g++ libssl-dev \ libssl-dev:i386 RUN git clone --depth 1 https://w1.fi/hostap.git hostap WORKDIR hostap COPY build.sh $SRC/ ================================================ FILE: projects/hostap/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd 'tests' export LDO=$CXX export LDFLAGS="$CXXFLAGS $LIB_FUZZING_ENGINE" export CFLAGS="$CFLAGS -MMD" if [[ "$ARCHITECTURE" == "i386" ]]; then # Force static link rm -v /lib/i386-linux-gnu/libcrypto.so* || : fi # Specific to hostap's rules.include: set empty, as we directly set required # sanitizer flags in CFLAGS and LDFLAGS (above). export FUZZ_FLAGS= for target in fuzzing/*; do [[ -d "$target" ]] || continue ( cd "$target" make clean if [[ "$target" == "fuzzing/tls-server" ]]; then export CFLAGS="$CFLAGS -DCERTDIR='\"hwsim/auth_serv/\"'" fi make -j$(nproc) V=1 LIBFUZZER=y mv -v "${target##*/}" "${OUT}/" if [[ -d 'corpus' ]]; then (cd 'corpus' && zip "${OUT}/${target##*/}_seed_corpus.zip" *) fi ) done # Copy required data. cp -a "hwsim" "${OUT}/" ================================================ FILE: projects/hostap/project.yaml ================================================ homepage: "https://w1.fi/cvs.html" language: c++ primary_contact: "j@w1.fi" auto_ccs: - "elver@google.com" fuzzing_engines: - afl - libfuzzer - honggfuzz sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory architectures: - x86_64 - i386 main_repo: 'git://w1.fi/srv/git/hostap.git' ================================================ FILE: projects/hpn-ssh/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN apt-get update && apt-get install -y libz-dev libssl1.1 libssl-dev libedit-dev zip RUN git clone https://github.com/rapier1/hpn-ssh RUN git clone --depth 1 https://github.com/djmdjm/openssh-fuzz-cases WORKDIR hpn-ssh COPY build.sh $SRC/ ================================================ FILE: projects/hpn-ssh/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git pull --all git checkout dev_minor # Enable null cipher sed -i 's/#define CFLAG_INTERNAL.*/#define CFLAG_INTERNAL 0/' cipher.c # Turn off agent unlock password failure delays sed -i 's|\(usleep.*\)|// \1|' ssh-agent.c # Build project autoreconf env if ! env CFLAGS="" ./configure \ --without-hardening \ --without-zlib-version-check \ --with-cflags="-DWITH_XMSS=1" \ --with-cflags-after="$CFLAGS" \ --with-ldflags-after="-g $CFLAGS" ; then echo "------ config.log:" 1>&2 cat config.log 1>&2 echo "ERROR: configure failed" 1>&2 exit 1 fi make -j$(nproc) all # Build fuzzers EXTRA_CFLAGS="-DCIPHER_NONE_AVAIL=1 -D_GNU_SOURCE -Iopenbsd-compat/include" STATIC_CRYPTO="-Wl,-Bstatic -lcrypto -Wl,-Bdynamic" SK_NULL=ssh-sk-null.o SK_DUMMY=sk-dummy.o COMMON_DEPS="ssh-pkcs11-client.o -lssh -lopenbsd-compat" $CC $CFLAGS $EXTRA_CFLAGS -I. -g -c \ regress/misc/fuzz-harness/ssh-sk-null.cc -o ssh-sk-null.o $CC $CFLAGS $EXTRA_CFLAGS -I. -g -c \ -DSK_DUMMY_INTEGRATE=1 regress/misc/sk-dummy/sk-dummy.c -o sk-dummy.o $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/pubkey_fuzz.cc -o $OUT/pubkey_fuzz \ $COMMON_DEPS $SK_NULL $STATIC_CRYPTO $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/privkey_fuzz.cc -o $OUT/privkey_fuzz \ $COMMON_DEPS $SK_NULL $STATIC_CRYPTO $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/sig_fuzz.cc -o $OUT/sig_fuzz \ $COMMON_DEPS $SK_NULL $STATIC_CRYPTO $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/authopt_fuzz.cc -o $OUT/authopt_fuzz \ auth-options.o $COMMON_DEPS $SK_NULL $STATIC_CRYPTO \ $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/sshsig_fuzz.cc -o $OUT/sshsig_fuzz \ sshsig.o $COMMON_DEPS $SK_NULL $STATIC_CRYPTO \ $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/sshsigopt_fuzz.cc -o $OUT/sshsigopt_fuzz \ sshsig.o $COMMON_DEPS $SK_NULL $STATIC_CRYPTO \ $LIB_FUZZING_ENGINE $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/kex_fuzz.cc -o $OUT/kex_fuzz \ $COMMON_DEPS -lz $SK_NULL $STATIC_CRYPTO \ $LIB_FUZZING_ENGINE $CC $CFLAGS $EXTRA_CFLAGS -I. -g -c \ regress/misc/fuzz-harness/agent_fuzz_helper.c -o agent_fuzz_helper.o $CC $CFLAGS $EXTRA_CFLAGS -I. -g -c -DENABLE_SK_INTERNAL=1 ssh-sk.c -o ssh-sk.o $CXX $CXXFLAGS -std=c++11 $EXTRA_CFLAGS -I. -L. -Lopenbsd-compat -g \ regress/misc/fuzz-harness/agent_fuzz.cc -o $OUT/agent_fuzz \ $SK_DUMMY agent_fuzz_helper.o ssh-sk.o $COMMON_DEPS -lz \ $STATIC_CRYPTO $LIB_FUZZING_ENGINE # Prepare seed corpora CASES="$SRC/openssh-fuzz-cases" (set -e ; cd ${CASES}/key ; zip -r $OUT/pubkey_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/privkey ; zip -r $OUT/privkey_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/sig ; zip -r $OUT/sig_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/authopt ; zip -r $OUT/authopt_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/sshsig ; zip -r $OUT/sshsig_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/sshsigopt ; zip -r $OUT/sshsigopt_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/kex ; zip -r $OUT/kex_fuzz_seed_corpus.zip .) (set -e ; cd ${CASES}/agent ; zip -r $OUT/agent_fuzz_seed_corpus.zip .) ================================================ FILE: projects/hpn-ssh/project.yaml ================================================ homepage: "https://www.psc.edu/home-hpn-ssh" language: c++ primary_contact: "rapier1@gmail.com" auto_ccs: - "rapier@psc.edu" - "mwd@psc.edu" main_repo: 'https://github.com/rapier1/hpn-ssh.git' fuzzing_engines: - afl - libfuzzer - honggfuzz - centipede ================================================ FILE: projects/hsqldb/ConnectionOptionsFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class ConnectionOptionsFuzzer extends TestServer { ConnectionOptionsFuzzer(boolean verbose) { super(verbose); } void testOneInput(String fuzzyString) { try { getConnection(fuzzyString); } catch (SQLException ex) { /* ignore */ } catch (IllegalArgumentException ex) { /* ??? */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { try (TestServer fuzzer = new ConnectionOptionsFuzzer(false)) { fuzzer.testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString()); } } } ================================================ FILE: projects/hsqldb/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://dlcdn.apache.org//ant/binaries/apache-ant-1.10.14-bin.zip -o ant.zip && \ unzip ant.zip -d $SRC/ant && \ rm -rf ant.zip ENV ANT $SRC/ant/apache-ant-1.10.14/bin/ant RUN svn checkout https://svn.code.sf.net/p/hsqldb/svn/base/trunk hsqldb-svn COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/hsqldb ================================================ FILE: projects/hsqldb/SqlPreparedStatementFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class SqlPreparedStatementFuzzer extends TestServer { SqlPreparedStatementFuzzer(boolean verbose) { super(verbose); } void testOneInput(String fuzzyString) { try (Connection connection = getConnection()) { PreparedStatement preparedStatement = connection.prepareStatement("UPDATE TestTable SET value=? WHERE key=1"); preparedStatement.setString(1, fuzzyString); preparedStatement.executeUpdate(); } catch (SQLException ex) { /* ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { try (TestServer fuzzer = new SqlPreparedStatementFuzzer(false)) { fuzzer.testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString()); } } } ================================================ FILE: projects/hsqldb/SqlStatementFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public class SqlStatementFuzzer extends TestServer { SqlStatementFuzzer(boolean verbose) { super(verbose); } void testOneInput(String fuzzyString) { try { getConnection().createStatement().execute(fuzzyString); } catch (SQLException ex) { /* ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { try (TestServer fuzzer = new SqlStatementFuzzer(false)) { fuzzer.testOneInput(fuzzedDataProvider.consumeRemainingAsAsciiString()); } } } ================================================ FILE: projects/hsqldb/TestServer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import org.hsqldb.server.Server; import org.hsqldb.server.ServerConstants; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.PreparedStatement; public abstract class TestServer extends Server implements AutoCloseable { private PrintWriter m_stderr = null; private PrintWriter m_stdout = null; TestServer(boolean verbose) { super(); setVerbose(verbose); setDatabaseName(0, getTestName()); setDatabasePath(0, "mem:" + getTestName()); start(); try { createTestTable(); } catch(SQLException ex) { /* cannot happen? */ } } void createTestTable() throws SQLException { try (Connection connection = getConnection()) { Statement statement = connection.createStatement(); statement.execute("DROP TABLE TestTable IF EXISTS"); statement.execute("CREATE TABLE TestTable (key INTEGER, value VARCHAR(256))"); statement.execute("INSERT INTO TestTable VALUES ((0, \"Hello\"),(1, \"World\"))"); } } public void close() throws Exception { stop(); } protected void setVerbose(boolean verbose) { if (verbose) { m_stderr = new PrintWriter(System.err); m_stdout = new PrintWriter(System.out); } else { m_stderr = null; m_stdout = null; } this.setErrWriter(m_stderr); this.setLogWriter(m_stdout); } public int stop() { int retval = super.stop(); /* * polling [...] */ while (getState() == ServerConstants.SERVER_STATE_CLOSING) { Thread.yield(); } return retval; } Connection getConnection(String options) throws SQLException { return DriverManager.getConnection("jdbc:hsqldb:mem:" + getTestName() + ";" + options, "sa", ""); } Connection getConnection() throws SQLException { return getConnection(""); } String getTestName() { return getClass().getSimpleName(); } abstract void testOneInput(String fuzzyString); } ================================================ FILE: projects/hsqldb/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd ${SRC}/hsqldb-svn/build $ANT -Dbuild.debug=true hsqldb cp ../lib/hsqldb.jar $OUT/ popd ALL_JARS="hsqldb.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir # compile all java files and copy them to $OUT javac -cp $SRC:$BUILD_CLASSPATH -g $SRC/*.java cp $SRC/*.class $OUT/ # generate jazzer start script for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) #javac -cp $SRC:$BUILD_CLASSPATH $fuzzer #cp $SRC/$fuzzer_basename.class $OUT/ #for member_class in $(find $SRC -maxdepth 1 -name "$fuzzer_basename\$*.class"); do # cp $member_class $OUT/ #done # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --disabled_hooks=\"com.code_intelligence.jazzer.sanitizers.SqlInjection\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/hsqldb/project.yaml ================================================ homepage: "www.hsqldb.org" language: jvm main_repo: "https://svn.code.sf.net/p/hsqldb/svn/" fuzzing_engines: - libfuzzer sanitizers: - address primary_contact: "ft@cluedup.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/html2text/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/Alir3z4/html2text html2text COPY *.sh *py $SRC/ WORKDIR $SRC/html2text ================================================ FILE: projects/html2text/build.sh ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/html2text/fuzz_html2text.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 import html2text def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) html_raw = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 4096)) html2text.html2text(html_raw) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/html2text/project.yaml ================================================ homepage: https://github.com/Alir3z4/html2text main_repo: https://github.com/Alir3z4/html2text language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/html5lib-python/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/html5lib/html5lib-python html5lib-python COPY *.sh *py $SRC/ WORKDIR $SRC/html5lib-python ================================================ FILE: projects/html5lib-python/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/html5lib-python/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import html5lib def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) html5lib.parse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/html5lib-python/project.yaml ================================================ homepage: https://github.com/html5lib/html5lib-python main_repo: https://github.com/html5lib/html5lib-python language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/htmlunit/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # # install maven configuration, which is also used by gradles's publishToMavenLocal # ADD maven-settings.xml ${SRC}/ RUN apt-get install -y xmlstarlet RUN mkdir -p ~/.m2 && \ xmlstarlet ed \ -u "settings/localRepository" -v "${OUT}/m2/repository" \ < ${SRC}/maven-settings.xml > ~/.m2/settings.xml # # install maven and gradle # RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.8.7 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.8.7/apache-maven-3.8.7/bin/mvn RUN curl -L https://services.gradle.org/distributions/gradle-7.6-bin.zip -o gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE $SRC/gradle/gradle-7.6/bin/gradle # # clone repository # WORKDIR ${SRC} ENV LIBRARY_NAME htmlunit RUN git clone https://github.com/HtmlUnit/htmlunit.git ${SRC}/${LIBRARY_NAME} # pgp now disabled by MVN_FLAGS in build.sh # ADD patch-disable-pgp.diff ${SRC}/ # RUN cd ${SRC}/htmlunit && (for i in ${SRC}/patch-*.diff; do tr -d '\015' < $i | git apply -v; done ) ADD build.sh ${SRC}/ ADD ${LIBRARY_NAME}-fuzzer ${SRC}/${LIBRARY_NAME}-fuzzer/ WORKDIR ${SRC}/${LIBRARY_NAME} ================================================ FILE: projects/htmlunit/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Added flag to skip dependency check for troubleshooting purposes MVN_FLAGS="-DskipTests -Dmaven.javadoc.skip -Denforcer.skip=true -Dgpg.skip -Ddependency-check.skip=true" ALL_JARS="" #LIBRARY_NAME="htmlunit" #set by Dockerfile # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} ${MVN_FLAGS} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/${LIBRARY_NAME}" ${MVN} ${MVN_FLAGS} install CURRENT_VERSION=$(${MVN} ${MVN_FLAGS} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}-fuzzer" ${MVN} ${MVN_FLAGS} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/htmlunit/htmlunit-fuzzer/pom.xml ================================================ 4.0.0 ossfuzz htmlunit-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 2.7.0 HtmlPageFuzzer com.code-intelligence jazzer-api 0.12.0 org.htmlunit htmlunit ${fuzzedLibaryVersion} org.apache.maven.plugins maven-shade-plugin 3.4.1 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/htmlunit/htmlunit-fuzzer/src/main/java/ossfuzz/HtmlParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.htmlunit.html.HtmlPage; import org.htmlunit.BrowserVersion; import org.htmlunit.StringWebResponse; import org.htmlunit.WebClient; import org.htmlunit.WebResponse; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; public class HtmlParserFuzzer { private FuzzedDataProvider fuzzedDataProvider; public HtmlParserFuzzer(FuzzedDataProvider fuzzedDataProvider) { this.fuzzedDataProvider = fuzzedDataProvider; } BrowserVersion getBrowserVersion() { /* * from src/test/java/org/htmlunit/WebTestCase.java */ return new BrowserVersion.BrowserVersionBuilder(BrowserVersion.BEST_SUPPORTED) .setApplicationName("FLAG_ALL_BROWSERS") .build(); } void test() { com.code_intelligence.jazzer.api.BugDetectors.allowNetworkConnections(); try (WebClient webClient = new WebClient(getBrowserVersion())) { // org.htmlunit.corejs.javascript.EvaluatorException seems to be fatal webClient.getOptions().setThrowExceptionOnScriptError(false); // no exception if linked resources are not available webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); webClient.loadHtmlCodeIntoCurrentWindow(fuzzedDataProvider.consumeRemainingAsString()); } catch (IllegalArgumentException e) { } catch (IOException e) { } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { HtmlParserFuzzer testFixture = new HtmlParserFuzzer(fuzzedDataProvider); testFixture.test(); } } ================================================ FILE: projects/htmlunit/maven-settings.xml ================================================ /path/to/local/repo/ ================================================ FILE: projects/htmlunit/project.yaml ================================================ homepage: "https://htmlunit.sourceforge.io" language: jvm main_repo: "https://github.com/HtmlUnit/htmlunit.git" primary_contact: "ronaldbrill@googlemail.com" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/htslib/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake zlib1g-dev libbz2-dev liblzma-dev libcurl4-gnutls-dev libssl-dev RUN git clone --depth 1 --shallow-submodules --recurse-submodules https://github.com/samtools/htslib.git htslib WORKDIR htslib COPY build.sh $SRC/ COPY run_tests.sh $SRC/ ================================================ FILE: projects/htslib/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project autoconf autoheader export LDFLAGS="$CFLAGS" ./configure LIBS="-lz -lm -lbz2 -llzma -lcurl -lcrypto -lpthread" make -j$(nproc) libhts.a bgzip htsfile tabix annot-tsv test/fuzz/hts_open_fuzzer.o # Build tests make -j$(nproc) test/hts_endian test/fieldarith test/hfile test/pileup test/pileup_mod \ test/sam test/test_bgzf test/test_expr test/test_faidx test/test_kfunc \ test/test_khash test/test_kstring test/test_mod test/test_nibbles test/test_realn \ test/test-regidx test/test_str2int test/test_time_funcs test/test_view \ test/test_index test/test-vcf-api test/test-vcf-sweep test/test-bcf-sr \ test/test-bcf-translate test/test-parse-reg test/test_introspection \ test/test-bcf_set_variant_type # build fuzzers $CXX $CXXFLAGS -o "$OUT/hts_open_fuzzer" test/fuzz/hts_open_fuzzer.o $LIB_FUZZING_ENGINE libhts.a -lz -lbz2 -llzma -lcurl -lcrypto -lpthread ================================================ FILE: projects/htslib/project.yaml ================================================ homepage: "https://www.htslib.org/" language: c++ primary_contact: "rmd@sanger.ac.uk" auto_ccs: - "aw7@sanger.ac.uk" - "jkb@sanger.ac.uk" - "vo2@sanger.ac.uk" main_repo: 'https://github.com/samtools/htslib.git' ================================================ FILE: projects/htslib/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run tests test/hts_endian test/test_expr test/test_kfunc test/test_khash test/test_kstring test/test_nibbles -v test/test_str2int test/test_time_funcs test/fieldarith test/fieldarith.sam test/hfile test/test_bgzf test/bgziptest.txt test/test-parse-reg -t test/colons.bam test/sam test/ce.fa test/faidx/faidx.fa test/faidx/fastqs.fq test/test-regidx # Run script tests (cd test/faidx && ./test-faidx.sh faidx.tst) (cd test/sam_filter && ./filter.sh filter.tst) (cd test/tabix && ./test-tabix.sh tabix.tst) (cd test/mpileup && ./test-pileup.sh mpileup.tst) (cd test/fastq && ./test-fastq.sh) (cd test/base_mods && ./base-mods.sh base-mods.tst) (cd test/tlen && ./tlen.sh tlen.tst) # Run perl tests # We need to be in test directory for test.pl to work correctly with relative paths if it expects that, # but Makefile runs it from test directory. # Remove failing tests (likely due to ASan/Memory limits in OSS-Fuzz environment) #rm -f test/ce#large_seq.sam test/xx#large_aux.sam mv test/ce#large_seq.sam /tmp/ mv test/xx#large_aux.sam /tmp/ (cd test && REF_PATH=: ./test.pl) # restore failing tests mv /tmp/ce#large_seq.sam test/ mv /tmp/xx#large_aux.sam test/ ================================================ FILE: projects/http-parser/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone https://github.com/nodejs/http-parser WORKDIR $SRC COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/http-parser/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build http-parser and unit test cd http-parser make http_parser.o test_g test_fast # Build fuzzers $CC $CFLAGS -I. -DHTTP_PARSER_STRICT=0 -Wall -Wextra -Werror -c fuzzers/fuzz_parser.c -o fuzz_parser.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -Wall -Wextra -Werror http_parser.o fuzz_parser.o -o $OUT/fuzz_parser $CC $CFLAGS -I. -DHTTP_PARSER_STRICT=0 -Wall -Wextra -Werror -c fuzzers/fuzz_url.c -o fuzz_url.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -Wall -Wextra -Werror http_parser.o fuzz_url.o -o $OUT/fuzz_url ================================================ FILE: projects/http-parser/project.yaml ================================================ homepage: "https://github.com/nodejs/http-parser" primary_contact: "info@bnoordhuis.nl" language: c++ auto_ccs: - "david@adalogics.com" main_repo: 'https://github.com/nodejs/http-parser' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/http-parser/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the unit testing http-parser/test_fast && http-parser/test_g ================================================ FILE: projects/http-pattern-matcher/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 MAINTAINER nareddyt@google.com RUN apt-get update && apt-get install python -y RUN git clone https://github.com/google/http_pattern_matcher.git WORKDIR $SRC/http_pattern_matcher/ COPY build.sh $SRC/ ================================================ FILE: projects/http-pattern-matcher/build.sh ================================================ #!/bin/bash -eu # # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This project uses bazel rules_fuzzing. bazel_build_fuzz_tests ================================================ FILE: projects/http-pattern-matcher/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/google/http_pattern_matcher" main_repo: "https://github.com/google/http_pattern_matcher.git" language: c++ primary_contact: "nareddyt@google.com" auto_ccs: - "yangshuo@google.com" - "taoxuy@google.com" - "qiwzhang@google.com" - "justinmp@google.com" sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory file_github_issue: True ================================================ FILE: projects/httparse/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone https://github.com/seanmonstar/httparse WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/httparse/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/httparse cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_request $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_headers $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_chunk_size $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_response $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_request_multspaces $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/parse_response_multspaces $OUT/ ================================================ FILE: projects/httparse/project.yaml ================================================ homepage: "https://github.com/seanmonstar/httparse" main_repo: "https://github.com/seanmonstar/httparse" primary_contact: "seanmonstar@gmail.com" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "david@adalogics.com" ================================================ FILE: projects/httpcomponents-client/ByteArrayBodyWriteToFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.hc.client5.http.entity.mime.ByteArrayBody; import org.apache.hc.core5.http.ContentType; public class ByteArrayBodyWriteToFuzzer { private static final int FILENAME_MAX_LENGTH = 255; public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create objects from fuzzer input final ContentType contentType = data.pickValue(contentTypes); final String filename = data.consumeString(FILENAME_MAX_LENGTH); final byte[] byteArray = data.consumeBytes(Integer.MAX_VALUE); // Actual fuzzing begins here try { final ByteArrayBody byteArrayBody = new ByteArrayBody(byteArray, contentType, filename); byteArrayBody.writeTo(new ByteArrayOutputStream()); } catch (IOException ignored) { // ignore expected exceptions } } private static final ContentType[] contentTypes = {ContentType.APPLICATION_ATOM_XML, ContentType.APPLICATION_FORM_URLENCODED, ContentType.APPLICATION_JSON, ContentType.APPLICATION_NDJSON, ContentType.APPLICATION_OCTET_STREAM, ContentType.APPLICATION_PDF, ContentType.APPLICATION_PROBLEM_JSON, ContentType.APPLICATION_PROBLEM_XML, ContentType.APPLICATION_RSS_XML, ContentType.APPLICATION_SOAP_XML, ContentType.APPLICATION_SVG_XML, ContentType.APPLICATION_XHTML_XML, ContentType.APPLICATION_XML, ContentType.DEFAULT_BINARY, ContentType.DEFAULT_TEXT, ContentType.IMAGE_BMP, ContentType.IMAGE_GIF, ContentType.IMAGE_JPEG, ContentType.IMAGE_PNG, ContentType.IMAGE_SVG, ContentType.IMAGE_TIFF, ContentType.IMAGE_WEBP, ContentType.MULTIPART_FORM_DATA, ContentType.MULTIPART_MIXED, ContentType.MULTIPART_RELATED, ContentType.TEXT_EVENT_STREAM, ContentType.TEXT_HTML, ContentType.TEXT_MARKDOWN, ContentType.TEXT_PLAIN, ContentType.TEXT_XML, ContentType.WILDCARD}; } ================================================ FILE: projects/httpcomponents-client/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN git clone --depth 1 https://github.com/apache/httpcomponents-client ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn WORKDIR httpcomponents-client RUN git clone --depth 1 https://github.com/apache/httpcomponents-core RUN git clone --depth 1 https://github.com/qos-ch/slf4j COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ ================================================ FILE: projects/httpcomponents-client/FileBodyWriteToFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import org.apache.hc.client5.http.entity.mime.FileBody; import org.apache.hc.core5.http.ContentType; public class FileBodyWriteToFuzzer { private static final int FILENAME_MAX_LENGTH = 255; public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create objects from fuzzer input final ContentType contentType = data.pickValue(contentTypes); final String filename = data.consumeString(FILENAME_MAX_LENGTH); final String fileContent = data.consumeRemainingAsString(); // Create needed objects final File tempFile; try { tempFile = File.createTempFile("FileBody", ".bin"); } catch (IOException ioe) { return; } try { final FileWriter fileWriter = new FileWriter(tempFile); fileWriter.write(fileContent); fileWriter.close(); } catch (IOException ioe) { tempFile.delete(); return; } // Actual fuzzing begins here try { final FileBody fileBody = new FileBody(tempFile, contentType, filename); fileBody.writeTo(new ByteArrayOutputStream()); } catch (IOException ignored) { // ignore expected exceptions } finally { tempFile.delete(); } } private static final ContentType[] contentTypes = {ContentType.APPLICATION_ATOM_XML, ContentType.APPLICATION_FORM_URLENCODED, ContentType.APPLICATION_JSON, ContentType.APPLICATION_NDJSON, ContentType.APPLICATION_OCTET_STREAM, ContentType.APPLICATION_PDF, ContentType.APPLICATION_PROBLEM_JSON, ContentType.APPLICATION_PROBLEM_XML, ContentType.APPLICATION_RSS_XML, ContentType.APPLICATION_SOAP_XML, ContentType.APPLICATION_SVG_XML, ContentType.APPLICATION_XHTML_XML, ContentType.APPLICATION_XML, ContentType.DEFAULT_BINARY, ContentType.DEFAULT_TEXT, ContentType.IMAGE_BMP, ContentType.IMAGE_GIF, ContentType.IMAGE_JPEG, ContentType.IMAGE_PNG, ContentType.IMAGE_SVG, ContentType.IMAGE_TIFF, ContentType.IMAGE_WEBP, ContentType.MULTIPART_FORM_DATA, ContentType.MULTIPART_MIXED, ContentType.MULTIPART_RELATED, ContentType.TEXT_EVENT_STREAM, ContentType.TEXT_HTML, ContentType.TEXT_MARKDOWN, ContentType.TEXT_PLAIN, ContentType.TEXT_XML, ContentType.WILDCARD}; } ================================================ FILE: projects/httpcomponents-client/FormBodyPartBuilderBuildFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import org.apache.hc.client5.http.entity.mime.ByteArrayBody; import org.apache.hc.client5.http.entity.mime.ContentBody; import org.apache.hc.client5.http.entity.mime.FileBody; import org.apache.hc.client5.http.entity.mime.FormBodyPartBuilder; import org.apache.hc.client5.http.entity.mime.InputStreamBody; import org.apache.hc.client5.http.entity.mime.StringBody; import org.apache.hc.core5.http.ContentType; public class FormBodyPartBuilderBuildFuzzer { private static final int builderNameLength = 255; private static final int fieldNameLength = 255; private static final int fieldValueLength = 500; private static final int bodyContentSize = 2 * fieldValueLength; private enum BodyType { ByteArray, File, InputStream, String } public static void fuzzerTestOneInput(FuzzedDataProvider data) { final String builderName = data.consumeString(builderNameLength); final ContentBody contentBody; try { contentBody = generateContentBody(data); } catch (IOException ioe) { // preparations failed ; exit early return; }; try { final FormBodyPartBuilder builder = FormBodyPartBuilder.create(builderName, contentBody); while (data.remainingBytes() > 0) { builder.addField(data.consumeString(fieldNameLength), data.consumeString(fieldValueLength)); } builder.build(); } catch (IllegalStateException ignored) { // ignore expected exceptions } } private static ContentBody generateContentBody(FuzzedDataProvider data) throws IOException { final BodyType choice = data.pickValue(BodyType.values()); final ContentBody contentBody; switch (choice) { case ByteArray: contentBody = new ByteArrayBody(data.consumeBytes(bodyContentSize), data.consumeString(fieldNameLength)); break; case File: final File tempFile = File.createTempFile("FileBody", ".bin"); try { final FileWriter fileWriter = new FileWriter(tempFile); fileWriter.write(data.consumeString(bodyContentSize)); fileWriter.close(); } catch (IOException ioe) { tempFile.delete(); throw ioe; } contentBody = new FileBody(tempFile); tempFile.delete(); break; case InputStream: final InputStream inputStream = new ByteArrayInputStream(data.consumeBytes(bodyContentSize)); contentBody = new InputStreamBody(inputStream, data.consumeString(fieldNameLength)); break; case String: contentBody = new StringBody(data.consumeString(bodyContentSize), ContentType.DEFAULT_BINARY); break; default: // should never be reached contentBody = null; break; } return contentBody; } } ================================================ FILE: projects/httpcomponents-client/HttpFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.ArrayList; import java.util.List; import java.net.URI; import java.io.IOException; import org.apache.hc.core5.http.io.support.ClassicRequestBuilder; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.auth.CredentialsProvider; import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.message.BasicNameValuePair; import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.client5.http.entity.UrlEncodedFormEntity; public class HttpFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() .add(new AuthScope(data.consumeRemainingAsString(), data.consumeInt()), data.consumeRemainingAsString(), data.consumeRemainingAsString().toCharArray()) .build(); final CloseableHttpClient httpClient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .build(); HttpPost httpPost = new HttpPost("http://localhost"); List nvps = new ArrayList<>(); nvps.add(new BasicNameValuePair(data.consumeRemainingAsString(), data.consumeRemainingAsString())); httpPost.setEntity(new UrlEncodedFormEntity(nvps)); try { httpClient.execute(httpPost); } catch (IOException e) { } } } ================================================ FILE: projects/httpcomponents-client/InputStreamBodyWriteToFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.hc.client5.http.entity.mime.InputStreamBody; import org.apache.hc.core5.http.ContentType; public class InputStreamBodyWriteToFuzzer { private static final int FILENAME_MAX_LENGTH = 255; public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create objects from fuzzer input final ContentType contentType = data.pickValue(contentTypes); final String filename = data.consumeString(FILENAME_MAX_LENGTH); final long contentLength = data.consumeLong(); final InputStream inputStream = new ByteArrayInputStream(data.consumeBytes(Integer.MAX_VALUE)); try { final InputStreamBody inputStreamBody = new InputStreamBody(inputStream, contentType, filename, contentLength); inputStreamBody.writeTo(new ByteArrayOutputStream()); } catch (IOException ignored) { // ignore expected exceptions } } private static final ContentType[] contentTypes = {ContentType.APPLICATION_ATOM_XML, ContentType.APPLICATION_FORM_URLENCODED, ContentType.APPLICATION_JSON, ContentType.APPLICATION_NDJSON, ContentType.APPLICATION_OCTET_STREAM, ContentType.APPLICATION_PDF, ContentType.APPLICATION_PROBLEM_JSON, ContentType.APPLICATION_PROBLEM_XML, ContentType.APPLICATION_RSS_XML, ContentType.APPLICATION_SOAP_XML, ContentType.APPLICATION_SVG_XML, ContentType.APPLICATION_XHTML_XML, ContentType.APPLICATION_XML, ContentType.DEFAULT_BINARY, ContentType.DEFAULT_TEXT, ContentType.IMAGE_BMP, ContentType.IMAGE_GIF, ContentType.IMAGE_JPEG, ContentType.IMAGE_PNG, ContentType.IMAGE_SVG, ContentType.IMAGE_TIFF, ContentType.IMAGE_WEBP, ContentType.MULTIPART_FORM_DATA, ContentType.MULTIPART_MIXED, ContentType.MULTIPART_RELATED, ContentType.TEXT_EVENT_STREAM, ContentType.TEXT_HTML, ContentType.TEXT_MARKDOWN, ContentType.TEXT_PLAIN, ContentType.TEXT_XML, ContentType.WILDCARD}; } ================================================ FILE: projects/httpcomponents-client/StringBodyWriteToFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.apache.hc.client5.http.entity.mime.StringBody; import org.apache.hc.core5.http.ContentType; public class StringBodyWriteToFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Create objects from fuzzer input final ContentType contentType = data.pickValue(contentTypes); final String stringData = data.consumeRemainingAsString(); // Actual fuzzing begins here try { final StringBody stringBody = new StringBody(stringData, contentType); stringBody.writeTo(new ByteArrayOutputStream()); } catch (IOException ignored) { // ignore expected exceptions } } private static final ContentType[] contentTypes = {ContentType.APPLICATION_ATOM_XML, ContentType.APPLICATION_FORM_URLENCODED, ContentType.APPLICATION_JSON, ContentType.APPLICATION_NDJSON, ContentType.APPLICATION_OCTET_STREAM, ContentType.APPLICATION_PDF, ContentType.APPLICATION_PROBLEM_JSON, ContentType.APPLICATION_PROBLEM_XML, ContentType.APPLICATION_RSS_XML, ContentType.APPLICATION_SOAP_XML, ContentType.APPLICATION_SVG_XML, ContentType.APPLICATION_XHTML_XML, ContentType.APPLICATION_XML, ContentType.DEFAULT_BINARY, ContentType.DEFAULT_TEXT, ContentType.IMAGE_BMP, ContentType.IMAGE_GIF, ContentType.IMAGE_JPEG, ContentType.IMAGE_PNG, ContentType.IMAGE_SVG, ContentType.IMAGE_TIFF, ContentType.IMAGE_WEBP, ContentType.MULTIPART_FORM_DATA, ContentType.MULTIPART_MIXED, ContentType.MULTIPART_RELATED, ContentType.TEXT_EVENT_STREAM, ContentType.TEXT_HTML, ContentType.TEXT_MARKDOWN, ContentType.TEXT_PLAIN, ContentType.TEXT_XML, ContentType.WILDCARD}; } ================================================ FILE: projects/httpcomponents-client/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "httpclient5/target/httpclient5-$CURRENT_VERSION.jar" "$OUT/httpclient5.jar" $MVN package $MAVEN_ARGS -f "httpcomponents-core/pom.xml" CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout -f httpcomponents-core/pom.xml) cp "httpcomponents-core/httpcore5/target/httpcore5-$CURRENT_VERSION.jar" "$OUT/httpcore5.jar" cp "httpcomponents-core/httpcore5-h2/target/httpcore5-h2-$CURRENT_VERSION.jar" "$OUT/httpcore5-h2.jar" cd slf4j $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "slf4j-api/target/slf4j-api-$CURRENT_VERSION.jar" "$OUT/slf4j.jar" cd $SRC ALL_JARS="httpclient5.jar httpcore5.jar slf4j.jar httpcore5-h2.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/httpcomponents-client/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/apache/httpcomponents-client language: jvm main_repo: https://github.com/apache/httpcomponents-client.git sanitizers: - address vendor_ccs: - patrice.salathe@code-intelligence.com - yakdan@code-intelligence.com - yoshi.weber@gmail.com ================================================ FILE: projects/httpcomponents-core/ClassicHttpRequestFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.hc.core5.http.Method; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.io.entity.*; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.impl.bootstrap.RequesterBootstrap; import org.apache.hc.core5.http.protocol.HttpCoreContext; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.impl.bootstrap.HttpRequester; import org.apache.hc.core5.util.Timeout; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.net.URIAuthority; import java.net.URI; import java.net.URISyntaxException; import java.lang.IllegalArgumentException; import java.io.File; import java.io.IOException; import java.io.ByteArrayInputStream; public class ClassicHttpRequestFuzzer { final static ContentType[] contentTypes = { ContentType.APPLICATION_ATOM_XML, ContentType.APPLICATION_FORM_URLENCODED, ContentType.APPLICATION_JSON, ContentType.APPLICATION_SVG_XML, ContentType.APPLICATION_XHTML_XML, ContentType.APPLICATION_XML, ContentType.IMAGE_BMP, ContentType.IMAGE_GIF, ContentType.IMAGE_JPEG, ContentType.IMAGE_PNG, ContentType.IMAGE_SVG, ContentType.IMAGE_TIFF, ContentType.IMAGE_WEBP, ContentType.MULTIPART_FORM_DATA, ContentType.TEXT_HTML, ContentType.TEXT_PLAIN, ContentType.TEXT_XML }; public static void fuzzerTestOneInput(FuzzedDataProvider data) { int entityChoice = data.consumeInt(0, 3); String name = data.consumeString(100); String value = data.consumeRemainingAsString(); BasicClassicHttpRequest request; try { request = new BasicClassicHttpRequest(data.pickValue(Method.values()), value); } catch (IllegalArgumentException e) { return; } request.setVersion(data.pickValue(HttpVersion.ALL)); request.addHeader(value, new Object()); request.addHeader(new BasicHeader(name, value)); request.setScheme(value); request.setAuthority(new URIAuthority(value, 8080)); setRequestEntity(request, value, entityChoice, data.pickValue(contentTypes)); request.getRequestUri(); request.getPath(); request.toString(); request.getScheme(); request.getEntity(); request.getAuthority(); try { request.getUri(); } catch (URISyntaxException e) { } HttpRequester requester = RequesterBootstrap.bootstrap() .setSslContext(null) .setMaxTotal(2) .setDefaultMaxPerRoute(2) .create(); final HttpHost target = new HttpHost(value, "localhost", 80); final HttpCoreContext context = HttpCoreContext.create(); try { requester.execute(target, request, Timeout.ofSeconds(0), context); } catch (HttpException | IOException e) { } } public static void setRequestEntity(BasicClassicHttpRequest request, String value, int entityChoice, ContentType contentType) { ByteArrayInputStream stream = new ByteArrayInputStream(value.getBytes()); switch (entityChoice) { case 0: request.setEntity(new StringEntity(value, contentType)); break; case 1: request.setEntity(new InputStreamEntity(stream,contentType)); break; case 2: request.setEntity(new BasicHttpEntity(stream, contentType)); break; case 3: request.setEntity(new ByteArrayEntity(value.getBytes(), contentType)); break; } } } ================================================ FILE: projects/httpcomponents-core/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN git clone --depth 1 https://github.com/apache/httpcomponents-core -b 5.1.x ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR httpcomponents-core ================================================ FILE: projects/httpcomponents-core/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "httpcore5/target/httpcore5-$CURRENT_VERSION.jar" "$OUT/httpcore5.jar" ALL_JARS="httpcore5.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/httpcomponents-core/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/apache/httpcomponents-core language: jvm main_repo: https://github.com/apache/httpcomponents-core.git sanitizers: - address vendor_ccs: - patrice.salathe@code-intelligence.com - yakdan@code-intelligence.com ================================================ FILE: projects/httpcore/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/encode/httpcore httpcore COPY *.sh *py $SRC/ WORKDIR $SRC/httpcore ================================================ FILE: projects/httpcore/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/httpcore/fuzz_http11.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import httpcore from httpcore._backends.mock import MockStream def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) stream = MockStream(fdp.ConsumeBytes(2048)) origin = httpcore.Origin(fdp.ConsumeBytes(24), fdp.ConsumeBytes(24), 443) try: with httpcore.HTTP11Connection(origin=origin, stream=stream, keepalive_expiry=5.0) as conn: with conn.stream("GET", "http://127.0.0.1") as response: response.status except RuntimeError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/httpcore/project.yaml ================================================ homepage: https://github.com/encode/httpcore main_repo: https://github.com/encode/httpcore language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/httplib2/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y libffi-dev RUN git clone --depth 1 https://github.com/httplib2/httplib2 RUN python3 -m pip install --upgrade pip pyparsing COPY build.sh $SRC/ WORKDIR $SRC/httplib2 ================================================ FILE: projects/httplib2/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install six pytest cryptography python3 setup.py install # Build fuzzers in $OUT. for fuzzer in $(find ./tests/ -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/httplib2/project.yaml ================================================ homepage: "https://github.com/httplib2/httplib2" language: python primary_contact: "temotor@gmail.com" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/httplib2/httplib2" ================================================ FILE: projects/httpretty/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip requests RUN git clone https://github.com/gabrielfalcao/httpretty httpretty COPY *.sh *py $SRC/ WORKDIR $SRC/httpretty ================================================ FILE: projects/httpretty/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/httpretty/fuzz_httpretty_e2e.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import requests import httpretty def test_one(input_data): fdp = atheris.FuzzedDataProvider(input_data) # Enable httpretty httpretty.enable(verbose=True, allow_net_connect=False) # Create arguments http_body = fdp.ConsumeUnicodeNoSurrogates(sys.maxsize) if fdp.ConsumeBool(): header_dict = { fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24), fdp.ConsumeUnicodeNoSurrogates(24): fdp.ConsumeUnicodeNoSurrogates(24) } else: header_dict = None # Pass random arguments to register_uri and ensure we can get it try: httpretty.register_uri(httpretty.GET, "http://fuzzing.com/", body=http_body, content_type=fdp.ConsumeUnicodeNoSurrogates(32), adding_headers=header_dict) response = requests.get('http://fuzzing.com') except httpretty.HTTPrettyError: pass httpretty.reset() if __name__ == "__main__": atheris.instrument_all() atheris.Setup(sys.argv, test_one) atheris.Fuzz() ================================================ FILE: projects/httpretty/project.yaml ================================================ homepage: https://github.com/gabrielfalcao/httpretty main_repo: https://github.com/gabrielfalcao/httpretty language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/httpx/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Held back because of github.com/google/oss-fuzz/pull/13407 # Please fix the build failure + upgrade. FROM gcr.io/oss-fuzz-base/base-builder-python@sha256:d223a882810372830fd7968eb3e64533f3a2318c90be43ac753a46a15946faec RUN git clone https://github.com/encode/httpx httpx COPY *.sh *py $SRC/ WORKDIR $SRC/httpx ================================================ FILE: projects/httpx/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/httpx/fuzz_api.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import httpx import time import socket import threading fuzzed_input = b"" # somehow ugly as fuzzing cannot be run in parallel def SetFuzzedInput(input_bytes): global fuzzed_input fuzzed_input = input_bytes class ServerThread(threading.Thread): def __init__(self): self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.s.bind(("127.0.0.1", 8001)) self.s.listen(1) threading.Thread.__init__(self) def run(self): global fuzzed_input conn, addr = self.s.accept() conn.recv(1024) conn.send(fuzzed_input) time.sleep(0.005) conn.close() self.s.shutdown(1) self.s.close() time.sleep(0.01) def TestOneInput(data): t1 = ServerThread() # Launch threads t1.start() SetFuzzedInput(data) try: httpx.get('http://127.0.0.1:8001/') except httpx.RemoteProtocolError: pass t1.join() def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/httpx/fuzz_decoders.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import httpx from httpx._decoders import ByteChunker, LineDecoder, TextChunker, TextDecoder def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) ByteChunker(chunk_size=fdp.ConsumeIntInRange(1, 100)).decode( fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 1024)) ) LineDecoder().decode(fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024))) TextChunker(chunk_size=fdp.ConsumeIntInRange(1, 100)).decode( fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(0, 1024)) ) TextDecoder().decode(fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 1024))) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/httpx/fuzz_url.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import httpx def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: httpx._urlparse.urlparse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except httpx._exceptions.InvalidURL: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/httpx/project.yaml ================================================ homepage: https://github.com/encode/httpx main_repo: https://github.com/encode/httpx language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/hugo/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone https://github.com/gohugoio/hugo COPY build.sh fuzz_pageparser.go $SRC/ WORKDIR $SRC/hugo ================================================ FILE: projects/hugo/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/fuzz_pageparser.go $SRC/hugo/parser/pageparser/ compile_go_fuzzer github.com/gohugoio/hugo/parser/pageparser FuzzParseFrontMatterAndContent FuzzParseFrontMatterAndContent ================================================ FILE: projects/hugo/fuzz_pageparser.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package pageparser import "bytes" func FuzzParseFrontMatterAndContent(data []byte) int { ParseFrontMatterAndContent(bytes.NewReader(data)) return 1 } ================================================ FILE: projects/hugo/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/gohugoio/hugo" primary_contact: "bjorn.erik.pedersen@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/gohugoio/hugo' ================================================ FILE: projects/hunspell/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y autoconf automake autopoint libtool RUN git clone --depth 1 https://github.com/hunspell/hunspell.git hunspell WORKDIR hunspell COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/hunspell/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/hunspell/oss-fuzz-build.sh ================================================ FILE: projects/hunspell/project.yaml ================================================ homepage: "https://hunspell.github.io/" language: c++ primary_contact: "caolanm@gmail.com" vendor_ccs: - "twsmith@mozilla.com" sanitizers: - address - memory - undefined architectures: - i386 - x86_64 main_repo: 'https://github.com/hunspell/hunspell.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/hunspell/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Successful unit test cases TESTS="affixes.dic flag.dic allcaps3.dic dotless_i.dic sug.dic ph.dic condition_utf.dic flaglong.dic sugutf.dic wordpair.dic phone.dic flagnum.dic sug2.dic flagutf8.dic allcaps2.dic base.dic allcaps.dic i58202.dic slash.dic allcaps_utf.dic base_utf.dic keepcase.dic alias.dic ph2.dic needaffix4.dic forbiddenword.dic complexprefixes2.dic alias2.dic break.dic needaffix.dic alias3.dic utf8_bom.dic needaffix5.dic needaffix3.dic utf8_bom2.dic utf8.dic needaffix2.dic fogemorpheme.dic complexprefixes.dic complexprefixesutf.dic nosuggest.dic breakdefault.dic zeroaffix.dic compoundaffix2.dic circumfix.dic compoundflag.dic onlyincompound.dic compoundrule3.dic compoundrule2.dic compoundrule.dic conditionalprefix.dic compoundrule6.dic compoundrule4.dic compoundrule7.dic checkcompoundrep2.dic compoundrule8.dic compoundaffix3.dic compoundaffix.dic utf8_nonbmp.test checkcompounddup.dic compoundforbid.dic simplifiedtriple.dic checkcompoundtriple.dic ignore.dic checkcompoundcaseutf.dic ignoreutf.dic compoundrule5.dic right_to_left_mark.dic checkcompoundpattern2.dic utfcompound.dic 1592880.dic checkcompoundpattern4.dic checkcompoundpattern3.dic colons_in_words.dic i53643.dic germancompoundingold.dic germancompounding.dic reputf.dic maputf.dic i68568utf.dic i68568.dic 1748408-1.dic 1706659.dic 1748408-3.dic digits_in_words.dic 1748408-2.dic 1748408-4.dic 1695964.dic checksharpsutf.dic fullstrip.dic 1463589_utf.dic i35725.dic iconv2.dic iconv.dic arabic.dic 1975530.dic IJ.dic morph.dic 2999225.dic warn.dic korean.dic 2970240.dic 2970242.dic ngram_utf_fix.dic breakoff.dic opentaal_cpdpat.dic opentaal_cpdpat2.dic onlyincompound2.dic oconv.dic nepali.dic hu.dic oconv2.dic opentaal_forbiddenword2.dic opentaal_forbiddenword1.dic opentaal_keepcase.dic forceucase.dic limit-multiple-compounding.dic ignoresug.dic timelimit.dic" # Failing unit test cases FAILED_TESTS="condition.dic rep.dic map.dic checkcompoundrep.dic checkcompoundcase2.dic checkcompoundpattern.dic checksharps.dic i54980.dic i54633.dic 1463589.dic encoding.dic" # Run unit test while temporarily ignore failing unit test cases make check -C tests -j$(nproc) TESTS="$TESTS" ================================================ FILE: projects/hwloc/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y python-is-python3 build-essential \ autoconf automake libtool zlib1g-dev pkg-config RUN git clone --recurse-submodules https://github.com/open-mpi/hwloc hwloc COPY *.sh *_fuzzer.c *.options $SRC/ WORKDIR $SRC/hwloc ================================================ FILE: projects/hwloc/build.sh ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./autogen.sh ./configure --enable-static --disable-shared LDFLAGS="-static" CFLAGS="${CFLAGS}" LDFLAGS="${CFLAGS}" make LDFLAGS=-all-static for f in $SRC/*_fuzzer.c; do fuzzer=$(basename "$f" _fuzzer.c) $CC $CFLAGS -I$SRC/hwloc/include -I$SRC/hwloc/private -c $SRC/${fuzzer}_fuzzer.c \ -o $SRC/${fuzzer}_fuzzer.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/${fuzzer}_fuzzer.o \ -o $OUT/${fuzzer}_fuzzer \ -Wl,--start-group ./hwloc/.libs/libhwloc.a \ ./utils/hwloc/.libs/libutils_common.a -Wl,--end-group done cp $SRC/*.options $OUT/ ================================================ FILE: projects/hwloc/hwloc_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "hwloc.h" #include "private/private.h" #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Fuzz base64 logic char *source = (char *)(data); char *target = (char *)malloc(100); hwloc_encode_to_base64(source, size, target, 100); char *new_str = (char *)malloc(size + 1); if (new_str == NULL) { return 0; } memcpy(new_str, data, size); new_str[size] = '\0'; hwloc_decode_from_base64(new_str, target, 100); free(new_str); free(target); return 0; } ================================================ FILE: projects/hwloc/hwloc_fuzzer.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/hwloc/project.yaml ================================================ homepage: "https://github.com/open-mpi/hwloc" main_repo: "https://github.com/open-mpi/hwloc" language: c vendor_ccs: - david@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/hwloc/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make -C utils/hwloc check ================================================ FILE: projects/hyperium/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone https://github.com/hyperium/http RUN git clone https://github.com/hyperium/h2 WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/hyperium/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/http cargo fuzz build -O cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_http $OUT/ cd $SRC/h2 cargo fuzz build -O cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_client $OUT/ cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_e2e $OUT/ cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_hpack $OUT/ for fuzz_name in fuzz_e2e fuzz_client; do echo "[libfuzzer]" > $OUT/${fuzz_name}.options echo "detect_leaks=0" >> $OUT/${fuzz_name}.options done ================================================ FILE: projects/hyperium/project.yaml ================================================ homepage: "https://github.com/hyperium/" main_repo: "https://github.com/hyperium/" primary_contact: "sean.monstar@gmail.com" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "ver@buoyant.io" - "eliza@buoyant.io" - "david@adalogics.com" ================================================ FILE: projects/ibmswtpm2/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder ARG SIM_DL_URL=https://downloads.sourceforge.net/project/ibmswtpm2/ibmtpm1332.tar.gz RUN apt-get update && apt-get install -y make autoconf automake libtool libssl-dev curl tar g++ RUN mkdir ibmswtpm2 && \ cd ibmswtpm2 && \ curl -sSL "${SIM_DL_URL}" | tar xvz WORKDIR ibmswtpm2/src COPY build.sh $SRC/ COPY fuzzer.cc ./ COPY no_writes.patch $SRC/ RUN patch -p1 < $SRC/no_writes.patch ================================================ FILE: projects/ibmswtpm2/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project make -j$(nproc) fuzz_tpm_server cp fuzz_tpm_server $OUT/fuzz_tpm_server ================================================ FILE: projects/ibmswtpm2/fuzzer.cc ================================================ #include "TpmBuildSwitches.h" #include #include #include #include #include #ifdef TPM_WINDOWS #include #include #endif extern "C" { #include "Implementation.h" /* kgold */ #include "TpmTcpProtocol.h" #include "Manufacture_fp.h" #include "Platform_fp.h" #include "Simulator_fp.h" #ifdef TPM_WINDOWS #include "TcpServer_fp.h" #endif #ifdef TPM_POSIX #include "TcpServerPosix_fp.h" #endif } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { int pipefd[2]; if (Data == NULL || Size == 0) { return 0; } if (pipe(pipefd) == -1) { perror("creating pipe"); exit(EXIT_FAILURE); } if (write(pipefd[1], Data, Size) != (ssize_t)Size) { perror("write to pipe"); exit(EXIT_FAILURE); } close(pipefd[1]); _plat__NVEnable(NULL); if (TPM_Manufacture(1) != 0) { dprintf(STDERR_FILENO, "[FAILED] manufacturing\n"); exit(1); } // Coverage test - repeated manufacturing attempt if (TPM_Manufacture(0) != 1) { dprintf(STDERR_FILENO, "[FAILED] Coverage test - repeated manufacturing attempt\n"); exit(2); } // Coverage test - re-manufacturing TPM_TearDown(); if (TPM_Manufacture(1) != 0) { dprintf(STDERR_FILENO, "[FAILED] Coverage test - re-manufacturing\n"); exit(3); } // Disable NV memory _plat__NVDisable(); /* power on the TPM kgold MS simulator comes up powered off */ _rpc__Signal_PowerOn(FALSE); _rpc__Signal_NvOn(); // From TSS2 MSSIM simulator_setup // tcti_platform_command (tctiContext, MS_SIM_POWER_ON); _rpc__Signal_PowerOn(FALSE); // tcti_platform_command (tctiContext, MS_SIM_NV_ON); _rpc__Signal_NvOn(); TpmServer(pipefd[0]); close(pipefd[0]); return 0; } ================================================ FILE: projects/ibmswtpm2/no_writes.patch ================================================ diff --git a/CompilerDependencies.h b/CompilerDependencies.h index b6c0577..c89b125 100644 --- a/CompilerDependencies.h +++ b/CompilerDependencies.h @@ -146,7 +146,7 @@ #ifndef NOT_REFERENCED # define NOT_REFERENCED(x) (x = x) #endif -#ifdef _POSIX_ +#ifdef IS_POSIX typedef int SOCKET; #endif // #ifdef TPM_POSIX diff --git a/GpMacros.h b/GpMacros.h index ff4251d..3494b55 100644 --- a/GpMacros.h +++ b/GpMacros.h @@ -84,7 +84,7 @@ # define TEST_HASH(alg) #endif // SELF_TEST /* 5.11.3 For Failures */ -#if defined _POSIX_ +#if defined IS_POSIX # define FUNCTION_NAME 0 #else # define FUNCTION_NAME __FUNCTION__ diff --git a/TPMCmds.c b/TPMCmds.c index 173dcf7..0805575 100644 --- a/TPMCmds.c +++ b/TPMCmds.c @@ -110,7 +110,12 @@ Usage( /* This is the main entry point for the simulator. */ /* It registers the interface and starts listening for clients */ int -main( +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +main +#else +tpm_server_main +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ +( int argc, char *argv[] ) diff --git a/TcpServerPosix.c b/TcpServerPosix.c index be48607..8dfcbea 100644 --- a/TcpServerPosix.c +++ b/TcpServerPosix.c @@ -721,9 +721,11 @@ TpmServer( memcpy(&CommandResponseSizes.largestResponse, &OutputBuffer[6], sizeof(UINT32)); } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ok = WriteVarBytes(s, (char*) OutBuffer.Buffer, OutBuffer.BufferSize); +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ if(!ok) return TRUE; break; @@ -737,9 +739,11 @@ TpmServer( printf("Unsupported client version (0).\n"); return TRUE; } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ok &= WriteUINT32(s, ServerVersion); ok &= WriteUINT32(s, tpmInRawMode | tpmPlatformAvailable | tpmSupportsPP); +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ break; case TPM_SET_ALTERNATIVE_RESULT: @@ -760,7 +764,9 @@ TpmServer( printf("Unrecognized TPM interface command %08x\n", Command); return TRUE; } +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ok = WriteUINT32(s,0); +#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ if(!ok) return TRUE; } diff --git a/makefile b/makefile index cc3e410..c10ba5a 100644 --- a/makefile +++ b/makefile @@ -40,16 +40,16 @@ -CC = /usr/bin/gcc -CCFLAGS = -Wall \ +CCFLAGS = $(CFLAGS) -Wall \ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \ - -Werror -Wsign-compare \ + -Wsign-compare \ -c -ggdb -O0 \ -DTPM_POSIX \ - -D_POSIX_ \ + -DIS_POSIX \ -DTPM_NUVOTON \ -I../utils \ - -I. + -I. \ + -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION LNFLAGS = -ggdb \ -DTPM_POSIX \ @@ -57,7 +60,8 @@ LNFLAGS = -ggdb \ -lcrypto \ -lpthread \ -lrt \ - -I. + -I. \ + -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION $(LIB_FUZZING_ENGINE) all: tpm_server @@ -75,9 +79,14 @@ TcpServerPosix.o : $(HEADERS) tpm_server: $(OBJFILES) $(CC) $(OBJFILES) $(LNFLAGS) -o tpm_server +fuzz_tpm_server: $(OBJFILES) fuzzer.o + $(CXX) $(CXXFLAGS) fuzzer.o $(OBJFILES) $(LNFLAGS) -o fuzz_tpm_server + clean: - rm -f *.o tpm_server *~ + rm -f *.o tpm_server fuzz_tpm_server *~ %.o: %.c $(CC) $(CCFLAGS) $< -o $@ +%.o: %.cc + $(CXX) $(CXXFLAGS) $(CCFLAGS) $(LIB_FUZZING_ENGINE) $< -o $@ ================================================ FILE: projects/ibmswtpm2/project.yaml ================================================ homepage: https://sourceforge.net/projects/ibmswtpm2/ language: c++ primary_contact: kgoldman@us.ibm.com main_repo: https://git.code.sf.net/p/ibmswtpm2/tpm2 auto_ccs: - "john.s.andersen@intel.com" - "william.c.roberts@intel.com" - "david.wooten@ieee.org" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/ical4j/project.yaml ================================================ homepage: "https://github.com/ical4j/ical4j" language: jvm primary_contact: "fortuna@micronode.com" sanitizers: - address main_repo: 'https://github.com/ical4j/ical4j.git' ================================================ FILE: projects/icalendar/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone --depth 1 https://github.com/collective/icalendar.git icalendar \ && cp icalendar/src/icalendar/fuzzing/build.sh $SRC/ RUN mv icalendar/src/icalendar/fuzzing/corpus $SRC/corpus WORKDIR $SRC/icalendar ================================================ FILE: projects/icalendar/project.yaml ================================================ homepage: "https://icalendar.readthedocs.io/en/latest/" language: python primary_contact: "johannes@raggam.co.at" auto_ccs: - "ennamarie19@gmail.com" - "niccokunzmann@googlemail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/collective/icalendar.git" ================================================ FILE: projects/icu/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make RUN git clone --depth 1 https://github.com/unicode-org/icu.git icu COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/icu/build.sh ================================================ #!/bin/bash -eux # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # need "-p" as otherwise centipede fails mkdir -p $WORK/icu cd $WORK/icu # TODO: icu build failes without -DU_USE_STRTOD_L=0 DEFINES="-DU_CHARSET_IS_UTF8=1 -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DU_USE_STRTOD_L=0" CFLAGS="$CFLAGS $DEFINES" CXXFLAGS="$CXXFLAGS $DEFINES" CFLAGS=$CFLAGS CXXFLAGS=$CXXFLAGS CC=$CC CXX=$CXX \ /bin/bash $SRC/icu/icu4c/source/runConfigureICU Linux \ --with-library-bits=64 --with-data-packaging=static --enable-static --disable-shared export ASAN_OPTIONS="detect_leaks=0" export UBSAN_OPTIONS="detect_leaks=0,enum=0" make -j$(nproc) # Pick up additional flags (-std=...) added by runConfigureICU. CXXFLAGS="$CXXFLAGS $(config/icu-config --noverify --cxxflags)" $CXX $CXXFLAGS -c $SRC/icu/icu4c/source/test/fuzzer/locale_util.cpp \ -I$SRC/icu/icu4c/source/common \ -I$SRC/icu4c/source/test/fuzzer FUZZER_PATH=$SRC/icu/icu4c/source/test/fuzzer # Assumes that all fuzzers files end with'_fuzzer.cpp'. FUZZERS=$FUZZER_PATH/*_fuzzer.cpp for fuzzer in $FUZZERS; do file=${fuzzer:${#FUZZER_PATH}+1} $CXX $CXXFLAGS \ $fuzzer -o $OUT/${file/.cpp/} locale_util.o \ -I$SRC/icu/icu4c/source/common -I$SRC/icu/icu4c/source/i18n -L$WORK/icu/lib \ $LIB_FUZZING_ENGINE -licui18n -licuuc -licutu -licudata done # Assumes that all seed files end with '*_fuzzer_seed_corpus.txt'. CORPUS=$SRC/icu/icu4c/source/test/fuzzer/*_fuzzer_seed_corpus.txt for corpus in $CORPUS; do zipfile=${corpus:${#FUZZER_PATH}+1} zip $OUT/${zipfile/.txt/.zip} $corpus done cp $SRC/icu/icu4c/source/test/fuzzer/*.dict $OUT/ ================================================ FILE: projects/icu/project.yaml ================================================ homepage: "https://icu.unicode.org" language: c++ primary_contact: "ftang@google.com" auto_ccs: - icu-security@unicode.org - andy.heninger@gmail.com - markus.icu@gmail.com - jefgen.msft@gmail.com - shane@unicode.org - srl295@gmail.com - ftang@google.com - roubert@google.com - elango@unicode.org - richard_gillam@apple.com - grhoten@gmail.com sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory fuzzing_engines: - libfuzzer - honggfuzz - afl # - centipede disabled due to https://github.com/google/oss-fuzz/pull/12365 clang 18 update main_repo: 'https://github.com/unicode-org/icu.git' ================================================ FILE: projects/icu/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $WORK/icu make check ================================================ FILE: projects/idna/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/kjd/idna idna WORKDIR idna COPY build.sh *.py $SRC/ ================================================ FILE: projects/idna/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/idna/fuzz_encode_decode.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import idna def TestOneInput(data): """Fuzz encode and decode""" fdp = atheris.FuzzedDataProvider(data) try: idna.core.encode(fdp.ConsumeString(1024)) except idna.IDNAError: pass try: idna.core.decode(fdp.ConsumeString(1024)) except idna.IDNAError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/idna/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/kjd/idna language: python main_repo: https://github.com/kjd/idna primary_contact: kim@cynosure.com.au sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/igraph/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake bison flex RUN git clone --branch main https://github.com/igraph/igraph WORKDIR igraph RUN cp $SRC/igraph/fuzzing/build.sh $SRC/build.sh ================================================ FILE: projects/igraph/project.yaml ================================================ homepage: "https://github.com/igraph/igraph" main_repo: "https://github.com/igraph/igraph" language: c primary_contact: "szhorvat@gmail.com" coverage_extra_args: -ignore-filename-regex=.*libxml2-2.*/.* -ignore-filename-regex=.*/vendor/.* auto_ccs: - "Adam@adalogics.com" - "ntamas@gmail.com" - "vtraag@gmail.com" - "igraphossfuzz@gmail.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 fuzzing_engines: - afl - honggfuzz - libfuzzer - centipede ================================================ FILE: projects/ijson/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y libffi-dev ruby mercurial RUN pip3 install --upgrade pip cffi RUN git clone https://github.com/ICRAR/ijson ijson RUN git clone https://github.com/lloyd/yajl COPY *.sh *py $SRC/ WORKDIR $SRC/ijson ================================================ FILE: projects/ijson/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ "$SANITIZER" == "introspector" ]; then export CFLAGS="" export CXXFLAGS="" fi cd $SRC/yajl/ ./configure make install cd $SRC/ijson python3 -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data /usr/local/lib/libyajl.so:. --add-data /usr/local/lib/libyajl.so.2:. done ================================================ FILE: projects/ijson/fuzz_all.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import sys import json import ijson import atheris def TestOneInput(data): for parser_type in ['yajl2_c', 'yajl2_cffi', 'yajl2', 'yajl', 'python']: try: backend = ijson.get_backend(parser_type) except: # If we can't get the backend, just continue to the next. continue try: parse_items = backend.parse(io.BytesIO(data)) for obj in ijson.items(parse_items, 'item'): pass except ( ijson.common.JSONError, json.JSONDecodeError ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ijson/fuzz_native_parser.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import sys import json import ijson import atheris from ijson.backends import yajl2_c def TestOneInput(data): native_backend = ijson.get_backend("yajl2_c") try: parse_items = native_backend.parse(io.BytesIO(data)) for obj in ijson.items(parse_items, 'item'): pass except ( ijson.common.JSONError, json.JSONDecodeError ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ijson/fuzz_parser.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import io import sys import json import ijson import atheris def TestOneInput(data): try: parse_items = ijson.parse(io.BytesIO(data)) for obj in ijson.items(parse_items, 'item'): pass except ( ijson.common.JSONError, json.JSONDecodeError ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ijson/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/ICRAR/ijson language: python main_repo: https://github.com/ICRAR/ijson sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/image-png/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool curl cmake python llvm-dev libclang-dev clang RUN git clone https://github.com/image-rs/image-png WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/image-png/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC cd image-png cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/decode $OUT/ find . -type f -name "*.png" -exec zip -r -j "$OUT/decode_seed_corpus.zip" {} + cp fuzz/target/x86_64-unknown-linux-gnu/release/buf_independent $OUT/ cp fuzz/target/x86_64-unknown-linux-gnu/release/roundtrip $OUT/ ================================================ FILE: projects/image-png/project.yaml ================================================ homepage: "https://github.com/image-rs/image-png" main_repo: "https://github.com/image-rs/image-png" primary_contact: "andreas.molzer@gmx.de" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "david@adalogics.com" file_github_issue: True ================================================ FILE: projects/image-rs/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone https://github.com/image-rs/image WORKDIR $SRC/image COPY build.sh $SRC/ ================================================ FILE: projects/image-rs/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # ---- Build fuzz corpuses ---- # function zip_files() { # Get the arguments directory=$1 extension=$2 zipfile=$3 # Find all files with the given extension in the given directory and its subdirectories # and add them to the zip file find "$directory" -type f -name "*.$extension" -exec zip -r -j "$zipfile" {} + } FORMATS=("bmp" "exr" "gif" "hdr" "ico" "jpeg" "png" "pnm" "tga" "tiff" "webp") for FORMAT in "${FORMATS[@]}" do zip_files . $FORMAT "$OUT/fuzzer_script_${FORMAT}_seed_corpus.zip" done # ---- Build fuzz harnesses ---- cargo fuzz build -O cargo fuzz list | while read i; do cp fuzz/target/x86_64-unknown-linux-gnu/release/$i $OUT/ done ================================================ FILE: projects/image-rs/project.yaml ================================================ homepage: "https://docs.rs/image/0.23.14/image" main_repo: "https://github.com/image-rs/image" primary_contact: "andreas.molzer@gmx.de" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "p.antoine@catenacyber.fr" ================================================ FILE: projects/imageio/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt update && apt-get install -y zlib1g-dev libjpeg8-dev RUN pip3 install cython numpy RUN git clone https://github.com/imageio/imageio COPY build.sh $SRC/ WORKDIR $SRC/imageio ================================================ FILE: projects/imageio/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 setup.py build install # Build fuzzers in $OUT. for fuzzer in $(find . -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/imageio/project.yaml ================================================ homepage: "https://imageio.github.io" language: python primary_contact: "almar.klein@gmail.com" auto_ccs: - "sebastian@wallkoetter.net" - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: 'https://github.com/imageio/imageio' ================================================ FILE: projects/imagemagick/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Install build tools RUN apt-get update && \ apt-get install -y make autoconf automake groff libtool pkg-config cmake nasm autopoint # Due to libtiff requirements, build requires autoconf 2.71 (or later) # Can probably be removed once base-builder switches to Ubuntu 22.04 RUN curl -LO https://mirrors.edge.kernel.org/ubuntu/pool/main/a/autoconf/autoconf_2.72-3.1ubuntu1_all.deb && \ apt install ./autoconf_2.72-3.1ubuntu1_all.deb # Clone dependencies RUN git clone --depth 1 https://github.com/imagemagick/imagemagick RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff RUN git clone --depth 1 https://github.com/strukturag/libde265 RUN git clone --depth 1 https://github.com/strukturag/libheif RUN git clone --depth 1 https://github.com/uclouvain/openjpeg RUN git clone --depth 1 https://github.com/webmproject/libwebp RUN git clone --depth 1 https://github.com/madler/zlib RUN git clone --depth 1 https://github.com/ebiggers/libdeflate RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo RUN git clone --depth 1 https://github.com/tukaani-project/xz RUN git clone --depth 1 https://github.com/libraw/libraw RUN git clone --depth 1 https://github.com/pnggroup/libpng RUN git clone --depth 1 https://github.com/mm2/Little-CMS RUN git clone --depth 1 https://github.com/freetype/freetype RUN git clone --depth 1 https://gitlab.com/federicomenaquintero/bzip2.git RUN git clone --depth 1 --recursive https://github.com/libjxl/libjxl RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit # does not support shallow ADD https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz afl_testcases.tgz WORKDIR imagemagick COPY build.sh run_tests.sh replay_build.sh $SRC/ ================================================ FILE: projects/imagemagick/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Temporarily Add -D_GNU_SOURCE to CFLAGS to fix freetype's dependence on GNU # extensions for dlsym to dynamically load harfbuzz. This feature # should potentially be disabled instead of fixing the compilation. But that is # not possible to do from the OSS-Fuzz repo :-) # See https://github.com/google/oss-fuzz/pull/13325 for more details. export CFLAGS="$CFLAGS -D_GNU_SOURCE" . oss-fuzz/build.sh ================================================ FILE: projects/imagemagick/project.yaml ================================================ homepage: "https://www.imagemagick.org" language: c++ primary_contact: "dirk@lemstra.org" auto_ccs: - paul.l.kehrer@gmail.com - alex.gaynor@gmail.com - urban.warrior.fuzz@gmail.com - jon.sneyers@gmail.com sanitizers: - address - memory - undefined main_repo: 'https://github.com/imagemagick/imagemagick' ================================================ FILE: projects/imagemagick/replay_build.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## # Prepare wrappers to make recompilation faster. if [ ! -f /usr/bin/bash.real ]; then # Only run this once. python /usr/local/bin/make_build_replayable.py fi MAGICK_COMPILER=$CXX MAGICK_COMPILER_FLAGS=$CXXFLAGS MAGICK_INCLUDE="$WORK/include/ImageMagick-7" MAGICK_SRC="$SRC/imagemagick/oss-fuzz" MAGICK_LIBS_NO_FUZZ="$WORK/lib/libMagick++-7.Q16HDRI.a $WORK/lib/libMagickWand-7.Q16HDRI.a $WORK/lib/libMagickCore-7.Q16HDRI.a $WORK/lib/libpng.a $WORK/lib/libtiff.a $WORK/lib/libheif.a $WORK/lib/libde265.a $WORK/lib/libopenjp2.a $WORK/lib/libwebp.a $WORK/lib/libwebpmux.a $WORK/lib/libwebpdemux.a $WORK/lib/libsharpyuv.a $WORK/lib/libhwy.a $WORK/lib/libbrotlicommon.a $WORK/lib/libbrotlidec.a $WORK/lib/libbrotlienc.a $WORK/lib/libjxl_threads.a $WORK/lib/libjxl_cms.a $WORK/lib/libjxl.a $WORK/lib/libturbojpeg.a $WORK/lib/libjpeg.a $WORK/lib/libfreetype.a $WORK/lib/libraw.a $WORK/lib/liblzma.a $WORK/lib/liblcms2.a $WORK/lib/libdeflate.a $WORK/lib/libz.a" MAGICK_LIBS="$LIB_FUZZING_ENGINE $MAGICK_LIBS_NO_FUZZ" MAGICK_OUTPUT=$OUT MAGICK_FAST_BUILD=0 . $MAGICK_SRC/build_dependencies.sh . $MAGICK_SRC/build_imagemagick.sh # Move on the building the fuzzers MAGICK_COMPILER_FLAGS="$MAGICK_COMPILER_FLAGS -fuse-ld=lld -DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16" $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE "$MAGICK_SRC/encoder_list.cc" \ -o "$MAGICK_SRC/encoder_list" $MAGICK_LIBS_NO_FUZZ # Control the target fuzzer from the command line. Hardcoded below commented # out is for testing purposes, and to illustrate the logic behind it. # TARGET_FUZZER="encoder_sgi_fuzzer" TARGET_FUZZER=$1 for f in $MAGICK_SRC/*_fuzzer.cc; do fuzzer=$(basename "$f" _fuzzer.cc) out_fuzzname=$(basename "$f" .cc) echo "Real fuzz name: ${out_fuzzname}" # encoder_fuzzer is special if [ "$fuzzer" == "encoder" ]; then continue fi if [ "$out_fuzzname" != "$TARGET_FUZZER" ]; then continue fi $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE \ "$f" -o "$MAGICK_OUTPUT/${fuzzer}_fuzzer" $MAGICK_LIBS & echo -e "[libfuzzer]\nclose_fd_mask=3" > "$MAGICK_OUTPUT/${fuzzer}_fuzzer.options" done for item in $("$MAGICK_SRC/encoder_list"); do info=${item:1} encoder=${info%:*} initializer=${info##*:} encoder_flags="-DFUZZ_IMAGEMAGICK_ENCODER=$encoder" out_fuzzname="encoder_${encoder,,}_fuzzer" if [ "$out_fuzzname" != "$TARGET_FUZZER" ]; then continue fi if [ "$initializer" != "" ]; then encoder_flags="$encoder_flags -DFUZZ_IMAGEMAGICK_ENCODER_INITIALIZER=$initializer" fi if [ "${item:0:1}" == "+" ]; then encoder_flags="$encoder_flags -DFUZZ_IMAGEMAGICK_ENCODER_WRITE=1" fi $MAGICK_COMPILER $MAGICK_COMPILER_FLAGS -std=c++11 -I$MAGICK_INCLUDE \ "$MAGICK_SRC/encoder_fuzzer.cc" -o "$MAGICK_OUTPUT/encoder_${encoder,,}_fuzzer" \ $encoder_flags $MAGICK_LIBS & echo -e "[libfuzzer]\nclose_fd_mask=3" > "$MAGICK_OUTPUT/encoder_${encoder,,}_fuzzer.options" if [ -f "$MAGICK_SRC/dictionaries/${encoder,,}.dict" ]; then cp "$MAGICK_SRC/dictionaries/${encoder,,}.dict" "$MAGICK_OUTPUT/encoder_${encoder,,}_fuzzer.dict" fi if [ $MAGICK_FAST_BUILD -eq 1 ]; then break fi done wait ================================================ FILE: projects/imagemagick/run_tests.sh ================================================ #!/bin/sh -e # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ rgrep --files-with-matches '\-lheif' . \ | xargs -r sed -i 's/-lheif/-lheif -lc++/' # TODO: `make check` is preferred over `make check-TESTS`, as it is the public # interface for comprehensive testing of ImageMagick. make -j"$(nproc)" check-TESTS # Undo patches. rgrep --files-with-matches -- '-lheif -lc++' . \ | xargs -r sed -i 's/-lheif -lc++/-lheif/' ================================================ FILE: projects/immer/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # ! This project was pinned after a clang bump. Please remove the pin, Try to fix any build warnings and errors, as well as runtime errors RUN apt-get update && apt-get install -y cmake libgc-dev pkg-config RUN git clone --depth 1 https://github.com/arximboldi/immer.git immer WORKDIR immer COPY build.sh $SRC/ ================================================ FILE: projects/immer/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake .. \ -DBoehmGC_INCLUDE_DIR=/usr/include \ -DBoehmGC_LIBRARIES=/usr/lib/x86_64-linux-gnu/libgc.a \ -Dimmer_BUILD_TESTS=OFF make -j$(nproc) fuzzers for fuzzer in extra/fuzzer/*; do if [[ -f $fuzzer && -x $fuzzer ]]; then cp $fuzzer $OUT fi done ================================================ FILE: projects/immer/project.yaml ================================================ homepage: "https://sinusoid.es/immer" language: c++ primary_contact: "juanpe@sinusoid.al" main_repo: 'https://github.com/arximboldi/immer.git' sanitizers: - address - memory fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/importlib_metadata/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/python/importlib_metadata importlib_metadata COPY *.sh *py $SRC/ WORKDIR $SRC/importlib_metadata ================================================ FILE: projects/importlib_metadata/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/importlib_metadata/fuzz_importlib.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris from importlib_metadata import ( Distribution, EntryPoints, PathDistribution, ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) fuzz_str = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 1024)) list(Distribution._deps_from_requires_text(fuzz_str)) try: list(EntryPoints._from_text(fuzz_str)) except TypeError: pass PathDistribution._name_from_stem(fuzz_str) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/importlib_metadata/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/python/importlib_metadata language: python main_repo: https://github.com/python/importlib_metadata sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/inchi/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget make unzip git RUN git clone --depth=1 https://github.com/IUPAC-InChI/InChI inchi WORKDIR inchi COPY run_tests.sh build.sh *_fuzzer.c $SRC/ ================================================ FILE: projects/inchi/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd INCHI-1-SRC # Compile library sources (exclude ichimain.c which is the standalone program main) # Remove -ansi flag since upstream now uses C99 features (loop-scoped variables) SRC_FILES=$(ls INCHI_BASE/src/*.c INCHI_API/libinchi/src/*.c INCHI_API/libinchi/src/ixa/*.c | grep -v ichimain.c) $CC $CFLAGS -Wno-everything -DTARGET_API_LIB -c $SRC_FILES ar rcs $WORK/libinchi.a *.o for fuzzer in $SRC/*_fuzzer.c; do fuzzer_basename=$(basename -s .c $fuzzer) $CC $CFLAGS \ -I INCHI_BASE/src/ \ -I INCHI_API/libinchi/src/ \ -I INCHI_API/libinchi/src/ixa/ \ $fuzzer -c -o ${fuzzer_basename}.o $CXX $CXXFLAGS \ ${fuzzer_basename}.o -o $OUT/$fuzzer_basename \ $LIB_FUZZING_ENGINE $WORK/libinchi.a done popd # Build test INCHI-1-TEST/build_with_cmake.sh all ================================================ FILE: projects/inchi/inchi_input_fuzzer.c ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include "inchi_api.h" // Define the maximum value for size_t. We return if the fuzzing input is equal // to kSizeMax because appending the null-terminator to the InChI buffer would // cause wraparound, thereby initializing the buffer to size 0. static const size_t kSizeMax = (size_t)-1; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == kSizeMax) return 0; char *szINCHISource = malloc(sizeof(char) * (size + 1)); memcpy(szINCHISource, data, size); szINCHISource[size] = '\0'; // InChI string must be null-terminated // Buffer lengths taken from InChI API reference, located at // https://www.inchi-trust.org/download/104/InChI_API_Reference.pdf, page 24 char szINCHIKey[28], szXtra1[65], szXtra2[65]; GetINCHIKeyFromINCHI(szINCHISource, 0, 0, szINCHIKey, szXtra1, szXtra2); inchi_InputINCHI inpInChI; inpInChI.szInChI = szINCHISource; inpInChI.szOptions = NULL; inchi_Output out; GetINCHIfromINCHI(&inpInChI, &out); inchi_OutputStruct outStruct; GetStructFromINCHI(&inpInChI, &outStruct); free(szINCHISource); FreeINCHI(&out); FreeStructFromINCHI(&outStruct); return 0; } ================================================ FILE: projects/inchi/project.yaml ================================================ homepage: "https://www.inchi-trust.org/" main_repo: "https://github.com/IUPAC-InChI/InChI" language: c primary_contact: "member-info@inchi-trust.org" sanitizers: - address fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/inchi/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Excluding unit test case that failed ctest --test-dir CMake_build/full_build -E "test_inchi_dll_b|test_permutation_util" ================================================ FILE: projects/influxdb/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 MAINTAINER william@influxdata.com RUN git clone https://github.com/influxdata/influxdb.git RUN git clone https://github.com/dgrijalva/jwt-go.git COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/influxdb/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/influxdata/influxdb/jsonweb FuzzJsonWeb fuzzjsonweb ================================================ FILE: projects/influxdb/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/influxdata/influxdb" language: go primary_contact: "william@influxdata.com" auto_ccs: - "palbert@influxdata.com" - "ryan@influxdata.com" fuzzing_engines: - libfuzzer sanitizers: - address disabled: true main_repo: 'https://github.com/influxdata/influxdb' ================================================ FILE: projects/iniconfig/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/pytest-dev/iniconfig WORKDIR iniconfig COPY build.sh *.py $SRC/ ================================================ FILE: projects/iniconfig/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/iniconfig/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris import iniconfig def TestOneInput(data): """Simple fuzzer that targets parse routine""" fdp = atheris.FuzzedDataProvider(data) try: ini = iniconfig.IniConfig( "", fdp.ConsumeUnicodeNoSurrogates(sys.maxsize) ) except iniconfig.ParseError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/iniconfig/project.yaml ================================================ file_github_issue: true fuzzing_engines: - libfuzzer homepage: https://github.com/pytest-dev/iniconfig language: python main_repo: https://github.com/pytest-dev/iniconfig sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com view_restrictions: none ================================================ FILE: projects/inih/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update RUN git clone https://github.com/benhoyt/inih.git COPY inihfuzz.c $SRC/inih/inihfuzz.c COPY build.sh $SRC/build.sh COPY run_tests.sh $SRC/ WORKDIR $SRC/inih/ ================================================ FILE: projects/inih/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Compile the fuzzer binary for oss-fuzz infrastructure. $CC $CFLAGS -c ini.c $CC $CFLAGS -c inihfuzz.c $CXX $CFLAGS $LIB_FUZZING_ENGINE inihfuzz.o ini.o -o inihfuzz # Setup for oss-fuzz infrastructure. cp inihfuzz $OUT/ zip -r inihfuzz_seed_corpus.zip tests/*.ini mv inihfuzz_seed_corpus.zip $OUT/ ================================================ FILE: projects/inih/inihfuzz.c ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include "ini.h" #define kMinInputLength 8 #define kMaxInputLength 512 int User; char Prev_section[50]; int dumper(void* user, const char* section, const char* name, const char* value) { User = *((int*)user); if (strcmp(section, Prev_section)) { strncpy(Prev_section, section, sizeof(Prev_section)); Prev_section[sizeof(Prev_section) - 1] = '\0'; } return 1; } extern int LLVMFuzzerTestOneInput(const char *data, size_t size) { char *data_in; static int u = 100; if (size < kMinInputLength || size > kMaxInputLength) { return 0; } Prev_section[0] = '\0'; data_in = calloc((size + 1), sizeof(char)); if (!data_in) return 0; memcpy(data_in, data, size); ini_parse_string(data_in, dumper, &u); free(data_in); return 0; } ================================================ FILE: projects/inih/project.yaml ================================================ homepage: "https://github.com/benhoyt/inih" language: c primary_contact: "benhoyt@gmail.com" auto_ccs: - "pkillarjun@protonmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/benhoyt/inih' ================================================ FILE: projects/inih/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd tests ./unittest.sh ================================================ FILE: projects/ion-java/.gitignore ================================================ project-parent/ion-java project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/ion-java/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/ion-java RUN git clone --recursive https://github.com/amazon-ion/ion-java.git $SRC/project-parent/ion-java COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/ion-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=ion-java PROJECT_GROUP_ID=com.amazon.ion PROJECT_ARTIFACT_ID=ion-java MAIN_REPOSITORY=https://github.com/amazon-ion/ion-java/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT # set_project_version_in_fuzz_targets_dependency pushd $PROJECT export ION_JAVA_VERSION=$(cat ./project.version) popd #install - use shadowJar instead of publishToMavenLocal to avoid ProGuard issues # The ProGuard minifyJar task fails because Gradle toolchain downloads a different JDK # than the one running Gradle, causing library jars to be missing. (cd $PROJECT && ./gradlew shadowJar --info --stacktrace -x javadoc) # Manually install the shadowJar to local Maven repository # The shadowJar uses "shaded" classifier, so the file is named ion-java-VERSION-shaded.jar $MVN install:install-file \ -Dfile=$PROJECT/build/libs/ion-java-$ION_JAVA_VERSION-shaded.jar \ -DgroupId=com.amazon.ion \ -DartifactId=ion-java \ -Dversion=$ION_JAVA_VERSION \ -Dpackaging=jar \ -Dmaven.repo.local=$OUT/m2 $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/ion-java/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.junit.platform junit-platform-launcher 1.9.2 com.amazon.ion ion-java ${env.ION_JAVA_VERSION} maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/ion-java/project-parent/fuzz-targets/src/test/java/com/example/IonReaderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.amazon.ion.*; import com.amazon.ion.system.IonReaderBuilder; import java.io.IOException; class IonReaderFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { IonReader reader = IonReaderBuilder .standard() .withIncrementalReadingEnabled(data.consumeBoolean()) .build(data.consumeRemainingAsString()); read(reader); reader.close(); } catch (IOException | IllegalStateException | IllegalArgumentException | IonException e) { // Need to be caught to get more interesting findings. } } void read(IonReader reader) { reader.next(); reader.stepIn(); reader.next(); reader.getFieldName(); reader.stringValue(); reader.stepOut(); } } ================================================ FILE: projects/ion-java/project-parent/fuzz-targets/src/test/java/com/example/IonWriterFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.amazon.ion.*; import com.amazon.ion.system.IonReaderBuilder; import com.amazon.ion.system.IonTextWriterBuilder; import com.amazon.ion.system.IonBinaryWriterBuilder; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; import static com.amazon.ion.system.IonTextWriterBuilder.ASCII; import static com.amazon.ion.system.IonTextWriterBuilder.UTF8; class IonWriterFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { int cn = 15; int dummyNum = data.consumeInt(0, 2^cn - 1); IonTextWriterBuilder ionTextWriterBuilder = null; IonBinaryWriterBuilder ionBinaryWriterBuilder = null; try { for (int bit = 0; bit < cn; ++bit) { if (((dummyNum >> bit) & 1) == 1) { switch (bit) { case 0: ionTextWriterBuilder = ionTextWriterBuilder.json(); break; case 1: ionTextWriterBuilder = ionTextWriterBuilder.minimal(); break; case 2: ionTextWriterBuilder = ionTextWriterBuilder.pretty(); break; case 3: ionTextWriterBuilder = ionTextWriterBuilder.standard(); break; case 4: ionTextWriterBuilder = ionTextWriterBuilder.withCharset(data.pickValue(new Charset[] {ASCII, UTF8})); break; case 5: ionTextWriterBuilder = ionTextWriterBuilder.withJsonDowngrade(); break; case 6: ionTextWriterBuilder = ionTextWriterBuilder.withMinimalSystemData(); break; case 7: ionTextWriterBuilder = ionTextWriterBuilder.withPrettyPrinting(); break; case 8: ionTextWriterBuilder = ionTextWriterBuilder.withWriteTopLevelValuesOnNewLines(data.consumeBoolean()); break; case 9: ionBinaryWriterBuilder = ionBinaryWriterBuilder.standard(); break; case 10: ionBinaryWriterBuilder = ionBinaryWriterBuilder.withFloatBinary32Disabled(); break; case 11: ionBinaryWriterBuilder = ionBinaryWriterBuilder.withFloatBinary32Enabled(); break; case 12: ionBinaryWriterBuilder = ionBinaryWriterBuilder.withLocalSymbolTableAppendDisabled(); break; case 13: ionBinaryWriterBuilder = ionBinaryWriterBuilder.withLocalSymbolTableAppendEnabled(); break; case 14: ionBinaryWriterBuilder = ionBinaryWriterBuilder.withStreamCopyOptimized(data.consumeBoolean()); break; } } } ByteArrayOutputStream out = new ByteArrayOutputStream(); String input = data.consumeRemainingAsString(); IonWriter ionWriter = ionTextWriterBuilder.build(out); rewrite(input, ionWriter); ionWriter.close(); ionWriter = ionBinaryWriterBuilder.build(out); rewrite(input, ionWriter); ionWriter.close(); } catch (IOException | NullPointerException | IllegalArgumentException | IonException | AssertionError e) { // Need to be caught to get more interesting findings. } } void rewrite(String textIon, IonWriter writer) throws IOException { try (IonReader reader = IonReaderBuilder.standard().build(textIon)) { writer.writeValues(reader); } } } ================================================ FILE: projects/ion-java/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom fuzz-targets ================================================ FILE: projects/ion-java/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/amazon-ion/ion-java/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/amazon-ion/ion-java/" sanitizers: - address auto_ccs: - "ion-team@amazon.com" ================================================ FILE: projects/ipaddress/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/phihag/ipaddress ipaddress COPY *.sh *py $SRC/ WORKDIR $SRC/ipaddress ================================================ FILE: projects/ipaddress/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/ipaddress/fuzz_ip_address.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import ipaddress def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) val_1 = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 1024)) try: ipaddress.ip_address(val_1) except (ValueError,ipaddress.AddressValueError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipaddress/fuzz_ip_interface.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import ipaddress def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) val_1 = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 1024)) try: ipaddress.ip_interface(val_1) except (ValueError,ipaddress.AddressValueError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipaddress/fuzz_ip_network.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-1 # Imports by the generated code import ipaddress def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) val_1 = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1, 1024)) try: ipaddress.ip_network(val_1) except (ValueError,ipaddress.AddressValueError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipaddress/project.yaml ================================================ homepage: https://github.com/phihag/ipaddress main_repo: https://github.com/phihag/ipaddress language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/iperf/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool libssl-dev RUN git clone --depth 1 https://github.com/esnet/iperf iperf WORKDIR iperf COPY build.sh $SRC/ COPY *_fuzzer.c $SRC/ ================================================ FILE: projects/iperf/auth_fuzzer.c ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include // Declaration of the function from iperf_auth.c (it is not static) int Base64Decode(const char* b64message, unsigned char** buffer, size_t* length); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Base64Decode expects a null-terminated string. char *str = (char *)malloc(size + 1); if (!str) { return 0; } memcpy(str, data, size); str[size] = '\0'; unsigned char *buffer = NULL; size_t length = 0; // Call the target function Base64Decode(str, &buffer, &length); if (buffer) { free(buffer); } free(str); return 0; } ================================================ FILE: projects/iperf/build.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build the project to ensure headers are generated if needed ./configure --enable-static --disable-shared make -j$(nproc) # Build the cJSON fuzzer # We link against src/cjson.c directly as it is a standalone file in the source $CC $CFLAGS -Isrc -c $SRC/cjson_fuzzer.c -o cjson_fuzzer.o $CC $CFLAGS -Isrc -c src/cjson.c -o cjson.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE cjson_fuzzer.o cjson.o -lm -o $OUT/cjson_fuzzer # Build the auth fuzzer $CC $CFLAGS -Isrc -DHAVE_SSL -c $SRC/auth_fuzzer.c -o auth_fuzzer.o $CC $CFLAGS -Isrc -DHAVE_SSL -c src/iperf_auth.c -o iperf_auth.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE auth_fuzzer.o iperf_auth.o -lssl -lcrypto -o $OUT/auth_fuzzer ================================================ FILE: projects/iperf/cjson_fuzzer.c ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include "cjson.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // cJSON_Parse expects a null-terminated string. char *str = (char *)malloc(size + 1); if (!str) { return 0; } memcpy(str, data, size); str[size] = '\0'; cJSON *json = cJSON_Parse(str); if (json) { cJSON_Delete(json); } free(str); return 0; } ================================================ FILE: projects/iperf/project.yaml ================================================ homepage: "https://github.com/esnet/iperf" language: c++ sanitizers: - address - undefined - memory main_repo: "https://github.com/esnet/iperf" primary_contact: "javanlacerda@google.com" auto_ccs: - "pedroysb@google.com" - "david@adalogics.com" - "cloud-ti-fuzzing+bugs@google.com" base_os_version: ubuntu-24-04 ================================================ FILE: projects/ipfs/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/ipfs/go-datastore COPY build.sh $SRC/ WORKDIR $SRC/go-datastore ================================================ FILE: projects/ipfs/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd fuzz function compile_ds_fuzzer { fuzzer=$1 if [ $# == 2 ]; then rm provider* || true DS_PROVIDERS="$2" go generate fi compile_go_fuzzer github.com/ipfs/go-datastore/fuzz Fuzz $fuzzer } compile_ds_fuzzer ipfs_ds_flatfs compile_ds_fuzzer ipfs_ds_pebble "github.com/ipfs/go-ds-pebble" ================================================ FILE: projects/ipfs/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/ipfs/go-datastore" primary_contact: "will.scott@protocol.ai" auto_ccs : - "stebalien@protocol.ai" - "yolan@protocol.ai" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/ipfs/go-datastore' ================================================ FILE: projects/ipp-usb/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt-get update && apt-get install -y \ make \ pkg-config \ libusb-1.0-0-dev \ libudev-dev \ libudev1 \ libavahi-client-dev \ libavahi-common-dev \ libavahi-client3 \ libavahi-core7 \ libavahi-common3 \ linux-tools-generic \ kmod \ && rm -rf /var/lib/apt/lists/* RUN git clone --depth 1 https://github.com/OpenPrinting/ipp-usb $SRC/ipp-usb RUN git clone --depth 1 https://github.com/OpenPrinting/go-mfp $SRC/go-mfp RUN git clone --depth 1 https://github.com/OpenPrinting/fuzzing $SRC/fuzzing WORKDIR $SRC/fuzzing COPY build.sh $SRC/ ================================================ FILE: projects/ipp-usb/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ chmod +x $SRC/fuzzing/projects/ipp-usb/oss_fuzz_build.sh $SRC/fuzzing/projects/ipp-usb/oss_fuzz_build.sh ================================================ FILE: projects/ipp-usb/project.yaml ================================================ homepage: "https://github.com/OpenPrinting/ipp-usb" main_repo: "https://github.com/OpenPrinting/ipp-usb" primary_contact: "mdimad005@gmail.com" auto_ccs: - "till.kamppeter@gmail.com" - "ossfuzz@iosifache.me" - "jiongchiyu@gmail.com" - "pzz@apevzner.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/ipykernel/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN pip3 install --upgrade pip ipyparallel RUN git clone https://github.com/ipython/ipykernel ipykernel COPY *.sh *py $SRC/ WORKDIR $SRC/ipykernel ================================================ FILE: projects/ipykernel/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/ipykernel/fuzz_serialization_roundtrip.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import ipykernel from ipykernel.serialize import deserialize_object, serialize_object def ConsumeRandomLengthBufferList(fdp): """Creates a list of buffers of various lengths""" buffers = [] max_range = fdp.ConsumeIntInRange(1, 50) for _ in range(1, max_range): buffers.append(fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 200))) return buffers def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: deserialized_obj = deserialize_object(ConsumeRandomLengthBufferList(fdp)) except Exception: return # Any deserizlied object should be serializable serialize_object(deserialized_obj) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipykernel/fuzz_unpack_roundtrip.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import ipykernel from ipykernel.serialize import unpack_apply_message, pack_apply_message def ConsumeRandomLengthBufferList(fdp): """Creates a list of buffers of various lengths""" buffers = [] max_range = fdp.ConsumeIntInRange(3, 50) for _ in range(3, max_range): buffers.append(fdp.ConsumeBytes(fdp.ConsumeIntInRange(0, 200))) return buffers def TestOneInput(data): if len(data) < 48: return fdp = atheris.FuzzedDataProvider(data) try: buffers = ConsumeRandomLengthBufferList(fdp) f, args, kwargs = unpack_apply_message(buffers) except Exception: return # Anything unpackable, should be packable. pack_apply_message(f, args, kwargs) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipykernel/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: https://github.com/ipython/ipykernel main_repo: https://github.com/ipython/ipykernel language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/ipython/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y python3.12 python3.12-dev python3.12-venv && \ rm -f /usr/lib/python3.12/EXTERNALLY-MANAGED && \ update-alternatives --install /usr/local/bin/python3 python3 /usr/bin/python3.12 1 && \ curl -sS https://bootstrap.pypa.io/get-pip.py | python3 && \ python3 -m pip install pyinstaller atheris RUN git clone --depth 1 https://github.com/ipython/ipython WORKDIR $SRC COPY build.sh fuzz_* $SRC/ ================================================ FILE: projects/ipython/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd ipython python3 -m pip install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/ipython/fuzz_inputsplitter.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from IPython.core.splitinput import split_user_input def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) user_input = fdp.ConsumeUnicode(sys.maxsize) pre, esc, ifun, rest = split_user_input(user_input) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/ipython/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: ipython.readthedocs.org language: python main_repo: https://github.com/ipython/ipython base_os_version: ubuntu-24-04 sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/iroha/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN set -e; \ apt-get update && \ apt-get -y --no-install-recommends install libicu-dev \ apt-utils git curl wget unzip tar; \ apt-get -y clean RUN git clone --depth 1 --single-branch --branch master https://github.com/hyperledger/iroha.git WORKDIR iroha RUN cp -R $SRC/iroha/vcpkg /tmp/vcpkg-vars RUN ["bash", "/tmp/vcpkg-vars/oss/build_deps.sh"] COPY build.sh $SRC/ ================================================ FILE: projects/iroha/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/iroha ./clean.sh mkdir build cd build cmake -DCMAKE_TOOLCHAIN_FILE=/opt/dependencies/scripts/buildsystems/vcpkg.cmake -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DFUZZING=ON .. make fuzzing cp test_bin/* $OUT/ ================================================ FILE: projects/iroha/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/hyperledger/iroha" language: c++ primary_contact: "boldrev@soramitsu.co.jp" auto_ccs: - "andrei@soramitsu.co.jp" - "kovalev@soramitsu.co.jp" - "igor@soramitsu.co.jp" - "gorbachev@soramitsu.co.jp" sanitizers: - address main_repo: 'https://github.com/hyperledger/iroha.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/irssi/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y pkg-config libncurses5-dev libssl-dev python3-pip RUN pip3 install -U meson ninja RUN git clone https://github.com/irssi/irssi WORKDIR irssi COPY run_tests.sh build.sh *.options *.dict $SRC/ ================================================ FILE: projects/irssi/build.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # setup BUILD=$WORK/Build fuzz_targets=( src/fe-fuzz/irssi-fuzz src/fe-fuzz/server-fuzz src/fe-fuzz/irc/core/event-get-params-fuzz src/fe-fuzz/fe-common/core/theme-load-fuzz ) if [ "$FUZZING_ENGINE" = honggfuzz ]; then export CC="$SRC"/"$FUZZING_ENGINE"/hfuzz_cc/hfuzz-clang export CXX="$SRC"/"$FUZZING_ENGINE"/hfuzz_cc/hfuzz-clang++ # hfuzz compilers automatically link libhfuzz, so pass empty fuzzer-lib # to avoid double-linking FUZZER_LIB_FLAG="" else FUZZER_LIB_FLAG="-Dwith-fuzzer-lib=$LIB_FUZZING_ENGINE" fi # cleanup rm -rf "$BUILD" mkdir -p "$BUILD" # Configure the project. meson "$BUILD" -Dstatic-dependency=yes -Dinstall-glib=force \ -Dwith-fuzzer=yes $FUZZER_LIB_FLAG \ -Dfuzzer-link-language=cpp \ || ( cat "$BUILD"/meson-logs/meson-log.txt && false ) # now build all fuzz targets ninja -C "$BUILD" -v "${fuzz_targets[@]}" ( cd "$BUILD" && mv "${fuzz_targets[@]}" "$OUT" ) git clone --depth 1 https://github.com/irssi-import/themes theme-load-fuzz_corpus git clone --depth 1 https://github.com/irssi/irssi-fuzzing-corpora find theme-load-fuzz_corpus -mindepth 1 -maxdepth 1 \( -type d -o \! -name \*.theme \) -exec rm -fr {} + zip -q -j "$OUT"/theme-load-fuzz_seed_corpus.zip theme-load-fuzz_corpus/* zip -q -j "$OUT"/irssi-fuzz_seed_corpus.zip irssi-fuzzing-corpora/irssi-fuzz-corpus/* zip -q -j "$OUT"/server-fuzz_seed_corpus.zip irssi-fuzzing-corpora/server-fuzz-corpus/* # get tokens.txt dictionary from irssi/src/fe-fuzz/ cp src/fe-fuzz/tokens.txt "$OUT"/server-fuzz.dict cp "$SRC"/*.options "$SRC"/*.dict "$OUT"/ ================================================ FILE: projects/irssi/irssi-fuzz.options ================================================ [libfuzzer] max_len = 2048 ================================================ FILE: projects/irssi/project.yaml ================================================ homepage: "https://github.com/irssi/irssi" language: c++ primary_contact: "ahf@irssi.org" auto_ccs: - "dx@dxzone.com.ar" - "joseph.bisch@gmail.com" - "ailin.nemui@gmail.com" - "staff@irssi.org" sanitizers: - address - undefined main_repo: 'https://github.com/irssi/irssi' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/irssi/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable leak sanitizer and run unit test export ASAN_OPTIONS="detect_leaks=0" meson test -C $WORK/Build ================================================ FILE: projects/irssi/theme-load-fuzz.dict ================================================ "{" "}" "\"" ";" "=" "formats" "replaces" "abstracts" "timestamp" ================================================ FILE: projects/isodate/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/gweis/isodate isodate COPY *.sh *py $SRC/ WORKDIR $SRC/isodate ================================================ FILE: projects/isodate/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/isodate/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import isodate def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: isodate.isodates.parse_date(fdp.ConsumeUnicodeNoSurrogates(1024)) except ( # parse_date can legitimately raise two types of exceptions: # https://github.com/gweis/isodate/blob/8856fdf0e46c7bca00229faa1aae6b7e8ad6e76c/src/isodate/isodates.py#L150-L151 isodate.ISO8601Error, ValueError, ): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/isodate/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/gweis/isodate language: python main_repo: https://github.com/gweis/isodate sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/istio/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Setup the builder for Istio. The standard Go builder is sufficient. FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/istio/istio RUN git clone --depth 1 --branch oss-fuzz-build-ref https://github.com/AdamKorcz/istio $SRC/temp-istio RUN git clone --depth 1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=v2_2 COPY build.sh $SRC/ WORKDIR $SRC/istio ================================================ FILE: projects/istio/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/go-118-fuzz-build go build mv go-118-fuzz-build $GOPATH/bin/go-118-fuzz-build_v2 pushd cmd/convertLibFuzzerTestcaseToStdLibGo go build . && mv convertLibFuzzerTestcaseToStdLibGo $GOPATH/bin/ popd pushd cmd/addStdLibCorpusToFuzzer go build . && mv addStdLibCorpusToFuzzer $GOPATH/bin/ popd cd $SRC/istio cp $SRC/temp-istio/tests/fuzz/oss_fuzz_build.sh $SRC/istio/tests/fuzz/ # Build fuzzers if [ -n "${OSS_FUZZ_CI-}" ] then echo "Skipping most fuzzers since the OSS-fuzz CI may fail from running out of disk space." compile_go_fuzzer istio.io/istio/tests/fuzz FuzzCRDRoundtrip fuzz_crd_roundtrip else $SRC/istio/tests/fuzz/oss_fuzz_build.sh fi ================================================ FILE: projects/istio/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/istio/istio" primary_contact: "istio-security-vulnerability-reports@googlegroups.com" auto_ccs : - "adam@adalogics.com" - "john.howard@solo.io" - "kconner@redhat.com" - "jdpettit@google.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/istio/istio' ================================================ FILE: projects/istio-ztunnel/Dockerfile ================================================ # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get --yes update \ && apt-get install --no-install-recommends --yes \ librust-clang-sys-dev \ protobuf-compiler \ libprotobuf-dev \ && apt-get clean \ && rm --recursive --force /var/lib/apt/lists/* RUN git clone --depth 1 https://github.com/istio/ztunnel COPY build.sh $SRC/ WORKDIR $SRC/ztunnel ================================================ FILE: projects/istio-ztunnel/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cargo fuzz build --release --debug-assertions FUZZ_TARGET_OUTPUT_DIR=out/rust/x86_64-unknown-linux-gnu/release for f in fuzz/fuzz_targets/*.rs do FUZZ_TARGET_NAME=$(basename ${f%.*}) cp $FUZZ_TARGET_OUTPUT_DIR/$FUZZ_TARGET_NAME $OUT/ done ================================================ FILE: projects/istio-ztunnel/project.yaml ================================================ homepage: "https://github.com/istio/ztunnel" main_repo: 'https://github.com/istio/ztunnel' primary_contact: "istio-security-vulnerability-reports@googlegroups.com" auto_ccs : - "adam@adalogics.com" - "howardjohn@google.com" - "gregory.hanson@solo.io" language: rust fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/itext7/.gitignore ================================================ project-parent/itext7 project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/itext7/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing RUN cp fuzzing/dictionaries/pdf.dict $SRC/PdfFuzzer.dict RUN git clone --depth 1 https://github.com/strongcourage/fuzzing-corpus.git && \ zip -q -r -j $SRC/PdfFuzzer_seed_corpus.zip fuzzing-corpus/pdf/* COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/itext7 RUN git clone --depth 1 https://github.com/itext/itext7 $SRC/project-parent/itext7 COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/itext7/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=itext7 PROJECT_GROUP_ID=com.itextpdf PROJECT_ARTIFACT_ID=kernel MAIN_REPOSITORY=https://github.com/itext/itext7 function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install mvn -pl $PROJECT install -DskipTests mvn -pl $PROJECT/kernel install -DskipTests #only build kernel subproject (root is useless) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install $MVN -pl $PROJECT install -DskipTests -Dmaven.repo.local=$OUT/m2 $MVN -pl $PROJECT/kernel install -DskipTests -Dmaven.repo.local=$OUT/m2 $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes # RUNTIME_CLASSPATH="$(cat fuzz-targets/cp.txt):$OUT/test-classes" RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/itext7/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test com.itextpdf kernel Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/itext7/project-parent/fuzz-targets/src/test/java/com/example/PdfFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import java.io.*; import java.nio.charset.StandardCharsets; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.io.exceptions.*; public class PdfFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { InputStream stream = new ByteArrayInputStream(data.consumeRemainingAsString().getBytes(StandardCharsets.UTF_8)); PdfReader reader = new PdfReader(stream); PdfDocument pdfDoc = new PdfDocument(reader); } /* Catching multiple exceptions and errors in order to allow fuzzing to continue to the most intresting findings. As of this commit, libfuzzer is triggering com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow in local testing. Once that issue is addressed, further testing can be performed by a removing some of these caught exceptions and errors. In particular, the java.lang.AssertionError may be a bug that should be addressed. */ catch (java.io.IOException | com.itextpdf.io.exceptions.IOException | com.itextpdf.kernel.exceptions.PdfException | java.lang.AssertionError | java.lang.ClassCastException | java.lang.StringIndexOutOfBoundsException e) { } } } ================================================ FILE: projects/itext7/project-parent/fuzz-targets/src/test/resources/junit-platform.properties ================================================ jazzer.instrument=com.example.**,com.other.package.**,org.jsoup.** ================================================ FILE: projects/itext7/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom itext7 fuzz-targets ================================================ FILE: projects/itext7/project.yaml ================================================ homepage: "https://itextpdf.com/products/itext-7" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/itext/itext7" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "michael.nothhard@code-intelligence.com" ================================================ FILE: projects/itoa/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/dtolnay/itoa WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/itoa/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC cd itoa cargo fuzz build -O cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_itoa $OUT/ ================================================ FILE: projects/itoa/project.yaml ================================================ homepage: "https://github.com/dtolnay/itoa" primary_contact: "dtolnay@gmail.com" main_repo: "https://github.com/dtolnay/itoa" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "adetaylor@chromium.org" ================================================ FILE: projects/itsdangerous/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/pallets/itsdangerous itsdangerous COPY *.sh *py $SRC/ WORKDIR $SRC/itsdangerous ================================================ FILE: projects/itsdangerous/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/itsdangerous/fuzz_itsdangerous.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import json import atheris from itsdangerous.serializer import Serializer def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) secret_key = fdp.ConsumeUnicodeNoSurrogates(124) salt = fdp.ConsumeBytes(24) try: random_obj = json.loads(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except: return serializer = Serializer(secret_key = secret_key) signed = serializer.dumps(random_obj, salt=salt) assert serializer.loads(signed, salt=salt) == random_obj def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/itsdangerous/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pallets/itsdangerous language: python main_repo: https://github.com/pallets/itsdangerous sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/iverilog/project.yaml ================================================ homepage: "https://steveicarus.github.io/iverilog" language: c++ primary_contact: "steve@icarus.com" auto_ccs: - "capuanobailey@gmail.com" main_repo: "https://github.com/steveicarus/iverilog" ================================================ FILE: projects/ja3/project.yaml ================================================ homepage: "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967/" language: python primary_contact: "jalthouse@salesforce.com" auto_ccs: - "ennamarie19@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/salesforce/ja3.git" ================================================ FILE: projects/jackson-core/DataInputFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JsonParser; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.json.JsonFactoryBuilder; import tools.jackson.core.Base64Variants; import tools.jackson.databind.ObjectMapper; import tools.jackson.core.json.JsonReadFeature; import tools.jackson.core.StreamReadFeature; import tools.jackson.core.JacksonException; import java.io.*; public class DataInputFuzzer { public static class MockFuzzDataInput implements DataInput { private final InputStream _input; public MockFuzzDataInput(byte[] data) { _input = new ByteArrayInputStream(data); } public MockFuzzDataInput(String utf8Data) throws IOException { _input = new ByteArrayInputStream(utf8Data.getBytes("UTF-8")); } public MockFuzzDataInput(InputStream in) { _input = in; } @Override public void readFully(byte[] b) throws IOException { throw new UnsupportedOperationException(); } @Override public void readFully(byte[] b, int off, int len) throws IOException { throw new UnsupportedOperationException(); } @Override public int skipBytes(int n) throws IOException { return (int) _input.skip(n); } @Override public boolean readBoolean() throws IOException { throw new UnsupportedOperationException(); } @Override public byte readByte() throws IOException { int ch = _input.read(); if (ch < 0) { throw new EOFException("End-of-input for readByte()"); } return (byte) ch; } @Override public int readUnsignedByte() throws IOException { return readByte() & 0xFF; } @Override public short readShort() throws IOException { throw new UnsupportedOperationException(); } @Override public int readUnsignedShort() throws IOException { throw new UnsupportedOperationException(); } @Override public char readChar() throws IOException { throw new UnsupportedOperationException(); } @Override public int readInt() throws IOException { throw new UnsupportedOperationException(); } @Override public long readLong() throws IOException { throw new UnsupportedOperationException(); } @Override public float readFloat() throws IOException { throw new UnsupportedOperationException(); } @Override public double readDouble() throws IOException { throw new UnsupportedOperationException(); } @Override public String readLine() throws IOException { throw new UnsupportedOperationException(); } @Override public String readUTF() throws IOException { throw new UnsupportedOperationException(); } } public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonReadFeature[] readFeatures = new JsonReadFeature[]{ JsonReadFeature.ALLOW_JAVA_COMMENTS, JsonReadFeature.ALLOW_YAML_COMMENTS, JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES, JsonReadFeature.ALLOW_SINGLE_QUOTES, JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS, JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS, JsonReadFeature.ALLOW_LEADING_PLUS_SIGN_FOR_NUMBERS, JsonReadFeature.ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS, JsonReadFeature.ALLOW_TRAILING_DECIMAL_POINT_FOR_NUMBERS, JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS, JsonReadFeature.ALLOW_MISSING_VALUES, JsonReadFeature.ALLOW_TRAILING_COMMA, }; StreamReadFeature[] streamFeatures = new StreamReadFeature[]{ StreamReadFeature.AUTO_CLOSE_SOURCE, StreamReadFeature.STRICT_DUPLICATE_DETECTION, StreamReadFeature.IGNORE_UNDEFINED, StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION, StreamReadFeature.USE_FAST_DOUBLE_PARSER, }; // Configure features using builder pattern JsonFactoryBuilder builder = JsonFactory.builder(); for (int i = 0; i < readFeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(readFeatures[i]); } else { builder.disable(readFeatures[i]); } } for (int i = 0; i < streamFeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(streamFeatures[i]); } else { builder.disable(streamFeatures[i]); } } JsonFactory jf = builder.build(); try { int typeOfNext = data.consumeInt(); JsonParser jp = jf.createParser(data.consumeRemainingAsBytes()); switch (typeOfNext%8) { case 0: while (jp.nextToken() != null) { ; } break; case 1: while (jp.nextValue() != null) { ; } break; case 2: while (jp.nextName() != null) { ; } break; case 3: ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Base64Variants b64vs = new Base64Variants(); jp.readBinaryValue(b64vs.MIME, outputStream); break; case 4: String outString = jp.getValueAsString(); break; case 5: int outInt = jp.getValueAsInt(); break; case 6: char[] textChars = jp.getTextCharacters(); break; case 7: int textLen = jp.getTextLength(); int textOffset = jp.getTextOffset(); break; } } catch (JacksonException | IllegalArgumentException ignored) { } } } ================================================ FILE: projects/jackson-core/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN apt-get update && apt-get install -y maven RUN git clone --depth 1 https://github.com/google/fuzzing RUN cat fuzzing/dictionaries/json.dict > $SRC/JsonFuzzer.dict RUN cat fuzzing/dictionaries/json.dict > $SRC/DataInputFuzzer.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JsonFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -j $SRC/DataInputFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* RUN git clone --depth 1 https://github.com/FasterXML/jackson-core RUN git clone --depth 1 https://github.com/FasterXML/jackson-databind RUN git clone --depth 1 https://github.com/FasterXML/jackson-annotations COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/jackson-core/JsonFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JsonParser; import tools.jackson.databind.ObjectMapper; import tools.jackson.core.json.JsonReadFeature; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.json.JsonFactoryBuilder; import tools.jackson.core.JacksonException; public class JsonFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Configure JsonFactory with features using builder pattern JsonFactoryBuilder builder = JsonFactory.builder(); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_JAVA_COMMENTS); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_SINGLE_QUOTES); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_YAML_COMMENTS); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_TRAILING_COMMA); if (data.consumeBoolean()) builder.enable(JsonReadFeature.ALLOW_NON_NUMERIC_NUMBERS); JsonFactory factory = builder.build(); ObjectMapper mapper = new ObjectMapper(factory); try { mapper.readTree(data.consumeRemainingAsBytes()); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-core/ParseNextTokenFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JsonParser; import tools.jackson.core.Base64Variant; import tools.jackson.core.Base64Variants; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.io.SerializedString; import java.io.Writer; import java.io.StringWriter; import tools.jackson.core.JacksonException; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.InputStream; public class ParseNextTokenFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonFactory jf = new JsonFactory(); JsonParser jp; try { jp = jf.createParser(data.consumeRemainingAsBytes()); for (int i = 0;i < data.consumeInt(3, 1000); i++) { int execType = data.consumeInt(0, 17); if (execType==0) { InputStream myInputStream = new ByteArrayInputStream(data.consumeRemainingAsBytes()); jp = jf.createParser(myInputStream); } else if(execType==1) { jp.nextToken(); } else if(execType==2) { jp.nextStringValue(); } else if(execType==3) { jp.nextBooleanValue(); } else if(execType==4) { jp.nextName(); } else if(execType==5) { jp.nextName(new SerializedString(data.consumeString(10000))); } else if(execType==6) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); Base64Variant orig = Base64Variants.PEM; jp.readBinaryValue(orig, bytes); } else if(execType==7) { String outString = jp.getValueAsString(); } else if(execType==8) { int outInt = jp.getValueAsInt(); } else if(execType==9) { String text = jp.getText(); } else if(execType==10) { char[] textChars = jp.getTextCharacters(); } else if(execType==11) { int textLen = jp.getTextLength(); } else if(execType==12) { int textOffset = jp.getTextOffset(); } else if(execType==13) { jp.getBinaryValue(Base64Variants.PEM); } else if(execType==14) { jp.nextIntValue(data.consumeInt()); } else if(execType==15) { jp.nextLongValue(data.consumeLong()); } else if(execType==16) { jp.finishToken(); } } } catch (JacksonException | IllegalArgumentException ignored) { } } } ================================================ FILE: projects/jackson-core/UTF8GeneratorFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.StringReader; import java.io.InputStream; import java.math.BigDecimal; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.Base64Variant; import tools.jackson.core.Base64Variants; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.json.UTF8JsonGenerator; import tools.jackson.core.JsonGenerator; import tools.jackson.core.StreamWriteFeature; import tools.jackson.core.SerializableString; import tools.jackson.core.io.SerializedString; import tools.jackson.core.JacksonException; public class UTF8GeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonFactory jf = new JsonFactory(); ByteArrayOutputStream out = new ByteArrayOutputStream(); String fuzzString; JsonGenerator g; int offset; byte[] b; Base64Variant b64v; StreamWriteFeature[] features = new StreamWriteFeature[]{ StreamWriteFeature.AUTO_CLOSE_TARGET, StreamWriteFeature.AUTO_CLOSE_CONTENT, StreamWriteFeature.FLUSH_PASSED_TO_STREAM, StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN, StreamWriteFeature.STRICT_DUPLICATE_DETECTION, StreamWriteFeature.IGNORE_UNKNOWN, }; try { g = jf.createGenerator(out); for (int i = 0; i < features.length; i++) { if (data.consumeBoolean()) { g.configure(features[i], true); } else { g.configure(features[i], false); } } } catch (JacksonException ignored) { return; } int numberOfOps = data.consumeInt(); for (int i = 0; i < numberOfOps%20; i++) { try { int apiType = data.consumeInt(); switch(apiType%13) { case 0: fuzzString = data.consumeString(1000000); StringReader targetReader = new StringReader(fuzzString); g.writeStartArray(); g.writeString(targetReader, fuzzString.length()); g.writeEndArray(); case 1: fuzzString = data.consumeString(1000000); g.writeStartArray(); g.writeString(fuzzString); g.writeEndArray(); case 2: fuzzString = data.consumeString(1000000); SerializableString ss = new SerializedString(fuzzString); g.writeStartArray(); g.writeString(ss); g.writeEndArray(); case 3: fuzzString = data.consumeString(1000000); g.writeStartArray(); g.writeRaw(fuzzString); g.writeEndArray(); case 4: fuzzString = data.consumeString(1000000); offset = data.consumeInt(); g.writeStartArray(); g.writeRaw(fuzzString, offset, fuzzString.length()); g.writeEndArray(); case 5: String key = data.consumeString(1000000); String value = data.consumeString(1000000); g.writeStartObject(); g.writeStringProperty(key, value); g.writeEndObject(); case 6: b64v = Base64Variants.getDefaultVariant(); b = data.consumeBytes(1000000); offset = data.consumeInt(); g.writeStartArray(); g.writeBinary(b64v, b, offset, b.length); g.writeEndArray(); case 7: b = data.consumeBytes(1000000); offset = data.consumeInt(); g.writeStartObject(); g.writeUTF8String(b, offset, b.length); g.writeEndObject(); case 8: b64v = Base64Variants.getDefaultVariant(); b = data.consumeBytes(1000000); int l = data.consumeInt(); InputStream targetStream = new ByteArrayInputStream(b); g.writeStartArray(); g.writeBinary(b64v, targetStream, l); g.writeEndArray(); case 9: String dcString = data.consumeString(10); BigDecimal BD = new BigDecimal(dcString); g.writeNumber(BD); case 10: int fuzzInt = data.consumeInt(); g.writeNumber(fuzzInt); case 11: float fuzzFloat = data.consumeFloat(); g.writeNumber(fuzzFloat); case 12: fuzzString = data.consumeString(100000); g.writeNumber(fuzzString); } } catch (JacksonException | IllegalArgumentException ignored) { } } try { g.close(); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-core/WriterBasedJsonGeneratorFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.json.*; import tools.jackson.core.io.ContentReference; import tools.jackson.core.io.IOContext; import tools.jackson.core.util.BufferRecycler; import tools.jackson.core.JsonGenerator; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.JacksonException; import java.io.*; import tools.jackson.core.io.SerializedString; import tools.jackson.core.SerializableString; public class WriterBasedJsonGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonFactory jf = new JsonFactory(); StringWriter w; JsonGenerator jg; try { w = new StringWriter(); jg = jf.createGenerator(w); } catch (JacksonException e) { return; } try { int numberOfOps = data.consumeInt(); for (int i=0;i $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-core/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/FasterXML/jackson-core" language: jvm primary_contact: "tatu@fasterxml.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/FasterXML/jackson-core" sanitizers: - address auto_ccs: - "Adam@adalogics.com" - "David@adalogics.com" - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/jackson-databind/AdaLObjectReader3Fuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.*; import java.util.regex.Pattern; import java.io.Reader; import java.io.StringReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.FileOutputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.io.File; import java.io.InputStream; import java.io.DataInput; import java.io.EOFException; import java.lang.IllegalArgumentException; import java.net.URI; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectReader; import tools.jackson.databind.DeserializationConfig; import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.MapperFeature; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.DefaultTyping; import tools.jackson.core.JsonParser; import tools.jackson.core.TreeNode; import tools.jackson.databind.json.JsonMapper; import tools.jackson.databind.node.ObjectNode; import tools.jackson.databind.JsonNode; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.JacksonException; // For NoCheckSubTypeValidator import tools.jackson.databind.JavaType; import tools.jackson.databind.cfg.MapperConfig; import tools.jackson.databind.DatabindContext; import tools.jackson.databind.jsontype.PolymorphicTypeValidator; public class AdaLObjectReader3Fuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { boolean doThis; byte[] fileData; int fuzzInt1, fuzzInt2; FileOutputStream out; Object o; Reader stringR; ObjectReader r, r2, r3; JsonParser jp; MapperFeature[] mapperfeatures = new MapperFeature[]{ MapperFeature.USE_ANNOTATIONS, MapperFeature.USE_GETTERS_AS_SETTERS, MapperFeature.PROPAGATE_TRANSIENT_MARKER, MapperFeature.REQUIRE_SETTERS_FOR_GETTERS, MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, MapperFeature.INFER_PROPERTY_MUTATORS, MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES, MapperFeature.ALLOW_VOID_VALUED_PROPERTIES, MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS, MapperFeature.USE_STATIC_TYPING, MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL, MapperFeature.DEFAULT_VIEW_INCLUSION, MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES, MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME, MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING, MapperFeature.ALLOW_COERCION_OF_SCALARS, MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE, MapperFeature.APPLY_DEFAULT_VALUES }; SerializationFeature[] serializationfeatures = new SerializationFeature[]{ SerializationFeature.WRAP_ROOT_VALUE, SerializationFeature.INDENT_OUTPUT, SerializationFeature.FAIL_ON_EMPTY_BEANS, SerializationFeature.FAIL_ON_SELF_REFERENCES, SerializationFeature.WRAP_EXCEPTIONS, SerializationFeature.CLOSE_CLOSEABLE, SerializationFeature.FLUSH_AFTER_WRITE_VALUE, SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS, SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, SerializationFeature.EAGER_SERIALIZER_FETCH, SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID }; DeserializationFeature[] deserializationfeatures = new DeserializationFeature[]{ DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, DeserializationFeature.USE_LONG_FOR_INTS, DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, DeserializationFeature.FAIL_ON_TRAILING_TOKENS, DeserializationFeature.WRAP_EXCEPTIONS, DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, DeserializationFeature.UNWRAP_ROOT_VALUE, DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, DeserializationFeature.ACCEPT_FLOAT_AS_INT, DeserializationFeature.EAGER_DESERIALIZER_FETCH }; DefaultTyping[] typings = new DefaultTyping[]{ DefaultTyping.JAVA_LANG_OBJECT, DefaultTyping.OBJECT_AND_NON_CONCRETE, DefaultTyping.NON_CONCRETE_AND_ARRAYS, DefaultTyping.NON_FINAL, DefaultTyping.NON_FINAL_AND_ENUMS }; ObjectMapper mapper; JsonMapper.Builder builder = JsonMapper.builder(); // Maybe create a mapper with different typing settings if (data.consumeBoolean()) { for (int i = 0; i < typings.length; i++) { if (data.consumeBoolean()) { builder.activateDefaultTyping(NoCheckSubTypeValidator.instance, typings[i]); } } } // Set mapper features via builder for (int i = 0; i < mapperfeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(mapperfeatures[i]); } else { builder.disable(mapperfeatures[i]); } } for (int i = 0; i < serializationfeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(serializationfeatures[i]); } else { builder.disable(serializationfeatures[i]); } } mapper = builder.build(); int idx = data.consumeInt(0, classes.length - 1); r = mapper.readerFor(classes[idx]); // To initialize switch (data.consumeInt(0, 4)) { case 0: r = mapper.readerFor(classes[idx]); case 1: r = mapper.readerForMapOf(classes[idx]); case 2: r = mapper.readerForListOf(classes[idx]); case 3: r = mapper.readerForArrayOf(classes[idx]); case 4: fuzzInt1 = data.consumeInt(0, classes.length - 1); r = r.forType(mapper.constructType(classes[fuzzInt1])); } // set reader settings for (int i = 0; i < deserializationfeatures.length; i++) { if (data.consumeBoolean()) { r = r.with(deserializationfeatures[i]); } else { r = r.without(deserializationfeatures[i]); } } try { // Select a method and call it int callType = data.consumeInt(); switch (callType%7) { case 0: // readValue switch (data.consumeInt(0, 14)){ case 0: r.readValue(data.consumeString(100000)); case 1: r.readValue(new MockFuzzDataInput(data.consumeString(100000))); case 2: r.readValue(data.consumeBytes(100000)); case 3: jp = _createParser(data, mapper, r); o = r.readValue(jp); doThis = data.consumeBoolean(); if (doThis) { r3 = r.withValueToUpdate(o); mapper.valueToTree(o); } case 4: jp = _createParser(data, mapper, r); fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readerFor(classes[fuzzInt1]).readValue(jp); case 5: jp = _createParser(data, mapper, r); fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readerFor(classes[fuzzInt1]).readValue(jp); case 6: stringR = new StringReader(new String(data.consumeBytes(100000))); r.readValue(stringR); case 7: fileData = data.consumeRemainingAsBytes(); out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); r.readValue(new File("fuzzFile")); case 8: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); r.readValue(data.consumeBytes(100000), fuzzInt1, fuzzInt2); case 9: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeBytes(100000), classes[fuzzInt1]); case 10: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeString(100000), classes[fuzzInt1]); case 11: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeBytes(1000000), data.consumeInt(), data.consumeInt(), classes[fuzzInt1]); case 12: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeBytes(1000000), mapper.constructType(classes[fuzzInt1])); case 13: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeString(1000000), mapper.constructType(classes[fuzzInt1])); case 14: r.readValue(new ByteArrayInputStream(data.consumeBytes(100000))); } case 1: // readTree switch (data.consumeInt(0, 7)){ case 0: jp = _createParser(data, mapper, r); o = r.readTree(jp); if (data.consumeBoolean()) { r3 = r.withValueToUpdate(o); mapper.valueToTree(o); mapper.readerForUpdating(o); } case 1: o = r.readTree(data.consumeString(100000)); if (data.consumeBoolean()) { r3 = r.withValueToUpdate(o); mapper.valueToTree(o); mapper.readerForUpdating(o); } case 2: o = r.readTree(data.consumeBytes(100000)); if (data.consumeBoolean()) { r3 = r.withValueToUpdate(o); mapper.valueToTree(o); mapper.readerForUpdating(o); } case 3: stringR = new StringReader(new String(data.consumeRemainingAsBytes())); r.readTree(stringR); case 4: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); r.readTree(data.consumeRemainingAsBytes(), fuzzInt1, fuzzInt2); case 5: mapper.readTree(data.consumeBytes(1000000)); case 6: mapper.readTree(data.consumeString(1000000)); case 7: fuzzInt1 = data.consumeInt(0, classes.length - 1); switch (data.consumeInt(0,1)) { case 0: mapper.readValue(data.consumeRemainingAsBytes(), classes[fuzzInt1]); case 1: mapper.readValue(data.consumeRemainingAsString(), classes[fuzzInt1]); } } case 2: _readValues(data, mapper, r); case 3: fuzzInt1 = data.consumeInt(0, classes.length - 1); fuzzInt2 = data.consumeInt(0, classes.length - 1); // addMixIn not available on immutable mapper in Jackson 3.x - skip case 4: JsonNode tree = mapper.readTree(data.consumeString(1000000)); JsonNode node = tree.at(data.consumeString(1000000)); doThis = data.consumeBoolean(); if (doThis) { fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.treeToValue(node, classes[fuzzInt1]); } doThis = data.consumeBoolean(); if (doThis) { fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.treeToValue(node, mapper.constructType(classes[fuzzInt1])); } doThis = data.consumeBoolean(); if (doThis) { r.readValue(node); } doThis = data.consumeBoolean(); fuzzInt1 = data.consumeInt(0, classes.length - 1); if (doThis) { mapper.treeToValue(node, classes[fuzzInt1]); } case 5: switch (data.consumeInt(0, 2)){ case 0: mapper.readTree(new ByteArrayInputStream(data.consumeBytes(100000))); case 1: ObjectNode src = (ObjectNode) mapper.readTree(data.consumeString(100000)); TreeNode tn = src; fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.treeToValue(tn, classes[fuzzInt1]); case 2: r.readTree(new MockFuzzDataInput(data.consumeString(100000))); } case 6: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.constructType(classes[fuzzInt1]); } // target with(); if (data.consumeBoolean()) { r2 = r.with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); } } catch (JacksonException | IOException | IllegalArgumentException | ClassCastException e) { } try { Files.delete(Paths.get("fuzzFile")); } catch (IOException e) { } } public static void _readValues(FuzzedDataProvider data, ObjectMapper mapper, ObjectReader r) throws IOException { Object o; ObjectReader r3; int fuzzInt1, fuzzInt2; JsonParser jp; byte[] fileData; FileOutputStream out; Reader stringR; // readValues switch (data.consumeInt(0, 8)){ case 0: stringR = new StringReader(new String(data.consumeRemainingAsBytes())); o = r.readValues(stringR); case 1: o = r.readValues(data.consumeRemainingAsString()); case 2: jp = _createParser(data, mapper, r); o = r.readValues(jp); case 3: fileData = data.consumeRemainingAsBytes(); out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); o = r.readValues(new File("fuzzFile")); case 4: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); o = r.readValues(data.consumeBytes(1000000), fuzzInt1, fuzzInt2); case 5: fuzzInt1 = data.consumeInt(0, classes.length - 1); jp = _createParser(data, mapper, r); o = mapper.readValues(jp, mapper.constructType(classes[fuzzInt1])); case 6: fuzzInt1 = data.consumeInt(0, classes.length - 1); jp = _createParser(data, mapper, r); o = mapper.readValues(jp, classes[fuzzInt1]); case 7: o = r.readValues(new MockFuzzDataInput(data.consumeString(1000000))); case 8: o = r.readValues(new ByteArrayInputStream(data.consumeBytes(100000))); default: o = r.readValues(data.consumeRemainingAsString()); // To avoid "variable o might not have been initialized" } if (data.consumeBoolean()) { r3 = r.withValueToUpdate(o); mapper.valueToTree(o); mapper.readerForUpdating(o); } } public static JsonParser _createParser(FuzzedDataProvider data, ObjectMapper mapper, ObjectReader r) throws IOException { int fuzzInt1, fuzzInt2; byte[] fileData; switch (data.consumeInt(0, 6)) { case 0: return r.createParser(data.consumeBytes(100000)); case 1: fileData = data.consumeBytes(100000); FileOutputStream out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); return r.createParser(new File("fuzzFile")); case 2: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); return r.createParser(data.consumeBytes(100000), fuzzInt1, fuzzInt2); case 3: mapper.createParser(data.consumeBytes(100000)); case 4: return mapper.createParser(data.consumeString(1000000)); case 5: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); return mapper.createParser(data.consumeBytes(100000), fuzzInt1, fuzzInt2); case 6: return r.createParser(new ByteArrayInputStream(data.consumeBytes(100000))); } return r.createParser(data.consumeBytes(100000)); } public static Class[] classes = { DummyClass.class, Integer.class, String.class, Byte.class, List.class, Map.class, TreeMap.class, BitSet.class, TimeZone.class, Date.class, Calendar.class, Locale.class, Long.class }; public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; public Long _long; public Double _double; } // Test util classes public static final class NoCheckSubTypeValidator extends PolymorphicTypeValidator.Base { private static final long serialVersionUID = 1L; protected final static Set DEFAULT_NO_DESER_CLASS_NAMES; static { Set s = new HashSet(); s.add("jaz.Zer"); DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s); } protected Set _cfgIllegalClassNames = DEFAULT_NO_DESER_CLASS_NAMES; public static final NoCheckSubTypeValidator instance = new NoCheckSubTypeValidator(); @Override public Validity validateBaseType(DatabindContext ctxt, JavaType baseType) { return Validity.INDETERMINATE; } @Override public Validity validateSubClassName(DatabindContext ctxt, JavaType baseType, String subClassName) { if (_cfgIllegalClassNames.contains(subClassName)) { return Validity.DENIED; } return Validity.ALLOWED; } @Override public Validity validateSubType(DatabindContext ctxt, JavaType baseType, JavaType subType) { final Class raw = baseType.getRawClass(); String full = raw.getName(); if (_cfgIllegalClassNames.contains(full)) { return Validity.DENIED; } return Validity.ALLOWED; } } public static class MockFuzzDataInput implements DataInput { private final InputStream _input; public MockFuzzDataInput(byte[] data) { _input = new ByteArrayInputStream(data); } public MockFuzzDataInput(String utf8Data) throws IOException { _input = new ByteArrayInputStream(utf8Data.getBytes("UTF-8")); } public MockFuzzDataInput(InputStream in) { _input = in; } @Override public void readFully(byte[] b) throws IOException { throw new UnsupportedOperationException(); } @Override public void readFully(byte[] b, int off, int len) throws IOException { throw new UnsupportedOperationException(); } @Override public int skipBytes(int n) throws IOException { return (int) _input.skip(n); } @Override public boolean readBoolean() throws IOException { throw new UnsupportedOperationException(); } @Override public byte readByte() throws IOException { int ch = _input.read(); if (ch < 0) { throw new EOFException("End-of-input for readByte()"); } return (byte) ch; } @Override public int readUnsignedByte() throws IOException { return readByte() & 0xFF; } @Override public short readShort() throws IOException { throw new UnsupportedOperationException(); } @Override public int readUnsignedShort() throws IOException { throw new UnsupportedOperationException(); } @Override public char readChar() throws IOException { throw new UnsupportedOperationException(); } @Override public int readInt() throws IOException { throw new UnsupportedOperationException(); } @Override public long readLong() throws IOException { throw new UnsupportedOperationException(); } @Override public float readFloat() throws IOException { throw new UnsupportedOperationException(); } @Override public double readDouble() throws IOException { throw new UnsupportedOperationException(); } @Override public String readLine() throws IOException { throw new UnsupportedOperationException(); } @Override public String readUTF() throws IOException { throw new UnsupportedOperationException(); } } } ================================================ FILE: projects/jackson-databind/AdaLObjectReader3Fuzzer.options ================================================ [libfuzzer] max_len = 1500000 len_control = 0 ================================================ FILE: projects/jackson-databind/ConvertValueFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.databind.JsonNode; import java.util.*; import java.lang.IllegalArgumentException; import tools.jackson.databind.ObjectMapper; public class ConvertValueFuzzer { public static Class[] classes = { DummyClass.class, Integer.class, String.class, Byte.class, List.class, Map.class, TreeMap.class, BitSet.class, TimeZone.class, Date.class, Calendar.class, Locale.class }; public static void fuzzerTestOneInput(FuzzedDataProvider data) { ObjectMapper mapper = new ObjectMapper(); try { int idx = data.consumeInt(0, classes.length - 1); String input = data.consumeRemainingAsString(); if (input == null || input.isEmpty()) { return; } mapper.convertValue(input, classes[idx]); } catch (IllegalArgumentException | tools.jackson.core.JacksonException e) { } } public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; } } ================================================ FILE: projects/jackson-databind/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/json.dict $SRC/ObjectReaderFuzzer.dict && \ cp fuzzing/dictionaries/json.dict $SRC/ObjectWriterFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/ObjectReaderFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -q $SRC/ObjectWriterFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/FasterXML/jackson-databind # Seed files RUN git clone --depth 1 https://github.com/AdamKorcz/github-samples ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn WORKDIR jackson-databind RUN git clone --depth 1 https://github.com/FasterXML/jackson-annotations RUN git clone --depth 1 https://github.com/FasterXML/jackson-core COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ ================================================ FILE: projects/jackson-databind/ObjectReader2Fuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.*; import java.io.Reader; import java.io.StringReader; import java.io.IOException; import java.io.FileOutputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.io.File; import java.lang.IllegalArgumentException; import java.net.URI; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectReader; import tools.jackson.databind.DeserializationFeature; import tools.jackson.core.JsonParser; import tools.jackson.core.json.JsonFactory; import tools.jackson.core.JacksonException; public class ObjectReader2Fuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { boolean doThis; byte[] fileData; int fuzzInt1, fuzzInt2; FileOutputStream out; Object o; Reader stringR; ObjectReader r, r2, r3; JsonParser jp; DeserializationFeature[] deserializationfeatures = new DeserializationFeature[]{ DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, DeserializationFeature.USE_LONG_FOR_INTS, DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY, DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, DeserializationFeature.FAIL_ON_NULL_CREATOR_PROPERTIES, DeserializationFeature.FAIL_ON_TRAILING_TOKENS, DeserializationFeature.WRAP_EXCEPTIONS, DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS, DeserializationFeature.UNWRAP_ROOT_VALUE, DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, DeserializationFeature.ACCEPT_FLOAT_AS_INT, DeserializationFeature.EAGER_DESERIALIZER_FETCH }; ObjectMapper mapper = new ObjectMapper(); int idx = data.consumeInt(0, classes.length - 1); r = mapper.readerFor(classes[idx]); // To initialize switch (data.consumeInt(0, 3)) { case 0: r = mapper.readerFor(classes[idx]); case 1: r = mapper.readerForMapOf(classes[idx]); case 2: r = mapper.readerForListOf(classes[idx]); case 3: r = mapper.readerForArrayOf(classes[idx]); } // set reader settings for (int i = 0; i < deserializationfeatures.length; i++) { if (data.consumeBoolean()) { r = r.with(deserializationfeatures[i]); } else { r = r.without(deserializationfeatures[i]); } } try { // Select a method and call it int callType = data.consumeInt(); switch (callType%23) { case 0: r.readValue(data.consumeRemainingAsString()); case 1: r.readValue(data.consumeRemainingAsBytes()); case 2: r.readTree(data.consumeRemainingAsString()); case 3: r.readTree(data.consumeRemainingAsBytes()); case 4: doThis = data.consumeBoolean(); jp = _createParser(data, mapper, r); o = r.readValue(jp); if (doThis) { r3 = r.withValueToUpdate(o); } case 5: stringR = new StringReader(new String(data.consumeRemainingAsBytes())); r.readValue(stringR); case 6: stringR = new StringReader(new String(data.consumeRemainingAsBytes())); r.readValues(stringR); case 7: r.readValues(data.consumeRemainingAsString()); case 8: r.readValue(data.consumeRemainingAsBytes()); case 9: doThis = data.consumeBoolean(); jp = _createParser(data, mapper, r); o = r.readValues(jp); if (doThis) { r3 = r.withValueToUpdate(o); } case 10: doThis = data.consumeBoolean(); jp = _createParser(data, mapper, r); o = r.readTree(jp); if (doThis) { r3 = r.withValueToUpdate(o); } case 11: stringR = new StringReader(new String(data.consumeRemainingAsBytes())); r.readTree(stringR); case 12: fileData = data.consumeRemainingAsBytes(); out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); r.readValue(new File("fuzzFile")); case 13: fileData = data.consumeRemainingAsBytes(); out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); r.readValues(new File("fuzzFile")); case 14: jp = _createParser(data, mapper, r); o = r.readTree(jp); case 15: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); r.readValue(data.consumeRemainingAsBytes(), fuzzInt1, fuzzInt2); case 16: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); r.readValues(data.consumeRemainingAsBytes(), fuzzInt1, fuzzInt2); case 17: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); r.readTree(data.consumeRemainingAsBytes(), fuzzInt1, fuzzInt2); case 18: jp = _createParser(data, mapper, r); case 19: int idx2 = data.consumeInt(0, classes.length - 1); switch (data.consumeInt()%4) { case 0: mapper.readValue(data.consumeRemainingAsBytes(), classes[idx]); case 1: mapper.readValue(data.consumeRemainingAsString(), classes[idx]); } case 20: fuzzInt1 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeBytes(1000000), data.consumeInt(), data.consumeInt(), classes[fuzzInt1]); case 21: int idx3 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeBytes(1000000), mapper.constructType(classes[idx])); case 22: int idx4 = data.consumeInt(0, classes.length - 1); mapper.readValue(data.consumeString(1000000), mapper.constructType(classes[idx])); } // target with(); if (data.consumeBoolean()) { r2 = r.with(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); } } catch (JacksonException | IOException | IllegalArgumentException e) { } try { Files.delete(Paths.get("fuzzFile")); } catch (IOException e) { } } public static JsonParser _createParser(FuzzedDataProvider data, ObjectMapper mapper, ObjectReader r) throws IOException { int fuzzInt1, fuzzInt2; byte[] fileData; switch (data.consumeInt(0, 5)) { case 0: return r.createParser(data.consumeBytes(100000)); case 1: fileData = data.consumeBytes(100000); FileOutputStream out = new FileOutputStream("fuzzFile"); out.write(fileData); out.close(); return r.createParser(new File("fuzzFile")); case 2: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); return r.createParser(data.consumeBytes(100000), fuzzInt1, fuzzInt2); case 3: mapper.createParser(data.consumeBytes(100000)); case 4: return mapper.createParser(data.consumeString(1000000)); case 5: fuzzInt1 = data.consumeInt(); fuzzInt2 = data.consumeInt(); return mapper.createParser(data.consumeBytes(100000), fuzzInt1, fuzzInt2); } return r.createParser(data.consumeBytes(100000)); } public static Class[] classes = { DummyClass.class, Integer.class, String.class, Byte.class, List.class, Map.class, TreeMap.class, BitSet.class, TimeZone.class, Date.class, Calendar.class, Locale.class, Long.class, File.class, Charset.class, URI.class }; public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; public Long _long; public Double _double; } } ================================================ FILE: projects/jackson-databind/ObjectReaderFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.*; import tools.jackson.databind.ObjectMapper; import tools.jackson.core.JacksonException; public class ObjectReaderFuzzer { public static Class[] classes = { DummyClass.class, Integer.class, String.class, Byte.class, List.class, Map.class, TreeMap.class, BitSet.class, TimeZone.class, Date.class, Calendar.class, Locale.class }; public static void fuzzerTestOneInput(FuzzedDataProvider data) { ObjectMapper mapper = new ObjectMapper(); int idx = data.consumeInt(0, classes.length - 1); try { mapper.readValue(data.consumeRemainingAsString(), classes[idx]); } catch (JacksonException e) { } } public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; } } ================================================ FILE: projects/jackson-databind/ObjectWriterFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.*; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.MapperFeature; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.json.JsonMapper; import tools.jackson.core.JacksonException; public class ObjectWriterFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { MapperFeature[] mapperfeatures = new MapperFeature[]{ MapperFeature.USE_ANNOTATIONS, MapperFeature.USE_GETTERS_AS_SETTERS, MapperFeature.PROPAGATE_TRANSIENT_MARKER, MapperFeature.REQUIRE_SETTERS_FOR_GETTERS, MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, MapperFeature.INFER_PROPERTY_MUTATORS, MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES, MapperFeature.ALLOW_VOID_VALUED_PROPERTIES, MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS, MapperFeature.USE_STATIC_TYPING, MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL, MapperFeature.DEFAULT_VIEW_INCLUSION, MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES, MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME, MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING, MapperFeature.ALLOW_COERCION_OF_SCALARS, MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE, MapperFeature.APPLY_DEFAULT_VALUES }; SerializationFeature[] serializationfeatures = new SerializationFeature[]{ SerializationFeature.WRAP_ROOT_VALUE, SerializationFeature.INDENT_OUTPUT, SerializationFeature.FAIL_ON_EMPTY_BEANS, SerializationFeature.FAIL_ON_SELF_REFERENCES, SerializationFeature.WRAP_EXCEPTIONS, SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL, SerializationFeature.CLOSE_CLOSEABLE, SerializationFeature.FLUSH_AFTER_WRITE_VALUE, SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS, SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, SerializationFeature.EAGER_SERIALIZER_FETCH, SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID }; // Build mapper with features via builder (Jackson 3.x style) JsonMapper.Builder builder = JsonMapper.builder(); for (int i = 0; i < mapperfeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(mapperfeatures[i]); } else { builder.disable(mapperfeatures[i]); } } for (int i = 0; i < serializationfeatures.length; i++) { if (data.consumeBoolean()) { builder.enable(serializationfeatures[i]); } else { builder.disable(serializationfeatures[i]); } } ObjectMapper mapper = builder.build(); try { DummyClass dc = mapper.readValue(data.consumeRemainingAsString(), DummyClass.class); byte[] jb = mapper.writeValueAsBytes(dc); } catch (JacksonException e) { } } public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; public Long _long; public Double _double; } } ================================================ FILE: projects/jackson-databind/ReadTreeFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.databind.JsonNode; import tools.jackson.databind.node.ObjectNode; import tools.jackson.databind.node.ArrayNode; import tools.jackson.databind.node.JsonNodeFactory; import java.util.*; import java.math.BigInteger; import java.math.BigDecimal; import java.lang.IllegalArgumentException; import tools.jackson.databind.ObjectMapper; import tools.jackson.core.JacksonException; public class ReadTreeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ObjectMapper mapper = new ObjectMapper(); try { JsonNode root = mapper.readTree(data.consumeString(500000)); if (root == null) return; // Test various JsonNode operations int numOperations = data.consumeInt(1, 20); for (int i = 0; i < numOperations && data.remainingBytes() > 10; i++) { int operation = data.consumeInt(0, 25); switch(operation) { case 0: // get by field name String fieldName = data.consumeString(100); JsonNode child = root.get(fieldName); if (child != null) { child.asText(); child.isNull(); child.isValueNode(); } break; case 1: // get by index int idx = data.consumeInt(); root.get(idx); break; case 2: // path operations String path = data.consumeString(200); JsonNode pathNode = root.path(path); pathNode.isMissingNode(); break; case 3: // at (JsonPointer) String pointer = data.consumeString(200); root.at(pointer); break; case 4: // type checks root.isArray(); root.isObject(); root.isTextual(); root.isNumber(); root.isBoolean(); root.isBinary(); root.isPojo(); root.isIntegralNumber(); root.isFloatingPointNumber(); root.isBigDecimal(); root.isBigInteger(); break; case 5: // value extraction root.asText(); root.asText("default"); break; case 6: root.asInt(); root.asInt(0); break; case 7: root.asLong(); root.asLong(0L); break; case 8: root.asDouble(); root.asDouble(0.0); break; case 9: root.asBoolean(); root.asBoolean(false); break; case 10: // tree traversal - Jackson 3.x uses values() and properties() root.values(); root.properties(); root.iterator(); break; case 11: // has operations String checkField = data.consumeString(100); root.has(checkField); root.has(data.consumeInt()); root.hasNonNull(checkField); break; case 12: // size root.size(); root.isEmpty(); break; case 13: // find operations String findField = data.consumeString(100); root.findValue(findField); root.findPath(findField); root.findValues(findField); root.findValuesAsString(findField); root.findParent(findField); root.findParents(findField); break; case 14: // withObject operations (for ObjectNode) if (root.isObject()) { try { String withField = data.consumeString(100); root.withObject(withField); } catch (UnsupportedOperationException e) {} } break; case 15: // withArray (for ObjectNode) if (root.isObject()) { try { String arrayField = data.consumeString(100); root.withArray(arrayField); } catch (UnsupportedOperationException e) {} } break; case 16: // equals String json2 = data.consumeString(10000); try { JsonNode other = mapper.readTree(json2); root.equals(other); } catch (JacksonException e) {} break; case 17: // treeToValue int classIdx = data.consumeInt(0, classes.length - 1); mapper.treeToValue(root, classes[classIdx]); break; case 18: // write operations mapper.writeValueAsString(root); break; case 19: mapper.writeValueAsBytes(root); break; case 20: // deepCopy root.deepCopy(); break; case 21: // number operations if applicable if (root.isNumber()) { root.numberValue(); root.canConvertToInt(); root.canConvertToLong(); root.canConvertToExactIntegral(); } break; case 22: // binary operations if applicable if (root.isBinary()) { root.binaryValue(); } break; case 23: // textValue root.textValue(); break; case 24: // pretty print root.toPrettyString(); break; case 25: // require operations try { root.require(); root.requireNonNull(); } catch (IllegalArgumentException e) {} break; } } } catch (JacksonException | IllegalArgumentException e) { } } public static Class[] classes = { DummyClass.class, Integer.class, String.class, Byte.class, List.class, Map.class, TreeMap.class, BitSet.class, TimeZone.class, Date.class, Calendar.class, Locale.class }; public static class DummyClass { public TreeMap _treeMap; public List _arrayList; public Set _hashSet; public Map _hashMap; public List _asList = Arrays.asList(1, 2, 3); public int[] _intArray; public long[] _longArray; public short[] _shortArray; public float[] _floatArray; public double[] _doubleArray; public byte[] _byteArray; public char[] _charArray; public String[] _stringArray; public BitSet _bitSet; public Date _date; public TimeZone _timeZone; public Calendar _calendar; public Locale _locale; public Integer[] _integerArray; public boolean _boolean; public char _char; public byte _byte; public short _short; public int _int; public float _float; } } ================================================ FILE: projects/jackson-databind/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/jackson-databind # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT mv $SRC/github-samples/jackson/*.zip $OUT/ # jackson-annotations (must be built first - no dependencies) MAVEN_ARGS="-Djavac.src.version=17 -Djavac.target.version=17 -DskipTests" $MVN package $MAVEN_ARGS -f "jackson-annotations/pom.xml" CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout -f "jackson-annotations/pom.xml") cp "jackson-annotations/target/jackson-annotations-$CURRENT_VERSION.jar" "$OUT/jackson-annotations.jar" # jackson-core (depends on jackson-annotations) MAVEN_ARGS="-Djavac.src.version=17 -Djavac.target.version=17 -DskipTests" $MVN package $MAVEN_ARGS -f "jackson-core/pom.xml" CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout -f "jackson-core/pom.xml") cp "jackson-core/target/jackson-core-$CURRENT_VERSION.jar" "$OUT/jackson-core.jar" # jackson-databind (depends on both jackson-core and jackson-annotations) MAVEN_ARGS="-Djavac.src.version=17 -Djavac.target.version=17 -DskipTests" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/jackson-databind-$CURRENT_VERSION.jar" "$OUT/jackson-databind.jar" ALL_JARS="jackson-databind.jar jackson-core.jar jackson-annotations.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ cp $SRC/$fuzzer_basename\$DummyClass.class $OUT/ 2>/dev/null || true if [ "$fuzzer_basename" == "AdaLObjectReader3Fuzzer" ]; then cp $SRC/$fuzzer_basename\$NoCheckSubTypeValidator.class $OUT/ cp $SRC/$fuzzer_basename\$MockFuzzDataInput.class $OUT/ fi # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --instrumentation_excludes=tools.jackson.core.** \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-databind/project.yaml ================================================ homepage: "https://github.com/FasterXML/jackson-databind" language: jvm primary_contact: "tatu@fasterxml.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/FasterXML/jackson-databind.git" auto_ccs: - "Adam@adalogics.com" - "David@adalogics.com" - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jackson-dataformat-xml/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/xml.dict $SRC/XmlFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/XmlFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 -b 3.x https://github.com/FasterXML/jackson-core RUN git clone --depth 1 -b 3.x https://github.com/FasterXML/jackson-databind RUN git clone --depth 1 -b 3.x https://github.com/FasterXML/jackson-dataformat-xml COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-dataformat-xml ================================================ FILE: projects/jackson-dataformat-xml/FromXmlParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.dataformat.xml.XmlFactory; import tools.jackson.dataformat.xml.XmlMapper; import tools.jackson.dataformat.xml.XmlReadFeature; import tools.jackson.dataformat.xml.deser.FromXmlParser; import java.util.EnumSet; /** This fuzzer targets the methods of the FromXmlParser object */ public class FromXmlParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer choice = data.consumeInt(1, 19); // Retrieve set of XmlReadFeature EnumSet featureSet = EnumSet.allOf(XmlReadFeature.class); // Create and configure XmlMapper XmlMapper mapper = null; if (data.consumeBoolean()) { mapper = XmlMapper.builder( XmlFactory.builder() .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()) .build(); } else { mapper = XmlMapper.builder().build(); } // Create and configure FromXmlParser FromXmlParser parser = (FromXmlParser) mapper.createParser(data.consumeRemainingAsString()); // Fuzz methods of FromXmlParser switch (choice) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.nextToken(); parser.getText(); break; case 8: parser.getText(); break; case 9: parser.getTextCharacters(); break; case 10: parser.getTextLength(); break; case 11: parser.getTextOffset(); break; case 12: parser.getNumberType(); break; case 13: parser.getNumberValue(); break; case 14: parser.getIntValue(); break; case 15: parser.getLongValue(); break; case 16: parser.getBigIntegerValue(); break; case 17: parser.getFloatValue(); break; case 18: parser.getDoubleValue(); break; case 19: parser.getDecimalValue(); break; } parser.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformat-xml/ToXmlGeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.io.SerializedString; import tools.jackson.dataformat.xml.XmlFactory; import tools.jackson.dataformat.xml.XmlMapper; import tools.jackson.dataformat.xml.XmlWriteFeature; import tools.jackson.dataformat.xml.ser.ToXmlGenerator; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.EnumSet; import javax.xml.namespace.QName; /** This fuzzer targets the methods of the ToXmlGenerator object */ public class ToXmlGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Retrieve set of XmlWriteFeature EnumSet featureSet = EnumSet.allOf(XmlWriteFeature.class); // Create and configure XmlMapper XmlMapper mapper = null; if (data.consumeBoolean()) { mapper = XmlMapper.builder( XmlFactory.builder() .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()) .build(); } else { mapper = XmlMapper.builder().build(); } // Create and configure ToXmlGenerator ToXmlGenerator generator = (ToXmlGenerator) mapper.createGenerator(new ByteArrayOutputStream()); generator.initGenerator(); generator.setNextName(new QName("OSS-Fuzz")); generator.writeStartObject(); // Fuzz methods of ToXmlGenerator String value = null; switch (data.consumeInt(1, 18)) { case 1: generator.writeName(data.consumeString(data.remainingBytes())); generator.writeString(data.consumeRemainingAsString()); break; case 2: generator.writeName(new SerializedString(data.consumeRemainingAsString())); break; case 3: value = data.consumeRemainingAsString(); generator.writeString(value.toCharArray(), 0, value.length()); break; case 4: generator.writeString(new SerializedString(data.consumeRemainingAsString())); break; case 5: generator.writeRawValue(data.consumeRemainingAsString()); break; case 6: value = data.consumeRemainingAsString(); generator.writeRawValue(value, 0, value.length()); break; case 7: value = data.consumeRemainingAsString(); generator.writeRawValue(value.toCharArray(), 0, value.length()); break; case 8: value = data.consumeRemainingAsString(); generator.writeRaw(value, 0, value.length()); break; case 9: value = data.consumeRemainingAsString(); generator.writeRaw(value.toCharArray(), 0, value.length()); break; case 10: generator.writeBoolean(data.consumeBoolean()); break; case 11: generator.writeNull(); break; case 12: generator.writeNumber(data.consumeInt()); break; case 13: generator.writeNumber(data.consumeLong()); break; case 14: generator.writeNumber(data.consumeDouble()); break; case 15: generator.writeNumber(data.consumeFloat()); break; case 16: generator.writeNumber(new BigDecimal(data.consumeLong())); break; case 17: generator.writeNumber(BigInteger.valueOf(data.consumeLong())); break; case 18: generator.writeNumber(data.consumeRemainingAsString()); break; } generator.writeEndObject(); generator.flush(); generator.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformat-xml/XmlDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.dataformat.xml.XmlMapper; import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Stream; /** This fuzzer targets the deserialization methods of Xml objects */ public class XmlDeserializerFuzzer { private static XmlMapper mapper; private static List choice; public static void fuzzerInitialize() { // Register the XmlModule for the deserialization mapper = XmlMapper.builder().build(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the deserialize methods for different xml objects Class type = data.pickValue(choice); String value = data.consumeRemainingAsString(); mapper.readValue(value, type); } catch (RuntimeException e) { // Known exception } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(ByteArrayContainer.class); choice.add(ByteArrayOutputStream.class); choice.add(Byte[].class); choice.add(ModelContainer.class); choice.add(DelegateContainer.class); choice.add(RawContainer.class); choice.add(MapContainer.class); choice.add(ListContainer.class); choice.add(ArrayContainer.class); choice.add(EnumFuzz.class); choice.add(EnumContainer.class); choice.add(Exception.class); choice.add(Map.class); choice.add(List.class); choice.add(Set.class); choice.add(Stream.class); choice.add(String.class); choice.add(Boolean.class); choice.add(Character.class); choice.add(Byte.class); choice.add(Integer.class); choice.add(Long.class); choice.add(Short.class); choice.add(Double.class); choice.add(Float.class); choice.add(BigInteger.class); choice.add(BigDecimal.class); choice.add(Number.class); } private static class ByteArrayContainer { public byte[] value; public ByteArrayContainer(byte[] value) { this.value = value; } } @JsonRootName("Model") private static class ModelContainer { @JacksonXmlProperty(isAttribute = true, localName = "string") public String string; @JsonCreator public ModelContainer(@JsonProperty(value = "string", required = true) String string) { this.string = string; } } private static class DelegateContainer { public String string; @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public DelegateContainer(String string) { this.string = string; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; } private static class MapContainer { public Map map; public void setMap(Map map) { this.map = map; } } private static class ListContainer { public List list; public void setList(List list) { this.list = list; } } private static class ArrayContainer { public String[] array; public String[] getArray() { return array; } public void setArray(String[] array) { this.array = array; } } private static enum EnumFuzz { A, B, C, D, E; } private static class EnumContainer { public EnumFuzz enumFuzz; public EnumContainer(EnumFuzz enumFuzz) { this.enumFuzz = enumFuzz; } } } ================================================ FILE: projects/jackson-dataformat-xml/XmlFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.xml.XmlMapper; public class XmlFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = XmlMapper.builder().build(); try { mapper.readTree(input); } catch (RuntimeException ignored) { } } } ================================================ FILE: projects/jackson-dataformat-xml/XmlSerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.databind.ObjectWriter; import tools.jackson.dataformat.xml.XmlMapper; import tools.jackson.dataformat.xml.XmlWriteFeature; import tools.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty; import tools.jackson.dataformat.xml.ser.ToXmlGenerator; import java.io.ByteArrayInputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Stream; /** This fuzzer targets the serialization methods of Hppc objects */ public class XmlSerializerFuzzer { private static ObjectWriter writer; public static void fuzzerInitialize() { // Register the XmlModule for the serialization writer = XmlMapper.builder().build().writer(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Object object = null; // Fuzz the serialize methods for different XML objects if (data.consumeBoolean()) { writer = writer.withDefaultPrettyPrinter(); } writer = writer.with(data.pickValue(EnumSet.allOf(XmlWriteFeature.class))); switch (data.consumeInt(1, 24)) { case 1: object = new ByteArrayContainer(data.consumeRemainingAsBytes()); break; case 2: List list = new ArrayList(); list.add(data.consumeRemainingAsString()); object = list; break; case 3: List listIter = new ArrayList(); listIter.add(data.consumeRemainingAsString()); object = listIter.iterator(); break; case 4: object = Stream.of(data.consumeRemainingAsString()).iterator(); break; case 5: List listIterCon = new ArrayList(); listIterCon.add(data.consumeRemainingAsString()); object = new IteratorContainer(listIterCon.iterator()); break; case 6: object = new ItemContainer(); break; case 7: object = new ModelContainer(data.consumeRemainingAsString()); break; case 8: object = new RawContainer(data.consumeRemainingAsString()); break; case 9: object = new ByteBufferContainer(data.consumeRemainingAsBytes()); break; case 10: object = new MapContainer(data.consumeRemainingAsString()); break; case 11: object = new ListContainer(data.consumeRemainingAsString()); break; case 12: object = BigInteger.valueOf(data.consumeLong()); break; case 13: object = data.consumeRemainingAsString(); break; case 14: object = data.consumeRemainingAsBytes(); break; case 15: object = BigDecimal.valueOf(data.consumeDouble()); break; case 16: object = data.consumeBoolean(); break; case 17: object = data.consumeInt(); break; case 18: object = data.consumeLong(); break; case 19: object = data.consumeDouble(); break; case 20: object = data.consumeBoolean(); break; case 21: object = data.consumeByte(); break; case 22: object = data.consumeChar(); break; case 23: object = data.consumeBoolean(); break; case 24: object = new ByteArrayInputStream(data.consumeRemainingAsBytes()); break; } writer.writeValueAsString(object); writer.writeValueAsBytes(object); } catch (RuntimeException e) { // Known exception } } private static class ByteArrayContainer { public byte[] value; public ByteArrayContainer(byte[] value) { this.value = value; } } private static class IteratorContainer { private Iterator iterator; @JacksonXmlElementWrapper(localName = "elements") @JacksonXmlProperty(localName = "element") public Iterator getIterator() { return iterator; } public IteratorContainer(Iterator iterator) { this.iterator = iterator; } } private static class ItemContainer { @JsonProperty("item") @JacksonXmlElementWrapper(localName = "list") public Iterator items() { return new Iterator() { int item = 5; @Override public boolean hasNext() { return item > 0; } @Override public String next() { return Integer.toString(--item); } }; } } @JsonRootName("Model") private static class ModelContainer { @JacksonXmlProperty(isAttribute = true, localName = "string") public String string; public ModelContainer(String string) { this.string = string; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; @JsonRawValue public char[] charArray; public RawContainer(String string) { this.string = string; this.charArray = string.toCharArray(); } } private static class ByteBufferContainer { public ByteBuffer byteBuffer; public ByteBufferContainer(byte[] byteArray) { this.byteBuffer = ByteBuffer.allocateDirect(byteArray.length); this.byteBuffer.put(byteArray); } } private static class MapContainer { public Map map; public MapContainer(String string) { this.map = new HashMap(); this.map.put(0, string); } } private static class ListContainer { public List list; public ListContainer(String string) { this.list = new ArrayList(); this.list.add(string); } } } ================================================ FILE: projects/jackson-dataformat-xml/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-P!java14+ -Dmaven.test.skip=true -Djavac.src.version=17 -Djavac.target.version=17" # Build jackson-core first (required dependency) cd $SRC/jackson-core $MVN install $MAVEN_ARGS # Build jackson-databind (required dependency) cd $SRC/jackson-databind $MVN install $MAVEN_ARGS # Build jackson-dataformat-xml cd $SRC/jackson-dataformat-xml $MVN package dependency:copy-dependencies $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) mkdir -p $OUT/dependency cp "target/jackson-dataformat-xml-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-xml.jar for jarfile in $(find $SRC/jackson-dataformat-xml/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done ALL_JARS="jackson-dataformat-xml.jar" ALL_DEPENDENCY=$(find $OUT/dependency -name *.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "$OUT/dependency/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "\$this_dir/dependency/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-dataformat-xml/project.yaml ================================================ homepage: "https://github.com/FasterXML/jackson-dataformat-xml" language: jvm primary_contact: "tatu@fasterxml.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/FasterXML/jackson-dataformat-xml" sanitizers: - address auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "norbert.schneider@code-intelligence.com" - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/jackson-dataformats-binary/AvroGeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.io.SerializedString; import tools.jackson.dataformat.avro.AvroFactory; import tools.jackson.dataformat.avro.AvroFactoryBuilder; import tools.jackson.dataformat.avro.AvroGenerator; import tools.jackson.dataformat.avro.AvroMapper; import tools.jackson.dataformat.avro.AvroWriteFeature; import tools.jackson.dataformat.avro.schema.AvroSchemaGenerator; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.EnumSet; import java.util.List; import java.util.HashMap; /** This fuzzer targets the methods of AvroGenerator */ public class AvroGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Retrieve set of AvroWriteFeature EnumSet featureSet = EnumSet.allOf(AvroWriteFeature.class); // Create and configure AvroMapper AvroFactoryBuilder avroFactoryBuilder; if (data.consumeBoolean()) { avroFactoryBuilder = AvroFactory.builderWithApacheDecoder(); } else { avroFactoryBuilder = AvroFactory.builderWithNativeDecoder(); } AvroMapper mapper = new AvroMapper( avroFactoryBuilder .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Generate schema for RootType AvroSchemaGenerator schemaGenerator = new AvroSchemaGenerator(); mapper.acceptJsonFormatVisitor(RootType.class, schemaGenerator); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); AvroGenerator generator = (AvroGenerator) mapper.writer() .with(schemaGenerator.getGeneratedSchema()) .createGenerator(outputStream); generator.writeStartObject(); // Fuzz methods of CBORGenerator String value = null; byte[] byteArray = null; switch (data.consumeInt(1, 18)) { case 1: generator.writeName("bo"); generator.writeBoolean(data.consumeBoolean()); break; case 2: generator.writeName("obj"); generator.writeNull(); break; case 3: generator.writeName("ia"); int[] intArray = data.consumeInts(data.consumeInt(1, 5)); generator.writeArray(intArray, 0, intArray.length); break; case 4: generator.writeName("la"); long[] longArray = data.consumeLongs(data.consumeInt(1, 5)); generator.writeArray(longArray, 0, longArray.length); break; case 5: generator.writeName("da"); double[] doubleArray = new double[data.consumeInt(1, 5)]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } generator.writeArray(doubleArray, 0, doubleArray.length); break; case 6: generator.writeName("string"); generator.writeString(data.consumeRemainingAsString()); break; case 7: generator.writeName("string"); value = data.consumeRemainingAsString(); generator.writeString(value.toCharArray(), 0, value.length()); break; case 8: generator.writeName("string"); generator.writeString(new SerializedString(data.consumeRemainingAsString())); break; case 9: generator.writeName("string"); byteArray = data.consumeRemainingAsBytes(); generator.writeRawUTF8String(byteArray, 0, byteArray.length); break; case 10: generator.writeName("ba"); byteArray = data.consumeRemainingAsBytes(); generator.writeUTF8String(byteArray, 0, byteArray.length); break; case 11: generator.writeName("ba"); byteArray = data.consumeRemainingAsBytes(); generator.writeBinary(new ByteArrayInputStream(byteArray), byteArray.length); break; case 12: generator.writeName("i"); generator.writeNumber(data.consumeInt()); break; case 13: generator.writeName("l"); generator.writeNumber(data.consumeLong()); break; case 14: generator.writeName("d"); generator.writeNumber(data.consumeDouble()); break; case 15: generator.writeName("f"); generator.writeNumber(data.consumeFloat()); break; case 16: generator.writeName("bd"); generator.writeNumber(new BigDecimal(data.consumeLong())); break; case 17: generator.writeName("bi"); generator.writeNumber(BigInteger.valueOf(data.consumeLong())); break; case 18: generator.writeName("obj"); generator.writeNumber(data.consumeRemainingAsString()); break; } generator.flush(); generator.close(); } catch (RuntimeException e) { // Known exception } } private static class RootType { public String string; public int i; public boolean bo; public double d; public float f; public short s; public long l; public BigDecimal bd; public BigInteger bi; public byte[] ba; public double[] da; public long[] la; public int[] ia; public Object obj; } } ================================================ FILE: projects/jackson-dataformats-binary/AvroParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonAlias; import tools.jackson.dataformat.avro.AvroFactory; import tools.jackson.dataformat.avro.AvroFactoryBuilder; import tools.jackson.dataformat.avro.AvroMapper; import tools.jackson.dataformat.avro.AvroParser; import tools.jackson.dataformat.avro.AvroReadFeature; import tools.jackson.dataformat.avro.schema.AvroSchemaGenerator; import java.util.EnumSet; import java.util.List; /** This fuzzer targets the methods of AvroParser */ public class AvroParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 100)); // Retrieve set of AvroReadFeature EnumSet featureSet = EnumSet.allOf(AvroReadFeature.class); // Create and configure AvroMapper AvroFactoryBuilder avroFactoryBuilder; if (data.consumeBoolean()) { avroFactoryBuilder = AvroFactory.builderWithApacheDecoder(); } else { avroFactoryBuilder = AvroFactory.builderWithNativeDecoder(); } AvroMapper mapper = new AvroMapper( avroFactoryBuilder .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Generate schema for RootType AvroSchemaGenerator schemaGenerator = new AvroSchemaGenerator(); mapper.acceptJsonFormatVisitor(RootType.class, schemaGenerator); byte[] inputBytes = data.consumeRemainingAsBytes(); AvroParser parser = (AvroParser) mapper.reader() .with(schemaGenerator.getGeneratedSchema()) .createParser(inputBytes); // Fuzz methods of AvroParser for (Integer choice : choices) { switch (Math.abs(choice) % 19) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.nextStringValue(); break; case 8: parser.getText(); break; case 9: parser.getTextCharacters(); break; case 10: parser.getTextLength(); break; case 11: parser.getTextOffset(); break; case 12: parser.getNumberType(); break; case 13: parser.getNumberValue(); break; case 14: parser.getIntValue(); break; case 15: parser.getLongValue(); break; case 16: parser.getBigIntegerValue(); break; case 17: parser.getFloatValue(); break; case 18: parser.getDoubleValue(); break; default: parser.getDecimalValue(); break; } } parser.close(); } catch (RuntimeException e) { // Known exception } } private static class RootType { @JsonAlias({"nm", "Name"}) public String name; public int value; List other; } } ================================================ FILE: projects/jackson-dataformats-binary/CborFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.cbor.CBORMapper; public class CborFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new CBORMapper(); try { mapper.readTree(input); } catch (RuntimeException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-binary/CborGeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.io.SerializedString; import tools.jackson.dataformat.cbor.CBORFactory; import tools.jackson.dataformat.cbor.CBORGenerator; import tools.jackson.dataformat.cbor.CBORMapper; import tools.jackson.dataformat.cbor.CBORWriteFeature; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.EnumSet; /** This fuzzer targets the methods of CBORGenerator */ public class CborGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Retrieve set of CBORWriteFeature EnumSet featureSet = EnumSet.allOf(CBORWriteFeature.class); // Create and configure CBORMapper CBORMapper mapper = new CBORMapper( CBORFactory.builder() .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Create CBORGenerator CBORGenerator generator = (CBORGenerator) ((CBORMapper) mapper).tokenStreamFactory().createGenerator(new ByteArrayOutputStream()); generator.writeStartObject(); // Fuzz methods of CBORGenerator String value = null; byte[] byteArray = null; generator.writeName("OSS-Fuzz"); switch (data.consumeInt(1, 18)) { case 1: generator.writeBoolean(data.consumeBoolean()); break; case 2: generator.writeNull(); break; case 3: int[] intArray = data.consumeInts(data.consumeInt(1, 5)); generator.writeArray(intArray, 0, intArray.length); break; case 4: long[] longArray = data.consumeLongs(data.consumeInt(1, 5)); generator.writeArray(longArray, 0, longArray.length); break; case 5: double[] doubleArray = new double[data.consumeInt(1, 5)]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } generator.writeArray(doubleArray, 0, doubleArray.length); break; case 6: generator.writeString(data.consumeRemainingAsString()); break; case 7: value = data.consumeRemainingAsString(); generator.writeString(value.toCharArray(), 0, value.length()); break; case 8: generator.writeString(new SerializedString(data.consumeRemainingAsString())); break; case 9: byteArray = data.consumeRemainingAsBytes(); generator.writeRawUTF8String(byteArray, 0, byteArray.length); break; case 10: byteArray = data.consumeRemainingAsBytes(); generator.writeUTF8String(byteArray, 0, byteArray.length); break; case 11: byteArray = data.consumeRemainingAsBytes(); generator.writeBinary(new ByteArrayInputStream(byteArray), byteArray.length); break; case 12: generator.writeNumber(data.consumeInt()); break; case 13: generator.writeNumber(data.consumeLong()); break; case 14: generator.writeNumber(data.consumeDouble()); break; case 15: generator.writeNumber(data.consumeFloat()); break; case 16: generator.writeNumber(new BigDecimal(data.consumeLong())); break; case 17: generator.writeNumber(BigInteger.valueOf(data.consumeLong())); break; case 18: generator.writeNumber(data.consumeRemainingAsString()); break; } generator.writeEndObject(); generator.flush(); generator.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/CborParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.dataformat.cbor.CBORFactory; import tools.jackson.dataformat.cbor.CBORParser; import tools.jackson.dataformat.cbor.CBORMapper; import java.util.EnumSet; /** This fuzzer targets the methods of CBORParser */ public class CborParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 100)); // Create and configure CBORParser CBORMapper mapper = new CBORMapper(CBORFactory.builder().build()); // Failsafe logic if (mapper == null) { return; } // Create and configure CBORParser CBORParser parser = (CBORParser) ((CBORMapper) mapper).tokenStreamFactory().createParser(data.consumeRemainingAsBytes()); // Fuzz methods of CBORParser for (Integer choice : choices) { switch (Math.abs(choice) % 19) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.nextStringValue(); break; case 8: parser.getText(); break; case 9: parser.getTextCharacters(); break; case 10: parser.getTextLength(); break; case 11: parser.getTextOffset(); break; case 12: parser.getNumberType(); break; case 13: parser.getNumberValue(); break; case 14: parser.getIntValue(); break; case 15: parser.getLongValue(); break; case 16: parser.getBigIntegerValue(); break; case 17: parser.getFloatValue(); break; case 18: parser.getDoubleValue(); break; default: parser.getDecimalValue(); break; } } parser.close(); } catch (RuntimeException e) { // Known exception - ignore internal errors if (e.getMessage() != null && !e.getMessage().contains("Internal error") && !e.getMessage().isEmpty()) { // Only rethrow if not a known internal error } } } } ================================================ FILE: projects/jackson-dataformats-binary/DeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.core.JsonParser; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.avro.AvroFactory; import tools.jackson.dataformat.avro.AvroFactoryBuilder; import tools.jackson.dataformat.avro.AvroMapper; import tools.jackson.dataformat.avro.AvroReadFeature; import tools.jackson.dataformat.cbor.CBORFactory; import tools.jackson.dataformat.cbor.CBORWriteFeature; import tools.jackson.dataformat.cbor.CBORMapper; import tools.jackson.dataformat.ion.IonFactory; import tools.jackson.dataformat.ion.IonFactoryBuilder; import tools.jackson.dataformat.ion.IonObjectMapper; import tools.jackson.dataformat.ion.IonReadFeature; import tools.jackson.dataformat.protobuf.ProtobufFactory; import tools.jackson.dataformat.protobuf.ProtobufMapper; import tools.jackson.dataformat.smile.SmileFactory; import tools.jackson.dataformat.smile.SmileReadFeature; import tools.jackson.dataformat.smile.SmileMapper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Stream; /** This fuzzer targets the deserialization methods of Avro/Cbor/Ion/Protobuf/Smile objects */ public class DeserializerFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { mapper = null; initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonParser parser = null; try { // Initialize ObjectMapper object switch (data.consumeInt(1, 5)) { case 1: AvroFactoryBuilder avroFactoryBuilder; if (data.consumeBoolean()) { avroFactoryBuilder = AvroFactory.builderWithApacheDecoder(); } else { avroFactoryBuilder = AvroFactory.builderWithNativeDecoder(); } mapper = AvroMapper.builder( avroFactoryBuilder .enable(data.pickValue(EnumSet.allOf(AvroReadFeature.class))) .build()) .build(); break; case 2: mapper = CBORMapper.builder( CBORFactory.builder() .enable(data.pickValue(EnumSet.allOf(CBORWriteFeature.class))) .build()) .build(); break; case 3: IonFactoryBuilder ionFactoryBuilder; if (data.consumeBoolean()) { ionFactoryBuilder = IonFactory.builderForBinaryWriters(); } else { ionFactoryBuilder = IonFactory.builderForTextualWriters(); } mapper = IonObjectMapper.builder( ionFactoryBuilder .enable(data.pickValue(EnumSet.allOf(IonReadFeature.class))) .build()) .build(); break; case 4: mapper = ProtobufMapper.builder(ProtobufFactory.builder().build()).build(); break; case 5: mapper = SmileMapper.builder( SmileFactory.builder() .enable(data.pickValue(EnumSet.allOf(SmileReadFeature.class))) .build()) .build(); break; } // Failsafe logic if (mapper == null) { return; } // Fuzz the deserialize methods for different Avro/Cbor/Ion/Protobuf/Smile objects if (data.consumeBoolean()) { byte[] output = data.consumeRemainingAsBytes(); parser = mapper.tokenStreamFactory().createParser(new ByteArrayInputStream(output)); mapper.readTree(parser); } else { Class type = data.pickValue(choice); String value = data.consumeRemainingAsString(); if ((value == null) || (value.isEmpty())) { return; } mapper.readValue(value, type); if (mapper instanceof AvroMapper) { try { mapper.readerFor(type).with(((AvroMapper) mapper).schemaFrom(value)).readValue(value); } catch (java.io.IOException e) { // Schema parsing can throw IOException } } } } catch (RuntimeException e) { // Known exception } finally { try { if (parser != null) { parser.close(); } } catch (RuntimeException e) { // Ignore exceptions for closing JsonParser object } } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(ByteArrayContainer.class); choice.add(ByteArrayOutputStream.class); choice.add(ModelContainer.class); choice.add(DelegateContainer.class); choice.add(RawContainer.class); choice.add(MapContainer.class); choice.add(ListContainer.class); choice.add(ArrayContainer.class); choice.add(UUIDContainer.class); choice.add(EnumFuzz.class); choice.add(EnumContainer.class); choice.add(Exception.class); choice.add(Error.class); choice.add(Map.class); choice.add(List.class); choice.add(Set.class); choice.add(Stream.class); choice.add(String.class); choice.add(Boolean.class); choice.add(Character.class); choice.add(Byte.class); choice.add(Integer.class); choice.add(Long.class); choice.add(Short.class); choice.add(Double.class); choice.add(Float.class); choice.add(BigInteger.class); choice.add(BigDecimal.class); choice.add(Number.class); choice.add(String.class); choice.add(Character[].class); choice.add(Date.class); } private static class ByteArrayContainer { public byte[] value; public ByteArrayContainer(byte[] value) { this.value = value; } } @JsonRootName("Model") private static class ModelContainer { public String string; @JsonCreator public ModelContainer(@JsonProperty(value = "string", required = true) String string) { this.string = string; } } private static class DelegateContainer { public String string; @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public DelegateContainer(String string) { this.string = string; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; } private static class MapContainer { public Map map; public void setMap(Map map) { this.map = map; } } private static class ListContainer { public List list; public void setList(List list) { this.list = list; } } private static class ArrayContainer { public String[] array; public String[] getArray() { return array; } public void setArray(String[] array) { this.array = array; } } private static class UUIDContainer { public UUID uuid; public UUIDContainer(UUID uuid) { this.uuid = uuid; } } private static enum EnumFuzz { A, B, C, D, E; } private static class EnumContainer { public EnumFuzz enumFuzz; public EnumContainer(EnumFuzz enumFuzz) { this.enumFuzz = enumFuzz; } } } ================================================ FILE: projects/jackson-dataformats-binary/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y maven RUN git clone --depth 1 https://github.com/FasterXML/jackson-dataformats-binary COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-dataformats-binary ================================================ FILE: projects/jackson-dataformats-binary/IonGeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JsonGenerator; import tools.jackson.core.io.SerializedString; import tools.jackson.dataformat.ion.IonFactory; import tools.jackson.dataformat.ion.IonFactoryBuilder; import tools.jackson.dataformat.ion.IonGenerator; import tools.jackson.dataformat.ion.IonObjectMapper; import tools.jackson.dataformat.ion.IonWriteFeature; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.util.EnumSet; /** This fuzzer targets the methods of IonGenerator */ public class IonGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Retrieve set of IonWriteFeature EnumSet featureSet = EnumSet.allOf(IonWriteFeature.class); // Create and configure IonObjectMapper IonFactoryBuilder ionFactoryBuilder; if (data.consumeBoolean()) { ionFactoryBuilder = IonFactory.builderForBinaryWriters(); } else { ionFactoryBuilder = IonFactory.builderForTextualWriters(); } IonObjectMapper mapper = new IonObjectMapper( ionFactoryBuilder .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Create and configure IonGenerator JsonGenerator generator = ((IonObjectMapper) mapper) .tokenStreamFactory() .createGenerator(new OutputStreamWriter(new ByteArrayOutputStream())); generator.writeStartObject(); // Fuzz methods of ProtobufGenerator String value = null; byte[] byteArray = null; generator.writeName("OSS-Fuzz"); switch (data.consumeInt(1, 18)) { case 1: generator.writeBoolean(data.consumeBoolean()); break; case 2: generator.writeNull(); break; case 3: int[] intArray = data.consumeInts(data.consumeInt(1, 5)); generator.writeArray(intArray, 0, intArray.length); break; case 4: long[] longArray = data.consumeLongs(data.consumeInt(1, 5)); generator.writeArray(longArray, 0, longArray.length); break; case 5: double[] doubleArray = new double[data.consumeInt(1, 5)]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } generator.writeArray(doubleArray, 0, doubleArray.length); break; case 6: generator.writeString(data.consumeRemainingAsString()); break; case 7: value = data.consumeRemainingAsString(); generator.writeString(value.toCharArray(), 0, value.length()); break; case 8: generator.writeString(new SerializedString(data.consumeRemainingAsString())); break; case 9: byteArray = data.consumeRemainingAsBytes(); generator.writeRawUTF8String(byteArray, 0, byteArray.length); break; case 10: byteArray = data.consumeRemainingAsBytes(); generator.writeUTF8String(byteArray, 0, byteArray.length); break; case 11: byteArray = data.consumeRemainingAsBytes(); generator.writeBinary(new ByteArrayInputStream(byteArray), byteArray.length); break; case 12: generator.writeNumber(data.consumeInt()); break; case 13: generator.writeNumber(data.consumeLong()); break; case 14: generator.writeNumber(data.consumeDouble()); break; case 15: generator.writeNumber(data.consumeFloat()); break; case 16: generator.writeNumber(new BigDecimal(data.consumeLong())); break; case 17: generator.writeNumber(BigInteger.valueOf(data.consumeLong())); break; case 18: generator.writeNumber(data.consumeRemainingAsString()); break; } generator.writeEndObject(); generator.flush(); generator.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/IonParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JsonParser; import tools.jackson.dataformat.ion.IonFactory; import tools.jackson.dataformat.ion.IonFactoryBuilder; import tools.jackson.dataformat.ion.IonObjectMapper; import tools.jackson.dataformat.ion.IonReadFeature; import java.util.EnumSet; /** This fuzzer targets the methods of IonParser */ public class IonParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 100)); // Retrieve set of IonReadFeature EnumSet featureSet = EnumSet.allOf(IonReadFeature.class); // Create and configure IonObjectMapper IonFactoryBuilder ionFactoryBuilder; if (data.consumeBoolean()) { ionFactoryBuilder = IonFactory.builderForBinaryWriters(); } else { ionFactoryBuilder = IonFactory.builderForTextualWriters(); } IonObjectMapper mapper = new IonObjectMapper( ionFactoryBuilder .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Create and configure IonParser byte[] byteArray = data.consumeRemainingAsBytes(); if ((byteArray == null) || (byteArray.length <= 0)) { return; } JsonParser parser = ((IonObjectMapper) mapper).tokenStreamFactory().createParser(byteArray); // Fuzz methods of IonParser for (Integer choice : choices) { switch (Math.abs(choice) % 19) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.nextStringValue(); break; case 8: parser.getText(); break; case 9: parser.getTextCharacters(); break; case 10: parser.getTextLength(); break; case 11: parser.getTextOffset(); break; case 12: parser.getNumberType(); break; case 13: parser.getNumberValue(); break; case 14: parser.getIntValue(); break; case 15: parser.getLongValue(); break; case 16: parser.getBigIntegerValue(); break; case 17: parser.getFloatValue(); break; case 18: parser.getDoubleValue(); break; default: parser.getDecimalValue(); break; } } parser.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/ProtobufParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.dataformat.protobuf.ProtobufFactory; import tools.jackson.dataformat.protobuf.ProtobufMapper; import tools.jackson.dataformat.protobuf.ProtobufParser; /** This fuzzer targets the methods of ProtobufParser */ public class ProtobufParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 100)); ProtobufMapper mapper = ProtobufMapper.builder(ProtobufFactory.builder().build()).build(); // Failsafe logic if (mapper == null) { return; } // Create and configure ProtobufParser ProtobufParser parser = (ProtobufParser) ((ProtobufMapper) mapper).tokenStreamFactory().createParser(data.consumeRemainingAsBytes()); parser.setSchema(mapper.generateSchemaFor(ProtobufParserFuzzer.class)); // Fuzz methods of ProtobufParser for (Integer choice : choices) { switch (Math.abs(choice) % 18) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.getText(); break; case 8: parser.getTextCharacters(); break; case 9: parser.getTextLength(); break; case 10: parser.getTextOffset(); break; case 11: parser.getNumberType(); break; case 12: parser.getNumberValue(); break; case 13: parser.getIntValue(); break; case 14: parser.getLongValue(); break; case 15: parser.getBigIntegerValue(); break; case 16: parser.getFloatValue(); break; case 17: parser.getDoubleValue(); break; default: parser.getDecimalValue(); break; } } parser.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/SerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.core.FormatFeature; import tools.jackson.core.TokenStreamFactory; import tools.jackson.core.JsonGenerator; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectWriter; import tools.jackson.databind.node.ObjectNode; import tools.jackson.dataformat.avro.AvroFactory; import tools.jackson.dataformat.avro.AvroFactoryBuilder; import tools.jackson.dataformat.avro.AvroMapper; import tools.jackson.dataformat.avro.AvroReadFeature; import tools.jackson.dataformat.cbor.CBORFactory; import tools.jackson.dataformat.cbor.CBORWriteFeature; import tools.jackson.dataformat.cbor.CBORMapper; import tools.jackson.dataformat.ion.IonFactory; import tools.jackson.dataformat.ion.IonFactoryBuilder; import tools.jackson.dataformat.ion.IonObjectMapper; import tools.jackson.dataformat.ion.IonReadFeature; import tools.jackson.dataformat.protobuf.ProtobufFactory; import tools.jackson.dataformat.protobuf.ProtobufMapper; import tools.jackson.dataformat.smile.SmileFactory; import tools.jackson.dataformat.smile.SmileReadFeature; import tools.jackson.dataformat.smile.SmileMapper; import java.io.ByteArrayInputStream; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; /** This fuzzer targets the serialization methods of Avro/Cbor/Ion/Protobuf/Smile objects */ public class SerializerFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { TokenStreamFactory factory = null; JsonGenerator generator = null; ObjectMapper mapper = null; FormatFeature feature = null; try { switch (data.consumeInt(1, 5)) { case 1: // Initialize AvroFactoryBuilder object AvroFactoryBuilder avroFactoryBuilder; if (data.consumeBoolean()) { avroFactoryBuilder = AvroFactory.builderWithApacheDecoder(); } else { avroFactoryBuilder = AvroFactory.builderWithNativeDecoder(); } // Initialize AvroFactory object factory = avroFactoryBuilder.build(); // Initialize AvroMapper object mapper = AvroMapper.builder((AvroFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(AvroReadFeature.class)); break; case 2: // Initialize CBORFactory object factory = CBORFactory.builder().build(); // Initialize CBORMapper object mapper = CBORMapper.builder((CBORFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(CBORWriteFeature.class)); break; case 3: // Initialize IonFactoryBuilder object IonFactoryBuilder ionFactoryBuilder; if (data.consumeBoolean()) { ionFactoryBuilder = IonFactory.builderForBinaryWriters(); } else { ionFactoryBuilder = IonFactory.builderForTextualWriters(); } // Initialize IonFactory object factory = ionFactoryBuilder.build(); // Initialize IonObjectMapper object mapper = IonObjectMapper.builder((IonFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(IonReadFeature.class)); break; case 4: // Initialize ProtobufFactory object factory = ProtobufFactory.builder().build(); // Initialize ProtobufMapper object mapper = ProtobufMapper.builder((ProtobufFactory) factory).build(); break; case 5: // Initialize SmileFactory object factory = SmileFactory.builder().build(); // Initialize SmileMapper object mapper = SmileMapper.builder((SmileFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(SmileReadFeature.class)); break; } // Failsafe logic if ((factory == null) || (mapper == null)) { return; } // Initialize ObjectWriter object ObjectWriter writer = mapper.writer(); // Initialize ObjectNode object ObjectNode node = mapper.createObjectNode(); // Randomize writer options if (data.consumeBoolean()) { writer = writer.withDefaultPrettyPrinter(); } if (feature != null) { writer = writer.with(feature); } // Object to write Object object = null; // Fuzz the serialize methods for different XML objects switch (data.consumeInt(1, 28)) { case 1: node.put("data", data.consumeRemainingAsBytes()); object = node; break; case 2: generator = factory.createGenerator(new StringWriter()); generator.writeStartObject(); generator.writeName("data"); byte[] binaryData = data.consumeRemainingAsBytes(); generator.writeBinary(binaryData, 0, binaryData.length); generator.writeEndObject(); break; case 3: generator = factory.createGenerator(new StringWriter()); generator.writeStartObject(); generator.writeString(data.consumeRemainingAsString()); generator.writeEndObject(); break; case 4: Map innerMap = Collections.singletonMap("inner_data", data.consumeRemainingAsString()); Map> map = Collections.singletonMap("data", innerMap); object = map; break; case 5: List innerList = Collections.singletonList(data.consumeRemainingAsString()); List> list = Collections.singletonList(innerList); object = list; break; case 6: object = BigInteger.valueOf(data.consumeLong()); break; case 7: object = data.consumeRemainingAsString(); break; case 8: object = data.consumeRemainingAsBytes(); break; case 9: object = BigDecimal.valueOf(data.consumeDouble()); break; case 10: object = data.consumeBoolean(); break; case 11: object = data.consumeInt(); break; case 12: object = data.consumeLong(); break; case 13: object = data.consumeDouble(); break; case 14: object = data.consumeBoolean(); break; case 15: object = data.consumeByte(); break; case 16: object = data.consumeChar(); break; case 17: object = data.consumeBoolean(); break; case 18: object = new ByteArrayInputStream(data.consumeRemainingAsBytes()); break; case 19: object = new RawContainer(data.consumeRemainingAsString()); break; case 20: object = new ByteBufferContainer(data.consumeRemainingAsBytes()); break; case 21: object = new MapContainer(data.consumeRemainingAsString()); break; case 22: object = new ListContainer(data.consumeRemainingAsString()); break; case 23: object = new ByteArrayContainer(data.consumeRemainingAsBytes()); break; case 24: object = new UUID(data.consumeLong(), data.consumeLong()); break; case 25: object = new UUIDContainer(data.consumeLong(), data.consumeLong()); break; case 26: object = new ArrayContainer(data.consumeRemainingAsString()); break; case 27: object = new Date(data.consumeLong()); break; case 28: object = data.consumeRemainingAsString().toCharArray(); break; } writer.writeValueAsString(object); writer.writeValueAsBytes(object); } catch (RuntimeException e) { // Known exception } finally { try { if (generator != null) { // Close JsonGenerator object generator.flush(); generator.close(); } } catch (RuntimeException e) { // Ignore exceptions for generator closing } } } @JsonRootName("ByteArray") private static class ByteArrayContainer { public byte[] value; public ByteArrayContainer(byte[] value) { this.value = value; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; @JsonRawValue public char[] charArray; public RawContainer(String string) { this.string = string; this.charArray = string.toCharArray(); } } private static class ByteBufferContainer { public ByteBuffer byteBuffer; public ByteBufferContainer(byte[] byteArray) { this.byteBuffer = ByteBuffer.allocateDirect(byteArray.length); this.byteBuffer.put(byteArray); } } private static class MapContainer { public Map map; public MapContainer(String string) { this.map = new HashMap(); this.map.put(0, string); } } private static class ListContainer { public List list; public ListContainer(String string) { this.list = new ArrayList(); this.list.add(string); } } private static class ArrayContainer { public char[] array; public ArrayContainer(String string) { this.array = string.toCharArray(); } public void setArray(char[] array) { this.array = array; } } private static class UUIDContainer { public UUID uuid; public UUIDContainer(long a, long b) { this.uuid = new UUID(a, b); } } } ================================================ FILE: projects/jackson-dataformats-binary/SmileFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.smile.SmileMapper; public class SmileFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new SmileMapper(); try { mapper.readTree(input); } catch (RuntimeException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-binary/SmileGeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.io.SerializedString; import tools.jackson.dataformat.smile.SmileFactory; import tools.jackson.dataformat.smile.SmileGenerator; import tools.jackson.dataformat.smile.SmileMapper; import tools.jackson.dataformat.smile.SmileWriteFeature; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.EnumSet; /** This fuzzer targets the methods of SmileGenerator */ public class SmileGeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Retrieve set of SmileWriteFeature EnumSet featureSet = EnumSet.allOf(SmileWriteFeature.class); // Create and configure SmileMapper SmileMapper mapper = new SmileMapper( SmileFactory.builder() .enable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Create SmileGenerator SmileGenerator generator = (SmileGenerator) ((SmileMapper) mapper).tokenStreamFactory().createGenerator(new ByteArrayOutputStream()); generator.writeStartObject(); // Fuzz methods of SmileGenerator String value = null; byte[] byteArray = null; generator.writeName("OSS-Fuzz"); switch (data.consumeInt(1, 20)) { case 1: generator.writeRaw(data.consumeByte()); break; case 2: byteArray = data.consumeRemainingAsBytes(); generator.writeBytes(byteArray, 0, byteArray.length); break; case 3: int[] intArray = data.consumeInts(data.consumeInt(1, 5)); generator.writeArray(intArray, 0, intArray.length); break; case 4: long[] longArray = data.consumeLongs(data.consumeInt(1, 5)); generator.writeArray(longArray, 0, longArray.length); break; case 5: double[] doubleArray = new double[data.consumeInt(1, 5)]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } generator.writeArray(doubleArray, 0, doubleArray.length); break; case 6: generator.writeString(data.consumeRemainingAsString()); break; case 7: value = data.consumeRemainingAsString(); generator.writeString(value.toCharArray(), 0, value.length()); break; case 8: generator.writeString(new SerializedString(data.consumeRemainingAsString())); break; case 9: byteArray = data.consumeRemainingAsBytes(); generator.writeRawUTF8String(byteArray, 0, byteArray.length); break; case 10: byteArray = data.consumeRemainingAsBytes(); generator.writeUTF8String(byteArray, 0, byteArray.length); break; case 11: byteArray = data.consumeRemainingAsBytes(); generator.writeBinary(new ByteArrayInputStream(byteArray), byteArray.length); break; case 12: generator.writeBoolean(data.consumeBoolean()); break; case 13: generator.writeNull(); break; case 14: generator.writeNumber(data.consumeInt()); break; case 15: generator.writeNumber(data.consumeLong()); break; case 16: generator.writeNumber(data.consumeDouble()); break; case 17: generator.writeNumber(data.consumeFloat()); break; case 18: generator.writeNumber(new BigDecimal(data.consumeLong())); break; case 19: generator.writeNumber(BigInteger.valueOf(data.consumeLong())); break; case 20: generator.writeNumber(data.consumeRemainingAsString()); break; } generator.writeEndObject(); generator.flush(); generator.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/SmileParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.dataformat.smile.SmileFactory; import tools.jackson.dataformat.smile.SmileParser; import tools.jackson.dataformat.smile.SmileMapper; import tools.jackson.dataformat.smile.SmileReadFeature; import java.util.EnumSet; /** This fuzzer targets the methods of SmileParser */ public class SmileParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 100)); // Retrieve set of SmileReadFeature EnumSet featureSet = EnumSet.allOf(SmileReadFeature.class); // Create and configure SmileMapper SmileMapper mapper = new SmileMapper( SmileFactory.builder() .enable(data.pickValue(featureSet)) .disable(data.pickValue(featureSet)) .build()); // Failsafe logic if (mapper == null) { return; } // Create and configure SmileParser SmileParser parser = (SmileParser) ((SmileMapper) mapper).tokenStreamFactory().createParser(data.consumeRemainingAsBytes()); // Fuzz methods of SmileParser for (Integer choice : choices) { switch (Math.abs(choice) % 19) { case 1: parser.currentName(); break; case 2: parser.currentTokenLocation(); break; case 3: parser.currentLocation(); break; case 4: parser.isExpectedStartArrayToken(); break; case 5: parser.isExpectedNumberIntToken(); break; case 6: parser.nextToken(); break; case 7: parser.nextStringValue(); break; case 8: parser.getText(); break; case 9: parser.getTextCharacters(); break; case 10: parser.getTextLength(); break; case 11: parser.getTextOffset(); break; case 12: parser.getNumberType(); break; case 13: parser.getNumberValue(); break; case 14: parser.getIntValue(); break; case 15: parser.getLongValue(); break; case 16: parser.getBigIntegerValue(); break; case 17: parser.getFloatValue(); break; case 18: parser.getDoubleValue(); break; default: parser.getDecimalValue(); break; } } parser.close(); } catch (RuntimeException e) { // Known exception } } } ================================================ FILE: projects/jackson-dataformats-binary/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true" mvn package dependency:copy-dependencies $MAVEN_ARGS CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) DATAFORMAT_PREFIX=jackson-dataformat mkdir -p $OUT/dependency cp "avro/target/$DATAFORMAT_PREFIX-avro-$CURRENT_VERSION.jar" $OUT/$DATAFORMAT_PREFIX-avro.jar for jarfile in $(find avro/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "cbor/target/$DATAFORMAT_PREFIX-cbor-$CURRENT_VERSION.jar" $OUT/$DATAFORMAT_PREFIX-cbor.jar for jarfile in $(find cbor/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "ion/target/$DATAFORMAT_PREFIX-ion-$CURRENT_VERSION.jar" $OUT/$DATAFORMAT_PREFIX-ion.jar for jarfile in $(find ion/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "protobuf/target/$DATAFORMAT_PREFIX-protobuf-$CURRENT_VERSION.jar" $OUT/$DATAFORMAT_PREFIX-protobuf.jar for jarfile in $(find protobuf/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "smile/target/$DATAFORMAT_PREFIX-smile-$CURRENT_VERSION.jar" $OUT/$DATAFORMAT_PREFIX-smile.jar for jarfile in $(find smile/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done ALL_JARS="$DATAFORMAT_PREFIX-cbor.jar $DATAFORMAT_PREFIX-smile.jar $DATAFORMAT_PREFIX-avro.jar $DATAFORMAT_PREFIX-ion.jar $DATAFORMAT_PREFIX-protobuf.jar" ALL_DEPENDENCY=$(find $OUT/dependency -name *.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "$OUT/dependency/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "\$this_dir/dependency/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-dataformats-binary/project.yaml ================================================ homepage: "https://github.com/FasterXML/jackson-dataformats-binary" language: jvm primary_contact: "tatu@fasterxml.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/FasterXML/jackson-dataformats-binary" sanitizers: - address auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "norbert.schneider@code-intelligence.com" - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" - "tyagregg@gmail.com" ================================================ FILE: projects/jackson-dataformats-text/CSVFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.csv.CsvMapper; public class CSVFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new CsvMapper(); try { mapper.readTree(input); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-text/DeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.core.JacksonException; import tools.jackson.core.JsonParser; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.csv.CsvFactory; import tools.jackson.dataformat.csv.CsvMapper; import tools.jackson.dataformat.javaprop.JavaPropsFactory; import tools.jackson.dataformat.javaprop.JavaPropsMapper; import tools.jackson.dataformat.toml.TomlFactory; import tools.jackson.dataformat.toml.TomlMapper; import tools.jackson.dataformat.toml.TomlReadFeature; import tools.jackson.dataformat.yaml.YAMLFactory; import tools.jackson.dataformat.yaml.YAMLMapper; import java.io.ByteArrayOutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.time.DateTimeException; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Stream; /** This fuzzer targets the deserialization methods of YAML/TOML/JavaProps/CSV objects */ public class DeserializerFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { mapper = null; initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonParser parser = null; try { // Initialize ObjectMapper object switch (data.consumeInt(1, 4)) { case 1: mapper = CsvMapper.builder(CsvFactory.builder().build()).build(); break; case 2: mapper = JavaPropsMapper.builder(JavaPropsFactory.builder().build()).build(); break; case 3: mapper = TomlMapper.builder( TomlFactory.builder() .enable(data.pickValue(EnumSet.allOf(TomlReadFeature.class))) .build()) .build(); break; case 4: mapper = YAMLMapper.builder(YAMLFactory.builder().build()).build(); break; } // Failsafe logic if (mapper == null) { return; } // Fuzz the deserialize methods for different Yaml/Toml/JavaProps/Csv objects if (data.consumeBoolean()) { byte[] output = new byte[data.remainingBytes()]; parser = mapper.tokenStreamFactory().createParser(output); mapper.readTree(parser); } else { Class type = data.pickValue(choice); String value = data.consumeRemainingAsString(); if ((value == null) || (value.isEmpty())) { return; } mapper.readValue(value, type); } } catch (JacksonException | IllegalArgumentException | DateTimeException | IllegalStateException e) { // Known exception } finally { try { if (parser != null) { parser.close(); } } catch (JacksonException e) { // Ignore exceptions for closing JsonParser object } } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(ByteArrayContainer.class); choice.add(ByteArrayOutputStream.class); choice.add(ModelContainer.class); choice.add(DelegateContainer.class); choice.add(RawContainer.class); choice.add(MapContainer.class); choice.add(ListContainer.class); choice.add(ArrayContainer.class); choice.add(EnumFuzz.class); choice.add(EnumContainer.class); choice.add(Exception.class); choice.add(Map.class); choice.add(List.class); choice.add(Set.class); choice.add(Stream.class); choice.add(String.class); choice.add(Boolean.class); choice.add(Character.class); choice.add(Byte.class); choice.add(Integer.class); choice.add(Long.class); choice.add(Short.class); choice.add(Double.class); choice.add(Float.class); choice.add(BigInteger.class); choice.add(BigDecimal.class); choice.add(Number.class); } private static class ByteArrayContainer { public byte[] value; @JsonCreator public ByteArrayContainer(byte[] value) { this.value = value; } } @JsonRootName("Model") private static class ModelContainer { public String string; @JsonCreator public ModelContainer(@JsonProperty(value = "string", required = true) String string) { this.string = string; } } private static class DelegateContainer { public String string; @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public DelegateContainer(String string) { this.string = string; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; } private static class MapContainer { public Map map; public void setMap(Map map) { this.map = map; } } private static class ListContainer { public List list; public void setList(List list) { this.list = list; } } private static class ArrayContainer { public String[] array; public String[] getArray() { return array; } public void setArray(String[] array) { this.array = array; } } private static enum EnumFuzz { A, B, C, D, E; } private static class EnumContainer { public EnumFuzz enumFuzz; public EnumContainer(EnumFuzz enumFuzz) { this.enumFuzz = enumFuzz; } } } ================================================ FILE: projects/jackson-dataformats-text/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/yaml.dict $SRC/YAMLFuzzer.dict && \ mv fuzzing/dictionaries/toml.dict $SRC/TOMLFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/FasterXML/jackson-dataformats-text.git RUN git clone --depth 1 https://github.com/FasterXML/jackson-core.git RUN git clone --depth 1 https://github.com/FasterXML/jackson-databind.git COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-dataformats-text ================================================ FILE: projects/jackson-dataformats-text/PropertiesFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.javaprop.JavaPropsMapper; public class PropertiesFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new JavaPropsMapper(); try { mapper.readTree(input); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-text/SerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRawValue; import com.fasterxml.jackson.annotation.JsonRootName; import tools.jackson.core.FormatFeature; import tools.jackson.core.JacksonException; import tools.jackson.core.JsonGenerator; import tools.jackson.core.TokenStreamFactory; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.ObjectWriter; import tools.jackson.databind.node.ObjectNode; import tools.jackson.dataformat.csv.CsvFactory; import tools.jackson.dataformat.csv.CsvMapper; import tools.jackson.dataformat.csv.CsvWriteFeature; import tools.jackson.dataformat.javaprop.JavaPropsFactory; import tools.jackson.dataformat.javaprop.JavaPropsMapper; import tools.jackson.dataformat.toml.TomlFactory; import tools.jackson.dataformat.toml.TomlMapper; import tools.jackson.dataformat.toml.TomlWriteFeature; import tools.jackson.dataformat.yaml.YAMLFactory; import tools.jackson.dataformat.yaml.YAMLMapper; import tools.jackson.dataformat.yaml.YAMLWriteFeature; import java.io.ByteArrayInputStream; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import org.snakeyaml.engine.v2.api.DumpSettings; import org.snakeyaml.engine.v2.common.FlowStyle; /** This fuzzer targets the serialization methods of YAML/TOML/JavaProps/CSV objects */ public class SerializerFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { TokenStreamFactory factory = null; JsonGenerator generator = null; ObjectMapper mapper = null; FormatFeature feature = null; try { switch (data.consumeInt(1, 4)) { case 1: // Initialize CsvFactory object factory = CsvFactory.builder().build(); // Initialize CsvMapper object mapper = CsvMapper.builder((CsvFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(CsvWriteFeature.class)); break; case 2: // Initialize JavaPropsFactory object factory = JavaPropsFactory.builder().build(); // Initialize JavaPropsMapper object mapper = JavaPropsMapper.builder((JavaPropsFactory) factory).build(); break; case 3: // Initialize TomlFactory object factory = TomlFactory.builder().build(); // Initialize TomlMapper object mapper = TomlMapper.builder((TomlFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(TomlWriteFeature.class)); break; case 4: // Initialize YAMLFactory object DumpSettings dumpSettings = DumpSettings.builder() .setDefaultFlowStyle(data.pickValue(EnumSet.allOf(FlowStyle.class))) .build(); factory = YAMLFactory.builder().dumperOptions(dumpSettings).build(); // Initialize YAMLMapper object mapper = YAMLMapper.builder((YAMLFactory) factory).build(); // Initialize format options feature = data.pickValue(EnumSet.allOf(YAMLWriteFeature.class)); break; } // Failsafe logic if ((factory == null) || (mapper == null)) { return; } // Initialize ObjectWriter object ObjectWriter writer = mapper.writer(); // Initialize ObjectNode object ObjectNode node = mapper.createObjectNode(); // Initialize JsonGenerator object generator = factory.createGenerator(new StringWriter()); // Randomize writer options if (data.consumeBoolean()) { writer = writer.withDefaultPrettyPrinter(); } if (feature != null) { writer = writer.with(feature); } // Failsafe logic if (generator == null) { return; } // Object to write Object object = null; // Fuzz the serialize methods for different XML objects switch (data.consumeInt(1, 23)) { case 1: node.put("data", data.consumeRemainingAsBytes()); object = node; break; case 2: generator.writeStartObject(); generator.writeBinary(data.consumeRemainingAsBytes()); generator.writeEndObject(); break; case 3: generator.writeStartObject(); generator.writeString(data.consumeRemainingAsString()); generator.writeEndObject(); break; case 4: Map innerMap = Collections.singletonMap("inner_data", data.consumeRemainingAsString()); Map> map = Collections.singletonMap("data", innerMap); object = map; break; case 5: List innerList = Collections.singletonList(data.consumeRemainingAsString()); List> list = Collections.singletonList(innerList); object = list; break; case 6: object = BigInteger.valueOf(data.consumeLong()); break; case 7: object = data.consumeRemainingAsString(); break; case 8: object = data.consumeRemainingAsBytes(); break; case 9: object = BigDecimal.valueOf(data.consumeDouble()); break; case 10: object = data.consumeBoolean(); break; case 11: object = data.consumeInt(); break; case 12: object = data.consumeLong(); break; case 13: object = data.consumeDouble(); break; case 14: object = data.consumeBoolean(); break; case 15: object = data.consumeByte(); break; case 16: object = data.consumeChar(); break; case 17: object = data.consumeBoolean(); break; case 18: object = new ByteArrayInputStream(data.consumeRemainingAsBytes()); break; case 19: object = new RawContainer(data.consumeRemainingAsString()); break; case 20: object = new ByteBufferContainer(data.consumeRemainingAsBytes()); break; case 21: object = new MapContainer(data.consumeRemainingAsString()); break; case 22: object = new ListContainer(data.consumeRemainingAsString()); break; case 23: object = new ByteArrayContainer(data.consumeRemainingAsBytes()); break; } writer.writeValueAsString(object); writer.writeValueAsBytes(object); } catch (JacksonException | IllegalArgumentException e) { // Known exception } finally { try { if (generator != null) { // Close JsonGenerator object generator.flush(); generator.close(); } } catch (JacksonException e) { // Ignore exceptions for generator closing } } } @JsonRootName("ByteArray") private static class ByteArrayContainer { public byte[] value; public ByteArrayContainer(byte[] value) { this.value = value; } } @JsonPropertyOrder({"id", "raw"}) private static class RawContainer { @JsonRawValue public String string; @JsonRawValue public char[] charArray; public RawContainer(String string) { this.string = string; this.charArray = string.toCharArray(); } } private static class ByteBufferContainer { public ByteBuffer byteBuffer; public ByteBufferContainer(byte[] byteArray) { this.byteBuffer = ByteBuffer.allocateDirect(byteArray.length); this.byteBuffer.put(byteArray); } } private static class MapContainer { public Map map; public MapContainer(String string) { this.map = new HashMap(); this.map.put(0, string); } } private static class ListContainer { public List list; public ListContainer(String string) { this.list = new ArrayList(); this.list.add(string); } } } ================================================ FILE: projects/jackson-dataformats-text/TOMLFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.toml.TomlMapper; public class TOMLFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new TomlMapper(); try { mapper.readTree(input); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-text/YAMLFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.dataformat.yaml.YAMLMapper; public class YAMLFuzzer { public static void fuzzerTestOneInput(byte[] input) { ObjectMapper mapper = new YAMLMapper(); try { mapper.readTree(input); } catch (JacksonException ignored) { } } } ================================================ FILE: projects/jackson-dataformats-text/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/jackson-core $MVN install -Dmaven.test.skip=true -Djavac.src.version=17 -Djavac.target.version=17 cd $SRC/jackson-databind $MVN install -Dmaven.test.skip=true -Djavac.src.version=17 -Djavac.target.version=17 cd $SRC/jackson-dataformats-text # Move seed corpus and dictionary. mv $SRC/*.dict $OUT MAVEN_ARGS="-P!java14+ -Dmaven.test.skip=true -Djavac.src.version=17 -Djavac.target.version=17" $MVN package dependency:copy-dependencies $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) mkdir -p $OUT/dependency cp "csv/target/jackson-dataformat-csv-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-csv.jar for jarfile in $(find csv/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "yaml/target/jackson-dataformat-yaml-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-yaml.jar for jarfile in $(find yaml/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "properties/target/jackson-dataformat-properties-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-properties.jar for jarfile in $(find properties/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "toml/target/jackson-dataformat-toml-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-toml.jar for jarfile in $(find toml/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done ALL_JARS="jackson-dataformat-csv.jar jackson-dataformat-yaml.jar jackson-dataformat-properties.jar jackson-dataformat-toml.jar" ALL_DEPENDENCY=$(find $OUT/dependency -name *.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "$OUT/dependency/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "\$this_dir/dependency/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-dataformats-text/project.yaml ================================================ homepage: "https://github.com/FasterXML/jackson-dataformats-text" language: jvm primary_contact: "tatu@fasterxml.com" main_repo: "https://github.com/FasterXML/jackson-dataformats-text" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/jackson-datatype-joda/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN git clone --depth 1 https://github.com/FasterXML/jackson-datatype-joda $SRC/jackson-datatype-joda RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-datatype-joda ================================================ FILE: projects/jackson-datatype-joda/JodaDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonTypeInfo; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.annotation.JsonDeserialize; import tools.jackson.databind.exc.MismatchedInputException; import tools.jackson.datatype.joda.JodaModule; import tools.jackson.datatype.joda.deser.DateTimeDeserializer; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.Duration; import org.joda.time.Instant; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import org.joda.time.MonthDay; import org.joda.time.Period; import org.joda.time.ReadableDateTime; import org.joda.time.ReadableInstant; import org.joda.time.ReadablePeriod; import org.joda.time.YearMonth; /** This fuzzer targets the deserialization methods of joda objects */ public class JodaDeserializerFuzzer { private static ObjectMapper mapper; private static ObjectMapper plainMapper; private static List choice; private static List typeChoice; public static void fuzzerInitialize() { // Register the JodaModule for the deserialization mapper = tools.jackson.databind.json.JsonMapper.builder() .addModule(new JodaModule()) .build(); plainMapper = new ObjectMapper(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the deserialize methods for different joda objects Class classReference = data.pickValue(choice); TypeReference typeReference = data.pickValue(typeChoice); String value = data.consumeRemainingAsString(); mapper.readValue(value, classReference); mapper.readValue(value, typeReference); plainMapper.readValue(value, AnnotationClass.class); } catch (IllegalArgumentException | ArithmeticException | UnsupportedOperationException | MismatchedInputException e) { // Known exception } } private static void initializeClassChoice() { choice = new ArrayList(); typeChoice = new ArrayList(); choice.add(DateTime.class); choice.add(DateTimeContainer.class); choice.add(DateTimeZone.class); choice.add(DateTimeZoneContainer.class); choice.add(Duration.class); choice.add(Instant.class); choice.add(Interval.class); choice.add(LocalDate.class); choice.add(LocalDateTime.class); choice.add(LocalTime.class); choice.add(MonthDay.class); choice.add(Period.class); choice.add(ReadableDateTime.class); choice.add(ReadableDateTimeContainer.class); choice.add(ReadableInstant.class); choice.add(ReadablePeriod.class); choice.add(YearMonth.class); typeChoice.add(new TypeReference>() {}); typeChoice.add(new TypeReference>() {}); typeChoice.add(new TypeReference>() {}); typeChoice.add(new TypeReference>() {}); } private static class ReadableDateTimeContainer { @JsonFormat(without = JsonFormat.Feature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) public ReadableDateTime readableDateTime; } private static class DateTimeContainer { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") public DateTime dateTime; public DateTime getDateTime() { return dateTime; } } private static class DateTimeZoneContainer { @JsonTypeInfo( use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_ARRAY, property = "@class") public DateTimeZone dateTimeZone; public DateTimeZoneContainer(DateTimeZone dateTimeZone) { this.dateTimeZone = dateTimeZone; } } private static class AnnotationClass { @JsonDeserialize(using = DateTimeDeserializer.class) private DateTime dateTime; public void setDateTime(DateTime dateTime) { this.dateTime = dateTime; } } } ================================================ FILE: projects/jackson-datatype-joda/JodaMapperFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.databind.json.JsonMapper; import tools.jackson.databind.ObjectReader; import tools.jackson.databind.cfg.DateTimeFeature; import tools.jackson.databind.exc.MismatchedInputException; import tools.jackson.datatype.joda.JodaModule; import org.joda.time.*; import java.io.IOException; import java.util.*; public class JodaMapperFuzzer { public static DateTimeFeature[] dateTimeFeatures = new DateTimeFeature[]{ DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS, DateTimeFeature.WRITE_DURATIONS_AS_TIMESTAMPS, DateTimeFeature.WRITE_DATES_WITH_ZONE_ID, }; public static Class[] classes = { DummyClass.class, DateTimeZone.class, Date.class, DateTime.class, org.joda.time.Duration.class, org.joda.time.Instant.class, org.joda.time.LocalDateTime.class, org.joda.time.LocalDate.class, org.joda.time.LocalTime.class, org.joda.time.Period.class, ReadablePeriod.class, ReadableDateTime.class, ReadableInstant.class, Interval.class, MonthDay.class, YearMonth.class }; public static void fuzzerTestOneInput(FuzzedDataProvider data) { JsonMapper.Builder builder = JsonMapper.builder() .addModule(new JodaModule()); boolean writeDatesAsTimestamps = data.consumeBoolean(); builder.configure(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS, writeDatesAsTimestamps); List pickedValues = data.pickValues(dateTimeFeatures, data.consumeInt(0, dateTimeFeatures.length)); for (DateTimeFeature feature : pickedValues) { builder.enable(feature); } JsonMapper jodaMapper = builder.build(); ObjectReader reader = jodaMapper.readerFor(data.pickValue(classes)); try { reader.readValue(data.consumeRemainingAsString()); } catch (IllegalArgumentException | ArithmeticException | MismatchedInputException e) {} } public static class DummyClass { public Date date; public TimeZone timeZone; public Calendar calendar; public Locale locale; public org.joda.time.Duration duration; public org.joda.time.LocalDateTime localDateTime; public org.joda.time.LocalDate localDate; public org.joda.time.LocalTime localTime; public org.joda.time.Period period; public ReadablePeriod readablePeriod; public ReadableDateTime readableDateTime; public ReadableInstant readableInstant; public Interval instant; public MonthDay monthDay; public YearMonth yearMonth; public DateTimeZone dateTimeZone; } } ================================================ FILE: projects/jackson-datatype-joda/JodaSerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.annotation.JsonSerialize; import tools.jackson.datatype.joda.JodaModule; import tools.jackson.datatype.joda.ser.DateTimeSerializer; import tools.jackson.databind.cfg.DateTimeFeature; import tools.jackson.databind.exc.MismatchedInputException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.joda.time.DateTime; import org.joda.time.Duration; import org.joda.time.Interval; import org.joda.time.Period; /** This fuzzer targets the serialization methods of joda objects */ public class JodaSerializerFuzzer { private static ObjectMapper mapper; private static ObjectMapper plainMapper; public static void fuzzerInitialize() { // Register the JodaModule for the serialization plainMapper = new ObjectMapper(); mapper = tools.jackson.databind.json.JsonMapper.builder() .addModule(new JodaModule()) .enable(tools.jackson.databind.cfg.DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS) .enable(tools.jackson.databind.cfg.DateTimeFeature.WRITE_DURATIONS_AS_TIMESTAMPS) .build(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the serialize methods for different joda objects mapper = tools.jackson.databind.json.JsonMapper.builder() .addModule(new JodaModule()) .configure(tools.jackson.databind.cfg.DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS, data.consumeBoolean()) .build(); DateTime dateTime = new DateTime(data.consumeLong()); switch (data.consumeInt(1, 11)) { case 1: plainMapper.writeValueAsString(new AnnotationClass(dateTime)); break; case 2: mapper.writeValueAsString(dateTime); break; case 3: mapper .writer() .without(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS) .writeValueAsString(dateTime); break; case 4: Map map = new HashMap(); map.put(data.consumeRemainingAsString(), dateTime); mapper.writeValueAsString(map); break; case 5: mapper.writeValueAsString(dateTime.toInstant()); break; case 6: mapper.writeValueAsString(new Interval(dateTime.toInstant(), dateTime.toInstant())); break; case 7: mapper.writeValueAsString(dateTime.toLocalDate()); break; case 8: mapper.writeValueAsString(dateTime.toLocalTime()); break; case 9: mapper.writeValueAsString(dateTime.toLocalDateTime()); break; case 10: mapper.writeValueAsString(new Duration(dateTime.toInstant(), dateTime.toInstant())); break; case 11: mapper.writeValueAsString(new Period(dateTime.getMillis())); break; } } catch (IllegalArgumentException | ArithmeticException | MismatchedInputException e) { // Known exception } } private static class AnnotationClass { @JsonSerialize(using = DateTimeSerializer.class) private DateTime dateTime; public AnnotationClass(DateTime dateTime) { this.dateTime = dateTime; } public DateTime getDateTime() { return this.dateTime; } } } ================================================ FILE: projects/jackson-datatype-joda/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) ./mvnw package dependency:copy-dependencies -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true mkdir -p $OUT/dependency cp "$SRC/jackson-datatype-joda/target/jackson-datatype-joda-$CURRENT_VERSION.jar" $OUT/joda.jar for jarfile in $(find $SRC/jackson-datatype-joda/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done ALL_JARS="joda.jar" ALL_DEPENDENCY=$(find $OUT/dependency -name *.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "$OUT/dependency/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "\$this_dir/dependency/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-datatype-joda/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/FasterXML/jackson-datatype-joda" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/FasterXML/jackson-datatype-joda" sanitizers: - address primary_contact: "tatu@fasterxml.com" auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/jackson-datatypes-collections/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN git clone --depth 1 https://github.com/FasterXML/jackson-datatypes-collections $SRC/jackson-datatypes-collections RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-datatypes-collections ================================================ FILE: projects/jackson-datatypes-collections/EclipseCollectionsDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.eclipsecollections.EclipseCollectionsModule; import java.util.ArrayList; import java.util.List; /** This fuzzer targets the deserialization methods of eclipse collections object */ public class EclipseCollectionsDeserializerFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { // Register the EclipseCollectionsModule for the deserialization mapper = JsonMapper.builder() .addModule(new EclipseCollectionsModule()) .build(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the deserialize methods for different eclipse collections object Class type = data.pickValue(choice); String value = data.consumeRemainingAsString(); mapper.readValue(value, type); } catch (JacksonException e) { // Known exception } } private static void initializeClassChoice() { final String[] types = {"Boolean", "Byte", "Char", "Double", "Float", "Int", "Long", "Short"}; choice = new ArrayList(); for (String key : types) { addClass("org.eclipse.collections.api.bag.primitive." + key + "Bag"); addClass("org.eclipse.collections.api.collection.primitive." + key + "Collection"); addClass("org.eclipse.collections.api.list.primitive." + key + "List"); addClass("org.eclipse.collections.api.set.primitive." + key + "Set"); for (String value : types) { addClass("org.eclipse.collections.api.tuple.primitive." + key + value + "Pair"); if (!key.equals("Boolean")) { addClass("org.eclipse.collections.api.map.primitive.Mutable" + key + value + "Map"); addClass("org.eclipse.collections.api.map.primitive.Immutable" + key + value + "Map"); addClass("org.eclipse.collections.api.map.primitive." + key + value + "Map"); } } } } private static void addClass(String name) { try { choice.add(Class.forName(name)); } catch (ClassNotFoundException e) { // Skip missing classes } } } ================================================ FILE: projects/jackson-datatypes-collections/EclipseCollectionsSerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonTypeInfo; import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.eclipsecollections.EclipseCollectionsModule; import org.eclipse.collections.api.map.ImmutableMap; import org.eclipse.collections.api.map.MapIterable; import org.eclipse.collections.api.map.MutableMap; import org.eclipse.collections.api.map.MutableMapIterable; import org.eclipse.collections.impl.factory.Maps; import org.eclipse.collections.impl.factory.Sets; import org.eclipse.collections.impl.factory.primitive.BooleanLists; import org.eclipse.collections.impl.factory.primitive.ByteLists; import org.eclipse.collections.impl.factory.primitive.CharLists; import org.eclipse.collections.impl.factory.primitive.DoubleLists; import org.eclipse.collections.impl.factory.primitive.FloatLists; import org.eclipse.collections.impl.factory.primitive.IntLists; import org.eclipse.collections.impl.factory.primitive.IntObjectMaps; import org.eclipse.collections.impl.factory.primitive.LongLists; import org.eclipse.collections.impl.factory.primitive.ShortLists; /** This fuzzer targets the serialization methods of eclipse collections object */ public class EclipseCollectionsSerializerFuzzer { private static ObjectMapper mapper; public static void fuzzerInitialize() { // Register the EclipseCollectionsModule for the serialization mapper = JsonMapper.builder() .addModule(new EclipseCollectionsModule()) .build(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the serialize methods for different eclipse collections object Integer listSize = data.consumeInt(1, 10); switch (data.consumeInt(1, 22)) { case 1: boolean[] boolArray = data.consumeBooleans(listSize); mapper.writeValueAsString(BooleanLists.immutable.of(boolArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(BooleanLists.immutable.of(boolArray))); break; case 2: byte[] byteArray = data.consumeRemainingAsBytes(); mapper.writeValueAsString(ByteLists.immutable.of(byteArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(ByteLists.immutable.of(byteArray))); break; case 3: char[] charArray = data.consumeRemainingAsString().toCharArray(); mapper.writeValueAsString(CharLists.immutable.of(charArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(CharLists.immutable.of(charArray))); break; case 4: double[] doubleArray = new double[listSize]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } mapper.writeValueAsString(DoubleLists.immutable.of(doubleArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(DoubleLists.immutable.of(doubleArray))); break; case 5: float[] floatArray = new float[listSize]; for (int i = 0; i < floatArray.length; i++) { floatArray[i] = data.consumeFloat(); } mapper.writeValueAsString(FloatLists.immutable.of(floatArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(FloatLists.immutable.of(floatArray))); break; case 6: int[] intArray = data.consumeInts(listSize); mapper.writeValueAsString(IntLists.immutable.of(intArray)); mapper.writeValueAsString(new PrimitiveIterativeObject(IntLists.immutable.of(intArray))); break; case 7: long[] longArray = data.consumeLongs(listSize); mapper.writeValueAsString(LongLists.immutable.of(longArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(LongLists.immutable.of(longArray))); break; case 8: short[] shortArray = data.consumeShorts(listSize); mapper.writeValueAsString(ShortLists.immutable.of(shortArray)); mapper.writeValueAsString( new PrimitiveIterativeObject(ShortLists.immutable.of(shortArray))); break; case 9: mapper.writeValueAsString(Sets.immutable.of(data.consumeRemainingAsString())); break; case 10: mapper.writeValueAsString(Sets.immutable.of(data.consumeRemainingAsBytes())); break; case 11: mapper .writerFor(MutableMap.class) .writeValueAsString(Maps.mutable.of(0, data.consumeRemainingAsString())); break; case 12: mapper .writerFor(MutableMap.class) .writeValueAsString(Maps.mutable.of(0, data.consumeRemainingAsBytes())); break; case 13: mapper .writerFor(ImmutableMap.class) .writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsString())); break; case 14: mapper .writerFor(ImmutableMap.class) .writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsBytes())); break; case 15: mapper .writerFor(MapIterable.class) .writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsString())); break; case 16: mapper .writerFor(MapIterable.class) .writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsBytes())); break; case 17: mapper .writerFor(MutableMapIterable.class) .writeValueAsString(Maps.mutable.of(0, data.consumeRemainingAsString())); break; case 18: mapper .writerFor(MutableMapIterable.class) .writeValueAsString(Maps.mutable.of(0, data.consumeRemainingAsBytes())); break; case 19: mapper.writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsString())); break; case 20: mapper.writeValueAsString(Maps.immutable.of(0, data.consumeRemainingAsBytes())); break; case 21: mapper.writeValueAsString(IntObjectMaps.immutable.of(0, data.consumeRemainingAsString())); break; case 22: mapper.writeValueAsString(IntObjectMaps.immutable.of(0, data.consumeRemainingAsBytes())); break; } } catch (JacksonException e) { // Known exception } } private static class PrimitiveIterativeObject { @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) Object object; public PrimitiveIterativeObject(Object object) { this.object = object; } } } ================================================ FILE: projects/jackson-datatypes-collections/GuavaDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonTypeInfo; import tools.jackson.core.JacksonException; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.guava.GuavaModule; import com.google.common.cache.Cache; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultiset; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMultiset; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.SortedMultiset; import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultiset; import com.google.common.hash.HashCode; import com.google.common.net.HostAndPort; import com.google.common.net.InternetDomainName; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** This fuzzer targets the deserialization methods of Guava object */ public class GuavaDeserializerFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { // Register the GuavaModule for the deserialization GuavaModule module = new GuavaModule(); module.configureAbsentsAsNulls(false); mapper = JsonMapper.builder() .addModule(module) .build(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the deserialization methods for different Guava objects TypeReference type = data.pickValue(choice); String value = data.consumeRemainingAsString(); mapper.readValue(value, type); } catch (JacksonException e) { // Known exception } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(new TypeReference>() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference() {}); } public static class ImmutableListContainer { public ImmutableList> lists = ImmutableList.of(); } private static class ImmutableMapContainer { public ImmutableMap> maps = ImmutableMap.of(); } private static class ArrayListMultimapContainer { @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.CLASS) public Object object; } } ================================================ FILE: projects/jackson-datatypes-collections/GuavaSerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.annotation.JsonTypeInfo; import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.SerializationFeature; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.guava.GuavaModule; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.FluentIterable; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.ImmutableTable; import com.google.common.collect.LinkedHashMultiset; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.collect.Range; import com.google.common.collect.RangeSet; import com.google.common.collect.TreeRangeSet; import com.google.common.hash.HashCode; import com.google.common.net.HostAndPort; import com.google.common.net.InternetDomainName; import com.google.common.primitives.Bytes; import java.io.IOException; /** This fuzzer targets the serialization methods of Guava objects */ public class GuavaSerializerFuzzer { private static ObjectMapper mapper; public static void fuzzerInitialize() { // Register the GuavaModule for the serialization GuavaModule module = new GuavaModule(); module.configureAbsentsAsNulls(false); mapper = JsonMapper.builder() .addModule(module) .build(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the serialize methods for different Guava objects Integer listSize = data.consumeInt(1, 10); switch (data.consumeInt(1, 12)) { case 1: Cache cache = CacheBuilder.newBuilder().build(); cache.put(data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); // Note: ObjectMapper is immutable in Jackson 3.x, cannot dynamically enable features mapper.writeValueAsString(cache); break; case 2: byte[] bytes = data.consumeRemainingAsBytes(); Byte[] byteArray = new Byte[bytes.length]; for (int i = 0; i < bytes.length; i++) { byteArray[i] = bytes[i]; } FluentIterable fluentIterable = FluentIterable.from(byteArray); mapper.writeValueAsString(fluentIterable); break; case 3: HashCode hashCode = HashCode.fromString(data.consumeRemainingAsString()); mapper.writeValueAsString(hashCode); break; case 4: HostAndPort hostAndPort = HostAndPort.fromParts( data.consumeString(data.remainingBytes()), data.consumeInt(1, 65536)); mapper.writeValueAsString(hostAndPort); break; case 5: Multimap multimap = HashMultimap.create(); multimap.put(data.consumeString(data.remainingBytes()), data.consumeRemainingAsBytes()); mapper .writer() .without(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS) .writeValueAsString(multimap); break; case 6: InternetDomainName internetDomainName = InternetDomainName.from(data.consumeRemainingAsString()); mapper.writeValueAsString(internetDomainName); break; case 7: ImmutableTable.Builder immutableTableBuilder = ImmutableTable.builder(); immutableTableBuilder.put( data.consumeInt(1, 10), data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); ImmutableTable immutableTable = immutableTableBuilder.build(); mapper.writeValueAsString(immutableTable); break; case 8: Multiset multiSet = LinkedHashMultiset.create(); multiSet.add(data.consumeRemainingAsString()); mapper.writeValueAsString(multiSet); break; case 9: RangeSet rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closedOpen(data.consumeInt(), data.consumeInt())); rangeSet.add(Range.openClosed(data.consumeInt(), data.consumeInt())); rangeSet.add(Range.all()); mapper.writeValueAsString(rangeSet); break; case 10: ImmutableRangeSet immutableRangeSet = ImmutableRangeSet.builder() .add(Range.closedOpen(data.consumeInt(), data.consumeInt())) .add(Range.openClosed(data.consumeInt(), data.consumeInt())) .add(Range.all()) .build(); mapper.writeValueAsString(immutableRangeSet); case 11: mapper.writeValueAsString(Bytes.asList(data.consumeRemainingAsBytes()).iterator()); case 12: ArrayListMultimap arrayListMultimap = ArrayListMultimap.create(); arrayListMultimap.put( data.consumeString(data.remainingBytes()), data.consumeRemainingAsString()); ArrayListMultimapContainer container = new ArrayListMultimapContainer(arrayListMultimap); mapper.writeValueAsString(container); } } catch (JacksonException e) { // Known exception } } private static class ArrayListMultimapContainer { @JsonTypeInfo(include = JsonTypeInfo.As.PROPERTY, use = JsonTypeInfo.Id.CLASS) public Object object; public ArrayListMultimapContainer(Object object) { this.object = object; } } } ================================================ FILE: projects/jackson-datatypes-collections/HppcDeserializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.carrotsearch.hppc.IntArrayDeque; import com.carrotsearch.hppc.IntArrayList; import com.carrotsearch.hppc.IntDeque; import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.IntIndexedContainer; import com.carrotsearch.hppc.IntSet; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.hppc.HppcModule; import java.util.ArrayList; import java.util.List; /** This fuzzer targets the deserialization methods of hppc object */ public class HppcDeserializerFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { // Register the Hppc for the deserialization mapper = JsonMapper.builder() .addModule(new HppcModule()) .build(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the deserialize methods for different eclipse collections object Class type = data.pickValue(choice); String value = data.consumeRemainingAsString(); mapper.readValue(value, type); } catch (JacksonException e) { // Known exception } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(IntArrayDeque.class); choice.add(IntArrayList.class); choice.add(IntDeque.class); choice.add(IntHashSet.class); choice.add(IntIndexedContainer.class); choice.add(IntSet.class); } } ================================================ FILE: projects/jackson-datatypes-collections/HppcSerializerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.carrotsearch.hppc.BitSet; import com.carrotsearch.hppc.ByteArrayList; import com.carrotsearch.hppc.CharArrayList; import com.carrotsearch.hppc.CharHashSet; import com.carrotsearch.hppc.DoubleArrayList; import com.carrotsearch.hppc.FloatArrayList; import com.carrotsearch.hppc.IntArrayList; import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.LongArrayList; import com.carrotsearch.hppc.LongHashSet; import com.carrotsearch.hppc.ShortArrayList; import com.carrotsearch.hppc.ShortHashSet; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JacksonException; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.hppc.HppcModule; /** This fuzzer targets the serialization methods of Hppc objects */ public class HppcSerializerFuzzer { private static ObjectMapper mapper; public static void fuzzerInitialize() { // Register the HppcModule for the serialization mapper = JsonMapper.builder() .addModule(new HppcModule()) .build(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the serialize methods for different Hppc objects Integer listSize = data.consumeInt(1, 10); switch (data.consumeInt(1, 8)) { case 1: byte[] byteArray = data.consumeRemainingAsBytes(); ByteArrayList byteArrayList = new ByteArrayList(); byteArrayList.add(byteArray); mapper.writeValueAsString(byteArray); mapper.writeValueAsString(byteArrayList); break; case 2: char[] charArray = data.consumeRemainingAsString().toCharArray(); CharArrayList charArrayList = new CharArrayList(); CharHashSet charHashSet = new CharHashSet(); charArrayList.add(charArray); charHashSet.addAll(charArray); mapper.writeValueAsString(charArrayList); mapper.writeValueAsString(charHashSet); break; case 3: double[] doubleArray = new double[listSize]; for (int i = 0; i < doubleArray.length; i++) { doubleArray[i] = data.consumeDouble(); } DoubleArrayList doubleArrayList = new DoubleArrayList(); doubleArrayList.add(doubleArray); mapper.writeValueAsString(doubleArrayList); break; case 4: float[] floatArray = new float[listSize]; for (int i = 0; i < floatArray.length; i++) { floatArray[i] = data.consumeFloat(); } FloatArrayList floatArrayList = new FloatArrayList(); floatArrayList.add(floatArray); mapper.writeValueAsString(floatArrayList); break; case 5: int[] intArray = data.consumeInts(listSize); IntArrayList intArrayList = new IntArrayList(); IntHashSet intHashSet = new IntHashSet(); intArrayList.add(intArray); intHashSet.addAll(intArray); mapper.writeValueAsString(intArrayList); mapper.writeValueAsString(intHashSet); break; case 6: long[] longArray = data.consumeLongs(listSize); LongArrayList longArrayList = new LongArrayList(); LongHashSet longHashSet = new LongHashSet(); longArrayList.add(longArray); longHashSet.addAll(longArray); mapper.writeValueAsString(longArrayList); mapper.writeValueAsString(longHashSet); break; case 7: short[] shortArray = data.consumeShorts(listSize); ShortArrayList shortArrayList = new ShortArrayList(); ShortHashSet shortHashSet = new ShortHashSet(); shortArrayList.add(shortArray); shortHashSet.addAll(shortArray); mapper.writeValueAsString(shortArrayList); mapper.writeValueAsString(shortHashSet); break; case 8: BitSet bitSet = new BitSet(); for (int i = 0; i < 5; i++) { bitSet.set(data.consumeInt(0, (int) bitSet.capacity())); } mapper.writeValueAsString(bitSet); break; } } catch (JacksonException e) { // Known exception } } } ================================================ FILE: projects/jackson-datatypes-collections/PCollectionsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import tools.jackson.core.JacksonException; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import tools.jackson.datatype.pcollections.PCollectionsModule; import java.util.ArrayList; import java.util.List; import org.pcollections.ConsPStack; import org.pcollections.HashPMap; import org.pcollections.MapPBag; import org.pcollections.MapPSet; import org.pcollections.OrderedPSet; import org.pcollections.PBag; import org.pcollections.PCollection; import org.pcollections.PMap; import org.pcollections.PSequence; import org.pcollections.PSet; import org.pcollections.PStack; import org.pcollections.PVector; import org.pcollections.TreePVector; /** This fuzzer targets the methods of PCollections object */ public class PCollectionsFuzzer { private static ObjectMapper mapper; private static List choice; public static void fuzzerInitialize() { // Register the PCollectionsModule for fuzzing mapper = JsonMapper.builder() .addModule(new PCollectionsModule()) .build(); initializeClassChoice(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Fuzz the methods for different PCollections objects TypeReference type = data.pickValue(choice); String value = data.consumeRemainingAsString(); mapper.readValue(value, type); } catch (JacksonException e) { // Known exception } } private static void initializeClassChoice() { choice = new ArrayList(); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); choice.add(new TypeReference>() {}); } } ================================================ FILE: projects/jackson-datatypes-collections/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) ./mvnw package dependency:copy-dependencies -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true mkdir -p $OUT/dependency cp "$SRC/jackson-datatypes-collections/eclipse-collections/target/jackson-datatype-eclipse-collections-$CURRENT_VERSION.jar" $OUT/collections.jar for jarfile in $(find $SRC/jackson-datatypes-collections/eclipse-collections/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "$SRC/jackson-datatypes-collections/guava/target/jackson-datatype-guava-$CURRENT_VERSION.jar" $OUT/guava.jar for jarfile in $(find $SRC/jackson-datatypes-collections/guava/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "$SRC/jackson-datatypes-collections/hppc/target/jackson-datatype-hppc-$CURRENT_VERSION.jar" $OUT/hppc.jar for jarfile in $(find $SRC/jackson-datatypes-collections/hppc/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done cp "$SRC/jackson-datatypes-collections/pcollections/target/jackson-datatype-pcollections-$CURRENT_VERSION.jar" $OUT/pcollections.jar for jarfile in $(find $SRC/jackson-datatypes-collections/pcollections/target/dependency/ -name *.jar ! -name junit*.jar ! -name hamcrest*.jar) do cp $jarfile $OUT/dependency done ALL_JARS="collections.jar guava.jar hppc.jar pcollections.jar" ALL_DEPENDENCY=$(find $OUT/dependency -name *.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$JAZZER_API_PATH:$(echo $ALL_JARS | xargs printf -- "$OUT/%s:")$(echo $ALL_DEPENDENCY | xargs printf -- "$OUT/dependency/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):$(echo $ALL_DEPENDENCY | xargs printf -- "\$this_dir/dependency/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-datatypes-collections/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/FasterXML/jackson-datatypes-collections" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/FasterXML/jackson-datatypes-collections" sanitizers: - address primary_contact: "tatu@fasterxml.com" auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/jackson-modules-java8/DatatypeFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import java.io.IOException; import java.util.Optional; import java.util.List; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.fasterxml.jackson.annotation.JsonMerge; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.OptionalLong; public class DatatypeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String content = data.consumeString(100); String merge = data.consumeRemainingAsString(); ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JavaTimeModule()); mapper.registerModule(new Jdk8Module()); try { Dummy dummy1 = mapper.readValue(content, Dummy.class); Dummy dummy2 = mapper.readValue(mapper.writeValueAsString(dummy1), Dummy.class); if (!dummy1.equals(dummy2)) { throw new FuzzerSecurityIssueLow("Different values " + dummy1.debug() + " != " + dummy2.debug()); } mapper.readerForUpdating(merge); } catch (IOException e) { } } public static class Dummy { public Optional value = Optional.empty(); public Optional bool = Optional.empty();; @JsonMerge public Optional> list = Optional.empty(); public OptionalInt optint = OptionalInt.empty(); public OptionalLong optlong = OptionalLong.empty(); public OptionalDouble optdouble = OptionalDouble.empty(); public String debug() { return "%s %s %s %s %s %s".formatted(this.value, this.bool, this.list, this.optint, this.optlong, this.optdouble); } } } ================================================ FILE: projects/jackson-modules-java8/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/json.dict $SRC/YamlFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/FasterXML/jackson-modules-java8 COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jackson-modules-java8 ================================================ FILE: projects/jackson-modules-java8/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/*.dict $OUT MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "datetime/target/jackson-datatype-jsr310-$CURRENT_VERSION.jar" "$OUT/jackson-datetime.jar" cp "datatypes/target/jackson-datatype-jdk8-$CURRENT_VERSION.jar" "$OUT/jackson-datatype.jar" ALL_JARS="jackson-datatype.jar jackson-datetime.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ cp $SRC/$fuzzer_basename\$Dummy.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --instrumentation_includes=com.fasterxml.jackson.datatype.** \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jackson-modules-java8/project.yaml ================================================ homepage: "https://github.com/FasterXML/jackson-modules-java8" language: jvm main_repo: "https://github.com/FasterXML/jackson-modules-java8.git" primary_contact: "tatu@fasterxml.com" fuzzing_engines: - libfuzzer sanitizers: - address auto_ccs: - "fanningpj@gmail.com" - "me@yawk.at" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jakarta-mail-api/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.6/bin/mvn RUN git clone --depth 1 https://github.com/eclipse-ee4j/mail.git jakarta-mail COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jakarta-mail ================================================ FILE: projects/jakarta-mail-api/HeaderTokenizerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import jakarta.mail.internet.HeaderTokenizer; import jakarta.mail.internet.ParseException; public class HeaderTokenizerFuzzer{ public static void fuzzerTestOneInput(FuzzedDataProvider data) { HeaderTokenizer ht = new HeaderTokenizer(data.consumeRemainingAsString()); HeaderTokenizer.Token tok; try{ while ((tok = ht.next()).getType() != HeaderTokenizer.Token.EOF){} } catch(ParseException e){ return; } } } ================================================ FILE: projects/jakarta-mail-api/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd api MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/jakarta.mail-api-$CURRENT_VERSION.jar" $OUT/jakarta-mail-api.jar ALL_JARS="jakarta-mail-api.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jakarta-mail-api/project.yaml ================================================ homepage: "https://eclipse-ee4j.github.io/mail" language: jvm primary_contact: "" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/eclipse-ee4j/mail.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" ================================================ FILE: projects/janet/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone https://github.com/janet-lang/janet WORKDIR $SRC/janet COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/janet/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CFLAGS="$CFLAGS -fPIC" make $CC -D_XOPEN_SOURCE=600 $CFLAGS -DJANET_BOOTSTRAP -Isrc/include -Isrc/conf -std=c99 -fPIC -o fuzz_dostring.o -c ./test/fuzzers/fuzz_dostring.c $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_dostring.o build/libjanet.a -o $OUT/fuzz_dostring ================================================ FILE: projects/janet/project.yaml ================================================ homepage: "https://github.com/janet-lang/janet" primary_contact: "calsrose@gmail.com" language: c++ auto_ccs: - "david@adalogics.com" main_repo: 'https://github.com/janet-lang/janet' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/janet/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" make test ================================================ FILE: projects/janino/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/janino-compiler/janino.git janino COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/janino ================================================ FILE: projects/janino/ExpressionEvaluatorFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.StringReader; import java.io.IOException; import java.lang.AssertionError; import org.codehaus.commons.compiler.CompileException; import org.codehaus.janino.ExpressionEvaluator; import org.codehaus.janino.Scanner; import org.codehaus.janino.ScriptEvaluator; public class ExpressionEvaluatorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ ExpressionEvaluator.guessParameterNames(new Scanner(null, new StringReader(data.consumeRemainingAsString()))); } catch(IOException | CompileException | AssertionError e){ return; } } } ================================================ FILE: projects/janino/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd janino-parent MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15 -Dmaven.javadoc.skip=true" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cd $SRC/janino cp "janino/target/janino-$CURRENT_VERSION.jar" $OUT/janino.jar ALL_JARS="janino.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/janino/project.yaml ================================================ homepage: "http://janino-compiler.github.io/janino/" language: jvm main_repo: "https://github.com/janino-compiler/janino.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jansi/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/fusesource/jansi jansi COPY *.sh *.java $SRC/ WORKDIR $SRC/jansi ================================================ FILE: projects/jansi/JansiFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.EnumSet; import org.fusesource.jansi.Ansi; import org.fusesource.jansi.AnsiConsole; public class JansiFuzzer { public static void fuzzerInitialize() { AnsiConsole.systemInstall(); } public static void fuzzerTearDown() { AnsiConsole.systemUninstall(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Ansi ansi = Ansi.ansi(); int[] choices = data.consumeInts(data.consumeInt(1, 10)); for (Integer choice : choices) { switch (choice % 27) { case 0: ansi = ansi.fg(data.pickValue(EnumSet.allOf(Ansi.Color.class))); break; case 2: ansi = ansi.fg(data.consumeInt()); break; case 3: ansi = ansi.fgRgb(data.consumeInt()); break; case 4: ansi = ansi.fgRgb(data.consumeInt(), data.consumeInt(), data.consumeInt()); break; case 5: ansi = ansi.fgBright(data.pickValue(EnumSet.allOf(Ansi.Color.class))); break; case 6: ansi = ansi.bg(data.pickValue(EnumSet.allOf(Ansi.Color.class))); break; case 7: ansi = ansi.bg(data.consumeInt()); break; case 8: ansi = ansi.bgRgb(data.consumeInt()); break; case 9: ansi = ansi.bgRgb(data.consumeInt(), data.consumeInt(), data.consumeInt()); break; case 10: ansi = ansi.bgBright(data.pickValue(EnumSet.allOf(Ansi.Color.class))); break; case 11: ansi = ansi.a(data.pickValue(EnumSet.allOf(Ansi.Attribute.class))); break; case 12: ansi = ansi.cursor(data.consumeInt(), data.consumeInt()); break; case 13: ansi = ansi.cursorToColumn(data.consumeInt()); break; case 14: ansi = ansi.cursorUp(data.consumeInt()); break; case 15: ansi = ansi.cursorDown(data.consumeInt()); break; case 16: ansi = ansi.cursorRight(data.consumeInt()); break; case 17: ansi = ansi.cursorLeft(data.consumeInt()); break; case 18: ansi = ansi.cursorMove(data.consumeInt(), data.consumeInt()); break; case 19: ansi = ansi.cursorUpLine(data.consumeInt()); break; case 20: ansi = ansi.cursorDownLine(data.consumeInt()); break; case 21: ansi = ansi.eraseScreen(data.pickValue(EnumSet.allOf(Ansi.Erase.class))); break; case 22: ansi = ansi.eraseLine(data.pickValue(EnumSet.allOf(Ansi.Erase.class))); break; case 23: ansi = ansi.scrollUp(data.consumeInt()); break; case 24: ansi = ansi.scrollDown(data.consumeInt()); break; case 25: ansi = ansi.a(data.consumeRemainingAsString()); break; case 26: ansi = ansi.render(data.consumeRemainingAsString()); break; } } } catch (IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/jansi/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/jansi-$CURRENT_VERSION.jar" $OUT/jansi.jar ALL_JARS="jansi.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jansi/project.yaml ================================================ homepage: https://github.com/fusesource/jansi main_repo: https://github.com/fusesource/jansi language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jansson/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/akheron/jansson.git /src/jansson WORKDIR $SRC/jansson COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/jansson/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # --default-symver does not work with lto, which fuzz introspector uses. if [ "$SANITIZER" == "introspector" ]; then sed -i 's/--default-symver/-flto/g' ./configure.ac fi # Run the OSS-Fuzz script in the project. ./test/ossfuzz/ossfuzz.sh ================================================ FILE: projects/jansson/project.yaml ================================================ homepage: "https://github.com/akheron/jansson" language: c++ primary_contact: "git@cfware.com" auto_ccs: - "cmeister2@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/akheron/jansson.git' ================================================ FILE: projects/jansson/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/janus-gateway/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ autoconf autoconf-archive \ automake \ gengetopt \ gtk-doc-tools \ libconfig-dev \ libglib2.0-dev \ libgnutls28-dev \ libini-config-dev \ libjansson-dev \ libnice-dev \ libssl-dev \ libtool \ openssl \ pkg-config # install libsrtp dep from source RUN git clone --single-branch --branch 2_2_x_throttle https://github.com/cisco/libsrtp.git libsrtp RUN cd libsrtp && ./configure --enable-openssl && make -j$(nproc) shared_library && make install # fetch Janus code RUN git clone --single-branch --branch master https://github.com/meetecho/janus-gateway.git janus-gateway WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/janus-gateway/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FUZZ_ENV=oss-fuzz $SRC/janus-gateway/fuzzers/build.sh ================================================ FILE: projects/janus-gateway/project.yaml ================================================ homepage: "https://github.com/meetecho/janus-gateway" language: c++ primary_contact: "lminiero@gmail.com" auto_ccs: - "lorenzo@meetecho.com" - "alex@meetecho.com" sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory coverage_extra_args: -ignore-filename-regex=.*glib.* -ignore-filename-regex=.*log.c main_repo: 'https://github.com/meetecho/janus-gateway.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/java-diff-utils/DiffUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.github.difflib.DiffUtils; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [com.github.difflib.DiffUtils] public static com.github.difflib.patch.Patch diffInline(java.lang.String,java.lang.String) public class DiffUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { DiffUtils.diffInline(data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); } catch (IllegalStateException e) { // Known exception } } } ================================================ FILE: projects/java-diff-utils/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/java-diff-utils/java-diff-utils java-diff-utils COPY *.sh *.java $SRC/ WORKDIR $SRC/java-diff-utils ================================================ FILE: projects/java-diff-utils/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "./java-diff-utils/target/java-diff-utils-$CURRENT_VERSION.jar" $OUT/java-diff-utils.jar ALL_JARS='java-diff-utils.jar' # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/java-diff-utils/project.yaml ================================================ homepage: https://github.com/java-diff-utils/java-diff-utils.git main_repo: https://github.com/java-diff-utils/java-diff-utils.git language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/java-example/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 COPY build.sh $SRC/ COPY ExampleFuzzerNative.h ExampleFuzzerNative.cpp $SRC/ COPY ExampleFuzzer.java ExampleValueProfileFuzzer.java ExampleFuzzerNative.java default.options $SRC/ COPY ExampleFuzzTest.java MutatorFuzzTest.java $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/java-example/ExampleFuzzTest.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; public class ExampleFuzzTest { @FuzzTest void exampleTest (FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); long random = 123123132; if (input.startsWith("magicstring" + random) && input.length() > 30 && input.charAt(25) == 'C') { throw new IllegalStateException("Not reached"); } } } ================================================ FILE: projects/java-example/ExampleFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.security.SecureRandom; public class ExampleFuzzer { public static void fuzzerInitialize() { // Optional initialization to be run before the first call to fuzzerTestOneInput. } public static void fuzzerTestOneInput(FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); long random = 123123132; if (input.startsWith("magicstring" + random) && input.length() > 30 && input.charAt(25) == 'C') { throw new IllegalStateException("Not reached"); } } } ================================================ FILE: projects/java-example/ExampleFuzzerNative.cpp ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "ExampleFuzzerNative.h" #include #include // simple function containing a crash that requires coverage and string compare // instrumentation for the fuzzer to find __attribute__((optnone)) void parseInternal(const std::string &input) { constexpr int bar = std::numeric_limits::max() - 5; // Crashes with UBSan. if (bar + input[0] == 300) { return; } if (input[0] == 'a' && input[1] == 'b' && input[5] == 'c') { if (input.find("secret_in_native_library") != std::string::npos) { // Crashes with ASan. [[maybe_unused]] char foo = input[input.size() + 2]; } } } JNIEXPORT jboolean JNICALL Java_ExampleFuzzerNative_parse( JNIEnv *env, jobject o, jstring bytes) { const char *input(env->GetStringUTFChars(bytes, nullptr)); parseInternal(input); env->ReleaseStringUTFChars(bytes, input); return false; } ================================================ FILE: projects/java-example/ExampleFuzzerNative.h ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class ExampleFuzzerNative */ #ifndef _Included_ExampleFuzzerNative #define _Included_ExampleFuzzerNative #ifdef __cplusplus extern "C" { #endif /* * Class: ExampleFuzzerNative * Method: parse * Signature: (Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL Java_ExampleFuzzerNative_parse(JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif ================================================ FILE: projects/java-example/ExampleFuzzerNative.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ExampleFuzzerNative { static { System.loadLibrary("native"); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { int val = data.consumeInt(); String stringData = data.consumeRemainingAsString(); if (val == 17759716 && stringData.length() > 10 && stringData.contains("jazzer")) { // call native function which contains a crash parse(stringData); } } private static native boolean parse(String bytes); } ================================================ FILE: projects/java-example/ExampleValueProfileFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.util.Base64; public class ExampleValueProfileFuzzer { private static String base64(byte[] input) { return Base64.getEncoder().encodeToString(input); } private static long insecureEncrypt(long input) { long key = 0xefe4eb93215cb6b0L; return input ^ key; } public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Without -use_value_profile=1, the fuzzer gets stuck here as there is no direct correspondence // between the input bytes and the compared string. With value profile, the fuzzer can guess the // expected input byte by byte, which takes linear rather than exponential time. if (base64(data.consumeBytes(6)).equals("SmF6emVy")) { long[] plaintextBlocks = data.consumeLongs(2); if (plaintextBlocks.length != 2) return; if (insecureEncrypt(plaintextBlocks[0]) == 0x9fc48ee64d3dc090L) { // Without --fake_pcs (enabled by default with -use_value_profile=1), the fuzzer would get // stuck here as the value profile information for long comparisons would not be able to // distinguish between this comparison and the one above. if (insecureEncrypt(plaintextBlocks[1]) == 0x888a82ff483ad9c2L) { mustNeverBeCalled(); } } } } private static void mustNeverBeCalled() { throw new IllegalStateException("mustNeverBeCalled has been called"); } } ================================================ FILE: projects/java-example/MutatorFuzzTest.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.driver.FuzzTargetRunner; import com.code_intelligence.jazzer.junit.FuzzTest; import com.code_intelligence.jazzer.mutation.annotation.NotNull; import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; class MutatorFuzzTest { @FuzzTest void mutatorFuzz(List<@NotNull String> list) { // Check that the mutator is actually doing something. if (list != null && list.size() > 3 && list.get(2).equals("mutator")) { throw new AssertionError("Found expected JUnit mutator test issue"); } } @BeforeAll static void beforeAll() { System.err.println("Starting MutatorFuzzTest"); } @AfterAll static void afterAll() { System.err.println("Finished MutatorFuzzTest"); } } ================================================ FILE: projects/java-example/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build native library. JVM_INCLUDES="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux" mkdir -p "$OUT"/native $CXX $CXXFLAGS $JVM_INCLUDES -fPIC -shared \ ExampleFuzzerNative.cpp -o $OUT/native/libnative.so mkdir -p "$OUT"/libs curl -o "$OUT"/libs/junit-jupiter-api-5.9.0.jar https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-api/5.9.0/junit-jupiter-api-5.9.0.jar curl -o "$OUT"/libs/junit-jupiter-engine-5.9.0.jar https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-engine/5.9.0/junit-jupiter-engine-5.9.0.jar curl -o "$OUT"/libs/junit-jupiter-params-5.9.0.jar https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-params/5.9.0/junit-jupiter-params-5.9.0.jar curl -o "$OUT"/libs/junit-platform-commons-1.9.0.jar https://repo1.maven.org/maven2/org/junit/platform/junit-platform-commons/1.9.0/junit-platform-commons-1.9.0.jar curl -o "$OUT"/libs/junit-platform-engine-1.9.0.jar https://repo1.maven.org/maven2/org/junit/platform/junit-platform-engine/1.9.0/junit-platform-engine-1.9.0.jar curl -o "$OUT"/libs/junit-platform-launcher-1.9.0.jar https://repo1.maven.org/maven2/org/junit/platform/junit-platform-launcher/1.9.0/junit-platform-launcher-1.9.0.jar curl -o "$OUT"/libs/opentest4j-1.2.0.jar https://repo1.maven.org/maven2/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar BUILD_CLASSPATH="$JAZZER_API_PATH:$JAZZER_JUNIT_PATH:$OUT/libs/junit-jupiter-api-5.9.0.jar" # All class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java' -or -name '*FuzzerNative.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ if [[ $fuzzer_basename == *FuzzerNative ]]; then driver=jazzer_driver_with_sanitizer else driver=jazzer_driver fi cp default.options $OUT/"$fuzzer_basename".options # Create execution wrapper. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir/native \ ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \ \$this_dir/$driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done for fuzzer in $(find $SRC -name '*FuzzTest.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp "$BUILD_CLASSPATH:/usr/local/bin/jazzer_agent_deploy.jar" $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create execution wrapper. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") java -cp \$this_dir:\$this_dir/jazzer_agent_deploy.jar:\$this_dir/jazzer_junit.jar:\$this_dir/libs/* \ com.code_intelligence.jazzer.Jazzer \ --target_class=$fuzzer_basename \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/java-example/default.options ================================================ [asan] handle_segv=1 allow_user_segv_handler=1 [ubsan] handle_segv=1 ================================================ FILE: projects/java-example/project.yaml ================================================ base_os_version: ubuntu-24-04 disabled: true fuzzing_engines: - libfuzzer homepage: https://github.com/CodeIntelligenceTesting/jazzer language: jvm main_repo: https://github.com/CodeIntelligenceTesting/jazzer sanitizers: - address - undefined vendor_ccs: - norbert.schneider@code-intelligence.com ================================================ FILE: projects/java-jwt/.gitignore ================================================ project-parent/java-jwt project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/java-jwt/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm ENV JAVA_HOME=$JAVA_15_HOME ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server ENV PATH=$JAVA_HOME/bin:$PATH RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN=$SRC/maven/apache-maven-3.9.11/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/java-jwt RUN git clone --depth 1 https://github.com/auth0/java-jwt/ $SRC/project-parent/java-jwt COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/java-jwt/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=java-jwt PROJECT_GROUP_ID=com.auth0 PROJECT_ARTIFACT_ID=java-jwt MAIN_REPOSITORY=https://github.com/auth0/java-jwt/ GRADLE_ARGS="-x javadoc -x test -x sign -PisSnapshot=false" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && ./gradlew build publishToMavenLocal exportVersion) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT # set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && ./gradlew build publishToMavenLocal $GRADLE_ARGS) export JAVA_JWT_VERSION=$(cat $PROJECT/.version | head -1 | tr -d '[:space:]') $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/java-jwt/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 15 15 15 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.junit.platform junit-platform-launcher 1.9.2 com.auth0 java-jwt ${env.JAVA_JWT_VERSION} maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/java-jwt/project-parent/fuzz-targets/src/test/java/com/example/JWTFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; class JWTFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { String secret = data.consumeString(500); Algorithm [] algorithms = {Algorithm.HMAC256(secret), Algorithm.HMAC384(secret), Algorithm.HMAC512(secret)}; try { String token = data.consumeRemainingAsString(); DecodedJWT decodedJWT = JWT.decode(token); DecodedJWT jwt = JWT.require(data.pickValue(algorithms)) .build() .verify(decodedJWT); } catch (JWTDecodeException | AlgorithmMismatchException | NullPointerException e) { } } } ================================================ FILE: projects/java-jwt/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom fuzz-targets ================================================ FILE: projects/java-jwt/project.yaml ================================================ homepage: "https://github.com/auth0/java-jwt/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/auth0/java-jwt/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/java-uuid-generator/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/cowtowncoder/java-uuid-generator java-uuid-generator COPY *.sh *.java $SRC/ WORKDIR $SRC/java-uuid-generator ================================================ FILE: projects/java-uuid-generator/GeneratorsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.fasterxml.uuid.EthernetAddress; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.UUIDUtil; import java.util.Random; import java.util.UUID; public class GeneratorsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { UUID uuid = null; EthernetAddress addr = null; Integer choice = data.consumeInt(1, 7); switch (choice) { case 1: Generators.randomBasedGenerator(new Random(data.consumeLong())).generate(); break; case 2: Generators.timeBasedEpochGenerator(new Random(data.consumeLong())).generate(); break; case 3: Generators.nameBasedGenerator().generate(data.consumeRemainingAsString()); break; case 4: uuid = UUIDUtil.uuid(data.consumeString(data.remainingBytes() / 2)); Generators.nameBasedGenerator(uuid).generate(data.consumeRemainingAsString()); break; case 5: uuid = UUIDUtil.uuid(data.consumeString(data.remainingBytes() / 2)); Generators.nameBasedGenerator(uuid, null).generate(data.consumeRemainingAsString()); break; case 6: addr = new EthernetAddress(data.consumeRemainingAsString()); Generators.timeBasedGenerator(addr).generate(); break; case 7: addr = new EthernetAddress(data.consumeRemainingAsString()); Generators.timeBasedReorderedGenerator(addr).generate(); break; } } catch (NumberFormatException e1) { // Known exceptions } } } ================================================ FILE: projects/java-uuid-generator/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## find ./ -name pom.xml -exec sed -i 's/source>1.61.81.61.8 $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/java-uuid-generator/project.yaml ================================================ homepage: https://github.com/cowtowncoder/java-uuid-generator main_repo: https://github.com/cowtowncoder/java-uuid-generator language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/java-xmlbuilder/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/AFL afl RUN git clone --depth 1 https://github.com/jmurty/java-xmlbuilder java-xmlbuilder COPY build.sh *.java $SRC/ WORKDIR $SRC/java-xmlbuilder ================================================ FILE: projects/java-xmlbuilder/XmlBuilderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.jamesmurty.utils.XMLBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.DOMException; public class XmlBuilderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 10)); XMLBuilder builder = XMLBuilder.create(data.consumeString(data.remainingBytes() / 2)); for (Integer choice : choices) { switch (choice % 13) { case 0: builder = builder.stripWhitespaceOnlyTextNodes(); break; case 1: builder = builder.up(data.consumeInt()); break; case 2: builder = builder.elem(data.consumeRemainingAsString()); break; case 3: builder = builder.elementBefore(data.consumeRemainingAsString()); break; case 4: builder = builder.attr( data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); break; case 5: builder = builder.text(data.consumeRemainingAsString()); break; case 6: builder = builder.data(data.consumeRemainingAsString()); break; case 7: builder = builder.data(data.consumeRemainingAsBytes()); break; case 8: builder = builder.cmnt(data.consumeRemainingAsString()); break; case 9: builder = builder.inst( data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); break; case 10: builder = builder.insertInstruction( data.consumeString(data.remainingBytes() / 2), data.consumeRemainingAsString()); break; case 11: builder = builder.ref(data.consumeRemainingAsString()); break; case 12: builder = builder.ns(data.consumeRemainingAsString()); break; } } } catch (ParserConfigurationException | XPathExpressionException | DOMException | IllegalStateException e) { // Known exception } } } ================================================ FILE: projects/java-xmlbuilder/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/java-xmlbuilder-$CURRENT_VERSION.jar" $OUT/java-xmlbuilder.jar ALL_JARS="java-xmlbuilder.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done cp $SRC/afl/dictionaries/xml.dict $OUT/XmlBuilderFuzzer.dict ================================================ FILE: projects/java-xmlbuilder/project.yaml ================================================ homepage: https://github.com/jmurty/java-xmlbuilder main_repo: https://github.com/jmurty/java-xmlbuilder language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/javacpp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/bytedeco/javacpp javacpp COPY *.sh *.java $SRC/ WORKDIR $SRC/javacpp ================================================ FILE: projects/javacpp/JavacppFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.bytedeco.javacpp.tools.Info; import org.bytedeco.javacpp.tools.InfoMap; // jvm-autofuzz-heuristics-2 // Heuristic name: jvm-autofuzz-heuristics-2 // Target method: [org.bytedeco.javacpp.tools.InfoMap] public org.bytedeco.javacpp.tools.Info getFirst(java.lang.String,boolean) // Target method: [org.bytedeco.javacpp.tools.InfoMap] public org.bytedeco.javacpp.tools.Info get(int,java.lang.String,boolean) public class JavacppFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { InfoMap obj = new InfoMap(); Boolean bool = data.consumeBoolean(); if (data.consumeBoolean()) { obj.getFirst(data.consumeRemainingAsString(), bool); } else { obj.get(data.consumeInt(), data.consumeRemainingAsString(), bool); } } } ================================================ FILE: projects/javacpp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade cp "./target/javacpp.jar" $OUT/javacpp.jar ALL_JARS="javacpp.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/javacpp/project.yaml ================================================ homepage: https://github.com/bytedeco/javacpp main_repo: https://github.com/bytedeco/javacpp language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/javaparser/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN apt-get update && apt-get install -y maven RUN git clone --depth 1 https://github.com/javaparser/javaparser COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/javaparser ================================================ FILE: projects/javaparser/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build the jar. CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) mvn package -Dmaven.test.skip=true cp "javaparser-core/target/javaparser-core-$CURRENT_VERSION.jar" $OUT/javaparser.jar # The jar files containing the project (separated by spaces). PROJECT_JARS=javaparser.jar # Build fuzzers in $OUT. BUILD_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All jars and class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create execution wrapper. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/javaparser/parseFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import static com.github.javaparser.ParseStart.COMPILATION_UNIT; import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ParserConfiguration; import static com.github.javaparser.Providers.provider; import java.io.ByteArrayInputStream; import java.io.InputStream; public class parseFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String datastring = data.consumeRemainingAsString(); InputStream datastream = new ByteArrayInputStream(datastring.getBytes()); try { ParserConfiguration configuration = new ParserConfiguration(); final ParseResult result = new JavaParser(configuration) .parse(COMPILATION_UNIT, provider(datastream, configuration.getCharacterEncoding())); } catch (Exception e) { return; } } } ================================================ FILE: projects/javaparser/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://javaparser.org" language: jvm primary_contact: "MysterAitch@users.noreply.github.com" auto_ccs: - "p.antoine@catenacyber.fr" - "jean-pierre.lerbscher@jperf.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/javaparser/javaparser" sanitizers: - address ================================================ FILE: projects/javapoet/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget openjdk-8-jdk RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/square/javapoet.git javapoet WORKDIR javapoet COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/javapoet/TypeSpecFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.squareup.javapoet.*; import javax.lang.model.element.Modifier; public class TypeSpecFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ TypeSpec taco = TypeSpec.classBuilder(data.consumeString(10)) .addMethod(MethodSpec.methodBuilder(data.consumeString(20)) .addAnnotation(Override.class) .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .returns(String.class) .addCode(data.consumeRemainingAsString()) .build()) .build(); taco.hashCode(); } // expected exceptions catch (java.lang.IllegalArgumentException e) {} catch (java.lang.IllegalStateException e) {} } } ================================================ FILE: projects/javapoet/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export JAVA_HOME="$OUT/open-jdk-8" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-8-openjdk-amd64/" "$JAVA_HOME" MAVEN_ARGS="-Dpropguard.skip -DskipTests -Dmaven.javadoc.skip=true" $MVN package $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) find ./ -name "javapoet-$CURRENT_VERSION.jar" -exec mv {} $OUT/javapoet.jar \; ALL_JARS="javapoet.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac -cp $BUILD_CLASSPATH ${SRC}/*.java install ${SRC}/*.class ${OUT}/ for fuzzer in $(find $SRC -name '*Fuzzer.java' -maxdepth 1); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-8/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-8/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/javapoet/project.yaml ================================================ homepage: "https://github.com/square/javapoet" language: jvm primary_contact: "irali@google.com" main_repo: "https://github.com/square/javapoet.git" auto_ccs: - "himkhurana@google.com" - "atulag@google.com" - "rashmivirdy@google.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/javascript-example/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ # For real projects, you would clone your repo in the next step. RUN mkdir -p $SRC/example # Ideally, you have already configured fuzz tests in your repo so that they # run (in Jazzer.js regression mode) as part of unit testing. Keeping the fuzz # tests in sync with the source code ensures that they are adjusted continue # to work after code changes. Here, we copy them into the example project directory. COPY fuzz_string_compare.js fuzz_promise.js fuzz_value_profiling.js package.json $SRC/example/ WORKDIR $SRC/example ================================================ FILE: projects/javascript-example/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies. npm install # Install Jazzer.js npm install --save-dev @jazzer.js/core # Build Fuzzers. compile_javascript_fuzzer example fuzz_promise.js compile_javascript_fuzzer example fuzz_string_compare.js --sync compile_javascript_fuzzer example fuzz_value_profiling.js --sync ================================================ FILE: projects/javascript-example/fuzz_promise.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// let lastInvocationCount = 0; let invocationCount = lastInvocationCount + 1; /** * @param { Buffer } data */ module.exports.fuzz = function (data) { return new Promise((resolve, reject) => { if (data.length < 3) { resolve(invocationCount++); return; } setTimeout(() => { let one = data.readInt8(0); let two = data.readInt8(1); let three = data.readInt8(2); if (one + two + three === 42) { reject( new Error( `${one} + ${two} + ${three} = 42 (invocation ${invocationCount})` ) ); } else { resolve(invocationCount++); } }, 10); }).then((value) => { if (value !== lastInvocationCount + 1) { throw new Error( `Invalid invocation order, received ${value} but last invocation was ${lastInvocationCount}.` ); } lastInvocationCount = value; }); }; ================================================ FILE: projects/javascript-example/fuzz_string_compare.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// /** * @param { Buffer } data */ module.exports.fuzz = function (data) { const s = data.toString(); if (s.length !== 16) { return; } if ( s.slice(0, 8) === "Awesome " && s.slice(8, 15) === "Fuzzing" && s[15] === "!" ) { throw Error("Welcome to Awesome Fuzzing!"); } }; ================================================ FILE: projects/javascript-example/fuzz_value_profiling.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// /** * @param {number} n */ function encrypt(n) { return n ^ 0x11223344; } /** * @param { Buffer } data */ module.exports.fuzz = function (data) { if (data.length < 16) { return; } if ( encrypt(data.readInt32BE(0)) === 0x50555637 && encrypt(data.readInt32BE(4)) === 0x7e4f5664 && encrypt(data.readInt32BE(8)) === 0x5757493e && encrypt(data.readInt32BE(12)) === 0x784c5465 ) { throw Error("XOR with a constant is not a secure encryption method ;-)"); } }; ================================================ FILE: projects/javascript-example/package.json ================================================ { "name": "jazzerjs-examples", "version": "1.0.0", "description": "Examples of fuzz tests for Jazzer.js" } ================================================ FILE: projects/javascript-example/project.yaml ================================================ homepage: https://github.com/CodeIntelligenceTesting/jazzer.js language: javascript main_repo: https://github.com/CodeIntelligenceTesting/jazzer.js fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - yakdan@code-intelligence.com - norbert.schneider@code-intelligence.com - peter.samarin@code-intelligence.com ================================================ FILE: projects/javassist/ClassFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.io.IOException; import java.lang.RuntimeException; import javassist.ClassPool; import javassist.CtClass; import javassist.CannotCompileException; import javassist.NotFoundException; import java.lang.NullPointerException; public class ClassFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ClassPool pool = ClassPool.getDefault(); CtClass cc = null; try { cc = pool.makeClass(new ByteArrayInputStream(data.consumeRemainingAsBytes())); } catch (IOException | RuntimeException e) { } try { cc.getSuperclass(); cc.getNestedClasses(); cc.getClassFile(); cc.getInterfaces(); cc.getDeclaringClass(); cc.getComponentType(); } catch (NotFoundException | NullPointerException e) { } try { cc.toBytecode(); } catch (IOException | NullPointerException | CannotCompileException e) { } } } ================================================ FILE: projects/javassist/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/jboss-javassist/javassist.git COPY build.sh $SRC/ COPY ClassFuzzer.java $SRC/ COPY pom.xml.diff $SRC/javassist WORKDIR $SRC/javassist ================================================ FILE: projects/javassist/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git apply pom.xml.diff mv ./src/main ./src/java mkdir ./src/main mv ./src/java ./src/main/java mv ./src/test ./src/java mkdir ./src/test mv ./src/java ./src/test/java $MVN clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -DskipTests CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/javassist-$CURRENT_VERSION.jar" $OUT/javassist.jar ALL_JARS="javassist.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/javassist/pom.xml.diff ================================================ diff --git a/pom.xml b/pom.xml index d13fee2..4157d4f 100644 --- a/pom.xml +++ b/pom.xml @@ -155,11 +155,11 @@ - src/main/ - src/test/ + src/main/java + src/test/java - src/test/resources + src/test/java/resources @@ -200,7 +200,7 @@ javassist.CtClass true - src/main/META-INF/MANIFEST.MF + src/main/java/META-INF/MANIFEST.MF ================================================ FILE: projects/javassist/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: http://www.javassist.org/ language: jvm main_repo: https://github.com/jboss-javassist/javassist sanitizers: - address vendor_ccs: - yakdan@code-intelligence.com ================================================ FILE: projects/javy/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update \ && apt-get install -y curl pkg-config libssl-dev clang \ && rustup target add wasm32-wasip1 \ && git clone https://github.com/bytecodealliance/javy WORKDIR javy COPY build.sh $SRC/ ================================================ FILE: projects/javy/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Using `--sanitizer none` because other sanitizers seem to cause out of memory errors # Setting `-fno-sanitize=all` since I see undefined references to `__sancov_gen_` if I don't CFLAGS="$CFLAGS -fno-sanitize=all" RUSTFLAGS="-C link-arg=-fno-sanitize=all" cargo fuzz build --sanitizer none cp target/x86_64-unknown-linux-gnu/release/json-differential $OUT/json-differential ================================================ FILE: projects/javy/project.yaml ================================================ homepage: "https://github.com/bytecodealliance/javy" language: rust main_repo: "https://github.com/bytecodealliance/javy.git" primary_contact: "saule.cabrera@gmail.com" auto_ccs: - "jeff.charles@shopify.com" sanitizers: - none fuzzing_engines: - libfuzzer ================================================ FILE: projects/jaxb/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/eclipse-ee4j/jaxb-ri.git ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/jaxb-ri ================================================ FILE: projects/jaxb/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-Dmaven.compiler.source=15 -Dmaven.compiler.target=15 -DskipTests" ALL_JARS="" # install the build servers' jazzer-api into the maven repository pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/jaxb-ri/jaxb-ri" ${MVN} package ${MVN_FLAGS} ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd ${SRC} ${MVN} package -DjaxbVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/jaxb-fuzzer-${CURRENT_VERSION}.jar ${OUT}/jaxb-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} jaxb-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|'); # the .java was stripped by sed if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/jaxb/pom.xml ================================================ 4.0.0 ossfuzz jaxb-fuzzer ${jaxbVersion} jar 15 15 ossfuzz.DataTypeConverterFuzzer UTF-8 com.code-intelligence jazzer-api 0.12.0 com.sun.xml.bind jaxb-ri ${jaxbVersion} pom org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/jaxb/project.yaml ================================================ homepage: "https://eclipse-ee4j.github.io/jaxb-ri/" language: jvm main_repo: "https://github.com/eclipse-ee4j/jaxb-ri.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" run_tests: False ================================================ FILE: projects/jaxb/src/main/java/ossfuzz/DataTypeConverterFuzzer.java ================================================ package ossfuzz; import com.code_intelligence.jazzer.api.*; import org.glassfish.jaxb.runtime.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; public class DataTypeConverterFuzzer { String m_string; int m_int; DataTypeConverterFuzzer(int integer, String string) { m_int = integer; m_string = string; } void test() { DatatypeConverterImpl.theInstance.printHexBinary(m_string.getBytes()); Calendar calendar = null; try { calendar = DatatypeConverterImpl.theInstance.parseTime(m_string); DatatypeConverterImpl.theInstance.printTime(calendar); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { String base64 = DatatypeConverterImpl.theInstance.printBase64Binary(m_string.getBytes()); DatatypeConverterImpl.theInstance.parseBase64Binary(base64); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { String type = DatatypeConverterImpl.theInstance.parseAnySimpleType(m_string); DatatypeConverterImpl.theInstance.printAnySimpleType(type); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { boolean bool = DatatypeConverterImpl.theInstance.parseBoolean(m_string); DatatypeConverterImpl.theInstance.printBoolean(bool); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { BigDecimal bigDecimal = DatatypeConverterImpl.theInstance.parseDecimal(m_string); DatatypeConverterImpl.theInstance.printDecimal(bigDecimal); } catch (NumberFormatException e) { /* documented, ignore */ } catch (IllegalArgumentException e) { } try { byte m_byte = DatatypeConverterImpl.theInstance.parseByte(m_string); DatatypeConverterImpl.theInstance.printByte(m_byte); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { double dbl = DatatypeConverterImpl.theInstance.parseDouble(m_string); DatatypeConverterImpl.theInstance.printDouble(dbl); } catch (NumberFormatException e) { /* documented, ignore */ } try { Calendar dateTime = DatatypeConverterImpl.theInstance.parseDateTime(m_string); DatatypeConverterImpl.theInstance.printDateTime(dateTime); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { long longV = DatatypeConverterImpl.theInstance.parseUnsignedInt(m_string); DatatypeConverterImpl.theInstance.printUnsignedInt(longV); } catch (NumberFormatException e) { /* documented, ignore */ } try { int shrt = DatatypeConverterImpl.theInstance.parseUnsignedShort(m_string); DatatypeConverterImpl.theInstance.printUnsignedShort(shrt); } catch (NumberFormatException e) { /* documented, ignore */ } try { Calendar time = DatatypeConverterImpl.theInstance.parseTime(m_string); DatatypeConverterImpl.theInstance.printTime(time); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { Calendar date = DatatypeConverterImpl.theInstance.parseDate(m_string); DatatypeConverterImpl.theInstance.printDate(date); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { String smplType = DatatypeConverterImpl.theInstance.parseAnySimpleType(m_string); DatatypeConverterImpl.theInstance.printAnySimpleType(smplType); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { String strg = DatatypeConverterImpl.theInstance.parseString(m_string); DatatypeConverterImpl.theInstance.printString(strg); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { BigInteger bigInteger = DatatypeConverterImpl.theInstance.parseInteger(m_string); DatatypeConverterImpl.theInstance.printInteger(bigInteger); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { int intgr = DatatypeConverterImpl.theInstance.parseInt(m_string); DatatypeConverterImpl.theInstance.printInt(intgr); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { long lng = DatatypeConverterImpl.theInstance.parseLong(m_string); DatatypeConverterImpl.theInstance.printLong(lng); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { short shrt = DatatypeConverterImpl.theInstance.parseShort(m_string); DatatypeConverterImpl.theInstance.printShort(shrt); } catch (IllegalArgumentException e) { /* documented, ignore */ } try { float flt = DatatypeConverterImpl.theInstance.parseFloat(m_string); DatatypeConverterImpl.theInstance.printFloat(flt); } catch (IllegalArgumentException e) { /* documented, ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { DataTypeConverterFuzzer testClosure = new DataTypeConverterFuzzer( fuzzedDataProvider.consumeInt(), fuzzedDataProvider.consumeRemainingAsString()); testClosure.test(); } } ================================================ FILE: projects/jbig2dec/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make libtool pkg-config vim libreadline-dev wget autoconf RUN git clone --recursive --depth 1 git://git.ghostscript.com/jbig2dec.git jbig2dec RUN mkdir tests RUN cp $SRC/jbig2dec/annex-h.jbig2 tests/annex-h.jb2 RUN cd tests && (wget -O t89-halftone.zip http://cgit.ghostscript.com/cgi-bin/cgit.cgi/tests.git/plain/jbig2/t89-halftone.zip && unzip t89-halftone.zip) || true RUN cd tests && (wget -O jb2streams.zip http://cgit.ghostscript.com/cgi-bin/cgit.cgi/tests.git/plain/jbig2/jb2streams.zip && unzip jb2streams.zip) || true RUN cd tests && zip -q $SRC/jbig2_fuzzer_seed_corpus.zip *.jb2 RUN rm -rf tests COPY *.dict $SRC/ WORKDIR jbig2dec COPY *.cc $SRC/ COPY run_tests.sh build.sh *.options $SRC/ ================================================ FILE: projects/jbig2dec/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd ${SRC}/jbig2dec ./autogen.sh make distclean mkdir -p ${WORK}/jbig2dec cd ${WORK}/jbig2dec ${SRC}/jbig2dec/configure LDFLAGS="$CXXFLAGS" make -C ${WORK}/jbig2dec jbig2dec -j$(nproc) fuzz_target=jbig2_fuzzer $CXX $CXXFLAGS -std=c++11 -I$SRC/jbig2dec -fno-inline-functions \ $SRC/jbig2_fuzzer.cc -o $OUT/$fuzz_target \ $LIB_FUZZING_ENGINE ${WORK}/jbig2dec/.libs/libjbig2dec.a unzip -l ${SRC}/${fuzz_target}_seed_corpus.zip mv $SRC/{*.zip,*.dict,*.options} $OUT if [ ! -f "${OUT}/${fuzz_target}_seed_corpus.zip" ]; then echo "missing seed corpus" exit 1 fi if [ ! -f "${OUT}/${fuzz_target}.dict" ]; then echo "missing dictionary" exit 1 fi if [ ! -f "${OUT}/${fuzz_target}.options" ]; then echo "missing options" exit 1 fi ================================================ FILE: projects/jbig2dec/jbig2_fuzzer.cc ================================================ /* # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include "jbig2.h" #define ALIGNMENT ((size_t) 16) #define KBYTE ((size_t) 1024) #define MBYTE (1024 * KBYTE) #define GBYTE (1024 * MBYTE) #define MAX_ALLOCATION (32 * MBYTE) static size_t used; static void *jbig2_fuzzer_reached_limit(size_t oldsize, size_t size) { if (oldsize == 0) fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte allocation: %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, size); else fprintf(stderr, "limit: %zu Mbyte used: %zu Mbyte reallocation: %zu -> %zu: limit reached\n", MAX_ALLOCATION / MBYTE, used / MBYTE, oldsize, size); fflush(0); return NULL; } static void *jbig2_fuzzer_alloc(Jbig2Allocator *allocator, size_t size) { char *ptr = NULL; if (size == 0) return NULL; if (size > SIZE_MAX - ALIGNMENT) return NULL; if (size + ALIGNMENT > MAX_ALLOCATION - used) return jbig2_fuzzer_reached_limit(0, size + ALIGNMENT); ptr = (char *) malloc(size + ALIGNMENT); if (ptr == NULL) return NULL; memcpy(ptr, &size, sizeof(size)); used += size + ALIGNMENT; return ptr + ALIGNMENT; } static void jbig2_fuzzer_free(Jbig2Allocator *allocator, void *ptr) { size_t size; if (ptr == NULL) return; if (ptr < (void *) ALIGNMENT) return; ptr = (char *) ptr - ALIGNMENT; memcpy(&size, ptr, sizeof(size)); used -= size + ALIGNMENT; free(ptr); } static void *jbig2_fuzzer_realloc(Jbig2Allocator *allocator, void *old, size_t size) { size_t oldsize; char *ptr; if (old == NULL) return jbig2_fuzzer_alloc(allocator, size); if (old < (void *) ALIGNMENT) return NULL; if (size == 0) { jbig2_fuzzer_free(allocator, old); return NULL; } if (size > SIZE_MAX - ALIGNMENT) return NULL; old = (char *) old - ALIGNMENT; memcpy(&oldsize, old, sizeof(oldsize)); if (size + ALIGNMENT > MAX_ALLOCATION - used + oldsize + ALIGNMENT) return jbig2_fuzzer_reached_limit(oldsize + ALIGNMENT, size + ALIGNMENT); ptr = (char *) realloc(old, size + ALIGNMENT); if (ptr == NULL) return NULL; used -= oldsize + ALIGNMENT; memcpy(ptr, &size, sizeof(size)); used += size + ALIGNMENT; return ptr + ALIGNMENT; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { Jbig2Allocator allocator; Jbig2Ctx *ctx = NULL; used = 0; allocator.alloc = jbig2_fuzzer_alloc; allocator.free = jbig2_fuzzer_free; allocator.realloc = jbig2_fuzzer_realloc; ctx = jbig2_ctx_new(&allocator, (Jbig2Options) 0, NULL, NULL, NULL); if (jbig2_data_in(ctx, data, size) == 0) { if (jbig2_complete_page(ctx) == 0) { Jbig2Image *image = jbig2_page_out(ctx); if (image != NULL) { int sum = 0; for (int i = 0; i < image->height * image->stride; i++) sum += image->data[i]; printf("sum of image data bytes: %d\n", sum); } jbig2_release_page(ctx, image); } } jbig2_ctx_free(ctx); return 0; } ================================================ FILE: projects/jbig2dec/jbig2_fuzzer.dict ================================================ # AFL dictionary for jbig2 images # by Sebastian Rasmussen id_string="\x97\x4a\x42\x32\x0d\x0a\x1a\x0a" # segments noretain_allpages_symbol_dictionary="\x00" noretain_allpages_intermediate_text_region="\x04" noretain_allpages_immediate_text_region="\x06" noretain_allpages_immediate_lossless_text_region="\x07" noretain_allpages_pattern_dictionary="\x10" noretain_allpages_intermediate_halftone_region="\x14" noretain_allpages_immediate_halftone_region="\x16" noretain_allpages_immediate_lossless_halftone_region="\x17" noretain_allpages_intermediate_generic_region="\x24" noretain_allpages_immediate_generic_region="\x26" noretain_allpages_immediate_lossless_generic_region="\x27" noretain_allpages_intermediate_generic_refinement_region="\x28" noretain_allpages_immediate_generic_refinement_region="\x2a" noretain_allpages_immediate_lossless_generic_refinement_region="\x2b" noretain_allpages_page_information="\x30" noretain_allpages_end_of_page="\x31" noretain_allpages_end_of_stripe="\x32" noretain_allpages_end_of_file="\x33" noretain_allpages_profiles="\x34" noretain_allpages_tables="\x35" noretain_allpages_color_palette="\x36" noretain_allpages_extension="\x3e" noretain_specificpage_symbol_dictionary="\x40" noretain_specificpage_intermediate_text_region="\x44" noretain_specificpage_immediate_text_region="\x46" noretain_specificpage_immediate_lossless_text_region="\x47" noretain_specificpage_pattern_dictionary="\x50" noretain_specificpage_intermediate_halftone_region="\x54" noretain_specificpage_immediate_halftone_region="\x56" noretain_specificpage_immediate_lossless_halftone_region="\x57" noretain_specificpage_intermediate_generic_region="\x64" noretain_specificpage_immediate_generic_region="\x66" noretain_specificpage_immediate_lossless_generic_region="\x67" noretain_specificpage_intermediate_generic_refinement_region="\x68" noretain_specificpage_immediate_generic_refinement_region="\x6a" noretain_specificpage_immediate_lossless_generic_refinement_regio6="\x6b" noretain_specificpage_page_information="\x70" noretain_specificpage_end_of_page="\x71" noretain_specificpage_end_of_stripe="\x72" noretain_specificpage_end_of_file="\x73" noretain_specificpage_profiles="\x74" noretain_specificpage_tables="\x75" noretain_specificpage_color_palette="\x76" noretain_specificpage_extension="\x7e" retain_allpages_symbol_dictionary="\x80" retain_allpages_intermediate_text_region="\x84" retain_allpages_immediate_text_region="\x86" retain_allpages_immediate_lossless_text_region="\x87" retain_allpages_pattern_dictionary="\x90" retain_allpages_intermediate_halftone_region="\x94" retain_allpages_immediate_halftone_region="\x96" retain_allpages_immediate_lossless_halftone_region="\x97" retain_allpages_intermediate_generic_region="\xa4" retain_allpages_immediate_generic_region="\xa6" retain_allpages_immediate_lossless_generic_region="\xa7" retain_allpages_intermediate_generic_refinement_region="\xa8" retain_allpages_immediate_generic_refinement_region="\xaa" retain_allpages_immediate_lossless_generic_refinement_regio6="\xab" retain_allpages_page_information="\xb0" retain_allpages_end_of_page="\xb1" retain_allpages_end_of_stripe="\xb2" retain_allpages_end_of_file="\xb3" retain_allpages_profiles="\xb4" retain_allpages_tables="\xb5" retain_allpages_color_palette="\xb6" retain_allpages_extension="\xbe" retain_specificpage_symbol_dictionary="\xc0" retain_specificpage_intermediate_text_region="\xc4" retain_specificpage_immediate_text_region="\xc6" retain_specificpage_immediate_lossless_text_region="\xc7" retain_specificpage_pattern_dictionary="\xd0" retain_specificpage_intermediate_halftone_region="\xd4" retain_specificpage_immediate_halftone_region="\xd6" retain_specificpage_immediate_lossless_halftone_region="\xd7" retain_specificpage_intermediate_generic_region="\xe4" retain_specificpage_immediate_generic_region="\xe6" retain_specificpage_immediate_lossless_generic_region="\xe7" retain_specificpage_intermediate_generic_refinement_region="\xe8" retain_specificpage_immediate_generic_refinement_region="\xea" retain_specificpage_immediate_lossless_generic_refinement_regio6="\xeb" retain_specificpage_page_information="\xf0" retain_specificpage_end_of_page="\xf1" retain_specificpage_end_of_stripe="\xf2" retain_specificpage_end_of_file="\xf3" retain_specificpage_profiles="\xf4" retain_specificpage_tables="\xf5" retain_specificpage_color_palette="\xf6" retain_specificpage_extension="\xfe" ================================================ FILE: projects/jbig2dec/jbig2_fuzzer.options ================================================ [libfuzzer] close_fd_mask = 3 ================================================ FILE: projects/jbig2dec/project.yaml ================================================ homepage: "https://www.jbig2dec.com" language: c++ primary_contact: sebastian.rasmussen@artifex.com sanitizers: - address - memory main_repo: 'git://git.ghostscript.com/jbig2dec.git' ================================================ FILE: projects/jbig2dec/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check -C $WORK/jbig2dec ================================================ FILE: projects/jboss-logging/.gitignore ================================================ project-parent/jboss-logging project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/jboss-logging/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/jboss-logging RUN git clone --depth 1 https://github.com/jboss-logging/jboss-logging $SRC/project-parent/jboss-logging COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/jboss-logging/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=jboss-logging PROJECT_GROUP_ID=org.jboss.logging PROJECT_ARTIFACT_ID=jboss-logging MAIN_REPOSITORY=https://github.com/jboss-logging/jboss-logging function set_project_version_in_fuzz_targets_dependency { #PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) PROJECT_VERSION=3.6.3.Final-SNAPSHOT #workaround to make it consistent with pom.xml # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install mvn -pl $PROJECT install -DskipTests mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install -DskipTests -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/jboss-logging/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.jboss.logging jboss-logging Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/jboss-logging/project-parent/fuzz-targets/src/test/java/com/example/LoggingFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.jboss.logging.*; import java.util.Properties; class LoggingFuzzer { private static final Logger LOGGER = Logger.getLogger(LoggingFuzzer.class); @FuzzTest void myFuzzTest(FuzzedDataProvider data) { String[] logManagers = { "jboss","jdk","log4j2","log4j","slf4j"}; String logManager = data.pickValue(logManagers); Properties props = System.getProperties(); props.setProperty("org.jboss.logging.provider", logManager); int i1 = data.consumeInt(); int i2 = data.consumeInt(); String s2 = data.consumeString(10); String s1 = data.consumeRemainingAsString(); LOGGER.debugf(s1,i1,i2,s2); LOGGER.tracef(s1,i1,i2,s2); LOGGER.errorf(s1,i1,i2,s2); } } ================================================ FILE: projects/jboss-logging/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom jboss-logging fuzz-targets ================================================ FILE: projects/jboss-logging/project.yaml ================================================ homepage: "https://github.com/jboss-logging/jboss-logging" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/jboss-logging/jboss-logging" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jc/project.yaml ================================================ homepage: "https://kellyjonbrazil.github.io/jc/docs/" language: python primary_contact: "kellyjonbrazil@gmail.com" auto_ccs: - "ennamarie19@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/kellyjonbrazil/jc.git" ================================================ FILE: projects/jdom/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.14-bin.tar.gz -o ant.tar.gz && \ mkdir -p $SRC/ant && \ tar -zxvf ant.tar.gz -C $SRC/ant --strip-components=1 && \ rm -rf ant.tar.gz ENV ANT_HOME=$SRC/ant ENV ANT $SRC/ant/bin/ant RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/xml.dict $SRC/xml.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/SAXBuilderFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/hunterhacker/jdom.git jdom COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jdom ================================================ FILE: projects/jdom/SAXBuilderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jdom2.input.SAXBuilder; import org.jdom2.Document; import java.io.StringReader; import org.jdom2.JDOMException; import java.io.IOException; import org.jdom2.IllegalNameException; import org.jdom2.IllegalTargetException; public class SAXBuilderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { SAXBuilder sax = new SAXBuilder(); sax.setValidation(data.consumeBoolean()); sax.setIgnoringElementContentWhitespace(data.consumeBoolean()); sax.setIgnoringBoundaryWhitespace(data.consumeBoolean()); StringReader xml_input = new StringReader(data.consumeRemainingAsString()); try{ Document doc = sax.build(xml_input); } catch (JDOMException | IOException | IllegalNameException | IllegalTargetException e){ return; } } } ================================================ FILE: projects/jdom/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT $ANT -Dcompile.target=15 -Dcompile.source=15 cp build/package/jdom-2.x-*[0-9][0-9].jar $OUT/jdom.jar ALL_JARS="jdom.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jdom/project.yaml ================================================ homepage: "http://jdom.org/" language: jvm primary_contact: "" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/hunterhacker/jdom.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" - "michael.nothhard@code-intelligence.com" ================================================ FILE: projects/jedi/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone --recurse-submodules https://github.com/davidhalter/jedi jedi COPY *.sh *py $SRC/ WORKDIR $SRC/jedi ================================================ FILE: projects/jedi/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ python3 setup.py install if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/jedi/fuzz_script.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import jedi def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) jedi.Script(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jedi/project.yaml ================================================ homepage: https://github.com/davidhalter/jedi main_repo: https://github.com/davidhalter/jedi language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/jedis/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool wget openjdk-11-jdk RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.5/binaries/apache-maven-3.9.5-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.5/bin/mvn RUN git clone --depth 1 https://github.com/redis/jedis.git jedis WORKDIR jedis COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/jedis/JedisURIFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import redis.clients.jedis.Jedis; import java.net.URI; import java.net.URISyntaxException; public class JedisURIFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ Jedis jedis = new Jedis(new URI(data.consumeRemainingAsString())); } catch (URISyntaxException e) {} catch (java.lang.NumberFormatException e) {} catch (redis.clients.jedis.exceptions.InvalidURIException e) {} } } ================================================ FILE: projects/jedis/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export JAVA_HOME="$OUT/open-jdk-11" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip --exclude 'lib/security/blacklisted.certs' "/usr/lib/jvm/java-11-openjdk-amd64/" "$JAVA_HOME" MAVEN_ARGS="-Dpropguard.skip -DskipTests -Dmaven.javadoc.skip=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True" $MVN clean package $MAVEN_ARGS org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) find ./ -name "jedis-$CURRENT_VERSION.jar" -exec mv {} $OUT/jedis.jar \; ALL_JARS="jedis.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac -cp $BUILD_CLASSPATH ${SRC}/*.java install ${SRC}/*.class ${OUT}/ for fuzzer in $(find $SRC -name '*Fuzzer.java' -maxdepth 1); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-11/\" \ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jedis/project.yaml ================================================ homepage: "https://github.com/redis/jedis" language: jvm primary_contact: "irali@google.com" main_repo: "https://github.com/redis/jedis.git" file_github_issue: false fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/jerryscript/project.yaml ================================================ homepage: "https://jerryscript.net" language: c primary_contact: "zherczeg7@gmail.com" auto_ccs: - "reni@inf.u-szeged.hu" sanitizers: - address - undefined - memory main_repo: "https://github.com/jerryscript-project/jerryscript" fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/jersey/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.11/bin/mvn RUN git clone --depth 1 https://github.com/eclipse-ee4j/jersey COPY build.sh $SRC/ COPY HttpHeaderReaderFuzzer.java $SRC/ WORKDIR $SRC/jersey ================================================ FILE: projects/jersey/HttpHeaderReaderFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.glassfish.jersey.message.internal.HttpHeaderReader; import org.glassfish.jersey.message.internal.MatchingEntityTag; import java.text.ParseException; public class HttpHeaderReaderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String value = data.consumeRemainingAsString(); try { HttpHeaderReader.readMatchingEntityTag(value); HttpHeaderReader.readQualityFactor(value); HttpHeaderReader.readDate(value); HttpHeaderReader.readAcceptToken(value); HttpHeaderReader.readAcceptLanguage(value); HttpHeaderReader.readStringList(value); HttpHeaderReader.readCookie(value); HttpHeaderReader.readCookies(value); HttpHeaderReader.readNewCookie(value); } catch (ParseException e) { } } } ================================================ FILE: projects/jersey/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package org.apache.maven.plugins:maven-dependency-plugin:3.6.1:copy -Dartifact=org.osgi:org.osgi.core:6.0.0 -DoutputDirectory=. $MAVEN_ARGS -Pstaging CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "core-server/target/jersey-server-$CURRENT_VERSION.jar" "$OUT/jersey-server.jar" cp "core-common/target/jersey-common-$CURRENT_VERSION.jar" "$OUT/jersey-common.jar" cp "core-client/target/jersey-client-$CURRENT_VERSION.jar" "$OUT/jersey-client.jar" cp "org.osgi.core-6.0.0.jar" "$OUT/org.osgi.core.jar" # Copy Jakarta WS RS API jar for compilation find . -path "*/jakarta.ws.rs-api*.jar" -not -name "*sources*" | head -1 | xargs -I{} cp {} "$OUT/jakarta.ws.rs-api.jar" ALL_JARS="jersey-server.jar jersey-common.jar jersey-client.jar org.osgi.core.jar jakarta.ws.rs-api.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH -d $OUT -encoding UTF-8 $fuzzer # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jersey/project.yaml ================================================ homepage: "https://github.com/eclipse-ee4j/jersey" language: jvm main_repo: "https://github.com/eclipse-ee4j/jersey.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jettison/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/json.dict $SRC/JsonFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JsonFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/jettison-json/jettison.git jettison COPY build.sh $SRC/ COPY JsonFuzzer.java $SRC/ WORKDIR $SRC/jettison ================================================ FILE: projects/jettison/JsonFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONException; public class JsonFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ JSONObject obj = new JSONObject(data.consumeRemainingAsString()); } catch (JSONException e){ return; } } } ================================================ FILE: projects/jettison/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/jettison-$CURRENT_VERSION.jar" $OUT/jettison.jar ALL_JARS="jettison.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jettison/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/jettison-json/jettison language: jvm main_repo: https://github.com/jettison-json/jettison.git sanitizers: - address vendor_ccs: - patrice.salathe@code-intelligence.com - yakdan@code-intelligence.com ================================================ FILE: projects/jetty/.gitignore ================================================ project-parent/jetty project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/jetty/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/http.dict $SRC/HTTP2CServerFuzzer.dict && \ mv fuzzing/dictionaries/http.dict $SRC/HttpParserFuzzer.dict && \ mv fuzzing/dictionaries/xml.dict $SRC/XmlParserFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/HTTP2CServerFuzzer_seed_corpus.zip go-fuzz-corpus/http2/corpus/* && \ zip -j $SRC/HttpParserFuzzer_seed_corpus.zip go-fuzz-corpus/httpreq/corpus/* && \ zip -j $SRC/XmlParserFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/jetty RUN git clone --depth 1 https://github.com/eclipse/jetty.project $SRC/project-parent/jetty # required by jetty's asciidoctor-maven-plugin RUN apt-get update && apt-get -y install fontconfig COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/jetty/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=jetty PROJECT_GROUP_ID=org.eclipse.jetty PROJECT_ARTIFACT_ID=jetty-project MAIN_REPOSITORY=https://github.com/eclipse/jetty.project MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=11 -Djavac.target.version=11 -Denforcer.skip=true -DskipTests" mv $SRC/{*.zip,*.dict} $OUT function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) FUZZ_TARGET_DEPENDENCIES=":jetty-http :jetty-server :jetty-util :jetty-io :jetty-runner :jetty-client .http2:http2-common .http2:http2-server" for dependency in $FUZZ_TARGET_DEPENDENCIES; do # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID$dependency -DdepVersion=$PROJECT_VERSION -DforceVersion=true) done } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) $MVN -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes $OUT/ RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent/fuzz-targets -name '*Fuzzer.java' ! -name WebAppDefaultServletFuzzer.java); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done # disable NamingContextLookup sanitizer for WebAppDefaultServletFuzzer.java echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.WebAppDefaultServletFuzzer \ --disabled_hooks=com.code_intelligence.jazzer.sanitizers.NamingContextLookup \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/WebAppDefaultServletFuzzer chmod u+x $OUT/WebAppDefaultServletFuzzer # add keystore to location required by SslConnectionFuzzer mkdir -p /out/src/test/resources cp $SRC/project-parent/jetty/jetty-io/src/test/resources/keystore.p12 /out/src/test/resources/ fi ================================================ FILE: projects/jetty/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.eclipse.jetty jetty-http Fuzzing-SNAPSHOT org.eclipse.jetty jetty-server Fuzzing-SNAPSHOT org.eclipse.jetty jetty-util Fuzzing-SNAPSHOT org.eclipse.jetty jetty-io Fuzzing-SNAPSHOT org.eclipse.jetty jetty-runner Fuzzing-SNAPSHOT org.junit.platform junit-platform-launcher 1.9.2 org.eclipse.jetty.toolchain jetty-test-helper 6.0 test org.eclipse.jetty jetty-client Fuzzing-SNAPSHOT test org.eclipse.jetty.http2 http2-common Fuzzing-SNAPSHOT test org.eclipse.jetty.http2 http2-server Fuzzing-SNAPSHOT test maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/AbstractHttpClientServerTest.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClientTransport; import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.util.SocketAddressResolver; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; public abstract class AbstractHttpClientServerTest { protected Server server; protected HttpClient client; protected ServerConnector connector; public void start(Scenario scenario, Handler handler) throws Exception { startServer(scenario, handler); startClient(scenario); } protected void startServer(Scenario scenario, Handler handler) throws Exception { if (server == null) { QueuedThreadPool serverThreads = new QueuedThreadPool(); serverThreads.setName("server"); server = new Server(serverThreads); } connector = new ServerConnector(server, scenario.newServerSslContextFactory()); connector.setPort(0); server.addConnector(connector); server.setHandler(handler); server.start(); } protected void startClient(Scenario scenario) throws Exception { startClient(scenario, null); } protected void startClient(Scenario scenario, Consumer config) throws Exception { startClient(scenario, HttpClientTransportOverHTTP::new, config); } protected void startClient(Scenario scenario, Function transport, Consumer config) throws Exception { ClientConnector clientConnector = new ClientConnector(); clientConnector.setSelectors(1); clientConnector.setSslContextFactory(scenario.newClientSslContextFactory()); QueuedThreadPool executor = new QueuedThreadPool(); executor.setName("client"); clientConnector.setExecutor(executor); Scheduler scheduler = new ScheduledExecutorScheduler("client-scheduler", false); clientConnector.setScheduler(scheduler); client = newHttpClient(transport.apply(clientConnector)); client.setSocketAddressResolver(new SocketAddressResolver.Sync()); if (config != null) config.accept(client); client.start(); } public HttpClient newHttpClient(HttpClientTransport transport) { return new HttpClient(transport); } @AfterEach public void disposeClient() throws Exception { if (client != null) { client.stop(); client = null; } } @AfterEach public void disposeServer() throws Exception { if (server != null) { server.stop(); server = null; } } public static class ScenarioProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext context) { return Stream.of( new NormalScenario() // TODO: add more ssl / non-ssl scenarios here ).map(Arguments::of); } } public interface Scenario { SslContextFactory.Client newClientSslContextFactory(); SslContextFactory.Server newServerSslContextFactory(); String getScheme(); } public static class NormalScenario implements Scenario { @Override public SslContextFactory.Client newClientSslContextFactory() { return null; } @Override public SslContextFactory.Server newServerSslContextFactory() { return null; } @Override public String getScheme() { return HttpScheme.HTTP.asString(); } @Override public String toString() { return "HTTP"; } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/AbstractServerTest.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import org.eclipse.jetty.http.*; import org.eclipse.jetty.http2.api.server.ServerSessionListener; import org.eclipse.jetty.http2.generator.Generator; import org.eclipse.jetty.http2.parser.Parser; import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory; import org.eclipse.jetty.http2.server.RawHTTP2ServerConnectionFactory; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.junit.jupiter.api.AfterEach; import javax.servlet.http.HttpServlet; import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.net.SocketTimeoutException; import java.nio.ByteBuffer; public abstract class AbstractServerTest { protected ServerConnector connector; protected ByteBufferPool byteBufferPool; protected Generator generator; protected Server server; protected String path; protected void startServer(HttpServlet servlet) throws Exception { prepareServer(new HTTP2ServerConnectionFactory(new HttpConfiguration())); ServletContextHandler context = new ServletContextHandler(server, "/"); context.addServlet(new ServletHolder(servlet), path); server.start(); } protected void startServer(ServerSessionListener listener) throws Exception { prepareServer(new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener)); server.start(); } private void prepareServer(ConnectionFactory connectionFactory) { QueuedThreadPool serverExecutor = new QueuedThreadPool(); serverExecutor.setName("server"); server = new Server(serverExecutor); connector = new ServerConnector(server, connectionFactory); server.addConnector(connector); path = "/test"; byteBufferPool = new MappedByteBufferPool(); generator = new Generator(byteBufferPool); } protected MetaData.Request newRequest(String method, HttpFields fields) { String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), path, HttpVersion.HTTP_2, fields, -1); } @AfterEach public void dispose() throws Exception { if (server != null) server.stop(); } protected boolean parseResponse(Socket client, Parser parser) throws IOException { return parseResponse(client, parser, 1000); } protected boolean parseResponse(Socket client, Parser parser, long timeout) throws IOException { byte[] buffer = new byte[2048]; InputStream input = client.getInputStream(); client.setSoTimeout((int)timeout); while (true) { try { int read = input.read(buffer); if (read < 0) return true; parser.parse(ByteBuffer.wrap(buffer, 0, read)); if (client.isClosed()) return true; } catch (SocketTimeoutException x) { return false; } } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/HTTP2CServer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; import org.eclipse.jetty.server.*; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.util.thread.QueuedThreadPool; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; public class HTTP2CServer extends Server { public HTTP2CServer(int port) { HttpConfiguration config = new HttpConfiguration(); // HTTP + HTTP/2 connector HttpConnectionFactory http1 = new HttpConnectionFactory(config); HTTP2CServerConnectionFactory http2c = new HTTP2CServerConnectionFactory(config); ServerConnector connector = new ServerConnector(this, http1, http2c); connector.setPort(port); addConnector(connector); ((QueuedThreadPool)getThreadPool()).setName("server"); setHandler(new SimpleHandler()); } public static void main(String... args) throws Exception { HTTP2CServer server = new HTTP2CServer(8080); server.start(); } private static class SimpleHandler extends AbstractHandler { @Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); String code = request.getParameter("code"); if (code != null) response.setStatus(Integer.parseInt(code)); response.setHeader("Custom", "Value"); response.setContentType("text/plain"); String content = "Hello from Jetty using " + request.getProtocol() + "\n"; content += "uri=" + request.getRequestURI() + "\n"; content += "date=" + new Date() + "\n"; response.setContentLength(content.length()); response.getOutputStream().print(content); } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/HTTP2CServerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.server.ServerConnector; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import java.net.Socket; import java.nio.charset.StandardCharsets; public class HTTP2CServerFuzzer extends AbstractServerTest { @BeforeEach public void before() throws Exception { server = new HTTP2CServer(0); server.start(); connector = (ServerConnector)server.getConnectors()[0]; } @AfterEach public void after() throws Exception { server.stop(); } @FuzzTest public void fuzzHTTP(FuzzedDataProvider data) throws Exception { try (Socket client = new Socket("localhost", connector.getLocalPort())) { client.getOutputStream().write(data.consumeRemainingAsString().getBytes(StandardCharsets.ISO_8859_1)); client.getOutputStream().flush(); } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/HttpClientFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.util.BytesRequestContent; import org.eclipse.jetty.server.handler.AbstractHandler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; public class HttpClientFuzzer extends AbstractHttpClientServerTest { @FuzzTest public void testPOSTWithParametersWithContent1(FuzzedDataProvider data) throws Exception { Scenario scenario = new NormalScenario(); String name = data.consumeString(50); String value = data.consumeString(50); byte[] content = data.consumeRemainingAsBytes(); if (content.length > 0) { String paramName = name; String paramValue = value; start(scenario, new AbstractHandler() { @Override public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { baseRequest.setHandled(true); consume(request.getInputStream(), true); String value = request.getParameter(paramName); if (paramValue.equals(value)) { response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain"); response.getOutputStream().write(content); } } }); ContentResponse response = client.POST(scenario.getScheme() + "://localhost:" + connector.getLocalPort() + "/?b=1") .param(paramName, paramValue) .body(new BytesRequestContent(content)) .timeout(5, TimeUnit.SECONDS) .send(); response.getStatus(); response.getContent(); disposeServer(); disposeClient(); } } private void consume(InputStream input, boolean eof) throws IOException { int crlfs = 0; while (true) { int read = input.read(); if (read == '\r' || read == '\n') ++crlfs; else crlfs = 0; if (!eof && crlfs == 4) break; if (read < 0) break; } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/HttpParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.http.*; import org.eclipse.jetty.http.HttpParser.State; import org.eclipse.jetty.util.BufferUtil; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; class HttpParserFuzzer { static void parseAll(HttpParser parser, ByteBuffer buffer) { if (parser.isState(State.END)) parser.reset(); if (!parser.isState(State.START)) throw new IllegalStateException("!START"); // continue parsing int remaining = buffer.remaining(); while (!parser.isState(State.END) && remaining > 0) { int wasRemaining = remaining; parser.parseNext(buffer); remaining = buffer.remaining(); if (remaining == wasRemaining) break; } } @FuzzTest void testFuzzParser(FuzzedDataProvider data) { ByteBuffer buffer = BufferUtil.toBuffer(data.consumeRemainingAsString()); HttpParser.RequestHandler handler = new Handler(); HttpParser parser = new HttpParser(handler, HttpCompliance.RFC7230_LEGACY); parseAll(parser, buffer); } private String _host; private int _port; private String _bad; private String _content; private String _methodOrVersion; private String _uriOrStatus; private String _versionOrReason; private final List _fields = new ArrayList<>(); private final List _trailers = new ArrayList<>(); private String[] _hdr; private String[] _val; private int _headers; private boolean _early; private boolean _headerCompleted; private boolean _contentCompleted; private boolean _messageCompleted; private final List _complianceViolation = new ArrayList<>(); private class Handler implements HttpParser.RequestHandler, HttpParser.ResponseHandler, ComplianceViolation.Listener { @Override public boolean content(ByteBuffer ref) { if (_content == null) _content = ""; String c = BufferUtil.toString(ref, StandardCharsets.UTF_8); _content = _content + c; ref.position(ref.limit()); return false; } @Override public void startRequest(String method, String uri, HttpVersion version) { _fields.clear(); _trailers.clear(); _headers = -1; _hdr = new String[10]; _val = new String[10]; _methodOrVersion = method; _uriOrStatus = uri; _versionOrReason = version == null ? null : version.asString(); _messageCompleted = false; _headerCompleted = false; _early = false; } @Override public void parsedHeader(HttpField field) { _fields.add(field); _hdr[++_headers] = field.getName(); _val[_headers] = field.getValue(); if (field instanceof HostPortHttpField) { HostPortHttpField hpfield = (HostPortHttpField) field; _host = hpfield.getHost(); _port = hpfield.getPort(); } } @Override public boolean headerComplete() { _content = null; _headerCompleted = true; return false; } @Override public void parsedTrailer(HttpField field) { _trailers.add(field); } @Override public boolean contentComplete() { _contentCompleted = true; return false; } @Override public boolean messageComplete() { _messageCompleted = true; return true; } @Override public void badMessage(BadMessageException failure) { String reason = failure.getReason(); _bad = reason == null ? String.valueOf(failure.getCode()) : reason; } @Override public void startResponse(HttpVersion version, int status, String reason) { _fields.clear(); _trailers.clear(); _methodOrVersion = version.asString(); _uriOrStatus = Integer.toString(status); _versionOrReason = reason; _headers = -1; _hdr = new String[10]; _val = new String[10]; _messageCompleted = false; _headerCompleted = false; } @Override public void earlyEOF() { _early = true; } @Override public void onComplianceViolation(ComplianceViolation.Mode mode, ComplianceViolation violation, String reason) { _complianceViolation.add(violation); } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/ServerHandlersFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.io.NullByteBufferPool; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.*; import org.junit.jupiter.api.BeforeAll; import java.util.Collection; class ServerHandlersFuzzer { static Server _server; static LocalConnector _connector; static HandlerCollection handlers; static String[] methods_arr = {"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"}; static Handler[] handler_arr = {new AsyncDelayHandler(), new BufferedResponseHandler(), new ContextHandler(), new DefaultHandler(), new ErrorHandler(), new FileBufferedResponseHandler(), new HotSwapHandler(), new IdleTimeoutHandler(), new InetAccessHandler(), new MovedContextHandler(), new RequestLogHandler(), new ResourceHandler(), new SecuredRedirectHandler(), new ThreadLimitHandler()}; @BeforeAll static void setup() { _server = new Server(); _server.addBean(new NullByteBufferPool()); _connector = new LocalConnector(_server, new HttpConnectionFactory(), null); _connector.setIdleTimeout(3000); _server.addConnector(_connector); } @FuzzTest void getResponse(FuzzedDataProvider data) { Collection handlersCollection = data.pickValues(handler_arr, data.consumeInt(0, handler_arr.length)); String method = data.pickValue(methods_arr); String str = data.consumeString(1000); String str1 = data.consumeString(1000); String str2 = data.consumeRemainingAsString(); handlers = new HandlerCollection(); for (Handler handler: handlersCollection) { handlers.addHandler(handler); } _server.setHandler(handlers); try { _server.start(); } catch (Exception e) { throw new RuntimeException("Server start error!"); } try { _connector.getResponse(method + " /" + str + " HTTP/1.0\r\n" + str1 + "\r\n\r\n" + str2); } catch (Exception e) { } try { _server.stop(); } catch (Exception e) { throw new RuntimeException("Server stop error!"); } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/SslConnectionFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.io.*; import org.eclipse.jetty.io.ssl.SslConnection; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.FutureCallback; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.TimerScheduler; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSocket; import java.io.File; import java.io.IOException; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; public class SslConnectionFuzzer { private static final Logger LOG = LoggerFactory.getLogger(SslConnectionFuzzer.class); private static final int TIMEOUT = 1000000; private static ByteBufferPool __byteBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged()); private final SslContextFactory _sslCtxFactory = new SslContextFactory.Server(); protected volatile EndPoint _lastEndp; private volatile boolean _testFill = true; private volatile boolean _onXWriteThenShutdown = false; private volatile FutureCallback _writeCallback; protected ServerSocketChannel _connector; final AtomicInteger _dispatches = new AtomicInteger(); protected QueuedThreadPool _threadPool = new QueuedThreadPool() { @Override public void execute(Runnable job) { _dispatches.incrementAndGet(); super.execute(job); } }; protected Scheduler _scheduler = new TimerScheduler(); protected SelectorManager _manager = new SelectorManager(_threadPool, _scheduler) { @Override public Connection newConnection(SelectableChannel channel, EndPoint endpoint, Object attachment) { SSLEngine engine = _sslCtxFactory.newSSLEngine(); engine.setUseClientMode(false); SslConnection sslConnection = new SslConnection(__byteBufferPool, getExecutor(), endpoint, engine); sslConnection.setRenegotiationAllowed(_sslCtxFactory.isRenegotiationAllowed()); sslConnection.setRenegotiationLimit(_sslCtxFactory.getRenegotiationLimit()); Connection appConnection = new TestConnection(sslConnection.getDecryptedEndPoint()); sslConnection.getDecryptedEndPoint().setConnection(appConnection); return sslConnection; } @Override protected EndPoint newEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey selectionKey) { SocketChannelEndPoint endp = new TestEP(channel, selector, selectionKey, getScheduler()); endp.setIdleTimeout(TIMEOUT); _lastEndp = endp; return endp; } }; static final AtomicInteger __startBlocking = new AtomicInteger(); static final AtomicInteger __blockFor = new AtomicInteger(); static final AtomicBoolean __onIncompleteFlush = new AtomicBoolean(); private static class TestEP extends SocketChannelEndPoint { public TestEP(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler) { super((SocketChannel)channel, selector, key, scheduler); } @Override protected void onIncompleteFlush() { __onIncompleteFlush.set(true); } @Override public boolean flush(ByteBuffer... buffers) throws IOException { __onIncompleteFlush.set(false); if (__startBlocking.get() == 0 || __startBlocking.decrementAndGet() == 0) { if (__blockFor.get() > 0 && __blockFor.getAndDecrement() > 0) { return false; } } return super.flush(buffers); } } @BeforeEach public void initSSL() throws Exception { File keystore = MavenTestingUtils.getTestResourceFile("keystore.p12"); _sslCtxFactory.setKeyStorePath(keystore.getAbsolutePath()); _sslCtxFactory.setKeyStorePassword("storepwd"); _sslCtxFactory.setRenegotiationAllowed(true); _sslCtxFactory.setRenegotiationLimit(-1); startManager(); } public void startManager() throws Exception { _testFill = true; _writeCallback = null; _lastEndp = null; _connector = ServerSocketChannel.open(); _connector.socket().bind(null); _threadPool.start(); _scheduler.start(); _manager.start(); } private void startSSL() throws Exception { _sslCtxFactory.start(); } @AfterEach public void stopSSL() throws Exception { stopManager(); _sslCtxFactory.stop(); } private void stopManager() throws Exception { if (_lastEndp != null && _lastEndp.isOpen()) _lastEndp.close(); _manager.stop(); _scheduler.stop(); _threadPool.stop(); _connector.close(); } public class TestConnection extends AbstractConnection { ByteBuffer _in = BufferUtil.allocate(8 * 1024); public TestConnection(EndPoint endp) { super(endp, _threadPool); } @Override public void onOpen() { super.onOpen(); if (_testFill) fillInterested(); else { getExecutor().execute(() -> getEndPoint().write(_writeCallback, BufferUtil.toBuffer("Hello Client"))); } } @Override public void onClose(Throwable cause) { super.onClose(cause); } @Override public void onFillable() { EndPoint endp = getEndPoint(); try { boolean progress = true; while (progress) { progress = false; // Fill the input buffer with everything available int filled = endp.fill(_in); while (filled > 0) { progress = true; filled = endp.fill(_in); } boolean shutdown = _onXWriteThenShutdown && BufferUtil.toString(_in).contains("X"); // Write everything int l = _in.remaining(); if (l > 0) { FutureCallback blockingWrite = new FutureCallback(); endp.write(blockingWrite, _in); blockingWrite.get(); if (shutdown) endp.shutdownOutput(); } // are we done? if (endp.isInputShutdown() || shutdown) endp.shutdownOutput(); } } catch (InterruptedException | EofException e) { LOG.trace("IGNORED", e); } catch (Exception e) { LOG.warn("During onFillable", e); } finally { if (endp.isOpen()) fillInterested(); } } } protected SSLSocket newClient() throws IOException { SSLSocket socket = _sslCtxFactory.newSslSocket(); socket.connect(_connector.socket().getLocalSocketAddress()); return socket; } @FuzzTest public void fuzz(FuzzedDataProvider data) throws Exception { startSSL(); try (Socket client = newClient()) { client.setSoTimeout(TIMEOUT); try (SocketChannel server = _connector.accept()) { server.configureBlocking(false); _manager.accept(server); client.getOutputStream().write(data.consumeString(10).getBytes(StandardCharsets.UTF_8)); client.getOutputStream().write(data.consumeRemainingAsString().getBytes(StandardCharsets.UTF_8)); } } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/URIUtilDecodePathFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.util.URIUtil; class URIUtilDecodePathFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { URIUtil.decodePath(data.consumeRemainingAsString()); } catch(IllegalArgumentException e) { } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/WebAppDefaultServletFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.server.HttpConnectionFactory; import org.eclipse.jetty.server.LocalConnector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.jupiter.api.BeforeAll; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; public class WebAppDefaultServletFuzzer { static Server server; static LocalConnector connector; @BeforeAll static void prepareServer() throws Exception { server = new Server(); connector = new LocalConnector(server); connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986); server.addConnector(connector); Path directoryPath = Files.createTempDirectory("test"); Path welcomeResource = directoryPath.resolve("index.html"); try (OutputStream output = Files.newOutputStream(welcomeResource)) { output.write("

welcome page

".getBytes(StandardCharsets.UTF_8)); } WebAppContext context = new WebAppContext(server, directoryPath.toString(), "/"); server.setHandler(context); } @FuzzTest public void testResourceService3(FuzzedDataProvider data) throws Exception { server.start(); String request = "GET " + data.consumeRemainingAsString() + " HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n" + "\r\n"; connector.getResponse(request); try { server.stop(); } catch (Exception e) { throw new RuntimeException("Server stop error!"); } } } ================================================ FILE: projects/jetty/project-parent/fuzz-targets/src/test/java/com/example/XmlParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in co mpliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ////////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.eclipse.jetty.xml.XmlParser; import org.xml.sax.SAXParseException; import java.io.ByteArrayInputStream; class XmlParserFuzzer { @FuzzTest void testXmlParser(FuzzedDataProvider data) throws Exception { XmlParser parser = new XmlParser(); try { parser.parse(new ByteArrayInputStream(data.consumeRemainingAsBytes())); } catch (SAXParseException e) {} } } ================================================ FILE: projects/jetty/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom jetty fuzz-targets ================================================ FILE: projects/jetty/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "www.eclipse.org/jetty" language: jvm main_repo: "https://github.com/eclipse/jetty.project" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jflex/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/jflex-de/jflex jflex COPY *.sh *.java $SRC/ WORKDIR $SRC/jflex ================================================ FILE: projects/jflex/JflexFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.file.Files; import jflex.exceptions.GeneratorException; import jflex.generator.LexGenerator; import jflex.logging.Out; public class JflexFuzzer { private static File tempDirectory; private static File tempFile; public static void fuzzerInitialize() { try { tempDirectory = Files.createTempDirectory("oss-fuzz").toFile().getAbsoluteFile(); tempFile = new File(tempDirectory + "/" + "oss-fuzz-temp.java"); } catch (IOException e) { // Known exception } } public static void fuzzerTearDown() { tempFile.delete(); tempDirectory.delete(); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { // Discard all log message Out.setOutputStream(OutputStream.nullOutputStream()); PrintWriter printWriter = new PrintWriter(new FileWriter(tempFile)); printWriter.print("%%" + data.consumeRemainingAsString()); printWriter.close(); LexGenerator generator = new LexGenerator(tempFile); generator.generate(); } catch (GeneratorException | IOException e) { // Known exception } } } ================================================ FILE: projects/jflex/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "jflex/target/jflex-$CURRENT_VERSION.jar" $OUT/jflex.jar ALL_JARS="jflex.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jflex/project.yaml ================================================ homepage: https://github.com/jflex-de/jflex main_repo: https://github.com/jflex-de/jflex language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jfreechart/DefaultCategoryDatasetChartFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.category.DefaultCategoryDataset; import ossfuzz.TestUtils; public class DefaultCategoryDatasetChartFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) throws Exception { DefaultCategoryDataset dataset = new DefaultCategoryDataset<>(); Integer numKeys = data.consumeInt(0, 1000); Integer numColumns = data.consumeInt(0, 1000); for (int i = 0; i < numKeys; i++) { String series = data.consumeString(100); for (int j = 0; j < numColumns; j++) { String category = data.consumeString(100); dataset.addValue(data.consumeDouble(), series, category); } } JFreeChart c1 = ChartFactory.createBarChart(data.consumeString(100), data.consumeString(100), data.consumeString(100), dataset); JFreeChart c2 = TestUtils.serialised(c1); if (!c1.equals(c2)) { throw new Exception("Charts with Default Category Datasets should be equal"); } } } ================================================ FILE: projects/jfreechart/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.0/binaries/apache-maven-3.9.0-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.0/bin/mvn RUN apt-get install -y libfreetype6 RUN git clone --depth 1 https://github.com/jfree/jfreechart.git $SRC/jfreechart COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ COPY src/ ${SRC}/jfreechart/src/ WORKDIR $SRC/jfreechart ================================================ FILE: projects/jfreechart/PieDatasetChartFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.general.DefaultPieDataset; import ossfuzz.TestUtils; public class PieDatasetChartFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) throws Exception { DefaultPieDataset dataSet = new DefaultPieDataset<>(); Integer numValues = data.consumeInt(0, 1000); for (int i = 0 ; i < numValues; i++) { dataSet.setValue(data.consumeString(100), data.consumeDouble()); } JFreeChart c1 = ChartFactory.createPieChart(data.consumeString(100), dataSet); JFreeChart c2 = TestUtils.serialised(c1); if (!c1.equals(c2)) { throw new Exception("Charts with Pie Datasets should be equal"); } } } ================================================ FILE: projects/jfreechart/TimeSeriesChartFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartFactory; import org.jfree.data.time.*; import ossfuzz.TestUtils; public class TimeSeriesChartFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) throws Exception { RegularTimePeriod t = new Day(); TimeSeries series = new TimeSeries<>(data.consumeString(100)); Integer numItems = data.consumeInt(0, 1000); for (int i = 0; i < numItems; i++) { series.add(t, data.consumeInt()); if (i != numItems - 1) { t = t.next(); } } TimeSeriesCollection dataset = new TimeSeriesCollection<>(); dataset.addSeries(series); JFreeChart c1 = ChartFactory.createTimeSeriesChart( data.consumeString(100), data.consumeString(100), data.consumeString(100), dataset); JFreeChart c2 = TestUtils.serialised(c1); if (!c1.equals(c2)) { throw new Exception("Charts with Time Series should be equal"); } } } ================================================ FILE: projects/jfreechart/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) $MVN package -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true cp "$SRC/jfreechart/target/jfreechart-$CURRENT_VERSION.jar" $OUT/ ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir javac $SRC/jfreechart/src/main/java/ossfuzz/TestUtils.java for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jfreechart/project.yaml ================================================ homepage: "https://www.jfree.org/jfreechart/" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/jfree/jfreechart.git" sanitizers: - address vendor_ccs: ================================================ FILE: projects/jfreechart/src/main/java/ossfuzz/TestUtils.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ossfuzz; import java.io.*; /** * Some utility methods for use by the testing code. */ public class TestUtils { /** * Serialises an object, deserialises it and returns the deserialised * version. * * @param original the original object. * * @return A serialised and deserialised version of the original. */ public static K serialised(K original) { K result = null; ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ObjectOutput out; try { out = new ObjectOutputStream(buffer); out.writeObject(original); out.close(); ObjectInput in = new ObjectInputStream( new ByteArrayInputStream(buffer.toByteArray())); result = (K) in.readObject(); in.close(); } catch (IOException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } return result; } } ================================================ FILE: projects/jimfs/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/jimfs COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jimfs ================================================ FILE: projects/jimfs/FileSystemFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.common.collect.ImmutableList; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; import static com.google.common.jimfs.PathNormalization.CASE_FOLD_UNICODE; import static com.google.common.jimfs.PathNormalization.NFD; public class FileSystemFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Configuration.Builder configBuilder; if (data.consumeBoolean()) { configBuilder = Configuration.unix().toBuilder(); } else { configBuilder = Configuration.windows().toBuilder(); } FileSystem fs; try { fs = Jimfs.newFileSystem(configBuilder .setNameCanonicalNormalization(NFD, CASE_FOLD_UNICODE) .setBlockSize(data.consumeInt(1, 1000)) .setMaxSize(data.consumeLong(1, 100000)) .setRoots(data.consumeString(50)) .setWorkingDirectory("/" + data.consumeString(50)) .setMaxCacheSize(data.consumeLong(1, 100000)) .setPathEqualityUsesCanonicalForm(data.consumeBoolean()) .build() ); } catch (java.lang.IllegalArgumentException e) { return; } Path foo; try { foo = fs.getPath(data.consumeString(50)); } catch (InvalidPathException e) { return; } String content = data.consumeRemainingAsString(); try { Files.createDirectory(foo); Path dummyFile = foo.resolve("dummy.txt"); Files.write(dummyFile, ImmutableList.of(content), StandardCharsets.UTF_8); String fileContent = Files.readString(dummyFile); if (!fileContent.contains(content)) { throw new FuzzerSecurityIssueLow("Content not entirely written to file"); } } catch (IOException ignored) {} } } ================================================ FILE: projects/jimfs/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" $MVN package $MAVEN_ARGS org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "jimfs/target/jimfs-$CURRENT_VERSION.jar" "$OUT/jimfs.jar" ALL_JARS="jimfs.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jimfs/project.yaml ================================================ homepage: "https://github.com/google/jimfs" language: jvm main_repo: "git@github.com:google/jimfs.git" primary_contact: "cgdecker@google.com" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/jimp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/jimp-dev/jimp COPY fuzz.js $SRC/jimp WORKDIR $SRC/jimp ================================================ FILE: projects/jimp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ npm install --global yarn yarn install yarn build yarn add -W -D @jazzer.js/core # Build Fuzzers. compile_javascript_fuzzer jimp fuzz.js -i jimp ================================================ FILE: projects/jimp/fuzz.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const Jimp = require('jimp'); const { writeFileSync } = require('fs'); module.exports.fuzz = async function(data) { try { const provider = new FuzzedDataProvider(data); const content = provider.consumeBytes(provider.consumeIntegralInRange(1, 4096)); let jimpInput; if (provider.consumeBoolean()) { jimpInput = Buffer.from(content); } else { jimpInput = "/tmp/fuzz.me"; writeFileSync(jimpInput, Buffer.from(content)); } Jimp.read(jimpInput, (err, image) => { if (err) return; const width = provider.consumeIntegralInRange(0, image.bitmap.width); const height = provider.consumeIntegralInRange(0, image.bitmap.height); const x = provider.consumeIntegralInRange(0, image.bitmap.width - width); const y = provider.consumeIntegralInRange(0, image.bitmap.height - height); const cropImage = image.crop(x, y, width, height); const resizeWidth = provider.consumeIntegralInRange(0, image.bitmap.width); const resizeHeight = provider.consumeIntegralInRange(0, image.bitmap.height); const resizeImage = cropImage.resize(resizeWidth, resizeHeight); const blurRadius = provider.consumeNumberinRange(0, 100); const blurImage = resizeImage.blur(blurRadius); const contrastValue = provider.consumeNumberinRange(-1, 1); const contrastImage = blurImage.contrast(contrastValue); const brightnessValue = provider.consumeNumberinRange(-1, 1); const brightnessImage = contrastImage.brightness(brightnessValue); const hueValue = provider.consumeNumberinRange(-1, 1); const hueImage = brightnessImage.hue(hueValue); const invertImage = hueImage.invert(); const greyscaleImage = invertImage.greyscale(); const sepiaImage = greyscaleImage.sepia(); const thresholdValue = provider.consumeNumberinRange(0, 1); sepiaImage.threshold(thresholdValue); const pixelColorX = provider.consumeIntegralInRange(0, image.bitmap.width); const pixelColorY = provider.consumeIntegralInRange(0, image.bitmap.height); image.getPixelColor(pixelColorX, pixelColorY); const fontPath = pickRandom([ provider.consumeString(128), Jimp.FONT_SANS_8_BLACK, Jimp.FONT_SANS_10_BLACK, Jimp.FONT_SANS_12_BLACK, Jimp.FONT_SANS_14_BLACK, Jimp.FONT_SANS_16_BLACK, Jimp.FONT_SANS_32_BLACK, Jimp.FONT_SANS_64_BLACK, Jimp.FONT_SANS_128_BLACK, Jimp.FONT_SANS_8_WHITE, Jimp.FONT_SANS_16_WHITE, Jimp.FONT_SANS_32_WHITE, Jimp.FONT_SANS_64_WHITE, Jimp.FONT_SANS_128_WHITE, ]); const fontColor = provider.consumeNumber(); const fontSize = provider.consumeIntegralInRange(0, 100); const fontX = provider.consumeIntegralInRange(0, image.bitmap.width); const fontY = provider.consumeIntegralInRange(0, image.bitmap.height); const text = provider.consumeString(10); Jimp.loadFont(fontPath).then((font) => { image.print(font, fontX, fontY, text, fontSize, fontColor); }); const color = Jimp.color([ provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), ]); image.color([ { apply: 'hue', params: [provider.consumeNumberinRange(-1, 1)] }, { apply: 'lighten', params: [provider.consumeNumberinRange(-1, 1)] }, { apply: 'saturate', params: [provider.consumeNumberinRange(-1, 1)] }, { apply: 'mix', params: [color, provider.consumeNumberinRange(0, 1)] }, ]); const filterType = pickRandom([ Jimp.AUTO, Jimp.BLUR, Jimp.SHARPEN, Jimp.EDGE_DETECT, Jimp.EMBOSS, Jimp.GAUSSIAN, ]); image.filter(filterType); const kernel = [ [-1, -1, -1], [-1, 9, -1], [-1, -1, -1], ]; image.convolution(kernel); const bufferType = pickRandom([ Jimp.MIME_PNG, Jimp.MIME_JPEG, Jimp.MIME_BMP, Jimp.MIME_TIFF, ]); image.getBuffer(bufferType); const compositeImage = image.clone(); const compositeX = provider.consumeIntegralInRange(0, image.bitmap.width); const compositeY = provider.consumeIntegralInRange(0, image.bitmap.height); compositeImage.composite(image, compositeX, compositeY, { mode: pickRandom([ Jimp.BLEND_SOURCE_OVER, Jimp.BLEND_DESTINATION_OVER, Jimp.BLEND_MULTIPLY, Jimp.BLEND_ADD, Jimp.BLEND_SCREEN, Jimp.BLEND_OVERLAY, Jimp.BLEND_DARKEN, Jimp.BLEND_LIGHTEN, Jimp.BLEND_HARDLIGHT, Jimp.BLEND_DIFFERENCE, Jimp.BLEND_EXCLUSION]), opacitySource: provider.consumeNumberinRange(-1, 1), opacityDest: provider.consumeNumberinRange(-1, 1), }); const backgroundColor = Jimp.color([ provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), provider.consumeIntegralInRange(0, 256), ]); const backgroundX = provider.consumeIntegralInRange(0, image.bitmap.width); const backgroundY = provider.consumeIntegralInRange(0, image.bitmap.height); const backgroundWidth = provider.consumeIntegralInRange(0, image.bitmap.width - backgroundX); const backgroundHeight = provider.consumeIntegralInRange(0, image.bitmap.height - backgroundY); image.background(backgroundColor, backgroundX, backgroundY, backgroundWidth, backgroundHeight); }); } catch (error) { if (!ignoredError(error)) throw error; } }; function ignoredError(error) { return Boolean(ignored.find((message) => error.message.indexOf(message) !== -1)); } const ignored = []; function pickRandom(array) { return array[Math.floor(Math.random() * array.length)]; } ================================================ FILE: projects/jimp/project.yaml ================================================ homepage: https://github.com/jimp-dev/jimp language: javascript main_repo: https://github.com/jimp-dev/jimp fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jinja2/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN python3 -m pip install --upgrade pip RUN python3 -m pip install --upgrade build RUN git clone https://github.com/pallets/jinja COPY build.sh *.py $SRC/ ================================================ FILE: projects/jinja2/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/jinja python3 -m build pip3 install ./dist/jinja*.whl # Build jinja2 fuzzers # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/jinja2/fuzz_env_jinja_lexer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import traceback with atheris.instrument_imports(): import jinja2 def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) original = fdp.ConsumeString(sys.maxsize) # Hit the parser env = jinja2.Environment() try: v1 = env.from_string(original) v1.render() except (jinja2.TemplateSyntaxError, jinja2.UndefinedError, RecursionError, MemoryError) as e: return except Exception as e2: # avoid raising anything that is raise by jinjas "handle_exception" tb = traceback.format_exc() if "handle_exception" in str(tb): pass else: raise e2 # Hit tokernizer directly env.lexer.tokenize(original) return def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jinja2/fuzz_jinja_compile_expr.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): import jinja2 def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) env = jinja2.Environment() try: v1 = env.compile_expression(fdp.ConsumeString(sys.maxsize)) except jinja2.TemplateSyntaxError: return except SyntaxError: return except RecursionError: return except MemoryError: return return def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jinja2/fuzz_jinja_compile_templates.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris with atheris.instrument_imports(): from jinja2.environment import Environment from jinja2.loaders import DictLoader def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) template_str = fdp.ConsumeString(sys.maxsize) tmp_path = "/tmp/mytemplates" temp_file = os.path.join(tmp_path, "template.jinja2") if not os.path.isdir(tmp_path): os.mkdir(tmp_path) if os.path.isfile(temp_file): os.remove(temp_file) with open(temp_file, "wb") as fd: fd.write(data) env = Environment(loader=DictLoader({"foo": template_str})) try: env.compile_templates(tmp_path, zip=None) except RecursionError: return return def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jinja2/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/pallets/jinja language: python main_repo: https://github.com/pallets/jinja sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jline3/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/jline/jline3 $SRC/jline3 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jline3 ================================================ FILE: projects/jline3/LineReaderFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jline.builtins.ConfigurationPath; import org.jline.builtins.SyntaxHighlighter; import org.jline.console.impl.SystemHighlighter; import org.jline.reader.*; import org.jline.reader.impl.DefaultHighlighter; import org.jline.reader.impl.DefaultParser; import org.jline.terminal.Size; import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder; import java.lang.IllegalArgumentException; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; public class LineReaderFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { InputStream in = new ByteArrayInputStream(data.consumeBytes(500)); OutputStream out = new ByteArrayOutputStream(); Path nanorc; try { nanorc = LineReaderFuzzer.generateNanorcFile(data); } catch (IOException e) { throw new RuntimeException(e); } SyntaxHighlighter syntaxHighlighter = SyntaxHighlighter.build(nanorc,data.consumeString(50)); SyntaxHighlighter argsHighlighter = SyntaxHighlighter.build(nanorc,data.consumeString(50)); SyntaxHighlighter groovyHighlighter = SyntaxHighlighter.build(nanorc,data.consumeString(50)); SystemHighlighter highlighter = new SystemHighlighter(syntaxHighlighter, argsHighlighter, groovyHighlighter); highlighter.addFileHighlight(data.consumeString(50), data.consumeString(50)); try { Terminal terminal = TerminalBuilder.builder() .system(data.consumeBoolean()) .streams(in, out) .name(data.consumeString(100)) .jna(data.consumeBoolean()) .build(); terminal.setSize(new Size(data.consumeInt(0, 1000), data.consumeInt(0, 1000))); LineReader reader = LineReaderBuilder.builder() .terminal(terminal) .highlighter(highlighter) .parser(new DefaultParser()) .variable(data.consumeString(50), data.consumeString(50)) .build(); reader.readLine(data.consumeString(500), data.consumeChar()); } catch (IOException | EndOfFileException | IllegalArgumentException | UserInterruptException e) {} } public static Path generateNanorcFile(FuzzedDataProvider data) throws IOException { Path nanorc = Files.createTempFile("nanorc", ""); Files.write(nanorc, data.consumeBytes(500)); return nanorc; } } ================================================ FILE: projects/jline3/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) $MVN package -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true cp "$SRC/jline3/jline/target/jline-$CURRENT_VERSION.jar" $OUT/ ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jline3/project.yaml ================================================ homepage: "https://github.com/jline/jline3" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/jline/jline3" sanitizers: - address vendor_ccs: ================================================ FILE: projects/jmespathpy/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/jmespath/jmespath.py jmespath.py COPY *.sh *py $SRC/ WORKDIR $SRC/jmespath.py ================================================ FILE: projects/jmespathpy/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/jmespathpy/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris from jmespath import parser from jmespath import exceptions def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) p = parser.Parser() try: p.parse(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except exceptions.JMESPathError: pass except RecursionError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jmespathpy/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/jmespath/jmespath.py language: python main_repo: https://github.com/jmespath/jmespath.py sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/jmh/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone https://github.com/openjdk/jmh ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/jmh ================================================ FILE: projects/jmh/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-Dmaven.compiler.source=15 -Dmaven.compiler.target=15 -DskipTests" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/jmh" ${MVN} package ${MVN_FLAGS} ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) popd pushd ${SRC} ${MVN} package -DjmhVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/jmh-fuzzer-${CURRENT_VERSION}.jar ${OUT}/jmh-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} jmh-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do stripped_path=$(echo ${fuzzer} | sed 's|^.*src/main/java/\(.*\).java$|\1|'); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if echo \"\$@\" | grep -qE '(^| )-runs=[0-9]+($| )'; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/jmh/pom.xml ================================================ 4.0.0 ossfuzz jmh-fuzzer ${jmhVersion} jar 15 15 UTF-8 com.code-intelligence jazzer-api 0.12.0 org.openjdk.jmh jmh-core ${jmhVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 package shade ================================================ FILE: projects/jmh/project.yaml ================================================ homepage: "https://openjdk.org/projects/code-tools/jmh/" language: jvm main_repo: "https://github.com/openjdk/jmh" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jmh/src/main/java/ossfuzz/OptionsBuilderFuzzer.java ================================================ /* * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import java.util.Collection; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.results.format.ResultFormatType; import org.openjdk.jmh.runner.BenchmarkListEntry; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.openjdk.jmh.runner.options.TimeValue; import org.openjdk.jmh.runner.options.VerboseMode; import org.openjdk.jmh.runner.options.WarmupMode; import org.openjdk.jmh.util.Optional; public class OptionsBuilderFuzzer { FuzzedDataProvider m_fuzzedDataProvider; Optional optionalInt() { if (m_fuzzedDataProvider.consumeBoolean()) { return Optional.of(m_fuzzedDataProvider.consumeInt(1, 1000)); } else { return Optional.none(); } } int[] intArray() { int retval[] = new int[m_fuzzedDataProvider.consumeInt(1,1000)]; for (int i=0; i stringCollection() { ArrayList s = new ArrayList(); int n = m_fuzzedDataProvider.consumeInt(1,10); for (int i = 0; i < n; ++i) { s.add(m_fuzzedDataProvider.consumeString(16)); } return s; } Optional> optionalStringCollection() { if (m_fuzzedDataProvider.consumeBoolean()) { return Optional.>of(stringCollection()); } else { return Optional.>none(); } } TimeValue timeValue() { return TimeValue.seconds(m_fuzzedDataProvider.consumeInt()); } Optional optionalTimeValue() { if (m_fuzzedDataProvider.consumeBoolean()) { return Optional.of(timeValue()); } else { return Optional.none(); } } VerboseMode verboseModeValue() { VerboseMode modes[] = VerboseMode.values(); return modes[m_fuzzedDataProvider.consumeInt(0, modes.length - 1)]; } ResultFormatType resultFormatValue() { switch(m_fuzzedDataProvider.consumeInt(0,4)) { case 0: return ResultFormatType.TEXT; case 1: return ResultFormatType.CSV; case 2: return ResultFormatType.SCSV; case 3: return ResultFormatType.JSON; default: return ResultFormatType.LATEX; } } WarmupMode warmupModeValue() { WarmupMode warmupModes[] = WarmupMode.values(); return warmupModes[m_fuzzedDataProvider.consumeInt(0, warmupModes.length - 1)]; } Mode modeValue() { Mode modes[] = Mode.values(); return modes[m_fuzzedDataProvider.consumeInt(0, modes.length - 1)]; } TimeUnit timeUnitValue() { TimeUnit tu[] = TimeUnit.values(); return tu[m_fuzzedDataProvider.consumeInt(0, tu.length - 1)]; } OptionsBuilderFuzzer(FuzzedDataProvider fuzzedDataProvider) { m_fuzzedDataProvider = fuzzedDataProvider; } String stringValue() { return m_fuzzedDataProvider.consumeString(16); } boolean boolValue() { return m_fuzzedDataProvider.consumeBoolean(); } int intValue() { return m_fuzzedDataProvider.consumeInt(); } void test() { try { Options options = new OptionsBuilder() .exclude(stringValue()) .output(stringValue()) .resultFormat(resultFormatValue()) .result(stringValue()) .shouldDoGC(boolValue()) .verbosity(verboseModeValue()) .shouldFailOnError(boolValue()) .threads(intValue()) .threadGroups(intArray()) .syncIterations(boolValue()) .warmupIterations(intValue()) .warmupBatchSize(intValue()) .warmupTime(timeValue()) .warmupMode(warmupModeValue()) .includeWarmup(stringValue()) .measurementIterations(intValue()) .measurementTime(timeValue()) .measurementBatchSize(intValue()) .mode(modeValue()) .timeUnit(timeUnitValue()) .operationsPerInvocation(intValue()) .forks(intValue()) .warmupForks(intValue()) .jvm(stringValue()) .jvmArgs(stringValue()) .jvmArgsAppend(stringValue()) .jvmArgsPrepend(stringValue()) .timeout(timeValue()) .build(); } catch (IllegalArgumentException e) { /* ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { OptionsBuilderFuzzer closure = new OptionsBuilderFuzzer(fuzzedDataProvider); closure.test(); } } ================================================ FILE: projects/joblib/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/joblib/joblib joblib COPY *.sh *py $SRC/ WORKDIR $SRC/joblib ================================================ FILE: projects/joblib/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/joblib/fuzz_serialization_roundtrip.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import joblib import traceback def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) fuzz_filename = '/tmp/file_to_load' with open(fuzz_filename, 'wb') as fuzz_file: fuzz_file.write(data) try: loaded_obj = joblib.load(fuzz_filename) except Exception as e: tb = ''.join(traceback.TracebackException.from_exception(e).format()) if "pickle.py" in tb: # Ignore exceptions thrown from the pickle level. return raise e # Anything loadable should be dumpable joblib.dump(loaded_obj, '/tmp/file_to_dump') def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/joblib/project.yaml ================================================ homepage: https://github.com/joblib/joblib main_repo: https://github.com/joblib/joblib language: python fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/joda-convert/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:latest RUN apt-get update && apt-get install -y openjdk-21-jdk make autoconf automake libtool wget RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && unzip maven.zip -d $SRC/maven && rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/JodaOrg/joda-convert.git joda-convert COPY build.sh $SRC/ COPY *.java $SRC/ WORKDIR $SRC/joda-convert ================================================ FILE: projects/joda-convert/FromStringFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.joda.convert.*; import java.io.*; import java.util.*; import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class FromStringFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ StringConvert.INSTANCE.convertFromString(Integer.class, data.consumeRemainingAsString()); } catch (java.lang.NumberFormatException e){} catch (java.lang.IllegalArgumentException e){} } } ================================================ FILE: projects/joda-convert/StringConvertFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.joda.convert.StringConvert; import org.joda.convert.factory.ByteObjectArrayStringConverterFactory; import java.util.Arrays; public class StringConvertFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try{ StringConvert test = new StringConvert(data.consumeBoolean(), ByteObjectArrayStringConverterFactory.INSTANCE); Byte[] array = test.convertFromString(Byte[].class, data.consumeRemainingAsString()); test.convertToString(array); test.convertToString(Byte[].class, array); test.convertFromString(Byte[].class, test.convertToString(array)); } catch (java.lang.NumberFormatException e){} catch (java.lang.IllegalArgumentException e){} } } ================================================ FILE: projects/joda-convert/ToStringFuzzer.java ================================================ // Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import org.joda.convert.*; import java.io.*; import java.util.*; import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ToStringFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { StringConvert.INSTANCE.convertToString(data.consumeRemainingAsBytes()); } } ================================================ FILE: projects/joda-convert/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export JAVA_HOME="$OUT/open-jdk-21" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip "/usr/lib/jvm/java-21-openjdk-amd64/" "$JAVA_HOME" # Skip ProGuard because it is only needed for tests (which are skipped as well) and # because it would fail since `jmods` JDK folder is removed from this Docker image MAVEN_ARGS="-Dpropguard.skip -DskipTests -Dmaven.javadoc.skip=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True -DbannedDependencies.includes.include=org.apache.maven:maven-embedder:jar:4.0.0-alpha-13-SNAPSHOT" $MVN clean package $MAVEN_ARGS org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) find ./ -name "joda-convert-$CURRENT_VERSION.jar" -exec mv {} $OUT/joda-convert.jar \; ALL_JARS="joda-convert.jar" BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-21/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-21/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/joda-convert/project.yaml ================================================ homepage: "https://github.com/JodaOrg/joda-convert" language: jvm primary_contact: "irali@google.com" main_repo: "https://github.com/JodaOrg/joda-convert.git" file_github_issue: false fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/joda-time/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone https://github.com/JodaOrg/joda-time.git --depth 1 WORKDIR joda-time COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/joda-time/TimeFuzzer.java ================================================ import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.joda.time.*; public class TimeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { DateTimeZone.forID(data.consumeRemainingAsString()); } catch (IllegalArgumentException e) {} return; } } ================================================ FILE: projects/joda-time/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed -i 's/1.5 $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/joda-time/project.yaml ================================================ homepage: "https://github.com/JodaOrg/joda-time" language: jvm primary_contact: "scolebourne@joda.org" fuzzing_engines: - libfuzzer main_repo: "https://github.com/JodaOrg/joda-time.git" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jolt/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/bazaarvoice/jolt/ jolt COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jolt ================================================ FILE: projects/jolt/JsonUtilsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.bazaarvoice.jolt.JsonUtils; import com.bazaarvoice.jolt.exception.JsonUnmarshalException; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.ByteArrayInputStream; import java.nio.charset.Charset; // jvm-autofuzz-heuristics-1 public class JsonUtilsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Heuristic name: jvm-autofuzz-heuristics-1 Integer choice = data.consumeInt(1, 9); try { switch (choice) { case 1: JsonUtils.javason(data.consumeRemainingAsString()); break; case 2: JsonUtils.jsonToObject( data.consumeRemainingAsString(), Charset.defaultCharset().toString()); break; case 3: JsonUtils.jsonToObject(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; case 4: JsonUtils.jsonToMap(data.consumeRemainingAsString()); break; case 5: JsonUtils.jsonToMap(data.consumeRemainingAsString(), Charset.defaultCharset().toString()); break; case 6: JsonUtils.jsonToMap(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; case 7: JsonUtils.jsonToList(data.consumeRemainingAsString()); break; case 8: JsonUtils.jsonToList( data.consumeRemainingAsString(), Charset.defaultCharset().toString()); break; case 9: JsonUtils.jsonToList(new ByteArrayInputStream(data.consumeRemainingAsBytes())); break; default: break; } } catch (JsonUnmarshalException e) { // Known exception } } } ================================================ FILE: projects/jolt/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export TARGET_PACKAGE_PREFIX="com.bazaarvoice.jolt." MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15 --update-snapshots" $MVN clean -pl "!cli,!guice" package $MAVEN_ARGS BUILD_CLASSPATH= RUNTIME_CLASSPATH= for JARFILE in $(find ./ -name *.jar) do cp $JARFILE $OUT/ BUILD_CLASSPATH=$BUILD_CLASSPATH$OUT/$(basename $JARFILE): RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH\$this_dir/$(basename $JARFILE): done # Retrieve apache-common-lang3 library # This library provides method to translate primitive type arrays to # their respective class object arrays to avoid compilation error. wget -P $OUT/ https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar wget -P $OUT/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.15.2/jackson-databind-2.15.2.jar wget -P $OUT/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.15.2/jackson-core-2.15.2.jar wget -P $OUT/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.15.2/jackson-annotations-2.15.2.jar BUILD_CLASSPATH=$BUILD_CLASSPATH:$JAZZER_API_PATH:$OUT/commons-lang3-3.12.0.jar:$OUT/jackson-databind-2.15.2.jar:$OUT/jackson-core-2.15.2.jar:$OUT/jackson-annotations-2.15.2.jar RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH:\$this_dir/commons-lang3-3.12.0.jar:\$this_dir/jackson-databind-2.15.2.jar:\$this_dir/jackson-core-2.15.2.jar:\$this_dir/jackson-annotations-2.15.2.jar:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jolt/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/bazaarvoice/jolt language: jvm main_repo: https://github.com/bazaarvoice/jolt sanitizers: - address vendor_ccs: - arthur.chan@adalogics.com - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/joni/AddrListFixFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.joni.Regex; import org.joni.Syntax; import org.joni.UnsetAddrList; import org.joni.exception.InternalException; import org.joni.exception.SyntaxException; import org.jcodings.exception.CharacterPropertyException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-2 // Heuristic name: jvm-autofuzz-heuristics-2 // Target method: [org.joni.UnsetAddrList] public void fix(org.joni.Regex) public class AddrListFixFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { UnsetAddrList obj = new UnsetAddrList(data.consumeInt(0, 1000)); try { obj.fix(new Regex(data.consumeRemainingAsString())); } catch (SyntaxException | CharacterPropertyException | InternalException | IllegalArgumentException e) { } } } ================================================ FILE: projects/joni/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/jruby/joni joni COPY *.sh *.java $SRC/ WORKDIR $SRC/joni ================================================ FILE: projects/joni/RegexMatcherFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.joni.Matcher; import org.joni.Regex; import org.joni.Syntax; import org.joni.exception.InternalException; import org.joni.exception.SyntaxException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-2 // Heuristic name: jvm-autofuzz-heuristics-2 // Target method: [org.joni.Regex] public org.joni.Matcher matcher(byte[],int,int) public class RegexMatcherFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { Integer int1 = data.consumeInt(); Integer int2 = data.consumeInt(); Regex obj = new Regex(data.consumeString(data.remainingBytes() / 2)); obj.matcher(data.consumeRemainingAsBytes(), int1, int2); } catch (SyntaxException | InternalException | IllegalArgumentException e) { } } } ================================================ FILE: projects/joni/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false dependency:copy-dependencies JARFILE_LIST= for JARFILE in $(find ./target -name *.jar) do cp $JARFILE $OUT/ JARFILE_LIST="$JARFILE_LIST$(basename $JARFILE) " done curr_dir=$PWD rm -rf $OUT/jar_temp mkdir $OUT/jar_temp cd $OUT/jar_temp for JARFILE in $JARFILE_LIST do jar -xf $OUT/$JARFILE done cd $curr_dir BUILD_CLASSPATH=$JAZZER_API_PATH:$OUT/jar_temp RUNTIME_CLASSPATH=\$this_dir/jar_temp:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/joni/project.yaml ================================================ homepage: https://github.com/jruby/joni main_repo: https://github.com/jruby/joni language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jooq/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip RUN curl -L https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_linux-x64_bin.tar.gz -o jdk.tar.gz && \ tar zxf jdk.tar.gz && \ rm -rf jdk.tar.gz RUN curl -L https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip -o protoc.zip && mkdir -p $SRC/protoc && unzip protoc.zip -d $SRC/protoc && rm -rf protoc.zip ENV MVN $SRC/maven/apache-maven-3.9.2/bin/mvn ENV JAVA_HOME="$SRC/jdk-21.0.2" ENV PATH="$JAVA_HOME/bin:$SRC/protoc/bin:$PATH" RUN git clone --depth 1 https://github.com/jOOQ/jOOQ.git jooq COPY *.sh *.java $SRC/ WORKDIR $SRC/jooq ================================================ FILE: projects/jooq/GenerationToolFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jooq.codegen.GeneratorException; import org.jooq.codegen.GenerationTool; import org.jooq.exception.ConfigurationException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [org.jooq.codegen.GenerationTool] public static void generate(java.lang.String) throws java.lang.Exception public class GenerationToolFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) throws Exception { try { GenerationTool.generate(data.consumeRemainingAsString()); } catch (ConfigurationException | GeneratorException e) { // Known exception } } } ================================================ FILE: projects/jooq/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## chmod +x $SRC/protoc/bin/protoc $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True -pl jOOQ -pl jOOQ-meta -pl jOOQ-codegen \ dependency:copy-dependencies CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "./jOOQ/target/jooq-$CURRENT_VERSION.jar" $OUT/jooq.jar cp "./jOOQ-meta/target/jooq-meta-$CURRENT_VERSION.jar" $OUT/jooq-meta.jar cp "./jOOQ-codegen/target/jooq-codegen-$CURRENT_VERSION.jar" $OUT/jooq-codegen.jar JARFILE_LIST= for JARFILE in $(find ./*/target/dependency -name *.jar) do cp $JARFILE $OUT/ JARFILE_LIST="$JARFILE_LIST$(basename $JARFILE) " done curr_dir=$(pwd) rm -rf $OUT/jar_temp mkdir $OUT/jar_temp cd $OUT/jar_temp for JARFILE in $JARFILE_LIST do jar -xf $OUT/$JARFILE done cd $curr_dir ALL_JARS='jooq.jar jooq-meta.jar jooq-codegen.jar' # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH:$OUT/jar_temp # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir:\$this_dir/jar_temp cp -r $JAVA_HOME $OUT/ for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) $JAVA_HOME/bin/javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi export JAVA_HOME=\$this_dir/$(basename $JAVA_HOME) export LD_LIBRARY_PATH="\$JAVA_HOME/lib/server":\$this_dir export PATH=\$JAVA_HOME/bin:\$PATH \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jooq/project.yaml ================================================ homepage: https://github.com/jOOQ/jOOQ.git main_repo: https://github.com/jOOQ/jOOQ.git language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jopt-simple/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.6.3 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.6.3/apache-maven-3.6.3/bin/mvn WORKDIR ${SRC} # # clone repository # RUN git clone "https://github.com/jopt-simple/jopt-simple.git" # Add pom.xml before copying ADD pom.xml ${SRC}/jopt-simple/ ADD build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/jopt-simple ================================================ FILE: projects/jopt-simple/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="-DskipTests" ALL_JARS="" LIBRARY_NAME="jopt-simple" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/${LIBRARY_NAME}" # Compile and package the project ${MVN} clean package ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) # Log contents of target directory for debug echo "Contents of target directory:" ls target/ # Directly hard code the target jar name based on existing listing TARGET_JAR="target/jopt-simple-fuzzer-${CURRENT_VERSION}.jar" if [[ ! -f "$TARGET_JAR" ]]; then echo "ERROR: Expected target jar not found!" exit 1 fi # Log the found jar echo "Target jar found: $TARGET_JAR" # Install the jar ${MVN} ${MVN_FLAGS} install:install-file -Dfile=${TARGET_JAR} \ -DgroupId="net.sf.jopt-simple" \ -DartifactId="jopt-simple" \ -Dversion="${CURRENT_VERSION}" \ -Dpackaging=jar # Execute second Maven command in correct directory ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v ${TARGET_JAR} ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" # Ensure `OptionParserFuzzer` is included in classpath FUZZER_CLASSPATH="$OUT/jopt-simple-fuzzer-${CURRENT_VERSION}.jar:$JAZZER_API_PATH" for fuzzer in $(find ${SRC}/src/main/java/ossfuzz -name '*.java'); do # Compile fuzzer into jar if not present javac -cp $FUZZER_CLASSPATH -d $OUT $fuzzer || echo "Compilation of $fuzzer failed" done popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|'); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"\$@\"" > $OUT/$(basename -s .java $fuzzer).sh chmod +x $OUT/$(basename -s .java $fuzzer).sh done ================================================ FILE: projects/jopt-simple/pom.xml ================================================ 4.0.0 ossfuzz jopt-simple-fuzzer ${fuzzedLibaryVersion} jar 17 17 UTF-8 6.0-alpha-3 ossfuzz.OptionParserFuzzer com.code-intelligence jazzer-api 0.12.0 net.sf.jopt-simple jopt-simple ${fuzzedLibaryVersion} org.junit.jupiter junit-jupiter-api 5.8.1 test org.junit.jupiter junit-jupiter-engine 5.8.1 test org.junit.jupiter junit-jupiter-params 5.8.1 test org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/jopt-simple/project.yaml ================================================ homepage: "http://jopt-simple.github.io/jopt-simple/" language: jvm main_repo: "https://github.com/jopt-simple/jopt-simple.git" fuzzing_engines: - libfuzzer sanitizers: - address disabled: true vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jopt-simple/src/main/java/ossfuzz/OptionParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionException; import java.util.Date; import java.util.ArrayList; public class OptionParserFuzzer { private FuzzedDataProvider fuzzedDataProvider; public OptionParserFuzzer(FuzzedDataProvider fuzzedDataProvider) { this.fuzzedDataProvider = fuzzedDataProvider; } void test() { try { OptionParser parser = new OptionParser(); var list = new ArrayList(); for (int i = 0; i < fuzzedDataProvider.consumeInt(0, 10); i ++) { list.add(fuzzedDataProvider.consumeString(100)); } parser.accepts(fuzzedDataProvider.consumeString(100)).withOptionalArg().ofType(Integer.class); parser.accepts(fuzzedDataProvider.consumeString(100)).withOptionalArg().ofType(Boolean.class); parser.accepts(fuzzedDataProvider.consumeString(100)).withOptionalArg().ofType(String.class); parser.accepts(fuzzedDataProvider.consumeString(100)).withOptionalArg().ofType(Float.class); parser.accepts(fuzzedDataProvider.consumeString(100)).withOptionalArg().ofType(Date.class); parser.accepts(fuzzedDataProvider.consumeString(100)); parser.acceptsAll(list); parser.parse(fuzzedDataProvider.consumeRemainingAsString()); } catch (IllegalArgumentException e) { } catch (OptionException e) { } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) { OptionParserFuzzer fixture = new OptionParserFuzzer(fuzzedDataProvider); fixture.test(); } } ================================================ FILE: projects/jose4j/.gitignore ================================================ project-parent/jose4j project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/jose4j/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/json.dict $SRC/JsonUtilFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JsonUtilFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/jose4j RUN git clone --depth 1 https://bitbucket.org/b_c/jose4j/src/master/ $SRC/project-parent/jose4j COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/jose4j/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=jose4j PROJECT_GROUP_ID=org.bitbucket.b_c PROJECT_ARTIFACT_ID=jose4j MAIN_REPOSITORY=https://bitbucket.org/b_c/jose4j/src/master/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/jose4j/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.bitbucket.b_c jose4j Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/jose4j/project-parent/fuzz-targets/src/test/java/com/example/JsonUtilFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import org.jose4j.json.JsonUtil; import org.jose4j.lang.JoseException; import java.util.*; import java.io.Serializable; import java.text.ParseException; import java.text.SimpleDateFormat; public class JsonUtilFuzzer { @FuzzTest public void myFuzzTest(FuzzedDataProvider data) { String json = data.consumeRemainingAsString(); try { JsonUtil.parseJson(json); } catch (JoseException e) { } } } ================================================ FILE: projects/jose4j/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom jose4j fuzz-targets ================================================ FILE: projects/jose4j/project.yaml ================================================ homepage: "https://bitbucket.org/b_c/jose4j/wiki/Home" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://bitbucket.org/b_c/jose4j/src/master/" sanitizers: - address primary_contact: "brian.d.campbell@gmail.com" vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jpeg-js/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/jpeg-js/jpeg-js COPY fuzz_encode.js $SRC/jpeg-js COPY fuzz_decode.js $SRC/jpeg-js WORKDIR $SRC/jpeg-js ================================================ FILE: projects/jpeg-js/build.sh ================================================ #!/bin/bash # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ npm install --save-dev @jazzer.js/core npm i # Build Fuzzers. compile_javascript_fuzzer jpeg-js fuzz_encode.js -i jpeg-js --sync compile_javascript_fuzzer jpeg-js fuzz_decode.js -i jpeg-js --sync ================================================ FILE: projects/jpeg-js/fuzz_decode.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const jpeg = require("./index"); module.exports.fuzz = function (data) { const provider = new FuzzedDataProvider(data); try { jpeg.decode(provider.consumeBytes(provider.consumeIntegralInRange(0, 2**48-1)), {useTArray: provider.consumeBoolean(), colorTransform: provider.consumeBoolean(), formatAsRGBA: provider.consumeBoolean(), tolerantDecoding: provider.consumeBoolean()} ); } catch (error) { // Catch all errors to find more critical bugs. } }; ================================================ FILE: projects/jpeg-js/fuzz_encode.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const jpeg = require("./index"); module.exports.fuzz = function (data) { const provider = new FuzzedDataProvider(data); var width = provider.consumeIntegralInRange(0, 2**48-1), height = provider.consumeIntegralInRange(0, 2**48-1), quality = provider.consumeIntegralInRange(0, 2**48-1); var frameData = provider.consumeRemainingAsBytes(); var rawImageData = { data: frameData, width: width, height: height, }; try { var jpegImageData = jpeg.encode(rawImageData, quality); } catch (error) { // Catch all errors to find critical bugs. } }; ================================================ FILE: projects/jpeg-js/project.yaml ================================================ homepage: https://github.com/jpeg-js/jpeg-js language: javascript main_repo: https://github.com/jpeg-js/jpeg-js fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jpegoptim/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder ENV DEBIAN_FRONTEND=noninteractive ENV ASAN_OPTIONS=detect_leaks=0 RUN apt update && apt install -y cmake make RUN git clone --depth 1 https://github.com/tjko/jpegoptim.git jpegoptim \ && cp jpegoptim/fuzz/build.sh $SRC/ RUN for script in jpegoptim/fuzz/libjpeg_builders/*.sh; do \ bash "$script"; \ done WORKDIR jpegoptim ================================================ FILE: projects/jpegoptim/project.yaml ================================================ homepage: "https://www.kokkonen.net/tjko/projects.html" language: c primary_contact: "tjko@iki.com" auto_ccs: - "capuanobailey@gmail.com" main_repo: "https://github.com/tjko/jpegoptim.git" fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/jq/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ make flex bison libtool automake autoconf RUN git clone --depth 1 https://github.com/jqlang/jq WORKDIR $SRC/jq COPY run_tests.sh build.sh *.dict $SRC/ ================================================ FILE: projects/jq/build.sh ================================================ #!/bin/bash -eu # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ git submodule init git submodule update autoreconf -fi ./configure --with-oniguruma=builtin make -j$(nproc) $CC $CFLAGS -c tests/jq_fuzz_parse.c \ -I./src -o ./jq_fuzz_parse.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./jq_fuzz_parse.o \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_parse -I./src $CC $CFLAGS -c tests/jq_fuzz_compile.c \ -I./src -o ./jq_fuzz_compile.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./jq_fuzz_compile.o \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_compile -I./src $CC $CFLAGS -c tests/jq_fuzz_load_file.c \ -I./src -o ./jq_fuzz_load_file.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./jq_fuzz_load_file.o \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_load_file -I./src $CC $CFLAGS -c tests/jq_fuzz_parse_extended.c \ -I./src -o ./jq_fuzz_parse_extended.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./jq_fuzz_parse_extended.o \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_parse_extended -I./src $CC $CFLAGS -c tests/jq_fuzz_parse_stream.c \ -I./src -o ./jq_fuzz_parse_stream.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./jq_fuzz_parse_stream.o \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_parse_stream -I./src $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./tests/jq_fuzz_execute.cpp \ -I./src -I./vendor/oniguruma/src \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a\ -o $OUT/jq_fuzz_execute -I./src $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./tests/jq_fuzz_fixed.cpp \ -I./src \ ./.libs/libjq.a ./vendor/oniguruma/src/.libs/libonig.a \ -o $OUT/jq_fuzz_fixed -I./src # Build corpus mkdir $SRC/seeds find . -name "*.jq" -exec cp {} $SRC/seeds/ \; zip -rj $OUT/jq_fuzz_execute_seed_corpus.zip $SRC/seeds/ # Copy dictionary cp $SRC/jq.dict $OUT/jq_fuzz_execute.dict ================================================ FILE: projects/jq/jq.dict ================================================ "acos" "acosh" "add" "all" "any" "arrays" "ascii_downcase" "ascii_upcase" "asin" "asinh" "atan" "atan2" "atanh" "booleans" "bsearch" "builtins" "capture" "cbrt" "ceil" "combinations" "contains" "copysign" "cos" "cosh" "debug" "del" "delpaths" "drem" "empty" "endswith" "env" "erf" "erfc" "error" "error" "exp" "exp10" "exp2" "explode" "expm1" "fabs" "fdim" "finites" "first" "first" "flatten" "floor" "fma" "fmax" "fmin" "fmod" "format" "frexp" "fromdate" "fromdateiso8601" "from_entries" "fromjson" "fromstream" "gamma" "get_jq_origin" "getpath" "get_prog_origin" "get_search_list" "gmtime" "group_by" "gsub" "halt" "halt_error" "halt_error" "has" "hypot" "implode" "in" "IN" "index" "INDEX" "indices" "infinite" "input" "input_filename" "input_line_number" "inputs" "inside" "isempty" "isfinite" "isinfinite" "isnan" "isnormal" "iterables" "j0" "j1" "jn" "join" "JOIN" "keys" "keys_unsorted" "last" "last" "ldexp" "leaf_paths" "length" "lgamma" "lgamma_r" "limit" "localtime" "log" "log10" "log1p" "log2" "logb" "ltrimstr" "map" "map_values" "match" "max" "max_by" "min" "min_by" "mktime" "modf" "modulemeta" "nan" "nearbyint" "nextafter" "nexttoward" "normals" "not" "now" "nth" "nth" "nulls" "numbers" "objects" "path" "paths" "pow" "pow10" "range" "range" "range" "recurse" "recurse_down" "remainder" "repeat" "reverse" "rindex" "rint" "round" "rtrimstr" "scalars" "scalars_or_empty" "scalb" "scalbln" "scan" "select" "setpath" "significand" "sin" "sinh" "sort" "sort_by" "split" "split" "splits" "sqrt" "startswith" "stderr" "strflocaltime" "strftime" "strings" "strptime" "sub" "tan" "tanh" "test" "tgamma" "todate" "todateiso8601" "to_entries" "tojson" "tonumber" "tostream" "tostring" "transpose" "trunc" "truncate_stream" "type" "unique" "unique_by" "until" "utf8bytelength" "values" "walk" "while" "with_entries" "y0" "y1" "yn" ================================================ FILE: projects/jq/project.yaml ================================================ homepage: "https://jqlang.github.io/jq" main_repo: "https://github.com/jqlang/jq" language: c primary_contact: "cryptonector@gmail.com" auto_ccs : - "torreemanuele6@gmail.com" - "pkoppstein@gmail.com" - "david@adalogics.com" - "mattias.wadman@gmail.com" ================================================ FILE: projects/jq/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./tests/setup && ./tests/base64test && ./tests/jq-f-test.sh && \ ./tests/jqtest && ./tests/manonigtest && ./tests/mantest && \ ./tests/onigtest && ./tests/optionaltest && ./tests/uritest && \ ./tests/utf8test ================================================ FILE: projects/js-yaml/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-javascript COPY build.sh $SRC/ RUN git clone --depth 1 https://github.com/nodeca/js-yaml COPY fuzz.js $SRC/js-yaml WORKDIR $SRC/js-yaml ================================================ FILE: projects/js-yaml/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install dependencies. npm install npm install --save-dev @jazzer.js/core # Build Fuzzers. compile_javascript_fuzzer js-yaml fuzz.js -i js-yaml --sync ================================================ FILE: projects/js-yaml/fuzz.js ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// const { FuzzedDataProvider } = require('@jazzer.js/core'); const yaml = require('./index'); module.exports.fuzz = function(data) { const provider = new FuzzedDataProvider(data); const loadOptions = generateRandomLoadOptions(provider); const dumpOptions = generateRandomDumpOptions(provider); const yamlString = provider.consumeRemainingAsString(); try { const parsedYaml = yaml.load(yamlString, loadOptions); const _serializedYaml = yaml.dump(parsedYaml, dumpOptions); } catch (e) { if (!(e instanceof yaml.YAMLException)) { throw e } } }; function generateRandomLoadOptions(provider) { const options = {}; options.schema = getSchema(provider.consumeIntegralInRange(0, 3)); options.json = provider.consumeBoolean(); return options; } function generateRandomDumpOptions(provider) { const options = {}; options.indent = provider.consumeIntegralInRange(0, 4096); options.skipInvalid = provider.consumeBoolean(); options.flowLevel = provider.consumeIntegralInRange(-1, 100); options.schema = getSchema(provider.consumeIntegralInRange(0, 3)); options.sortKeys = provider.consumeBoolean(); options.lineWidth = provider.consumeIntegralInRange(0, 4096); options.noRefs = provider.consumeBoolean(); options.noCompatMode = provider.consumeBoolean(); options.condenseFlow = provider.consumeBoolean(); options.forceQuotes = provider.consumeBoolean(); return options; } function getSchema(number) { switch (number) { case 0: return yaml.DEFAULT_SCHEMA case 1: return yaml.FAILSAFE_SCHEMA case 2: return yaml.JSON_SCHEMA case 3: return yaml.CORE_SCHEMA } } ================================================ FILE: projects/js-yaml/project.yaml ================================================ homepage: https://github.com/nodeca/js-yaml language: javascript main_repo: https://github.com/nodeca/js-yaml fuzzing_engines: - libfuzzer sanitizers: - none vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jsc/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool python ruby ninja-build bison flex gperf wget RUN git clone --depth 1 https://github.com/WebKit/WebKit.git RUN wget https://github.com/unicode-org/icu/releases/download/release-74-1/icu4c-74_1-src.tgz && tar xzvf icu4c-74_1-src.tgz WORKDIR WebKit COPY build.sh $SRC ================================================ FILE: projects/jsc/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export DEPS_PATH=/src/deps mkdir $DEPS_PATH # build ICU for linking statically. cd $SRC/icu/source ./configure --disable-shared --enable-static --disable-layoutex \ --disable-tests --disable-samples --with-data-packaging=static --prefix=$DEPS_PATH make install -j$(nproc) # Ugly ugly hack to get static linking to work for icu. cd $DEPS_PATH/lib ls *.a | xargs -n1 ar x rm *.a ar r libicu.a *.{ao,o} ln -s libicu.a libicudata.a ln -s libicu.a libicuuc.a ln -s libicu.a libicui18n.a export CFLAGS="$CFLAGS -DU_STATIC_IMPLEMENTATION" export CXXFLAGS="$CXXFLAGS -DU_STATIC_IMPLEMENTATION" export ICU_ROOT=$DEPS_PATH cd $SRC/WebKit Tools/Scripts/build-jsc \ --debug \ --jsc-only \ --cmakeargs="-DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF -DWEBKIT_LIBRARIES_DIR=$DEPS_PATH -DWEBKIT_LIBRARIES_INCLUDE_DIR=$DEPS_PATH/include -DWEBKIT_LIBRARIES_LINK_DIR=$DEPS_PATH/lib" \ --makeargs='-v' cp WebKitBuild/JSCOnly/Debug/bin/jsc $OUT ================================================ FILE: projects/jsc/project.yaml ================================================ homepage: https://webkit.org/ language: c++ primary_contact: "ddkilzer@apple.com" auto_ccs: - "mark.lam@apple.com" - "ddkilzer@apple.com" - "jfb@chromium.org" - "product-security@apple.com" - "sbarati@apple.com" - "simon.lewis@apple.com" - "ysuzuki@apple.com" - "dkishore@apple.com" - "phan@apple.com" - "ebanniettis@apple.com" - "jm.park@apple.com" - "james_e_kim@apple.com" - "rding23@apple.com" - "albassam@apple.com" - "zakr@apple.com" - "roberto_rodriguez2@apple.com" - "k_monsen@apple.com" - "nnothstine@apple.com" fuzzing_engines: - none sanitizers: - address blackbox: true main_repo: 'https://github.com/WebKit/WebKit.git' ================================================ FILE: projects/jsch/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # # install maven configuration, which is also used by gradles's publishToMavenLocal # ADD maven-settings.xml ${SRC}/ RUN apt-get update && apt-get install -y xmlstarlet curl unzip zip \ && mkdir -p ~/.m2 \ && xmlstarlet ed -u "settings/localRepository" -v "${OUT}/m2/repository" "${SRC}/maven-settings.xml" > ~/.m2/settings.xml # # install maven and gradle # RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.zip -o maven.zip \ && unzip maven.zip -d $SRC/maven-3.9.11 \ && rm -rf maven.zip ENV MVN=$SRC/maven-3.9.11/apache-maven-3.9.11/bin/mvn RUN curl -L https://services.gradle.org/distributions/gradle-7.6-bin.zip -o gradle.zip \ && unzip gradle.zip -d $SRC/gradle \ && rm -rf gradle.zip ENV GRADLE=$SRC/gradle/gradle-7.6/bin/gradle ENV LIBRARY_NAME=jsch WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/mwiede/jsch ${LIBRARY_NAME} # # Install SDKMAN! and use it to install the required JDK version # RUN curl -s "https://get.sdkman.io" | bash && \ /bin/bash -c "source /root/.sdkman/bin/sdkman-init.sh && \ sdk install java 24.0.1-open && \ sdk use java 24.0.1-open" ENV JAVA_HOME=/root/.sdkman/candidates/java/current ENV PATH="$JAVA_HOME/bin:$PATH" ADD build.sh ${SRC}/ ADD ${LIBRARY_NAME}-fuzzer ${SRC}/${LIBRARY_NAME}-fuzzer/ WORKDIR ${SRC}/${LIBRARY_NAME} ================================================ FILE: projects/jsch/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SRC_SUBDIR="" MVN_FLAGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.14.0" \ -Dpackaging=jar popd pushd "${SRC}/${LIBRARY_NAME}/${SRC_SUBDIR}" ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}-fuzzer" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/jsch/jsch-fuzzer/pom.xml ================================================ 4.0.0 ossfuzz jsch-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 0.2.7 com.sun.xml.rpc.processor.modeler.rmi.SOAPSimpleTypeCreatorFuzzer com.code-intelligence jazzer-api 0.14.0 com.github.mwiede jsch ${fuzzedLibaryVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/jsch/jsch-fuzzer/src/main/java/com/jcraft/jsch/OpenSSHConfigFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.jcraft.jsch; import java.io.IOException; import java.nio.ByteBuffer; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.jcraft.jsch.OpenSSHConfig; public class OpenSSHConfigFuzzer { private FuzzedDataProvider fuzzedDataProvider; public OpenSSHConfigFuzzer(FuzzedDataProvider fuzzedDataProvider) throws Exception { this.fuzzedDataProvider = fuzzedDataProvider; } void test() { try { OpenSSHConfig config = OpenSSHConfig.parse(fuzzedDataProvider.consumeRemainingAsString()); } catch (IOException exception) { /* ignore */ } catch (IllegalArgumentException excepion) { /* ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { OpenSSHConfigFuzzer fixture = new OpenSSHConfigFuzzer(fuzzedDataProvider); fixture.test(); } } ================================================ FILE: projects/jsch/maven-settings.xml ================================================ ${user.home}/.m2/repository ================================================ FILE: projects/jsch/project.yaml ================================================ homepage: "https://github.com/mwiede/jsch" language: jvm main_repo: "https://github.com/mwiede/jsch" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jsemver/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/zafarkhaja/jsemver jsemver COPY *.sh *.java $SRC/ WORKDIR $SRC/jsemver ================================================ FILE: projects/jsemver/VersionFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.github.zafarkhaja.semver.Version; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-1 // Heuristic name: jvm-autofuzz-heuristics-1 // Target method: [com.github.zafarkhaja.semver.Version] public static boolean isValid(java.lang.String) public class VersionFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Version.isValid(data.consumeRemainingAsString()); } } ================================================ FILE: projects/jsemver/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/java-semver-$CURRENT_VERSION.jar" $OUT/jsemver.jar ALL_JARS="jsemver.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar --cp=$RUNTIME_CLASSPATH --target_class=$fuzzer_basename --jvm_args="\$mem_settings" \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jsemver/project.yaml ================================================ homepage: https://github.com/zafarkhaja/jsemver main_repo: https://github.com/zafarkhaja/jsemver language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/jsign/AuthenticodeAppxSignerFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.security.KeyStore; import net.jsign.AuthenticodeSigner; import net.jsign.appx.APPXFile; public class AuthenticodeAppxSignerFuzzer { public static void fuzzerTestOneInput(byte[] data) throws Exception { File file = File.createTempFile("jsign-fuzzer", "msix"); file.deleteOnExit(); Files.write(file.toPath(), data); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("keystore.jks"), "password".toCharArray()); try { AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "password").withTimestamping(false); signer.sign(new APPXFile(file)); } catch (IOException e) { // expected } } } ================================================ FILE: projects/jsign/AuthenticodeCabSignerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.security.KeyStore; import net.jsign.AuthenticodeSigner; import net.jsign.mscab.MSCabinetFile; public class AuthenticodeCabSignerFuzzer { public static void fuzzerTestOneInput(byte[] data) throws Exception { File file = File.createTempFile("jsign-fuzzer", "cab"); file.deleteOnExit(); Files.write(file.toPath(), data); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("keystore.jks"), "password".toCharArray()); try { AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "password").withTimestamping(false); signer.sign(new MSCabinetFile(file)); } catch (IOException e) { // expected } } } ================================================ FILE: projects/jsign/AuthenticodeExeSignerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.security.KeyStore; import net.jsign.AuthenticodeSigner; import net.jsign.pe.PEFile; public class AuthenticodeExeSignerFuzzer { public static void fuzzerTestOneInput(byte[] data) throws Exception { File file = File.createTempFile("jsign-fuzzer", "exe"); file.deleteOnExit(); Files.write(file.toPath(), data); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("keystore.jks"), "password".toCharArray()); try { AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "password").withTimestamping(false); signer.sign(new PEFile(file)); } catch (IOException e) { // expected } } } ================================================ FILE: projects/jsign/AuthenticodeMsiSignerFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.file.Files; import java.security.KeyStore; import net.jsign.AuthenticodeSigner; import net.jsign.msi.MSIFile; public class AuthenticodeMsiSignerFuzzer { public static void fuzzerTestOneInput(byte[] data) throws Exception { File file = File.createTempFile("jsign-fuzzer", "msi"); file.deleteOnExit(); Files.write(file.toPath(), data); KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("keystore.jks"), "password".toCharArray()); try { AuthenticodeSigner signer = new AuthenticodeSigner(keystore, "test", "password").withTimestamping(false); signer.sign(new MSIFile(file)); } catch (IOException | net.jsign.poi.EmptyFileException e) { // expected } } } ================================================ FILE: projects/jsign/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/ebourg/jsign.git RUN zip -j $SRC/AuthenticodeExeSignerFuzzer_seed_corpus.zip jsign/jsign-core/src/test/resources/*.exe && \ zip -j $SRC/AuthenticodeMsiSignerFuzzer_seed_corpus.zip jsign/jsign-core/src/test/resources/*.msi && \ zip -j $SRC/AuthenticodeAppxSignerFuzzer_seed_corpus.zip jsign/jsign-core/src/test/resources/*.msix && \ zip -j $SRC/AuthenticodeCabSignerFuzzer_seed_corpus.zip jsign/jsign-core/src/test/resources/mscab/*.cab COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jsign ================================================ FILE: projects/jsign/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $MVN package --projects jsign-crypto,jsign-core,jsign-cli,jsign-ant,jsign \ -DskipTests -Dmaven.javadoc.skip -Djacoco.skip -Dproguard.skip -Djapicmp.skip -Djdeb.skip -Dmaven.antrun.skip CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) cp "jsign/target/jsign-$CURRENT_VERSION.jar" $OUT/jsign.jar cp "jsign-core/src/test/resources/keystores/keystore.jks" $OUT/ cp $SRC/*seed_corpus.zip $OUT/ PROJECT_JARS="jsign.jar" # The classpath at build-time includes the project jars in $OUT as well as the Jazzer API. BUILD_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $PROJECT_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings:-Djava.awt.headless=true\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/jsign/project.yaml ================================================ homepage: "https://ebourg.github.io/jsign/" language: jvm primary_contact: "ebourg@apache.org" auto_ccs: - "emmanuel.bourg@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address main_repo: "https://github.com/ebourg/jsign.git" ================================================ FILE: projects/jsmin/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/tikitu/jsmin jsmin WORKDIR jsmin COPY build.sh *.py $SRC/ ================================================ FILE: projects/jsmin/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/jsmin/fuzz_minimize.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys from jsmin import jsmin def TestOneInput(data): with open('myfile.js', "wb") as js_file: js_file.write(data) with open('myfile.js') as js_file: try: minified = jsmin(js_file.read()) except UnicodeDecodeError: pass def main(): atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.instrument_all() atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jsmin/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/tikitu/jsmin language: python main_repo: https://github.com/tikitu/jsmin sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/json/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y binutils make RUN git clone --depth 1 -b develop https://github.com/nlohmann/json.git WORKDIR json/ COPY run_tests.sh build.sh *.options parse_afl_fuzzer.dict $SRC/ ================================================ FILE: projects/json/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make FUZZER_ENGINE="$LIB_FUZZING_ENGINE" fuzzers -Ctests FUZZER_FILES=$(find tests/ -maxdepth 1 -executable -type f) for F in $FUZZER_FILES; do cp $F $OUT/ FUZZER=$(basename $F .cpp) cp $SRC/fuzzer-parse.options $OUT/$FUZZER.options done cp $SRC/parse_afl_fuzzer.dict $OUT/ # Build unit tests mkdir build-tests pushd build-tests cmake .. make -C tests popd # Pre-download test data ctest --test-dir build-tests -R download_test_data ================================================ FILE: projects/json/fuzzer-parse.options ================================================ [libfuzzer] max_len = 456 timeout = 10 ================================================ FILE: projects/json/parse_afl_fuzzer.dict ================================================ # # AFL dictionary for JSON # ----------------------- # # Just the very basics. # # Inspired by a dictionary by Jakub Wilk # "0" ",0" ":0" "0:" "-1.2e+3" "true" "false" "null" "\"\"" ",\"\"" ":\"\"" "\"\":" "{}" ",{}" ":{}" "{\"\":0}" "{{}}" "[]" ",[]" ":[]" "[0]" "[[]]" "''" "\\" "\\b" "\\f" "\\n" "\\r" "\\t" "\\u0000" "\\x00" "\\0" "\\uD800\\uDC00" "\\uDBFF\\uDFFF" "\"\":0" "//" "/**/" ================================================ FILE: projects/json/project.yaml ================================================ homepage: "https://github.com/nlohmann/json" language: c++ primary_contact: "niels.lohmann@gmail.com" auto_ccs: - "tanujgarg@google.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/nlohmann/json.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/json/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Skip download of test data # Temporarily skip test-class_parser_cpp11 which throws exception ctest --test-dir build-tests -E "download_test_data|test-class_parser_cpp11" ================================================ FILE: projects/json-c/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone --depth 1 https://github.com/json-c/json-c.git json-c WORKDIR json-c COPY run_tests.sh build.sh *.cc *.dict $SRC/ ================================================ FILE: projects/json-c/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir json-c-build cd json-c-build cmake -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=ON .. make -j$(nproc) cd .. cp $SRC/json-c/fuzz/*.dict $OUT/ for f in $SRC/json-c/fuzz/*_fuzzer.cc; do fuzzer=$(basename "$f" _fuzzer.cc) $CXX $CXXFLAGS -std=c++17 -I$SRC/json-c -I$SRC/json-c/json-c-build\ $SRC/json-c/fuzz/${fuzzer}_fuzzer.cc -o $OUT/${fuzzer}_fuzzer \ $LIB_FUZZING_ENGINE $SRC/json-c/json-c-build/libjson-c.a done ================================================ FILE: projects/json-c/project.yaml ================================================ homepage: "https://json-c.github.io/json-c/" language: c++ primary_contact: "erh+git@nimenees.com" auto_ccs: - "chriswwolfe@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/json-c/json-c.git' ================================================ FILE: projects/json-c/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ cd json-c-build make test ================================================ FILE: projects/json-flattener/.gitignore ================================================ project-parent/json-flattener project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/json-flattener/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/json.dict $SRC/FlattenFuzzer.dict && \ cp fuzzing/dictionaries/json.dict $SRC/UnflattenFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/FlattenFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -j $SRC/UnflattenFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/json-flattener RUN git clone --depth 1 https://github.com/wnameless/json-flattener/ $SRC/project-parent/json-flattener COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/json-flattener/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=json-flattener PROJECT_GROUP_ID=com.github.wnameless.json PROJECT_ARTIFACT_ID=json-flattener MAIN_REPOSITORY=https://github.com/wnameless/json-flattener/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests -Dgpg.skip" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/json-flattener/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test com.github.wnameless.json json-flattener Fuzzing-SNAPSHOT com.google.code.gson gson 2.10.1 maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/json-flattener/project-parent/fuzz-targets/src/test/java/com/example/FlattenFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.github.wnameless.json.flattener.*; import com.github.wnameless.json.base.JsonCore; import com.github.wnameless.json.base.GsonJsonCore; import java.util.function.Consumer; class FlattenFuzzer { static PrintMode [] printModes = {PrintMode.PRETTY, PrintMode.MINIMAL}; static FlattenMode [] flattenModes = {FlattenMode.NORMAL, FlattenMode.MONGODB, FlattenMode.KEEP_ARRAYS, FlattenMode.KEEP_PRIMITIVE_ARRAYS}; static StringEscapePolicy [] stringEscapePolicies = {StringEscapePolicy.DEFAULT, StringEscapePolicy.ALL, StringEscapePolicy.ALL_BUT_SLASH, StringEscapePolicy.ALL_BUT_UNICODE, StringEscapePolicy.ALL_BUT_SLASH_AND_UNICODE}; static JsonCore [] jsonCores = {new GsonJsonCore()}; @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { JsonFlattenerFactory jsonFlattenerFactory = jsonFlattenerFactory(data.pickValue(printModes), data.pickValue(flattenModes), data.pickValue(stringEscapePolicies), data.pickValue(jsonCores)); String json = data.consumeRemainingAsString(); JsonFlattener jf = jsonFlattenerFactory.build(json); jf.flatten(); jf.flattenAsMap(); } catch (RuntimeException e) { // Need to catch it to let fuzzer find interesting findings. } } static JsonFlattenerFactory jsonFlattenerFactory(PrintMode pm, FlattenMode fm, StringEscapePolicy sep, JsonCore jc) { Consumer configurer = jf -> jf.withPrintMode(pm).withFlattenMode(fm).withStringEscapePolicy(sep); return new JsonFlattenerFactory(configurer, jc); } } ================================================ FILE: projects/json-flattener/project-parent/fuzz-targets/src/test/java/com/example/UnflattenFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import com.github.wnameless.json.flattener.*; import com.github.wnameless.json.base.JsonCore; import com.github.wnameless.json.base.GsonJsonCore; import com.github.wnameless.json.unflattener.JsonUnflattener; import com.github.wnameless.json.unflattener.JsonUnflattenerFactory; import java.util.function.Consumer; class UnflattenFuzzer { static PrintMode [] printModes = {PrintMode.PRETTY, PrintMode.MINIMAL}; static FlattenMode [] flattenModes = {FlattenMode.NORMAL, FlattenMode.MONGODB, FlattenMode.KEEP_ARRAYS, FlattenMode.KEEP_PRIMITIVE_ARRAYS}; static JsonCore [] jsonCores = {new GsonJsonCore()}; @FuzzTest void myFuzzTest(FuzzedDataProvider data) { try { JsonUnflattenerFactory jsonUnflattenerFactory = jsonUnflattenerFactory(data.pickValue(printModes), data.pickValue(flattenModes), data.pickValue(jsonCores)); String json = data.consumeRemainingAsString(); JsonUnflattener ju = jsonUnflattenerFactory.build(json); ju.unflatten(); ju.unflattenAsMap(); } catch (RuntimeException e) { // Need to catch it to let fuzzer find initeresting findings. } } static JsonUnflattenerFactory jsonUnflattenerFactory(PrintMode pm, FlattenMode fm, JsonCore jc) { Consumer configurer = ju -> ju.withPrintMode(pm).withFlattenMode(fm); return new JsonUnflattenerFactory(configurer, jc); } } ================================================ FILE: projects/json-flattener/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom json-flattener fuzz-targets ================================================ FILE: projects/json-flattener/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/wnameless/json-flattener/" language: jvm primary_contact: "wnameless@gmail.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/wnameless/json-flattener/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/json-java/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt-get update && apt-get install -y make autoconf automake libtool RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/stleary/JSON-java json-java WORKDIR json-java COPY build.sh $SRC/ COPY *.java $SRC/ ================================================ FILE: projects/json-java/JsonJavaFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.json.JSONObject; import org.json.JSONException; public class JsonJavaFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { JSONObject jo = new JSONObject(data.consumeRemainingAsString()); } catch(JSONException e) {} } } ================================================ FILE: projects/json-java/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd src/main/java javac org/json/*.java jar cf $OUT/json-java.jar org/json/*.class ALL_JARS="json-java.jar" BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir # Let's try and build a simple fuzzer. for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/json-java/project.yaml ================================================ homepage: "https://github.com/stleary/JSON-java" language: jvm primary_contact: "jsonjava060@gmail.com" main_repo: "https://github.com/stleary/JSON-java" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/json-patch/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/evanphx/json-patch RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.23.4.linux-amd64.tar.gz COPY fuzz_*.go $SRC/json-patch/ COPY build.sh $SRC/ WORKDIR $SRC/json-patch ================================================ FILE: projects/json-patch/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ compile_go_fuzzer github.com/evanphx/json-patch FuzzCreateMerge fuzz_create_merge compile_go_fuzzer github.com/evanphx/json-patch FuzzDecodeApply fuzz_decode_apply ================================================ FILE: projects/json-patch/fuzz_create_merge.go ================================================ package jsonpatch import ( "bytes" ) func FuzzCreateMerge(data []byte) int { s := bytes.Split(data, []byte{0}) if len(s) != 3 { return 0 } original := s[0] target := s[1] alternative := s[2] patch, err := CreateMergePatch(original, target) if err != nil { return 0 } _, err = MergePatch(alternative, patch) if err != nil { return 0 } return 1 } ================================================ FILE: projects/json-patch/fuzz_decode_apply.go ================================================ package jsonpatch import ( "bytes" ) func FuzzDecodeApply(data []byte) int { s := bytes.Split(data, []byte{0}) if len(s) != 2 { return 0 } patchJSON := s[0] original := s[1] patch, err := DecodePatch(patchJSON) if err != nil { return 0 } _, err = patch.Apply(original) if err != nil { return 0 } return 1 } ================================================ FILE: projects/json-patch/project.yaml ================================================ homepage: "https://github.com/evanphx/json-patch" primary_contact: "evan@phx.io" auto_ccs: - "p.antoine@catenacyber.fr" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/evanphx/json-patch' ================================================ FILE: projects/json-sanitizer/DenylistFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium; import com.google.json.JsonSanitizer; public class DenylistFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); String output; try { output = JsonSanitizer.sanitize(input, 10); } catch (ArrayIndexOutOfBoundsException e) { // ArrayIndexOutOfBoundsException is expected if nesting depth is // exceeded. return; } // Check for forbidden substrings. As these would enable Cross-Site // Scripting, treat every finding as a high severity vulnerability. assert !output.contains("") : new FuzzerSecurityIssueHigh("Output contains ]]>"); // Check for more forbidden substrings. As these would not directly enable // Cross-Site Scripting in general, but may impact script execution on the // embedding page, treat each finding as a medium severity vulnerability. assert !output.contains(" $SRC/DenylistFuzzer.dict RUN cp fuzzing/dictionaries/json.dict $SRC/IdempotenceFuzzer.dict RUN cp fuzzing/dictionaries/json.dict $SRC/ValidJsonFuzzer.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/DenylistFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -q $SRC/IdempotenceFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ zip -q $SRC/ValidJsonFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* RUN git clone --depth 1 https://github.com/OWASP/json-sanitizer COPY build.sh $SRC/ COPY DenylistFuzzer.java IdempotenceFuzzer.java ValidJsonFuzzer.java $SRC/ WORKDIR $SRC/json-sanitizer ================================================ FILE: projects/json-sanitizer/IdempotenceFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.google.json.JsonSanitizer; public class IdempotenceFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); String output; try { output = JsonSanitizer.sanitize(input, 10); } catch (ArrayIndexOutOfBoundsException e) { // ArrayIndexOutOfBoundsException is expected if nesting depth is // exceeded. return; } // Ensure that sanitizing twice does not give different output // (idempotence). Since failure to be idempotent is not a security issue in // itself, fail with a regular AssertionError. assert JsonSanitizer.sanitize(output).equals(output) : "Not idempotent"; } } ================================================ FILE: projects/json-sanitizer/ValidJsonFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.json.JsonSanitizer; public class ValidJsonFuzzer { private static Gson gson = new Gson(); public static void fuzzerTestOneInput(FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); String output; try { output = JsonSanitizer.sanitize(input, 10); } catch (ArrayIndexOutOfBoundsException e) { // ArrayIndexOutOfBoundsException is expected if nesting depth is // exceeded. return; } // Check that the output is valid JSON. Invalid JSON may crash other parts // of the application that trust the output of the sanitizer. try { Gson gson = new Gson(); gson.fromJson(output, JsonElement.class); } catch (Exception e) { throw new FuzzerSecurityIssueLow("Output is invalid JSON", e); } } } ================================================ FILE: projects/json-sanitizer/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT # Build the json-sanitizer jar. CURRENT_VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) mvn package cp "target/json-sanitizer-$CURRENT_VERSION.jar" $OUT/json-sanitizer.jar # The jar files containing the project (separated by spaces). PROJECT_JARS=json-sanitizer.jar # Get the fuzzer dependencies (gson). mvn dependency:copy -Dartifact=com.google.code.gson:gson:2.8.6 -DoutputDirectory=$OUT/ # The jar files containing further dependencies of the fuzz targets (separated # by spaces). FUZZER_JARS=gson-2.8.6.jar # Build fuzzers in $OUT. ALL_JARS="$PROJECT_JARS $FUZZER_JARS" BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All jars and class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):.:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create execution wrapper. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/json-sanitizer/project.yaml ================================================ homepage: "https://github.com/OWASP/json-sanitizer" language: jvm primary_contact: "mikesamuel@gmail.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/OWASP/json-sanitizer" sanitizers: - address vendor_ccs: - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/json-simple/.gitignore ================================================ project-parent/json-simple project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/json-simple/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing RUN cp fuzzing/dictionaries/json.dict $SRC/JsonParserFuzzer.dict RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -q $SRC/JsonParserFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/json-simple RUN git clone --depth 1 https://github.com/fangyidong/json-simple $SRC/project-parent/json-simple COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/json-simple/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=json-simple PROJECT_GROUP_ID=com.googlecode.json-simple PROJECT_ARTIFACT_ID=json-simple MAIN_REPOSITORY=https://github.com/fangyidong/json-simple function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install mvn -pl $PROJECT install -DskipTests mvn -pl fuzz-targets install else # Move seed corpus and dictionary. # mv $SRC/{*.zip,*.dict} $OUT set_project_version_in_fuzz_targets_dependency #install $MVN -pl $PROJECT install -DskipTests -Dmaven.repo.local=$OUT/m2 $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace dirname with placeholder $this_dir that will be replaced at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings:-Djava.awt.headless=true\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/json-simple/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.0 test com.googlecode.json-simple json-simple Fuzzing-SNAPSHOT maven-surefire-plugin 2.22.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/json-simple/project-parent/fuzz-targets/src/test/java/com/example/JsonEncodeDecodeFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import com.code_intelligence.jazzer.junit.FuzzTest; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import java.io.*; public class JsonEncodeDecodeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { String fuzzingString = data.consumeRemainingAsString(); JSONObject srcObj = new JSONObject(); srcObj.put("item1", fuzzingString); StringWriter out = new StringWriter(); srcObj.writeJSONString(out); String jsonText = out.toString(); StringReader in = new StringReader(jsonText); JSONParser parser = new JSONParser(); JSONObject destObj = (JSONObject)parser.parse(in); if (!destObj.equals(srcObj)) { throw new IllegalStateException("Decoded object: " + destObj.toString() + " doesn't match original object: " + srcObj.toString()); } } catch (IOException | ParseException e){ } } } ================================================ FILE: projects/json-simple/project-parent/fuzz-targets/src/test/java/com/example/JsonParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; public class JsonParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { JSONParser parser = new JSONParser(); try { JSONObject jsonObj = (JSONObject)parser.parse(data.consumeRemainingAsString()); } // ParseExeception is expected when JSON is invalid // ClassCastException occurs when parser returns primitive // NumberFormatException occurs when input at root level exceeds long size catch (ParseException | ClassCastException | NumberFormatException e) { } } } ================================================ FILE: projects/json-simple/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom json-simple fuzz-targets ================================================ FILE: projects/json-simple/project.yaml ================================================ homepage: "https://github.com/fangyidong/json-simple" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/fangyidong/json-simple" sanitizers: - address vendor_ccs: - "michael.nothhard@code-intelligence.com" - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/json-smart-v2/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ mv fuzzing/dictionaries/json.dict $SRC/json.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JSONParserFuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/netplex/json-smart-v2.git json-smart COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/json-smart ================================================ FILE: projects/json-smart-v2/JSONParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; public class JSONParserFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String input = data.consumeRemainingAsString(); JSONParser jp = new JSONParser(JSONParser.MODE_PERMISSIVE); try { jp.parse(input); } catch (ParseException | NumberFormatException e) { return; } } } ================================================ FILE: projects/json-smart-v2/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/{*.zip,*.dict} $OUT MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15 \ -Dmaven.javadoc.skip=true -Dmaven.repo.local=$WORK/m2" # first install accessors-smart in local $WORK/m2. json-smart depends on it cd accessors-smart $MVN install $MAVEN_ARGS cd .. # build the actual json-smart cd json-smart $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/json-smart-$CURRENT_VERSION.jar" $OUT/json-smart.jar # do not include accessors-smart.jar in ALL_JARS as it is already included with # maven-shade-plugin:3.2.4:shade ALL_JARS="json-smart.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/json-smart-v2/project.yaml ================================================ homepage: "https://github.com/netplex/json-smart-v2" language: jvm primary_contact: "uchemouni@gmail.com" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/netplex/json-smart-v2.git" vendor_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" - "jacek.trossen@code-intelligence.com" ================================================ FILE: projects/json2avro/ConverterFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.apache.avro.Schema; import tech.allegro.schema.json2avro.converter.AvroConversionException; import tech.allegro.schema.json2avro.converter.JsonAvroConverter; // jvm-autofuzz-heuristics-2 public class ConverterFuzzer { private static final String schemaStr = "{\"type\" : \"record\"," + "\"name\" : \"name\"," + "\"fields\" : [" + "{\"name\" : \"name1\", \"type\" : [\"null\", \"string\"], \"default\": null}," + "{\"name\" : \"name2\", \"type\" : [\"null\", \"int\"], \"default\": null}" + "]}"; public static void fuzzerTestOneInput(FuzzedDataProvider data) { // Heuristic name: jvm-autofuzz-heuristics-2 Schema schema = new Schema.Parser().parse(schemaStr); try { new JsonAvroConverter().convertToGenericDataRecord(data.consumeRemainingAsBytes(), schema); } catch (AvroConversionException e) { // Known exception } } } ================================================ FILE: projects/json2avro/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/allegro/json-avro-converter/ json2avro COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ ENV TARGET_PACKAGE_PREFIX tech.allegro.schema.json2avro.converter.* ENV JAVA_HOME=/usr/lib/jvm/java-15-openjdk-amd64/ WORKDIR $SRC/json2avro ================================================ FILE: projects/json2avro/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ chmod +x ./gradlew ./gradlew clean build -x test BUILD_CLASSPATH= RUNTIME_CLASSPATH= for JARFILE in $(find ./ -name *.jar) do cp $JARFILE $OUT/ BUILD_CLASSPATH=$BUILD_CLASSPATH$OUT/$(basename $JARFILE): RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH\$this_dir/$(basename $JARFILE): done # Retrieve apache-common-lang3 library # This library provides method to translate primitive type arrays to # their respective class object arrays to avoid compilation error. wget -P $OUT/ https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.12.0/commons-lang3-3.12.0.jar BUILD_CLASSPATH=$BUILD_CLASSPATH:$JAZZER_API_PATH:$OUT/commons-lang3-3.12.0.jar RUNTIME_CLASSPATH=$RUNTIME_CLASSPATH:\$this_dir/commons-lang3-3.12.0.jar:\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") mem_settings='-Xmx2048m:-Xss1024k' if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' fi LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ "\$@"" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/json2avro/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/allegro/json-avro-converter language: jvm main_repo: https://github.com/allegro/json-avro-converter sanitizers: - address vendor_ccs: - arthur.chan@adalogics.com - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/json5format/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN git clone --depth 1 https://github.com/google/json5format WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/json5format/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/json5format cargo fuzz build -O cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_parse $OUT/fuzz_parse ================================================ FILE: projects/json5format/project.yaml ================================================ homepage: "https://crates.io/crates/json5format" main_repo: "https://github.com/google/json5format" primary_contact: "richkadel@google.com" sanitizers: - address fuzzing_engines: - libfuzzer language: rust auto_ccs: - "david@adalogics.com" file_github_issue: True ================================================ FILE: projects/jsoncons/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake RUN git clone https://github.com/danielaparker/jsoncons WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/jsoncons/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd jsoncons/fuzzers # Ensure script is executable chmod +x ./build_fuzzers.sh ./build_fuzzers.sh ================================================ FILE: projects/jsoncons/project.yaml ================================================ homepage: "https://github.com/danielaparker/jsoncons" primary_contact: "danielaparker@gmail.com" language: c++ auto_ccs : - "david@adalogics.com" main_repo: 'https://github.com/danielaparker/jsoncons' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/jsoncpp/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update -y && apt-get install -y curl wget \ binutils cmake ninja-build liblzma-dev libz-dev pkg-config autoconf libtool RUN git clone --depth 1 https://github.com/open-source-parsers/jsoncpp WORKDIR jsoncpp RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git RUN (mkdir LPM && cd LPM && cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release && ninja) COPY run_tests.sh build.sh *.proto *.h *.cc $SRC/ ================================================ FILE: projects/jsoncpp/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed -i 's/set(CMAKE_CXX_STANDARD 11)/set(CMAKE_CXX_STANDARD 17)/' CMakeLists.txt mkdir -p build cd build cmake -DCMAKE_CXX_COMPILER=$CXX -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_SHARED_LIBS=OFF \ -DJSONCPP_WITH_TESTS=ON \ -DJSONCPP_WITH_POST_BUILD_UNITTEST=OFF \ -G "Unix Makefiles" .. make # Compile fuzzer. $CXX $CXXFLAGS -I../include $LIB_FUZZING_ENGINE \ ../src/test_lib_json/fuzz.cpp -o $OUT/jsoncpp_fuzzer \ lib/libjsoncpp.a # Add dictionary. cp $SRC/jsoncpp/src/test_lib_json/fuzz.dict $OUT/jsoncpp_fuzzer.dict if [[ $CFLAGS != *sanitize=memory* ]]; then # Compile json proto. rm -rf genfiles && mkdir genfiles && ../LPM/external.protobuf/bin/protoc json.proto --cpp_out=genfiles --proto_path=$SRC # Compile LPM fuzzer. $CXX $CXXFLAGS -DNDEBUG -I genfiles -I .. -I ../libprotobuf-mutator/ -I ../LPM/external.protobuf/include -I ../include $LIB_FUZZING_ENGINE \ $SRC/jsoncpp_fuzz_proto.cc genfiles/json.pb.cc $SRC/json_proto_converter.cc \ ../LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ ../LPM/src/libprotobuf-mutator.a \ -Wl,--start-group ../LPM/external.protobuf/lib/lib*.a -Wl,--end-group \ -o $OUT/jsoncpp_proto_fuzzer \ lib/libjsoncpp.a fi ================================================ FILE: projects/jsoncpp/json.proto ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// // The proto definition for JSON format has been written based on // http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf syntax = "proto2"; package json_proto; message JsonParseAPI { required int32 settings = 1; required JsonObject object_value = 2; } message JsonObject { required int32 settings = 1; required string name = 2; required JsonValue value = 3; } message JsonValue { oneof value { // Json value types: // null: null, will be used when 'oneof' contains nothing // object: another json object of any type JsonObject object_value = 1; // array: an array of values ArrayValue array_value = 2; // number: can be an integer, a float, an exponent NumberValue number_value = 3; // string: unicode string StringValue string_value = 4; // boolean: true or talse BooleanValue boolean_value = 5; } } message ArrayValue { repeated JsonValue value = 1; } message NumberInteger { required int64 value = 1; } message NumberFloat { required double value = 1; } message NumberExponent { required int32 base = 1; required int32 exponent = 2; required bool use_uppercase = 3; } message NumberExponentFrac { required float base = 1; required int32 exponent = 2; required bool use_uppercase = 3; } message NumberValue { required NumberInteger integer_value = 1; // integer_value is used when oneof field below has nothing. oneof value { NumberFloat float_value = 2; NumberExponent exponent_value = 3; NumberExponentFrac exponent_frac_value = 4; } } message StringValue { required string value = 1; } message BooleanValue { required bool value = 1; } ================================================ FILE: projects/jsoncpp/json_proto_converter.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "json_proto_converter.h" namespace json_proto { void JsonProtoConverter::AppendArray(const ArrayValue& array_value) { data_ << '['; bool need_comma = false; for (const auto& value : array_value.value()) { // Trailing comma inside of an array makes JSON invalid, avoid adding that. if (need_comma) data_ << ','; else need_comma = true; AppendValue(value); } data_ << ']'; } void JsonProtoConverter::AppendNumber(const NumberValue& number_value) { if (number_value.has_float_value()) { data_ << number_value.float_value().value(); } else if (number_value.has_exponent_value()) { auto value = number_value.exponent_value(); data_ << value.base(); data_ << (value.use_uppercase() ? 'E' : 'e'); data_ << value.exponent(); } else if (number_value.has_exponent_frac_value()) { auto value = number_value.exponent_value(); data_ << value.base(); data_ << (value.use_uppercase() ? 'E' : 'e'); data_ << value.exponent(); } else { data_ << number_value.integer_value().value(); } } void JsonProtoConverter::AppendObject(const JsonObject& json_object) { data_ << '{' << '"' << json_object.name() << '"' << ':'; AppendValue(json_object.value()); data_ << '}'; } void JsonProtoConverter::AppendValue(const JsonValue& json_value) { if (json_value.has_object_value()) { AppendObject(json_value.object_value()); } else if (json_value.has_array_value()) { AppendArray(json_value.array_value()); } else if (json_value.has_number_value()) { AppendNumber(json_value.number_value()); } else if (json_value.has_string_value()) { data_ << '"' << json_value.string_value().value() << '"'; } else if (json_value.has_boolean_value()) { data_ << (json_value.boolean_value().value() ? "true" : "false"); } else { data_ << "null"; } } std::string JsonProtoConverter::Convert(const JsonObject& json_object) { AppendObject(json_object); return data_.str(); } std::string JsonProtoConverter::Convert( const json_proto::ArrayValue& json_array) { AppendArray(json_array); return data_.str(); } } // namespace json_proto ================================================ FILE: projects/jsoncpp/json_proto_converter.h ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #ifndef JSON_PROTO_CONVERTER_H_ #define JSON_PROTO_CONVERTER_H_ #include #include #include "json.pb.h" namespace json_proto { class JsonProtoConverter { public: std::string Convert(const json_proto::JsonObject&); std::string Convert(const json_proto::ArrayValue&); private: std::stringstream data_; void AppendArray(const json_proto::ArrayValue&); void AppendNumber(const json_proto::NumberValue&); void AppendObject(const json_proto::JsonObject&); void AppendValue(const json_proto::JsonValue&); }; } // namespace json_proto #endif // TESTING_LIBFUZZER_PROTO_JSON_PROTO_CONVERTER_H_ ================================================ FILE: projects/jsoncpp/jsoncpp_fuzz_proto.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "json.pb.h" #include "json_proto_converter.h" #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" #include #include #include #include #include #include #include #include #include #include namespace Json { class Exception; } void FuzzJson(std::string data_str, int32_t hash_settings) { Json::CharReaderBuilder builder; builder.settings_["failIfExtra"] = hash_settings & (1 << 0); builder.settings_["allowComments_"] = hash_settings & (1 << 1); builder.settings_["strictRoot_"] = hash_settings & (1 << 2); builder.settings_["allowDroppedNullPlaceholders_"] = hash_settings & (1 << 3); builder.settings_["allowNumericKeys_"] = hash_settings & (1 << 4); builder.settings_["allowSingleQuotes_"] = hash_settings & (1 << 5); builder.settings_["failIfExtra_"] = hash_settings & (1 << 6); builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7); builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8); builder.settings_["collectComments"] = hash_settings & (1 << 9); builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10); std::unique_ptr reader(builder.newCharReader()); const char* begin = data_str.c_str(); const char* end = begin + data_str.length(); Json::Value root; try { reader->parse(begin, end, &root, nullptr); } catch (Json::Exception const&) { } } DEFINE_PROTO_FUZZER(const json_proto::JsonParseAPI &json_proto) { json_proto::JsonProtoConverter converter; std::string data_str = converter.Convert(json_proto.object_value()); int32_t hash_settings = json_proto.settings(); FuzzJson(data_str, hash_settings); } ================================================ FILE: projects/jsoncpp/project.yaml ================================================ homepage: "https://github.com/open-source-parsers/jsoncpp/" language: c++ primary_contact: "chenguopingdota@163.com" auto_ccs: - "jophba@chromium.org" sanitizers: - address - undefined # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory main_repo: 'https://github.com/open-source-parsers/jsoncpp' coverage_extra_args: -ignore-filename-regex=.*/LPM/.* fuzzing_engines: - afl - honggfuzz - libfuzzer base_os_version: ubuntu-24-04 ================================================ FILE: projects/jsoncpp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd build make test ================================================ FILE: projects/jsonnet/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y build-essential cmake RUN git clone --depth 1 https://github.com/google/jsonnet.git jsonnet WORKDIR $SRC/ COPY build.sh run_tests.sh $SRC/ COPY *.cc $SRC/ ================================================ FILE: projects/jsonnet/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install google test to be compatible with LLVM 21 git clone --depth 1 https://github.com/google/googletest cd $SRC/googletest mkdir build cd build cmake .. make -j$(nproc) make install cd $SRC/ mkdir jsonnet/build pushd jsonnet/build cmake -DUSE_SYSTEM_GTEST=ON -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \ -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DBUILD_TESTS=ON .. make -j$(nproc) all popd INSTALL_DIR="$SRC/jsonnet" for fuzzer in convert_jsonnet_fuzzer_regular \ convert_jsonnet_fuzzer_stream \ convert_jsonnet_fuzzer_multi; do $CXX $CXXFLAGS -I${INSTALL_DIR}/include $LIB_FUZZING_ENGINE \ $fuzzer.cc -o $OUT/$fuzzer \ ${INSTALL_DIR}/build/libjsonnet.a done ================================================ FILE: projects/jsonnet/convert_jsonnet_fuzzer_multi.cc ================================================ // Copyright 2022 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include extern "C" { #include "libjsonnet.h" } int ImportCallback(void* ctx, const char* base, const char* rel, char** found_here, char **buf, size_t *buflen) { // Don't load file and mark it as failure. *buf = NULL; *buflen = 0; return 1; } std::string ConvertJsonnetToJson(const std::string& jsonnet) { JsonnetVm* jvm = jsonnet_make(); jsonnet_import_callback(jvm, ImportCallback, jvm); int error = 0; char* res = jsonnet_evaluate_snippet_multi(jvm, /*filename=*/"", jsonnet.c_str(), &error); std::string json; if (error == 0 && res != nullptr) { json = res; } if (res) { jsonnet_realloc(jvm, res, 0); } jsonnet_destroy(jvm); return json; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string fuzz_jsonnet(reinterpret_cast(data), size); ConvertJsonnetToJson(fuzz_jsonnet); return 0; } ================================================ FILE: projects/jsonnet/convert_jsonnet_fuzzer_regular.cc ================================================ // Copyright 2022 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include extern "C" { #include "libjsonnet.h" } int ImportCallback(void* ctx, const char* base, const char* rel, char** found_here, char **buf, size_t *buflen) { // Don't load file and mark it as failure. *buf = NULL; *buflen = 0; return 1; } std::string ConvertJsonnetToJson(const std::string& jsonnet) { JsonnetVm* jvm = jsonnet_make(); jsonnet_import_callback(jvm, ImportCallback, jvm); int error = 0; char* res = jsonnet_evaluate_snippet(jvm, /*filename=*/"", jsonnet.c_str(), &error); std::string json; if (error == 0 && res != nullptr) { json = res; } if (res) { jsonnet_realloc(jvm, res, 0); } jsonnet_destroy(jvm); return json; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string fuzz_jsonnet(reinterpret_cast(data), size); ConvertJsonnetToJson(fuzz_jsonnet); return 0; } ================================================ FILE: projects/jsonnet/convert_jsonnet_fuzzer_stream.cc ================================================ // Copyright 2022 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include extern "C" { #include "libjsonnet.h" } int ImportCallback(void* ctx, const char* base, const char* rel, char** found_here, char **buf, size_t *buflen) { // Don't load file and mark it as failure. *buf = NULL; *buflen = 0; return 1; } std::string ConvertJsonnetToJson(const std::string& jsonnet) { JsonnetVm* jvm = jsonnet_make(); jsonnet_import_callback(jvm, ImportCallback, jvm); int error = 0; char* res = jsonnet_evaluate_snippet_stream(jvm, /*filename=*/"", jsonnet.c_str(), &error); std::string json; if (error == 0 && res != nullptr) { json = res; } if (res) { jsonnet_realloc(jvm, res, 0); } jsonnet_destroy(jvm); return json; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { std::string fuzz_jsonnet(reinterpret_cast(data), size); ConvertJsonnetToJson(fuzz_jsonnet); return 0; } ================================================ FILE: projects/jsonnet/project.yaml ================================================ homepage: "https://github.com/google/jsonnet" language: c++ primary_contact: "dcunnin@google.com" auto_ccs: - "sparkprime@gmail.com" - "jpa.bartholomew@gmail.com" - "jpab@google.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined labels: convert_jsonnet_fuzzer: - sundew architectures: - x86_64 - i386 main_repo: 'https://github.com/google/jsonnet.git' file_github_issue: True ================================================ FILE: projects/jsonnet/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/jsonnet/build make test ================================================ FILE: projects/jsonp-api/CreateJsonFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import ee.jakarta.tck.jsonp.common.JSONP_Util; import jakarta.json.*; import jakarta.json.stream.JsonParsingException; import java.io.PrintStream; import java.io.OutputStream; public class CreateJsonFuzzer { private static final PrintStream noopStream = new PrintStream(new OutputStream() { @Override public void write(int b) {} }); public static void fuzzerInitialize() { System.setErr(noopStream); System.setOut(noopStream); } public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { testJsonCreators(data); JsonValue.ValueType.valueOf(data.consumeString(100)); } catch (IllegalArgumentException | JsonParsingException e) {} } public static void testJsonCreators(FuzzedDataProvider data) { JsonArray jsonArray = JSONP_Util.createJsonArrayFromString(data.consumeString(200)); JSONP_Util.toStringJsonArray(jsonArray); JsonObject jsonObject = JSONP_Util.createJsonObjectFromString(data.consumeString(200)); JSONP_Util.toStringJsonObject(jsonObject); String inStr = data.consumeAsciiString(200); JsonString jsonString = JSONP_Util.createJsonString(inStr); String outString = JSONP_Util.toStringJsonString(jsonString); String intJsonStr = "\"" + inStr + "\""; if (!intJsonStr.equals(outString)) { throw new FuzzerSecurityIssueLow("JsonString: " + intJsonStr + " Expected. Got " + outString); } int inNumber = data.consumeInt(); JsonNumber jsonNumber = JSONP_Util.createJsonNumber(inNumber); String outNumber = JSONP_Util.toStringJsonNumber(jsonNumber); if (!Integer.toString(inNumber).equals(outNumber)) { throw new FuzzerSecurityIssueLow("JsonNumber: " + inNumber + " Expected. Got " + outNumber); } } } ================================================ FILE: projects/jsonp-api/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN git clone --depth 1 https://github.com/jakartaee/jsonp-api $SRC/jsonp-api RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/jsonp-api ================================================ FILE: projects/jsonp-api/GeneratorFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow; import ee.jakarta.tck.jsonp.common.JSONP_Util; import jakarta.json.*; import jakarta.json.stream.JsonGenerator; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; public class GeneratorFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); JsonGenerator generator = Json.createGenerator(baos).writeStartObject(); try { for (int i = 0; i < data.consumeInt(0, 10); i++) { if (data.consumeBoolean()) { generator.writeStartObject(data.consumeString(20)); } else { generator.writeStartArray(data.consumeString(20)); } for (int j = 0; j < data.consumeInt(0, 20); j++) { int writeChoice = data.consumeInt(0, 3); switch (writeChoice) { case 0: generator.write(data.consumeString(50), data.consumeInt()); break; case 1: generator.write(data.consumeString(50), data.consumeString(50)); break; case 2: generator.write(data.consumeString(50), data.consumeBoolean()); break; case 3: generator.write(JSONP_Util.createJsonString(data.consumeString(50))); break; } } generator.writeEnd(); } generator.writeEnd(); generator.close(); baos.close(); JSONP_Util.removeWhitespace(baos.toString("UTF-8")); } catch (JsonException | IOException | IllegalArgumentException e) {} } } ================================================ FILE: projects/jsonp-api/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cd tck $MVN -U -C clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true cp tck-common/target/jakarta*.jar $OUT/ cp tck-tests/target/jakarta*.jar $OUT/ cd .. cd api $MVN -U -C clean package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -DskipTests -Dmaven.test.skip=true -Dmaven.javadoc.skip=true cp target/jakarta*.jar $OUT/ cd .. # parsson dependencies need to be downloaded manually $MVN dependency:get -Dartifact=org.eclipse.parsson:parsson:1.1.1 cp ~/.m2/repository/org/eclipse/parsson/parsson/1.1.1/*.jar $OUT/ ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer mv $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jsonp-api/project.yaml ================================================ homepage: "https://github.com/jakartaee/jsonp-api" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/jakartaee/jsonp-api" sanitizers: - address vendor_ccs: ================================================ FILE: projects/jsonparser/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/buger/jsonparser COPY build.sh $SRC/ WORKDIR $SRC/jsonparser ================================================ FILE: projects/jsonparser/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./oss-fuzz-build.sh ================================================ FILE: projects/jsonparser/project.yaml ================================================ homepage: "https://github.com/buger/jsonparser" primary_contact: "leonsbox@gmail.com" auto_ccs : - "adam@adalogics.com" - "leloucharcher@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/buger/jsonparser' ================================================ FILE: projects/jsonpath/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.6.3 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.6.3/apache-maven-3.6.3/bin/mvn WORKDIR ${SRC} # # clone repository # RUN git clone https://github.com/json-path/JsonPath.git ADD pom.xml build.sh ${SRC}/ ADD src/ ${SRC}/src/ WORKDIR ${SRC}/JsonPath ================================================ FILE: projects/jsonpath/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MVN_FLAGS="" ALL_JARS="" LIBRARY_NAME="jsonpath" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.12.0" \ -Dpackaging=jar popd pushd "${SRC}/JsonPath" ./gradlew publishToMavenLocal CURRENT_VERSION=$(./gradlew properties --console=plain | sed -nr "s/^version:\ (.*)/\1/p") popd pushd "${SRC}" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" ${MVN_FLAGS} install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/jsonpath/pom.xml ================================================ 4.0.0 ossfuzz jsonpath-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 2.9.0 PathParserFuzzer com.code-intelligence jazzer-api 0.12.0 com.jayway.jsonpath json-path ${fuzzedLibaryVersion} org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/jsonpath/project.yaml ================================================ homepage: "https://goessner.net/articles/JsonPath/" language: jvm main_repo: "https://github.com/json-path/JsonPath.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jsonpath/src/main/java/ossfuzz/PathParserFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package ossfuzz; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.PathNotFoundException; import java.io.*; public class PathParserFuzzer { private FuzzedDataProvider fuzzedDataProvider; public PathParserFuzzer(FuzzedDataProvider fuzzedDataProvider) { this.fuzzedDataProvider = fuzzedDataProvider; } void test() throws IOException { try { InputStream in = getClass().getResourceAsStream("/test.json"); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder result = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { result.append(line); } Object document = Configuration.defaultConfiguration().jsonProvider().parse(result.toString()); JsonPath.read(document, fuzzedDataProvider.consumeRemainingAsString()); } catch (IllegalArgumentException e) { } catch (PathNotFoundException e) { } catch (InvalidPathException e) { } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws IOException { PathParserFuzzer loggingInterceptorFuzzer = new PathParserFuzzer(fuzzedDataProvider); loggingInterceptorFuzzer.test(); } } ================================================ FILE: projects/jsonpath/src/main/resources/test.json ================================================ { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 10 } ================================================ FILE: projects/jsonpickle/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone --depth 1 https://github.com/jsonpickle/jsonpickle $SRC/jsonpickle RUN $SRC/jsonpickle/fuzzing/oss-fuzz-scripts/container-environment-bootstrap.sh COPY build.sh $SRC/ WORKDIR $SRC/jsonpickle/ ================================================ FILE: projects/jsonpickle/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ . "$SRC/jsonpickle/fuzzing/oss-fuzz-scripts/build.sh" ================================================ FILE: projects/jsonpickle/project.yaml ================================================ homepage: https://github.com/jsonpickle/jsonpickle main_repo: https://github.com/jsonpickle/jsonpickle language: python primary_contact: "davvid@gmail.com" auto_ccs: - "theelgirl4@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/jsonschema/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN pip3 install --upgrade pip hypothesis rpds-py RUN git clone --depth=1 https://github.com/python-jsonschema/jsonschema.git RUN git clone --depth=1 https://github.com/python-jsonschema/jsonschema-specifications jsonschema_specifications WORKDIR $SRC/jsonschema COPY build.sh $SRC/ ================================================ FILE: projects/jsonschema/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data $SRC/jsonschema_specifications/jsonschema_specifications/schemas:jsonschema_specifications/schemas done ================================================ FILE: projects/jsonschema/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/Julian/jsonschema" language: python primary_contact: "Julian+Security@GrayVines.com" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: 'https://github.com/Julian/jsonschema' ================================================ FILE: projects/jsoup/CssHtmlFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /// ///////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jsoup.Jsoup; import org.jsoup.helper.ValidationException; import org.jsoup.nodes.Document; import org.jsoup.select.Evaluator; import org.jsoup.select.Selector; public class CssHtmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { String css = data.consumeString(100); Evaluator query; try { query = Selector.evaluatorOf(css); } catch (ValidationException | Selector.SelectorParseException ignored) { return; } String html = data.consumeRemainingAsString(); Document doc = Jsoup.parse(html, "https://example.com"); doc.select(query); } } ================================================ FILE: projects/jsoup/CssHtmlFuzzer.options ================================================ [libfuzzer] dict = combo.dict max_len = 1024 ================================================ FILE: projects/jsoup/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm ARG MAVEN_VERSION=3.9.11 RUN curl -L https://archive.apache.org/dist/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-$MAVEN_VERSION/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cat fuzzing/dictionaries/html.dict \ fuzzing/dictionaries/svg.dict \ fuzzing/dictionaries/mathml.dict \ fuzzing/dictionaries/css.dict \ fuzzing/dictionaries/xml.dict \ fuzzing/dictionaries/xpath.dict \ fuzzing/dictionaries/http.dict >> $SRC/combo.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/XmlFuzzer_seed_corpus.zip go-fuzz-corpus/xml/corpus/* && \ rm -rf go-fuzz-corpus RUN git clone --depth 1 https://github.com/jhy/jsoup/ # re2j is an optional/test dependency, but we want it available on the fuzzed classpath RUN curl -L https://github.com/google/re2j/releases/download/re2j-1.8/re2j-1.8.jar -o $SRC/re2j.jar COPY build.sh *.java *.options $SRC/ WORKDIR $SRC/jsoup ================================================ FILE: projects/jsoup/FragmentHtmlFuzzer.java ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /// ///////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jsoup.helper.ValidationException; import org.jsoup.nodes.Element; import org.jsoup.parser.Parser; public class FragmentHtmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { String contextElName = data.consumeString(20); Element contextEl = new Element(contextElName); String html = data.consumeRemainingAsString(); Parser.htmlParser().parseFragmentInput(html, contextEl, "https://example.com/"); } catch (ValidationException ignored) { } } } ================================================ FILE: projects/jsoup/FragmentHtmlFuzzer.options ================================================ [libfuzzer] dict = combo.dict max_len = 1024 ================================================ FILE: projects/jsoup/HtmlFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jsoup.Jsoup; public class HtmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Jsoup.parse(data.consumeRemainingAsString()); } } ================================================ FILE: projects/jsoup/HtmlFuzzer.options ================================================ [libfuzzer] dict = combo.dict max_len = 1024 ================================================ FILE: projects/jsoup/XmlFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jsoup.Jsoup; import org.jsoup.parser.Parser; public class XmlFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Jsoup.parse(data.consumeRemainingAsString(), "", Parser.xmlParser()); } } ================================================ FILE: projects/jsoup/XmlFuzzer.options ================================================ [libfuzzer] dict = combo.dict max_len = 1024 ================================================ FILE: projects/jsoup/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict,*.options} $OUT MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=17 -Djavac.target.version=17" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.6.1:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.5.1:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/jsoup-$CURRENT_VERSION.jar" $OUT/jsoup.jar # re2j into classpath cp "$SRC/re2j.jar" $OUT/re2j.jar ALL_JARS="jsoup.jar re2j.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jsoup/project.yaml ================================================ homepage: "https://github.com/jhy/jsoup/" language: jvm primary_contact: "jonathan@hedley.net" fuzzing_engines: - libfuzzer main_repo: "https://github.com/jhy/jsoup/" sanitizers: - address auto_ccs: - "ffrr33aakk@gmail.com" vendor_ccs: ================================================ FILE: projects/jsqlparser/.gitignore ================================================ project-parent/jsqlparser project-parent/fuzz-targets/target project-parent/fuzz-targets/src/test/resources project-parent/fuzz-targets/pom.xml.versionsBackup ================================================ FILE: projects/jsqlparser/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/google/fuzzing && \ cp fuzzing/dictionaries/sql.dict $SRC/JSqlParserFuzzer.dict && \ rm -rf fuzzing RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus && \ zip -j $SRC/JSqlParserFuzzer_seed_corpus.zip go-fuzz-corpus/sqlparser/corpus/* && \ rm -rf go-fuzz-corpus # if not set python infra helper cannot be used for local testing COPY project-parent $SRC/project-parent/ RUN rm -rf $SRC/project-parent/jsqlparser RUN apt update && apt install -y openjdk-11-jdk RUN git clone --depth 1 https://github.com/JSQLParser/JSqlParser/ $SRC/project-parent/jsqlparser COPY build.sh $SRC/ WORKDIR $SRC/ ================================================ FILE: projects/jsqlparser/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ PROJECT=jsqlparser PROJECT_GROUP_ID=com.github.jsqlparser PROJECT_ARTIFACT_ID=jsqlparser MAIN_REPOSITORY=https://github.com/JSQLParser/JSqlParser/ MAVEN_ARGS="-Djavac.src.version=11 -Djavac.target.version=11 -DskipTests" function set_project_version_in_fuzz_targets_dependency { PROJECT_VERSION=$(cd $PROJECT && $MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) # set dependency project version in fuzz-targets (cd fuzz-targets && $MVN versions:use-dep-version -Dincludes=$PROJECT_GROUP_ID:$PROJECT_ARTIFACT_ID -DdepVersion=$PROJECT_VERSION -DforceVersion=true) } cd project-parent # LOCAL_DEV env variable need to be set in local development env if [[ -v LOCAL_DEV ]]; then MVN=mvn # checkout latest project version git -C $PROJECT pull || git clone $MAIN_REPOSITORY $PROJECT set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS) mvn -pl fuzz-targets install else # Move seed corpus and dictionary. mv $SRC/{*.zip,*.dict} $OUT export JAVA_HOME="$OUT/open-jdk-11" mkdir -p $JAVA_HOME rsync -aL --exclude=*.zip --exclude 'lib/security/blacklisted.certs' "/usr/lib/jvm/java-11-openjdk-amd64/" "$JAVA_HOME" set_project_version_in_fuzz_targets_dependency #install (cd $PROJECT && $MVN install $MAVEN_ARGS -Dmaven.repo.local=$OUT/m2) $MVN -pl fuzz-targets install -Dmaven.repo.local=$OUT/m2 # build classpath $MVN -pl fuzz-targets dependency:build-classpath -Dmdep.outputFile=cp.txt -Dmaven.repo.local=$OUT/m2 cp -r $SRC/project-parent/fuzz-targets/target/test-classes/ $OUT/test-classes RUNTIME_CLASSPATH_ABSOLUTE="$(cat fuzz-targets/cp.txt):$OUT/test-classes" # replace $OUT with placeholder $this_dir that will be dissolved at runtime RUNTIME_CLASSPATH=$(echo $RUNTIME_CLASSPATH_ABSOLUTE | sed "s|$OUT|\$this_dir|g") for fuzzer in $(find $SRC/project-parent -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) # Create an execution wrapper for every fuzztarget echo "#!/bin/bash # LLVMFuzzerTestOneInput comment for fuzzer detection by infrastructure. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi JAVA_HOME=\"\$this_dir/open-jdk-11/\" \ LD_LIBRARY_PATH=\"\$this_dir/open-jdk-17/lib/server\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=com.example.$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ --instrumentation_includes=\"com.**:org.**:net.**\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done fi ================================================ FILE: projects/jsqlparser/project-parent/fuzz-targets/pom.xml ================================================ 4.0.0 com.fuzzer fuzz-targets 0.0.1-SNAPSHOT fuzz fuzz 11 11 11 com.code-intelligence jazzer-junit 0.19.0 org.junit.jupiter junit-jupiter-engine 5.9.2 test org.junit.platform junit-platform-launcher 1.9.2 com.github.jsqlparser jsqlparser Fuzzing-SNAPSHOT maven-surefire-plugin 3.1.2 ${project.basedir}/src/test/resources ================================================ FILE: projects/jsqlparser/project-parent/fuzz-targets/src/test/java/com/example/JSqlParserFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package com.example; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.junit.FuzzTest; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.parser.TokenMgrException; class JSqlParserFuzzer { @FuzzTest void myFuzzTest(FuzzedDataProvider data) { String simpleSql = data.consumeString(1000); String sqlScript = data.consumeString(1000); String expression = data.consumeString(1000); String ast = data.consumeString(1000); String condExp = data.consumeString(1000); try { CCJSqlParserUtil.parse( simpleSql, parser -> parser .withSquareBracketQuotation(data.consumeBoolean()) .withAllowComplexParsing(data.consumeBoolean()) .withUnsupportedStatements(data.consumeBoolean()) .withBackslashEscapeCharacter(data.consumeBoolean()) ); } catch (JSQLParserException e) { } try { CCJSqlParserUtil.parseStatements( sqlScript, parser -> parser .withSquareBracketQuotation(data.consumeBoolean()) .withAllowComplexParsing(data.consumeBoolean()) .withUnsupportedStatements(data.consumeBoolean()) .withBackslashEscapeCharacter(data.consumeBoolean()) ); } catch (JSQLParserException e) { } try { CCJSqlParserUtil.parseAST(ast); } catch (JSQLParserException e) { } try { CCJSqlParserUtil.parseExpression( expression, data.consumeBoolean(), parser -> parser .withSquareBracketQuotation(data.consumeBoolean()) .withAllowComplexParsing(data.consumeBoolean()) .withUnsupportedStatements(data.consumeBoolean()) .withBackslashEscapeCharacter(data.consumeBoolean()) ); } catch (JSQLParserException e) { } catch (ArrayIndexOutOfBoundsException | TokenMgrException e) { // Needed to catch to enable fuzzer to continue } try { CCJSqlParserUtil.parseCondExpression( condExp, data.consumeBoolean(), parser -> parser .withSquareBracketQuotation(data.consumeBoolean()) .withAllowComplexParsing(data.consumeBoolean()) .withUnsupportedStatements(data.consumeBoolean()) .withBackslashEscapeCharacter(data.consumeBoolean()) ); } catch (JSQLParserException e) { } catch (ArrayIndexOutOfBoundsException | TokenMgrException e) { // Needed to catch to enable fuzzer to continue } } } ================================================ FILE: projects/jsqlparser/project-parent/pom.xml ================================================ 4.0.0 com.fuzzer project-parent 0.1.0 pom jsqlparser fuzz-targets ================================================ FILE: projects/jsqlparser/project.yaml ================================================ homepage: "https://jsqlparser.github.io/JSqlParser/index.html" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/JSQLParser/JSqlParser/" sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jstl-api/0001-support-new-jdk.patch ================================================ diff --git a/jaxrpc-ri/pom.xml b/jaxrpc-ri/pom.xml --- a/jaxrpc-ri/pom.xml +++ b/jaxrpc-ri/pom.xml @@ -49,6 +49,8 @@ 1.2.16 1.4.2 1.9.13 + 1.8 + 1.8 ${maven.multiModuleProjectDirectory}/.. ================================================ FILE: projects/jstl-api/0002-avoid-ConcurrentModificationException.patch ================================================ diff --git a/jaxrpc-ri/pom.xml b/jaxrpc-ri/pom.xml --- a/jaxrpc-ri/pom.xml +++ b/jaxrpc-ri/pom.xml @@ -147,7 +149,7 @@ org.apache.felix maven-bundle-plugin - 4.2.1 + 5.1.8 <_removeheaders>Bnd-LastModified,Build-Jdk,Built-By,Include-Resource ================================================ FILE: projects/jstl-api/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm # Install maven configuration, which is also used by gradles's publishToMavenLocal. ADD maven-settings.xml ${SRC}/ RUN apt-get install -y xmlstarlet RUN mkdir -p ~/.m2 && \ xmlstarlet ed \ -u "settings/localRepository" -v "${OUT}/m2/repository" \ < ${SRC}/maven-settings.xml > ~/.m2/settings.xml # install maven and gradle RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven-3.8.7 && \ rm -rf maven.zip ENV MVN $SRC/maven-3.8.7/apache-maven-3.8.7/bin/mvn RUN curl -L https://services.gradle.org/distributions/gradle-7.6-bin.zip -o gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE $SRC/gradle/gradle-7.6/bin/gradle ENV LIBRARY_NAME jstl-api WORKDIR ${SRC} RUN git clone https://github.com/eclipse-ee4j/jstl-api.git ${LIBRARY_NAME} ADD build.sh ${SRC}/ ADD ${LIBRARY_NAME}-fuzzer ${SRC}/${LIBRARY_NAME}-fuzzer/ WORKDIR ${SRC}/${LIBRARY_NAME} ================================================ FILE: projects/jstl-api/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SRC_SUBDIR="" MVN_FLAGS="-Djavac.src.version=15 -Djavac.target.version=15 -DskipTests" ALL_JARS="" # Install the build servers' jazzer-api into the maven repository. pushd "/tmp" ${MVN} install:install-file -Dfile=${JAZZER_API_PATH} \ -DgroupId="com.code-intelligence" \ -DartifactId="jazzer-api" \ -Dversion="0.14.0" \ -Dpackaging=jar popd pushd "${SRC}/${LIBRARY_NAME}/${SRC_SUBDIR}" ${MVN} install ${MVN_FLAGS} CURRENT_VERSION=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd #this package uses multiple versions [...] pushd "${SRC}/${LIBRARY_NAME}/api" CURRENT_VERSION_API=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}/impl" CURRENT_VERSION_IMPL=$(${MVN} org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout) popd pushd "${SRC}/${LIBRARY_NAME}-fuzzer" ${MVN} package -DfuzzedLibaryVersion="${CURRENT_VERSION}" \ -DapiVersion="${CURRENT_VERSION_API}" \ -DimplVersion="${CURRENT_VERSION_IMPL}" \ ${MVN_FLAGS} install -v target/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ${OUT}/${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar ALL_JARS="${ALL_JARS} ${LIBRARY_NAME}-fuzzer-${CURRENT_VERSION}.jar" popd # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir MVN_FUZZERS_PREFIX="src/main/java" for fuzzer in $(find ${SRC} -name '*Fuzzer.java'); do # Find our fuzzer inside the maven structure stripped_path=$(echo ${fuzzer} | sed \ -e 's|^.*src/main/java/\(.*\).java$|\1|' \ -e 's|^.*src/test/java/\(.*\).java$|\1|' \ ); # The .java suffix was stripped by sed. if (echo ${stripped_path} | grep ".java$"); then continue; fi fuzzer_basename=$(basename -s .java $fuzzer) fuzzer_classname=$(echo ${stripped_path} | sed 's|/|.|g'); # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/sh # LLVMFuzzerTestOneInput Magic String required for infra/base-images/base-runner/test_all.py. DO NOT REMOVE this_dir=\$(dirname \"\$0\") LD_LIBRARY_PATH=\"\$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=${RUNTIME_CLASSPATH} \ --target_class=${fuzzer_classname} \ --jvm_args=\"-Xmx2048m\" \ \$@" > $OUT/${fuzzer_basename} chmod u+x $OUT/${fuzzer_basename} done ================================================ FILE: projects/jstl-api/jstl-api-fuzzer/pom.xml ================================================ 4.0.0 ossfuzz jstl-api-fuzzer ${fuzzedLibaryVersion} jar 15 15 UTF-8 3.0.0 com.sun.xml.rpc.processor.modeler.rmi.SOAPSimpleTypeCreatorFuzzer com.code-intelligence jazzer-api 0.14.0 jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api ${apiVersion} org.glassfish.web jakarta.servlet.jsp.jstl ${implVersion} jakarta.servlet jakarta.servlet-api 6.0.0 jakarta.servlet.jsp jakarta.servlet.jsp-api 3.1.0 jakarta.el jakarta.el-api 5.0.0 org.apache.maven.plugins maven-shade-plugin 3.3.0 *:* META-INF/*.SF META-INF/*.DSA META-INF/*.RSA package shade ================================================ FILE: projects/jstl-api/jstl-api-fuzzer/src/main/java/jakarta/servlet/jsp/ParserFuzzer.java ================================================ package jakarta.servlet.jsp; import org.apache.taglibs.standard.lang.jstl.Evaluator; import com.code_intelligence.jazzer.api.FuzzedDataProvider; public class ParserFuzzer { private FuzzedDataProvider fuzzedDataProvider; public ParserFuzzer(FuzzedDataProvider fuzzedDataProvider) throws Exception { this.fuzzedDataProvider = fuzzedDataProvider; } void test() { try { String result = Evaluator.parseAndRender(fuzzedDataProvider.consumeRemainingAsString()); } catch (JspException ex) { /* documented, ignore */ } catch (IllegalArgumentException ex) { /* general purpose, ignore */ } } public static void fuzzerTestOneInput(FuzzedDataProvider fuzzedDataProvider) throws Exception { ParserFuzzer fixture = new ParserFuzzer(fuzzedDataProvider); fixture.test(); } } ================================================ FILE: projects/jstl-api/maven-settings.xml ================================================ ${user.home}/.m2/repository ================================================ FILE: projects/jstl-api/project.yaml ================================================ homepage: "https://github.com/eclipse-ee4j/jstl-api" language: jvm main_repo: "https://github.com/eclipse-ee4j/jstl-api.git" fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "yakdan@code-intelligence.com" - "patrice.salathe@code-intelligence.com" ================================================ FILE: projects/jts/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip \ -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm maven.zip RUN curl -L https://github.com/protocolbuffers/protobuf/releases/download/v3.15.8/protoc-3.15.8-linux-x86_64.zip \ -o protoc.zip && \ mkdir -p $SRC/protoc && \ unzip protoc.zip -d $SRC/protoc && \ rm -rf protoc.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn ENV PATH="$SRC/protoc/bin:$PATH" RUN git clone --depth 1 https://github.com/locationtech/jts jts COPY build.sh *.java $SRC/ WORKDIR $SRC/jts ================================================ FILE: projects/jts/JtsFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.PrecisionModel; import org.locationtech.jts.geom.TopologyException; import org.locationtech.jts.io.ParseException; import org.locationtech.jts.io.WKTReader; import org.locationtech.jts.util.AssertionFailedException; public class JtsFuzzer { private static PrecisionModel.Type[] types = { PrecisionModel.FIXED, PrecisionModel.FLOATING, PrecisionModel.FLOATING_SINGLE}; public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { int[] choices = data.consumeInts(data.consumeInt(1, 10)); GeometryFactory factory = new GeometryFactory(new PrecisionModel(data.pickValue(types))); WKTReader reader = new WKTReader(factory); Geometry g1 = reader.read(data.consumeString(data.remainingBytes() / 2)); Geometry g2 = reader.read(data.consumeRemainingAsString()); for (Integer choice : choices) { switch (choice % 16) { case 0: g1.equalsNorm(g2); break; case 1: g1.distance(g2); break; case 2: g1.disjoint(g2); break; case 3: g1.touches(g2); break; case 4: g1.intersects(g2); break; case 5: g1.crosses(g2); break; case 6: g1.within(g2); break; case 7: g1.contains(g2); break; case 8: g1.overlaps(g2); break; case 9: g1.covers(g2); break; case 10: g1.coveredBy(g2); break; case 11: g1.relate(g2); break; case 12: g1.intersection(g2); break; case 13: g1.union(g2); break; case 14: g1.difference(g2); break; case 15: g1.symDifference(g2); break; } } } catch (ParseException | TopologyException | AssertionFailedException | IllegalArgumentException e) { // Known exception } } } ================================================ FILE: projects/jts/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## chmod +x $SRC/protoc/bin/protoc $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -Denforcer.fail=false org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "modules/core/target/jts-core-$CURRENT_VERSION.jar" $OUT/jts-core.jar cp "modules/lab/target/jts-lab-$CURRENT_VERSION.jar" $OUT/jts-lab.jar cp "modules/io/common/target/jts-io-common-$CURRENT_VERSION.jar" $OUT/jts-io-common.jar cp "modules/app/target/jts-app-$CURRENT_VERSION.jar" $OUT/jts-app.jar ALL_JARS="jts-core.jar:jts-lab.jar:jts-io-common.jar:jts-app.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name 'JtsFuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jts/project.yaml ================================================ homepage: https://github.com/locationtech/jts main_repo: https://github.com/locationtech/jts language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/juju/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/juju/juju RUN wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.23.4.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ && rm -rf temp-go go1.23.4.linux-amd64.tar.gz COPY build.sh devices_fuzzer.go $SRC/ WORKDIR $SRC/juju ================================================ FILE: projects/juju/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ go mod download # A fuzzer in this dependency is broken: find /root/go/pkg/mod/github.com/aws/aws-sdk-go-v2 -name "*fuzz.go" -exec rm -rf {} \; # Compile fuzzer: mv $SRC/devices_fuzzer.go $SRC/juju/core/devices/ compile_go_fuzzer github.com/juju/juju/core/devices Fuzz devices_fuzzer ================================================ FILE: projects/juju/devices_fuzzer.go ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package devices func Fuzz(data []byte) int { _, err := ParseConstraints(string(data)) if err != nil { return 0 } return 1 } ================================================ FILE: projects/juju/project.yaml ================================================ homepage: "https://juju.is" main_repo: "https://github.com/juju/juju" primary_contact: "stickupkid@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/jul-to-slf4j/BridgeFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.slf4j.bridge.SLF4JBridgeHandler; import java.util.logging.Logger; public class BridgeFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { SLF4JBridgeHandler.install(); Logger julLogger = Logger.getLogger("fuzzLogger"); julLogger.fine(data.consumeRemainingAsString()); } } ================================================ FILE: projects/jul-to-slf4j/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn RUN git clone --depth 1 https://github.com/qos-ch/slf4j.git slf4j COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ WORKDIR $SRC/slf4j ================================================ FILE: projects/jul-to-slf4j/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-DskipTests -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "jul-to-slf4j/target/jul-to-slf4j-$CURRENT_VERSION.jar" $OUT/jul-to-slf4j.jar ALL_JARS="jul-to-slf4j.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jul-to-slf4j/project.yaml ================================================ homepage: "https://www.slf4j.org/" language: jvm primary_contact: "dev.qos.ch@gmail.com" fuzzing_engines: - "libfuzzer" sanitizers: - "address" main_repo: "https://github.com/qos-ch/slf4j.git" auto_ccs: - "patrice.salathe@code-intelligence.com" - "yakdan@code-intelligence.com" ================================================ FILE: projects/junrar/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm:ubuntu-24-04 RUN curl -L https://services.gradle.org/distributions/gradle-7.4.2-bin.zip -o gradle.zip && \ unzip gradle.zip -d $SRC/gradle && \ rm -rf gradle.zip ENV GRADLE_HOME $SRC/gradle/gradle-7.4.2 ENV PATH $GRADLE_HOME/bin:$PATH # Dict # no existing rar.dict found on web, build rar dict manually later # Seeds RUN git clone --depth 1 https://github.com/strongcourage/fuzzing-corpus.git && \ zip -j $SRC/JunrarFuzzer_seed_corpus.zip fuzzing-corpus/rar/* && \ rm -rf fuzzing-corpus RUN git clone --depth 1 https://github.com/junrar/junrar.git junrar COPY build.sh $SRC/ COPY JunrarFuzzer.java $SRC/ WORKDIR $SRC/junrar ================================================ FILE: projects/junrar/JunrarFuzzer.java ================================================ // Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.io.ByteArrayInputStream; import com.github.junrar.Archive; import com.github.junrar.rarfile.FileHeader; import com.github.junrar.exception.RarException; import com.github.junrar.io.SeekableReadOnlyByteChannel; import com.github.junrar.rarfile.MainHeader; import com.github.junrar.volume.Volume; public class JunrarFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { InputStream inputStream = new ByteArrayInputStream(data.consumeRemainingAsBytes()); Archive v0 = null; FileHeader v1 = null; SeekableReadOnlyByteChannel v2 = null; MainHeader v3 = null; Volume v4 = null; v0 = new Archive(inputStream); v2 = v0.getChannel(); if (v2 != null) { v2.getPosition(); } v0.getFileHeaders(); v0.getHeaders(); v3 = v0.getMainHeader(); if (v3 != null) { v3.getEncryptVersion(); v3.isEncrypted(); //v3.print(); } v4 = v0.getVolume(); if (v4 != null) { v4.getChannel(); v4.getLength(); } v0.isEncrypted(); while (true) { v1 = v0.nextFileHeader(); if (v1 == null) { break; } v1.getCTime(); v1.hasVolumeNumber(); v1.isSubBlock(); v0.extractFile(v1, OutputStream.nullOutputStream()); } } catch (IOException e1) { } catch (RarException e2) { return; } } } ================================================ FILE: projects/junrar/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/*.zip $OUT #mv $SRC/{*.zip,*.dict} $OUT ./gradlew build CURRENT_VERSION=$(./gradlew properties --no-daemon --console=plain -q | grep "^version:" | awk '{printf $2}') cp "build/libs/junrar-$CURRENT_VERSION-sources.jar" $OUT/junrar.jar curl -L https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar -o $OUT/slf4j-api.jar curl -L https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/1.7.36/slf4j-simple-1.7.36.jar -o $OUT/slf4j-simple.jar ALL_JARS="junrar.jar slf4j-api.jar slf4j-simple.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/junrar/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/junrar/junrar language: jvm main_repo: https://github.com/junrar/junrar.git sanitizers: - address vendor_ccs: - all.u.ever.know@gmail.com base_os_version: ubuntu-24-04 ================================================ FILE: projects/jupyter-nbconvert/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/jupyter/nbconvert nbconvert COPY *.sh *py $SRC/ WORKDIR $SRC/nbconvert ================================================ FILE: projects/jupyter-nbconvert/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/jupyter-nbconvert/fuzz_markdown_converter.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import nbconvert def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) nbconvert.filters.markdown_mistune.markdown2html_mistune( fdp.ConsumeUnicodeNoSurrogates(sys.maxsize) ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jupyter-nbconvert/project.yaml ================================================ homepage: https://github.com/jupyter/nbconvert language: python main_repo: https://github.com/jupyter/nbconvert fuzzing_engines: - libfuzzer sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/jupyter_server/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt install -y nodejs RUN pip3 install --upgrade pip RUN curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh RUN git clone https://github.com/jupyter/jupyter_events $SRC/jupyter_events RUN bash nodesource_setup.sh RUN apt install -y nodejs RUN git clone https://github.com/jupyter-server/jupyter_server/ COPY build.sh *.py $SRC/ WORKDIR jupyter_server ================================================ FILE: projects/jupyter_server/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install -e ".[test]" for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer --add-data $SRC/jupyter_events/jupyter_events/schemas/:./jupyter_events/schemas/ --hidden-import=tornado.web done ================================================ FILE: projects/jupyter_server/fuzz_serialization.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from jupyter_client.session import Session from jupyter_server.base.zmqhandlers import ( deserialize_binary_message, serialize_binary_message, ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) s1 = fdp.ConsumeString(50) s2 = fdp.ConsumeString(50) if len(s1) == 0 or len(s2) == 0: return s = Session() msg = s.msg("data_pub", content={s1: s2}) msg["buffers"] = [ memoryview(fdp.ConsumeBytes(5)), memoryview(fdp.ConsumeBytes(5)), memoryview(fdp.ConsumeBytes(5)) ] bmsg = serialize_binary_message(msg) msg2 = deserialize_binary_message(bmsg) assert msg2 == msg def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/jupyter_server/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/jupyter-server/jupyter_server language: python main_repo: https://github.com/jupyter-server/jupyter_server sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com ================================================ FILE: projects/jupytext/project.yaml ================================================ homepage: "https://jupytext.readthedocs.io/en/latest/developing.html" language: python primary_contact: "marc.wouts@gmail.com" auto_ccs: - "ennamarie19@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/mwouts/jupytext.git" ================================================ FILE: projects/jwt-verify-lib/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install python3 -y RUN git clone --depth 1 https://github.com/google/jwt_verify_lib.git WORKDIR $SRC/jwt_verify_lib/ COPY build.sh $SRC/ ================================================ FILE: projects/jwt-verify-lib/build.sh ================================================ #!/bin/bash -eu # # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ bazel_build_fuzz_tests ================================================ FILE: projects/jwt-verify-lib/project.yaml ================================================ homepage: "https://github.com/google/jwt_verify_lib" language: c++ primary_contact: "qiwzhang@google.com" auto_ccs: - "nareddyt@google.com" - "yangshuo@google.com" - "taoxuy@google.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/google/jwt_verify_lib.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/jxls/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN rm -rf $SRC/project-parent/jxls RUN git clone --depth 1 https://github.com/jxlsteam/jxls $SRC/jxls RUN chmod +x $SRC/jxls/gradlew RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.8.7/binaries/apache-maven-3.8.7-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.8.7/bin/mvn COPY *.patch $SRC/ COPY build.sh $SRC/ COPY *Fuzzer.java $SRC/ COPY *.dict $SRC/ WORKDIR $SRC/jxls ================================================ FILE: projects/jxls/ProcessTemplateFuzzer.dict ================================================ "${}" "jx:area()" "jx:each()" "jx:if()" "lastCell=" "items=" "var=" "varIndex=" "select=" "!A1:B1" ================================================ FILE: projects/jxls/ProcessTemplateFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.jxls.common.JxlsException; import org.jxls.util.CannotOpenWorkbookException; import org.jxls.transform.poi.JxlsPoiTemplateFillerBuilder; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.Drawing; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; public class ProcessTemplateFuzzer { private static Path templatePath; public static void fuzzerInitialize() throws IOException { templatePath = new File("/out/template.xlsx").toPath(); templatePath.toFile().createNewFile(); } private static Map generateHashMap(FuzzedDataProvider data) { Map model = new HashMap(); for (int i = 0; i <= data.consumeInt(0, 10); i++) { model.put(data.consumeString(50), data.consumeBytes(200)); } return model; } public static Comment generateComment(XSSFSheet sheet, CreationHelper factory, FuzzedDataProvider data) { ClientAnchor anchor = factory.createClientAnchor(); Drawing drawing = sheet.createDrawingPatriarch(); Comment comment = drawing.createCellComment(anchor); comment.setString(factory.createRichTextString(data.consumeString(200))); comment.setAuthor(data.consumeString(100)); return comment; } public static Path createDocument(FuzzedDataProvider data) throws IOException { XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet(data.consumeString(50)); CreationHelper factory = workbook.getCreationHelper(); for (int i = 0; i < data.consumeInt(0, 50); i++) { Row row = sheet.createRow(i); for (int j = 0; j < data.consumeInt(0, 50); j++) { Cell cell = row.createCell(j); cell.setCellValue(data.consumeString(200)); if (data.consumeBoolean()) { cell.setCellComment(ProcessTemplateFuzzer.generateComment(sheet, factory, data)); } } } FileOutputStream out = new FileOutputStream(templatePath.toFile()); workbook.write(out); out.close(); return templatePath; } public static void fuzzerTestOneInput(FuzzedDataProvider data) { Path templatePath = null; try { templatePath = ProcessTemplateFuzzer.createDocument(data); } catch (IOException | IllegalArgumentException e) { return; } Map contextData = ProcessTemplateFuzzer.generateHashMap(data); OutputStream os = new ByteArrayOutputStream(); InputStream in = null; try { in = Files.newInputStream(templatePath.toFile().toPath()); } catch (IOException e) { throw new RuntimeException(e); } try { JxlsPoiTemplateFillerBuilder.newInstance() .withTemplate(in) .buildAndFill(contextData, () -> os); } catch (JxlsException e) {} } } ================================================ FILE: projects/jxls/build.patch ================================================ diff --git a/build.gradle b/build.gradle index 80c19ff..77377ba 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,7 @@ +plugins { + id 'com.github.johnrengelman.shadow' version '7.1.2' +} + allprojects { apply plugin: 'jacoco' apply plugin: 'org.owasp.dependencycheck' @@ -13,6 +17,7 @@ subprojects { apply plugin: 'java-library' apply plugin: 'eclipse' apply plugin: 'maven-publish' + apply plugin: 'com.github.johnrengelman.shadow' java { toolchain { ================================================ FILE: projects/jxls/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ CURRENT_VERSION=$(./gradlew properties --no-daemon --console=plain | sed -nr "s/^version:\ (.*)/\1/p") mv $SRC/*.dict $OUT git apply $SRC/build.patch --whitespace=fix --reject ./gradlew clean shadowJar -x :jxls:javadoc -x :jxls-poi:test cp "../jxls/jxls/build/libs/jxls-$CURRENT_VERSION-all.jar" $OUT/jxls.jar cp "../jxls/jxls-poi/build/libs/jxls-poi-$CURRENT_VERSION-all.jar" $OUT/jxls-poi.jar ALL_JARS=$(find $OUT/ -name *.jar ! -name jazzer*.jar -printf "%f ") echo $ALL_JARS # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer #cp $SRC/$fuzzer_basename.class $OUT/ cp $SRC/*.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings\" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/jxls/project.yaml ================================================ homepage: "https://github.com/jxlsteam/jxls" language: jvm fuzzing_engines: - libfuzzer main_repo: "https://github.com/jxlsteam/jxls" sanitizers: - address vendor_ccs: ================================================ FILE: projects/kafka/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update -y && apt-get install -y wget software-properties-common RUN wget -qO - https://packages.confluent.io/deb/7.0/archive.key | apt-key add - RUN add-apt-repository "deb https://packages.confluent.io/clients/deb $(lsb_release -cs) main" RUN apt-get update -y && apt-get install librdkafka-dev software-properties-common lsb-release gcc make python3-dev libsasl2-modules-gssapi-mit krb5-user -y RUN pip3 install --upgrade pip RUN git clone --depth=1 https://github.com/confluentinc/confluent-kafka-python kafka WORKDIR kafka COPY build.sh fuzz_*.py $SRC/ ================================================ FILE: projects/kafka/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build and install project (using current CFLAGS, CXXFLAGS). pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/kafka/fuzz_consumer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys from confluent_kafka import Consumer, KafkaException, TopicPartition def TestInput(data): fdp = atheris.FuzzedDataProvider(data) def dummy_callback(err, partitions): pass try: c = Consumer({ 'group.id': fdp.ConsumeConsumeUnicodeNoSurrogates(10), 'socket.timeout.ms': fdp.ConsumeIntInRange(10,2000), 'session.timeout.ms': fdp.ConsumeIntInRange(10,2000), 'on_commit': dummy_callback}) except Exception as e: # If the consumer fails, we just retry return try: c.subscribe( [fdp.ConsumeUnicodeNoSurrogates(10)], on_assign=dummy_callback, on_revoke=dummy_callback ) c.unsubscribe() msg = c.poll(timeout=0.001) msglist = c.consume( num_messages=fdp.ConsumeIntInRange(1,10), timeout=0.001 ) partitions = list( map( lambda part: TopicPartition(fdp.ConsumeUnicodeNoSurrogates(10).replace('\x00', ''), part), range(0, 100, 3) ) ) c.assign(partitions) c.unassign() c.commit(asynchronous=fdp.ConsumeBool()) c.committed(partitions, timeout=0.001) c.list_topics(timeout=0.2) c.list_topics(topic=fdp.ConsumeString(10), timeout=0.1) except KafkaException as e: pass c.close() def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/kafka/fuzz_producer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import atheris import sys with atheris.instrument_imports(): from confluent_kafka import Producer, KafkaException def TestInput(data): fdp = atheris.FuzzedDataProvider(data) p = Producer({ 'socket.timeout.ms': fdp.ConsumeIntInRange(10,2000), 'message.timeout.ms': fdp.ConsumeIntInRange(10,2000) }) p.produce(fdp.ConsumeUnicodeNoSurrogates(20).replace('\x00', '')) p.produce( fdp.ConsumeUnicodeNoSurrogates(20).replace('\x00', ''), value=fdp.ConsumeString(20), key=fdp.ConsumeString(20) ) def on_delivery(err, msg): pass p.produce( topic=fdp.ConsumeUnicodeNoSurrogates(20), value=fdp.ConsumeUnicodeNoSurrogates(20), partition=fdp.ConsumeIntInRange(1,10), callback=on_delivery ) p.poll(0.001) p.flush(0.002) p.flush() try: p.list_topics(timeout=0.2) except KafkaException as e: pass def main(): atheris.Setup(sys.argv, TestInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/kafka/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/confluentinc/confluent-kafka-python language: python main_repo: https://github.com/confluentinc/confluent-kafka-python sanitizers: - address - undefined vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/kamailio/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y bison flex RUN git clone https://github.com/kamailio/kamailio WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/kamailio/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/kamailio export CC_OPT="${CFLAGS}" export LD_EXTRA_OPTS="${CFLAGS}" sed -i 's/int main(/int main2(/g' ./src/main.c export MEMPKG=sys make Q=verbose || true cd src mkdir objects && find . -name "*.o" -exec cp {} ./objects/ \; ar -r libkamilio.a ./objects/*.o cd ../ $CC $CFLAGS -c ./misc/fuzz/fuzz_uri.c \ -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \ -I./src/ -I./src/core/parser -ldl -lresolv -lm $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_uri.o -o $OUT/fuzz_uri \ -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \ -I./src/ -I./src/core/parser -ldl -lresolv -lm $CC $CFLAGS ./misc/fuzz/fuzz_parse_msg.c -c \ -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \ -I./src/ -I./src/core/parser -ldl -lresolv -lm $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_parse_msg.o -o $OUT/fuzz_parse_msg \ -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \ -I./src/ -I./src/core/parser -ldl -lresolv -lm ================================================ FILE: projects/kamailio/project.yaml ================================================ homepage: "www.kamailio.org" main_repo: "https://github.com/kamailio/kamailio" primary_contact: "ossfuzz@kamailio.org" language: c auto_ccs: - "miconda@gmail.com" - "david@adalogics.com" - "mail@gilawa.com" - "qxork.droid@gmail.com" ================================================ FILE: projects/karchive/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 -b master https://invent.kde.org/frameworks/karchive.git RUN $SRC/karchive/autotests/ossfuzz/prepare_build.sh RUN cp $SRC/karchive/autotests/ossfuzz/build_fuzzers.sh $SRC/build.sh WORKDIR $SRC/karchive ================================================ FILE: projects/karchive/project.yaml ================================================ homepage: https://invent.kde.org/frameworks/karchive.git/ language: c++ primary_contact: tsdgeos@gmail.com sanitizers: - address - memory - undefined main_repo: 'https://invent.kde.org/frameworks/karchive.git' ================================================ FILE: projects/kcodecs/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 -b master https://invent.kde.org/frameworks/kcodecs.git RUN $SRC/kcodecs/autotests/ossfuzz/prepare_build.sh RUN cp $SRC/kcodecs/autotests/ossfuzz/build_fuzzers.sh $SRC/build.sh WORKDIR $SRC/kcodecs ================================================ FILE: projects/kcodecs/project.yaml ================================================ homepage: https://invent.kde.org/frameworks/kcodecs.git/ language: c++ primary_contact: tsdgeos@gmail.com sanitizers: - address - memory - undefined main_repo: 'https://invent.kde.org/frameworks/kcodecs.git' ================================================ FILE: projects/kde-thumbnailers/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://invent.kde.org/network/kio-extras.git RUN git clone --depth 1 https://invent.kde.org/graphics/kdegraphics-thumbnailers.git RUN git clone --depth 1 https://invent.kde.org/sdk/kdesdk-thumbnailers.git RUN git clone --depth 1 https://invent.kde.org/multimedia/ffmpegthumbs.git RUN $SRC/kio-extras/thumbnail/autotests/ossfuzz/prepare_build.sh RUN $SRC/kdegraphics-thumbnailers/autotests/ossfuzz/prepare_build.sh RUN $SRC/kdesdk-thumbnailers/autotests/ossfuzz/prepare_build.sh RUN $SRC/ffmpegthumbs/autotests/ossfuzz/prepare_build.sh COPY build.sh $SRC WORKDIR $SRC ================================================ FILE: projects/kde-thumbnailers/build.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/kio-extras/thumbnail/autotests/ossfuzz/build_fuzzers.sh $SRC/kdegraphics-thumbnailers/autotests/ossfuzz/build_fuzzers.sh $SRC/kdesdk-thumbnailers/autotests/ossfuzz/build_fuzzers.sh $SRC/ffmpegthumbs/autotests/ossfuzz/build_fuzzers.sh # Cleanup rm -rf $WORK/* ================================================ FILE: projects/kde-thumbnailers/project.yaml ================================================ homepage: "https://invent.kde.org/network/kio-extras.git" language: c++ primary_contact: tsdgeos@gmail.com sanitizers: - address - undefined fuzzing_engines: - libfuzzer - honggfuzz main_repo: "https://invent.kde.org/network/kio-extras.git" ================================================ FILE: projects/kea/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && \ apt-get install --no-install-recommends -y meson ninja-build pkg-config \ build-essential python3 libssl-dev libboost-dev libboost-system-dev \ libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \ libpq-dev libmariadb-dev libkrb5-dev RUN mkdir -p /opt/boost-headers && \ wget https://archives.boost.io/release/1.83.0/source/boost_1_83_0.tar.gz && \ tar -xzf boost_1_83_0.tar.gz -C /opt/boost-headers --strip-components=1 && \ rm -f boost_1_83_0.tar.gz && mkdir -p /usr/local/include && \ ln -s /opt/boost-headers/boost /usr/local/include/boost RUN mkdir -p /src/log4cplus && \ wget https://github.com/log4cplus/log4cplus/releases/download/REL_2_1_2/log4cplus-2.1.2.tar.gz && \ tar -xzf log4cplus-2.1.2.tar.gz -C /src/log4cplus --strip-components=1 && \ rm -f log4cplus-2.1.2.tar.gz RUN python3 -m pip install --no-cache-dir --upgrade "meson>=1.1,<2" RUN git clone https://gitlab.isc.org/isc-projects/kea kea RUN git clone https://github.com/AdaLogics/ada-fuzzers ada-fuzzers COPY build.sh $SRC/ WORKDIR kea ================================================ FILE: projects/kea/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Copy key fuzzers/dict/seeds cp -r $SRC/ada-fuzzers/projects/kea $SRC/kea-fuzzer # Run build script $SRC/kea-fuzzer/build.sh ================================================ FILE: projects/kea/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://gitlab.isc.org/isc-projects/kea" language: c++ primary_contact: "david@adalogics.com" auto_ccs: - "adam@adalogics.com" - "arthur.chan@adalogics.com" - "tomek@isc.org" - "razvan@isc.org" - "andrei@isc.org" - "wlodek.wencel@gmail.com" main_repo: 'https://gitlab.isc.org/isc-projects/kea' fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/keras/Dockerfile ================================================ # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python:ubuntu-24-04 RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ rsync \ && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* RUN python3 -m pip install --upgrade pip chardet # We install Keras by way of Tensorflow. As such, this build instructions # follow the logic of tensorflow-py project. # Due to Bazel bug, need to symlink python3 to python # See https://github.com/bazelbuild/bazel/issues/8665 RUN ln -s /usr/local/bin/python3 /usr/local/bin/python # Install Bazelisk to keep bazel in sync with the version required by TensorFlow RUN curl -Lo /usr/bin/bazel \ https://github.com/bazelbuild/bazelisk/releases/download/v1.1.0/bazelisk-linux-amd64 \ && \ chmod +x /usr/bin/bazel RUN git clone --depth 1 https://github.com/tensorflow/tensorflow tensorflow RUN git clone --depth 1 https://github.com/DavidKorczynski/hdf5-files $SRC/hdf5-files WORKDIR $SRC/tensorflow COPY build.sh *.py $SRC/ ================================================ FILE: projects/keras/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ORIG_CFLAGS="$CFLAGS" export ORIG_CXXFLAGS="$CXXFLAGS" export CFLAGS="" export CXXFLAGS="" python3 -m pip install numpy export CFLAGS=$ORIG_CFLAGS export CXXFLAGS=$ORIG_CXXFLAGS python3 -m pip install tf-nightly-cpu # Rename to avoid the following: https://github.com/tensorflow/tensorflow/issues/40182 mv $SRC/tensorflow/tensorflow $SRC/tensorflow/tensorflow_src compile_python_fuzzer $SRC/fuzz_serialization.py compile_python_fuzzer $SRC/fuzz_model.py zip $OUT/fuzz_model_seed_corpus.zip $SRC/hdf5-files/basic-model.h5 ================================================ FILE: projects/keras/fuzz_model.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import json import h5py import chardet with atheris.instrument_imports(): import keras @atheris.instrument_func def TestOneInput(data): with open("model.hdf5", "wb") as mf: mf.write(data) try: keras.models.load_model("model.hdf5") # Catch all sorts of exceptions. The goal right now is capturing more security # relevant properties so focus on code coverage. except OSError: return except KeyError: return except TypeError: return except ValueError: return def main(): atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/keras/fuzz_serialization.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import json import keras from keras.saving import serialization_lib def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) try: json_dict = json.loads(fdp.ConsumeUnicodeNoSurrogates(sys.maxsize)) except: return if not isinstance(json_dict, dict): return serialization_lib.deserialize_keras_object( json_dict, custom_objects=None ) def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/keras/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://keras.io" main_repo: 'https://github.com/keras-team/keras' language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - "david@adalogics.com" ================================================ FILE: projects/keycloak/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN apt update && apt install libxext6 libxrender1 libxtst6 -y RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.2/binaries/apache-maven-3.9.2-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.2/bin/mvn ENV TARGET_PACKAGE_PREFIX org.keycloak.* RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing cncf-fuzzing RUN git clone --depth 1 https://github.com/keycloak/keycloak keycloak COPY build.sh $SRC/ WORKDIR $SRC/keycloak ================================================ FILE: projects/keycloak/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/cncf-fuzzing/projects/keycloak/*.java $SRC/ $SRC/cncf-fuzzing/projects/keycloak/build.sh ================================================ FILE: projects/keycloak/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: "https://www.keycloak.org/" language: jvm main_repo: "https://github.com/keycloak/keycloak" sanitizers: - address primary_contact: "abstractj@redhat.com" auto_ccs: - "keycloak-oss-fuzz@redhat.com" - "pigor.craveiro@gmail.com" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" - "arthur.chan@adalogics.com" ================================================ FILE: projects/keystone/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make cmake RUN git clone --depth 1 https://github.com/keystone-engine/keystone.git # Prepare tests RUN export CFLAGS="-pthread" && \ export CXXFLAGS="-pthread" && \ cd keystone/bindings/python && \ make install -j$(nproc) && \ python3 -m pip install . WORKDIR $SRC COPY *.sh $SRC/ ================================================ FILE: projects/keystone/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="${CXXFLAGS} -pthread" export CFLAGS="${CFLAGS} -pthread" #builds project cd keystone mkdir build cd build cmake .. make -j$(nproc) make install -j$(nproc) ldconfig # build fuzz target cd ../suite/fuzz ls fuzz_*.c | cut -d_ -f2-4 | cut -d. -f1 | while read target do $CC $CFLAGS -I../../include -c fuzz_$target.c -o fuzz_$target.o $CXX $CXXFLAGS fuzz_$target.o -o $OUT/fuzz_$target ../../build/llvm/lib/libkeystone.a $LIB_FUZZING_ENGINE #TODO corpuses cp fuzz_asm.options $OUT/fuzz_$target.options done ================================================ FILE: projects/keystone/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.keystone-engine.org" language: c++ primary_contact: "keystone.engine@gmail.com" auto_ccs : - "p.antoine@catenacyber.fr" - "stalkr@stalkr.net" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined main_repo: 'https://github.com/keystone-engine/keystone.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/keystone/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd keystone/suite ./test-all.sh cd regress # Some of the tests have syntax errors because they are written for Python2. # Other tests are failing and we're not sure why. Remove these tests for now. mkdir -p /tmp/saved_tests for failing_testcase in x86_issue293.py x64_sym_resolver.py all_archs_branch_addr.py x64_RSP_index_reg.py x86_nasm_directives.py x86_ds_default.py x86_issue10.py x86_call0.py x86_lea_three.py arm_sym_resolver_thumb.py test_all_archs.py x86_call_ptr_sym.py arm_sym_resolver.py all_archs_value_directive.py; do mv ${failing_testcase} /tmp/saved_tests/ done python3 ./regress.py mv /tmp/saved_tests/* . ================================================ FILE: projects/kie-soup/CronExpressionFuzzer.java ================================================ // Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import org.kie.soup.commons.cron.CronExpression; import java.text.ParseException; // Generated with https://github.com/ossf/fuzz-introspector/tree/main/tools/auto-fuzz // Minor modifications to beautify code and ensure exception is caught. // jvm-autofuzz-heuristics-11 // Heuristic name: jvm-autofuzz-heuristics-11 // Target method: [org.kie.soup.commons.cron.CronExpression] public (java.lang.String) throws java.text.ParseException public class CronExpressionFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { try { new CronExpression(data.consumeRemainingAsString()); } catch (ParseException e1) { // Known exception } } } ================================================ FILE: projects/kie-soup/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.6.3/bin/mvn RUN git clone --depth 1 https://github.com/kiegroup/kie-soup kie-soup COPY *.sh *.java $SRC/ WORKDIR $SRC/kie-soup ================================================ FILE: projects/kie-soup/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## $MVN clean package -Dmaven.javadoc.skip=true -DskipTests=true -Dpmd.skip=true \ -Dencoding=UTF-8 -Dmaven.antrun.skip=true -Dcheckstyle.skip=true \ -DperformRelease=True org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade CURRENT_VERSION=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "./kie-soup-commons/target/kie-soup-commons-$CURRENT_VERSION.jar" $OUT/kie-soup.jar ALL_JARS='kie-soup.jar' # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java') do fuzzer_basename=$(basename -s .java $fuzzer) javac -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname "\$0") if [[ "\$@" =~ (^| )-runs=[0-9]+($| ) ]] then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH="$JVM_LD_LIBRARY_PATH":\$this_dir \ \$this_dir/jazzer_driver \ --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args="\$mem_settings" \ \$@" > $OUT/$fuzzer_basename chmod u+x $OUT/$fuzzer_basename done ================================================ FILE: projects/kie-soup/project.yaml ================================================ homepage: https://github.com/kiegroup/kie-soup main_repo: https://github.com/kiegroup/kie-soup language: jvm fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com - adam@adalogics.com - arthur.chan@adalogics.com ================================================ FILE: projects/kimageformats/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 -b master https://invent.kde.org/frameworks/kimageformats.git RUN $SRC/kimageformats/autotests/ossfuzz/prepare_build.sh RUN cp $SRC/kimageformats/autotests/ossfuzz/build_fuzzers.sh $SRC/build.sh WORKDIR $SRC/kimageformats ================================================ FILE: projects/kimageformats/project.yaml ================================================ homepage: https://invent.kde.org/frameworks/kimageformats.git/ language: c++ primary_contact: tsdgeos@gmail.com sanitizers: - address - memory - undefined main_repo: 'https://invent.kde.org/frameworks/kimageformats.git' auto_ccs: - dnovomesky@gmail.com - mircomir@gmail.com ================================================ FILE: projects/kiwisolver/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-python RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/nucleic/kiwi kiwi WORKDIR kiwi COPY build.sh *.py $SRC/ ================================================ FILE: projects/kiwisolver/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pip3 install . for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/kiwisolver/fuzz_solver.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import atheris from kiwisolver import ( Solver, UnsatisfiableConstraint, Variable, ) def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) s = Solver() # Create an arbitrary set of variables variables = [] num_of_variables = fdp.ConsumeIntInRange(2, 10) for v in range(num_of_variables): variables.append(Variable(fdp.ConsumeUnicodeNoSurrogates(20))) s.addEditVariable(variables[-1], "weak") # Apply a random set of constraints on these variables num_of_ops = fdp.ConsumeIntInRange(2, 10) for i in range(num_of_ops): op = fdp.ConsumeIntInRange(1,3) var = variables[fdp.ConsumeIntInRange(0,len(variables)-1)] c = 1 * var for i2 in range(fdp.ConsumeIntInRange(2, 5)): if op == 1: c = c + fdp.ConsumeIntInRange(1, 100) elif op == 2: c = c - fdp.ConsumeIntInRange(1, 100) elif op == 3: c = c * fdp.ConsumeIntInRange(1, 100) # Add constraint constr = fdp.ConsumeIntInRange(0,2) if constr == 0: c = c >= 0 elif constr == 1: c = c <= 0 else: c = c == 0 try: s.addConstraint(c) except UnsatisfiableConstraint: return # Set a condition/update variables. s.updateVariables() def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/kiwisolver/project.yaml ================================================ auto_ccs: - david@adalogics.com - adam@adalogics.com fuzzing_engines: - libfuzzer homepage: https://github.com/nucleic/kiwi language: python main_repo: https://github.com/nucleic/kiwi primary_contact: m.dartiailh@gmail.com sanitizers: - address - undefined ================================================ FILE: projects/kmime/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 -b master https://invent.kde.org/pim/kmime.git RUN $SRC/kmime/autotests/ossfuzz/prepare_build.sh RUN cp $SRC/kmime/autotests/ossfuzz/build_fuzzers.sh $SRC/build.sh WORKDIR $SRC/kmime ================================================ FILE: projects/kmime/project.yaml ================================================ homepage: https://invent.kde.org/pim/kmime.git/ language: c++ primary_contact: tsdgeos@gmail.com sanitizers: - address - undefined - memory main_repo: "https://invent.kde.org/pim/kmime.git" ================================================ FILE: projects/knative/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN git clone --depth 1 https://github.com/knative/pkg RUN git clone --depth 1 https://github.com/knative/serving WORKDIR $SRC/pkg COPY build.sh $SRC/ ================================================ FILE: projects/knative/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/knative/build.sh ================================================ FILE: projects/knative/project.yaml ================================================ homepage: "https://knative.dev/" language: go primary_contact: "security@knative.team" main_repo: "https://github.com/knative" vendor_ccs: - "adam@adalogics.com" - "david@adalogics.com" auto_ccs: - "evana@vmware.com" - "evan.k.anderson@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/knot-dns/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y \ autoconf \ autogen \ automake \ autopoint \ bison \ gettext \ gperf \ gtk-doc-tools \ libev-dev \ libev4 \ libtasn1-bin \ libtool \ make \ pkg-config \ texinfo \ wget ENV GNULIB_TOOL $SRC/gnulib/gnulib-tool RUN git clone git://git.savannah.gnu.org/gnulib.git RUN git clone --depth=1 --recursive https://git.savannah.gnu.org/git/libunistring.git RUN git clone --depth=1 --branch nettle_3.9.1_release_20230601 https://git.lysator.liu.se/nettle/nettle.git RUN git clone --depth=1 https://gitlab.com/gnutls/gnutls.git -b 3.8.3 RUN git clone --depth=1 https://github.com/LMDB/lmdb.git RUN git clone --depth=1 https://gitlab.labs.nic.cz/knot/knot-dns WORKDIR knot-dns COPY build.sh $SRC/ ================================================ FILE: projects/knot-dns/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Compile and install dependencies for static linking # Cribbed from projects/wget2, thanks rockdaboot@gmail.com export DEPS_PATH=$SRC/knot_deps export PKG_CONFIG_PATH=$DEPS_PATH/lib64/pkgconfig:$DEPS_PATH/lib/pkgconfig export CPPFLAGS="-I$DEPS_PATH/include" export LDFLAGS="-L$DEPS_PATH/lib" export GNULIB_SRCDIR=$SRC/gnulib cd $SRC/libunistring ./autogen.sh ./configure --enable-static --disable-shared --prefix=$DEPS_PATH make -j$(nproc) make install GNUTLS_CONFIGURE_FLAGS="" NETTLE_CONFIGURE_FLAGS="--disable-assembler" # Temporarily disalbe asm to work around error "Libnettle 3.6 was not found." if [[ $CFLAGS = *sanitize=memory* ]]; then GNUTLS_CONFIGURE_FLAGS="--disable-hardware-acceleration" NETTLE_CONFIGURE_FLAGS="--disable-assembler --disable-fat" fi cd $SRC/nettle bash .bootstrap ./configure --enable-mini-gmp --enable-static --disable-shared --disable-documentation --prefix=$DEPS_PATH $NETTLE_CONFIGURE_FLAGS ( make -j$(nproc) || make -j$(nproc) ) && make install cd $SRC/gnutls touch .submodule.stamp ./bootstrap LIBS="-lunistring" \ ./configure --with-nettle-mini --disable-gcc-warnings --enable-static --disable-shared --with-included-libtasn1 \ --with-included-unistring --without-p11-kit --disable-doc --disable-tests --disable-tools --disable-cxx \ --disable-maintainer-mode --disable-libdane --disable-full-test-suite --prefix=$DEPS_PATH $GNUTLS_CONFIGURE_FLAGS make -j$(nproc) make install cd $SRC/lmdb/libraries/liblmdb make -j$(nproc) make install # Compile knot, install fuzzers to $OUT cd $SRC/knot-dns sed -i 's/-llmdb/-Wl,-Bstatic,-llmdb,-Bdynamic/' configure.ac autoreconf -if ./configure --with-oss-fuzz=yes --disable-shared --enable-static --disable-daemon --disable-utilities --disable-documentation \ --disable-fastparser --disable-modules make -j$(nproc) cd $SRC/knot-dns/tests-fuzz make check /bin/bash ../libtool --mode=install /usr/bin/install -c fuzz_packet fuzz_zscanner fuzz_dname_to_str fuzz_dname_from_str "$OUT" # Set up fuzzing seeds git submodule update --init -- ./fuzz_packet.in git submodule update --init -- ./fuzz_zscanner.in # ./fuzz_dname_to_str.in/ and ./fuzz_dname_from_str.in/ are stored in the base repository find ./fuzz_packet.in/ -type f -exec zip -u $OUT/fuzz_packet_seed_corpus.zip {} \; find ./fuzz_zscanner.in/ -type f -exec zip -u $OUT/fuzz_zscanner_seed_corpus.zip {} \; find ./fuzz_dname_to_str.in/ -type f -exec zip -u $OUT/fuzz_dname_to_str_seed_corpus.zip {} \; find ./fuzz_dname_from_str.in/ -type f -exec zip -u $OUT/fuzz_dname_from_str_seed_corpus.zip {} \; ================================================ FILE: projects/knot-dns/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.knot-dns.cz/" main_repo: "https://gitlab.nic.cz/knot/knot-dns.git" language: c++ primary_contact: "knot.dns@gmail.com" auto_ccs: - "jonathan.foote@gmail.com" sanitizers: - address - memory - undefined fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/krb5/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf bison RUN git clone --depth=1 https://github.com/krb5/krb5.git RUN cp $SRC/krb5/src/tests/fuzzing/oss-fuzz.sh $SRC/build.sh WORKDIR $SRC/krb5/ ================================================ FILE: projects/krb5/project.yaml ================================================ homepage: "https://web.mit.edu/kerberos/" language: c primary_contact: "krbcore-security@mit.edu" auto_ccs: - "pkillarjun@protonmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/krb5/krb5' ================================================ FILE: projects/kryo/DeserializeCollectionsFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer; import java.util.*; public class DeserializeCollectionsFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Kryo kryo = new Kryo(); kryo.register(SomeClass.class); kryo.setReferences(data.consumeBoolean()); if (data.consumeBoolean()) kryo.setDefaultSerializer(CompatibleFieldSerializer.class); Input in = new Input(data.consumeRemainingAsBytes()); try { kryo.readObject(in, SomeClass.class); } catch (KryoException e) { } finally { in.close(); } } public static final class SomeClass { List _emptyList = Collections.emptyList(); Set _emptySet = Collections.emptySet(); Map _emptyMap = Collections.emptyMap(); List _singletonList = Collections.singletonList("foo"); Set _singletonSet = Collections.emptySet(); Map _singletonMap; TreeSet _treeSet; TreeMap _treeMap; List _arrayList; Set _hashSet; Map _hashMap; List _asList = Arrays.asList(1, 2, 3); int[] _intArray; long[] _longArray; short[] _shortArray; float[] _floatArray; double[] _doubleArray; byte[] _byteArray; char[] _charArray; String[] _stringArray; Integer[] _integerArray; BitSet _bitSet; } } ================================================ FILE: projects/kryo/DeserializeNumbersFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.math.BigDecimal; import java.math.BigInteger; public class DeserializeNumbersFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Kryo kryo = new Kryo(); kryo.register(SomeClass.class); kryo.setReferences(data.consumeBoolean()); if (data.consumeBoolean()) kryo.setDefaultSerializer(CompatibleFieldSerializer.class); Input in = new Input(data.consumeRemainingAsBytes()); try { kryo.readObject(in, SomeClass.class); } catch (KryoException e) { } finally { in.close(); } } public static final class SomeClass { Date _date; TimeZone _timeZone; Calendar _calendar; Locale _locale; Integer[] _integerArray; boolean _boolean; char _char; byte _byte; short _short; int _int1; int _int2; long _long; float _float; double _double; Boolean _Boolean; Character _Character; Byte _Byte; Short _Short; Integer _Integer; Long _Long; Float _Float; Double _Double; BigInteger _bigInteger; BigDecimal _bigDecimal; AtomicInteger _atomicInteger; AtomicLong _atomicLong; } } ================================================ FILE: projects/kryo/DeserializeStringFuzzer.java ================================================ // Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.KryoException; import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer; public class DeserializeStringFuzzer { public static void fuzzerTestOneInput(FuzzedDataProvider data) { Kryo kryo = new Kryo(); kryo.register(SomeClass.class); kryo.setReferences(data.consumeBoolean()); if (data.consumeBoolean()) kryo.setDefaultSerializer(CompatibleFieldSerializer.class); Input in = new Input(data.consumeRemainingAsBytes()); try { kryo.readObject(in, SomeClass.class); } catch (KryoException e) { } finally { in.close(); } } public static final class SomeClass { String value; } } ================================================ FILE: projects/kryo/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-jvm RUN curl -L https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.zip -o maven.zip && \ unzip maven.zip -d $SRC/maven && \ rm -rf maven.zip ENV MVN $SRC/maven/apache-maven-3.9.9/bin/mvn RUN git clone --depth 1 https://github.com/EsotericSoftware/kryo COPY build.sh $SRC/ COPY DeserializeCollectionsFuzzer.java DeserializeNumbersFuzzer.java DeserializeStringFuzzer.java $SRC/ WORKDIR $SRC/kryo ================================================ FILE: projects/kryo/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15" $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS current_version=$($MVN org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate \ -Dexpression=project.version -q -DforceStdout) cp "target/kryo-$current_version.jar" $OUT/kryo.jar ALL_JARS="kryo.jar" # The classpath at build-time includes the project jars in $OUT as well as the # Jazzer API. BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH # All .jar and .class files lie in the same directory as the fuzzer at runtime. RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir for fuzzer in $(find $SRC -name '*Fuzzer.java'); do fuzzer_basename=$(basename -s .java $fuzzer) javac --enable-preview --release 17 -cp $BUILD_CLASSPATH $fuzzer cp $SRC/$fuzzer_basename.class $OUT/ cp $SRC/${fuzzer_basename}\$SomeClass.class $OUT/ # Create an execution wrapper that executes Jazzer with the correct arguments. echo "#!/bin/bash # LLVMFuzzerTestOneInput for fuzzer detection. this_dir=\$(dirname \"\$0\") if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then mem_settings='-Xmx1900m:-Xss900k' else mem_settings='-Xmx2048m:-Xss1024k' fi LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \ \$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \ --cp=$RUNTIME_CLASSPATH \ --target_class=$fuzzer_basename \ --jvm_args=\"\$mem_settings:--enable-preview\" \ \$@" > $OUT/$fuzzer_basename chmod +x $OUT/$fuzzer_basename done ================================================ FILE: projects/kryo/project.yaml ================================================ homepage: "http://esotericsoftware.com/" language: jvm primary_contact: "thomas@umschalt.com" fuzzing_engines: - libfuzzer main_repo: "https://github.com/EsotericSoftware/kryo" sanitizers: - address vendor_ccs: - "norbert.schneider@code-intelligence.com" ================================================ FILE: projects/kubearmor/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go ENV FUZZING_LANGUAGE=go RUN git clone https://github.com/kubearmor/KubeArmor COPY build.sh $SRC/ WORKDIR $SRC/KubeArmor/KubeArmor ================================================ FILE: projects/kubearmor/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ chmod +x $SRC/KubeArmor/KubeArmor/fuzz/build.sh $SRC/KubeArmor/KubeArmor/fuzz/build.sh ================================================ FILE: projects/kubearmor/project.yaml ================================================ homepage: "https://kubearmor.io/" main_repo: "https://github.com/kubearmor/KubeArmor" primary_contact: "kubearmor@accuknox.com" auto_ccs : - "barun.acharya@accuknox.com" - "rudraksh@accuknox.com" - "ramakant@accuknox.com" - "rickprimeranjan@gmail.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubeedge/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubeedge/kubeedge RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing COPY build.sh $SRC/ WORKDIR $SRC/kubeedge ================================================ FILE: projects/kubeedge/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed 's/go 1.16/go 1.19 /g' -i $SRC/kubeedge/go.mod cd $SRC/kubeedge && go mod tidy $SRC/cncf-fuzzing/projects/kubeedge/build.sh ================================================ FILE: projects/kubeedge/project.yaml ================================================ homepage: "https://kubeedge.io/en/" primary_contact: "linguohui1@huawei.com" auto_ccs : - "xufei40@huawei.com" - "wangzefeng@huawei.com" vendor_ccs : - "Adam@adalogics.com" - "David@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/kubeedge/kubeedge' ================================================ FILE: projects/kubeflow-katib/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubeflow/katib RUN wget https://go.dev/dl/go1.25.1.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.25.1.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ WORKDIR katib COPY build.sh *.go $SRC/ ================================================ FILE: projects/kubeflow-katib/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/generateNNImage_fuzzer.go $SRC/katib/pkg/ui/v1beta1/ compile_native_go_fuzzer_v2 github.com/kubeflow/katib/pkg/ui/v1beta1 FuzzGenerateNNImage FuzzGenerateNNImage ================================================ FILE: projects/kubeflow-katib/generateNNImage_fuzzer.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package v1beta1 import ( "testing" ) func FuzzGenerateNNImage(f *testing.F) { f.Fuzz(func(t *testing.T, input1, input2 string) { // the target function is full of panics, // so we fuzz only for unrecoverable bugs. defer func() { if r := recover(); r != nil { } }() generateNNImage(input1, input2) }) } ================================================ FILE: projects/kubeflow-katib/project.yaml ================================================ homepage: "https://github.com/kubeflow/katib" language: go primary_contact: "andrey.velichkevich@gmail.com" main_repo: "https://github.com/kubeflow/katib" auto_ccs: - "adam@adalogics.com" - "johnugeorge109@gmail.com" - "antonin@stefanutti.fr" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubeflow-model-registry/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubeflow/model-registry WORKDIR model-registry COPY build.sh *.go $SRC/ ================================================ FILE: projects/kubeflow-model-registry/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mv $SRC/filter_fuzzer.go $SRC/model-registry/internal/db/filter/ compile_native_go_fuzzer_v2 github.com/kubeflow/model-registry/internal/db/filter FuzzFilterParse FuzzFilterParse ================================================ FILE: projects/kubeflow-model-registry/filter_fuzzer.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package filter import ( "testing" ) func FuzzFilterParse(f *testing.F) { f.Fuzz(func(t *testing.T, data string) { Parse(data) }) } ================================================ FILE: projects/kubeflow-model-registry/project.yaml ================================================ homepage: "https://github.com/kubeflow/model-registry" language: go primary_contact: "mmortari@redhat.com" main_repo: "https://github.com/kubeflow/model-registry" auto_ccs: - "adam@adalogics.com" - "ignatowicz@gmail.com" - "seth.pro@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubeflow-pipelines/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubeflow/pipelines WORKDIR pipelines COPY build.sh *.go $SRC/ ================================================ FILE: projects/kubeflow-pipelines/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ rm $SRC/pipelines/backend/src/v2/expression/expression_test.go mv $SRC/expr_fuzzer.go $SRC/pipelines/backend/src/v2/expression/ compile_native_go_fuzzer_v2 github.com/kubeflow/pipelines/backend/src/v2/expression FuzzExprSelect FuzzExprSelect ================================================ FILE: projects/kubeflow-pipelines/expr_fuzzer.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package expression import ( "testing" "google.golang.org/protobuf/types/known/structpb" ) func FuzzExprSelect(f *testing.F) { f.Fuzz(func(t *testing.T, input1, input2, input3, input4 string, inputType uint8) { var input *structpb.Value switch int(inputType) % 2 { case 0: input = structpb.NewStringValue(input1) case 1: m := map[string]interface{}{ input2: input3, } s, err := structpb.NewStruct(m) if err != nil { return } input = structpb.NewStructValue(s) } expr, err := New() if err != nil { t.Fatal(err) } expr.Select(input, input4) }) } ================================================ FILE: projects/kubeflow-pipelines/project.yaml ================================================ homepage: "https://github.com/kubeflow/pipelines" language: go primary_contact: "rmartine@redhat.com" main_repo: "https://github.com/kubeflow/pipelines" auto_ccs: - "adam@adalogics.com" - "humair88@hotmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubeflow-spark-operator/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubeflow/spark-operator WORKDIR spark-operator COPY build.sh *.go $SRC/ ================================================ FILE: projects/kubeflow-spark-operator/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ rm $SRC/spark-operator/pkg/certificate/certificate_test.go rm $SRC/spark-operator/pkg/certificate/suite_test.go rm $SRC/spark-operator/pkg/certificate/util_test.go mv $SRC/parseSecret_fuzzer.go $SRC/spark-operator/pkg/certificate/ compile_native_go_fuzzer_v2 github.com/kubeflow/spark-operator/v2/pkg/certificate FuzzParseCertManagerSecret FuzzParseCertManagerSecret compile_native_go_fuzzer_v2 github.com/kubeflow/spark-operator/v2/pkg/certificate FuzzParseInternalCertSecret FuzzParseInternalCertSecret ================================================ FILE: projects/kubeflow-spark-operator/parseSecret_fuzzer.go ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package certificate import ( "testing" "github.com/kubeflow/spark-operator/v2/pkg/common" corev1 "k8s.io/api/core/v1" ) func FuzzParseCertManagerSecret(f *testing.F) { f.Fuzz(func(t *testing.T, input1, input2, input3 []byte) { cp := &Provider{} cp.parseCertManagerSecret(&corev1.Secret{ Data: map[string][]byte{ common.CACert: input1, common.TLSCert: input2, common.TLSKey: input3, }, }) }) } func FuzzParseInternalCertSecret(f *testing.F) { f.Fuzz(func(t *testing.T, input1, input2, input3, input4 []byte) { cp := &Provider{} cp.parseInternalCertSecret(&corev1.Secret{ Data: map[string][]byte{ common.CACertPem: input1, common.CAKeyPem: input2, common.ServerCertPem: input3, common.ServerKeyPem: input4, }, }) }) } ================================================ FILE: projects/kubeflow-spark-operator/project.yaml ================================================ homepage: "https://github.com/kubeflow/spark-operator" language: go primary_contact: "github@chenyicn.net" main_repo: "https://github.com/kubeflow/spark-operator" auto_ccs: - "adam@adalogics.com" - "vara.bonthu@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubernetes/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kubernetes/kubernetes.git RUN git clone --depth 1 https://github.com/google/AFL RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus RUN git clone --depth 1 https://github.com/kubernetes/kops RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing RUN git clone --depth 1 https://github.com/AdamKorcz/instrumentation RUN git clone --depth 1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=november-backup RUN wget https://go.dev/dl/go1.24.5.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ && tar -C temp-go/ -xzf go1.24.5.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ WORKDIR $SRC/ COPY build.sh $SRC/ ================================================ FILE: projects/kubernetes/build.sh ================================================ #!/bin/bash # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -o nounset set -o pipefail set -o errexit set -x # Compile kOps fuzzers ( cd kops ./tests/fuzz/build.sh ) # Compile Kubernetes fuzzers cd $SRC/kubernetes function compile_fuzzer { local pkg=$1 local function=$2 local fuzzer="${pkg}_${function}" compile_go_fuzzer "k8s.io/kubernetes/test/fuzz/${pkg}" $function $fuzzer } # Build fuzzers from cncf-fuzzing: $SRC/cncf-fuzzing/projects/kubernetes/build.sh compile_fuzzer "yaml" "FuzzDurationStrict" compile_fuzzer "yaml" "FuzzMicroTimeStrict" compile_fuzzer "yaml" "FuzzSigYaml" compile_fuzzer "yaml" "FuzzTimeStrict" compile_fuzzer "yaml" "FuzzYamlV2" compile_fuzzer "json" "FuzzStrictDecode" compile_fuzzer "json" "FuzzNonStrictDecode" ================================================ FILE: projects/kubernetes/project.yaml ================================================ homepage: "https://kubernetes.io" primary_contact: "security@kubernetes.io" auto_ccs : - "adam@adalogics.com" - "aojea@google.com" - "david@adalogics.com" - "mikedanese@google.com" - "tabitha.c.sable@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address language: go main_repo: 'https://github.com/kubernetes/kubernetes.git' ================================================ FILE: projects/kubernetes-cluster-api/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go:ubuntu-24-04 RUN git clone --depth 1 https://github.com/kubernetes-sigs/cluster-api RUN git clone --depth 1 https://github.com/cncf/cncf-fuzzing COPY build.sh $SRC/ WORKDIR $SRC/cluster-api ================================================ FILE: projects/kubernetes-cluster-api/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/cluster-api/build.sh ================================================ FILE: projects/kubernetes-cluster-api/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://cluster-api.sigs.k8s.io" main_repo: "https://github.com/kubernetes-sigs/cluster-api" primary_contact: "sishivani@vmware.com" auto_ccs : - "adam@adalogics.com" - "david@adalogics.com" - "jeewan@vmware.com" - "naadir@randomvariable.co.uk" - "buringerst@vmware.com" - "swamyan@vmware.com" - "kmuldoon@vmware.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/kubevirt/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN apt update && apt install -y qemu-kvm libvirt-daemon-system RUN git clone --depth 1 https://github.com/kubevirt/kubevirt RUN git clone --depth=1 https://github.com/AdamKorcz/go-118-fuzz-build --branch=v2_2 $SRC/go-118-fuzz-build RUN git clone --depth=1 --branch=2025-work https://github.com/AdamKorcz/go-fuzz-headers-1 $SRC/go-fuzz-headers RUN git clone --depth=1 https://github.com/cncf/cncf-fuzzing COPY build.sh $SRC/ WORKDIR $SRC ================================================ FILE: projects/kubevirt/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/cncf-fuzzing/projects/kubevirt/build.sh ================================================ FILE: projects/kubevirt/project.yaml ================================================ homepage: "https://kubevirt.io" primary_contact: "adam@adalogics.com" auto_ccs : - "david@adalogics.com" - "cncf-kubevirt-maintainers@lists.cncf.io" - "vromanso@redhat.com" - "rhallisey@nvidia.com" - "bcarey@redhat.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address main_repo: 'https://github.com/kubevirt/kubevirt' ================================================ FILE: projects/kyverno/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-go RUN git clone --depth 1 https://github.com/kyverno/kyverno COPY build.sh $SRC/ WORKDIR $SRC/kyverno ================================================ FILE: projects/kyverno/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/kyverno/test/fuzz/oss_fuzz_build.sh ================================================ FILE: projects/kyverno/project.yaml ================================================ homepage: "https://www.kyverno.io" main_repo: "https://github.com/kyverno/kyverno" primary_contact: "chipzoller@gmail.com" auto_ccs : - "adam@adalogics.com" language: go fuzzing_engines: - libfuzzer sanitizers: - address ================================================ FILE: projects/lame/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool subversion pkg-config wget # ubuntu apt has not recent enough mpg123 RUN wget https://www.mpg123.de/snapshot RUN tar -xvf snapshot RUN mv mpg123* mpg123 RUN git clone --depth 1 https://github.com/guidovranken/LAME-fuzzers RUN svn checkout https://svn.code.sf.net/p/lame/svn/trunk/lame $SRC/lame COPY build.sh $SRC/ ================================================ FILE: projects/lame/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd mpg123 if [[ "$ARCHITECTURE" == "i386" ]]; then ./configure --enable-static --with-cpu=$ARCHITECTURE else ./configure --enable-static fi make -j$(nproc) make install popd cd $SRC/lame ./configure make -j$(nproc) cd $SRC/LAME-fuzzers if [[ $CXXFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi $CXX -std=c++17 -Wall -Wextra -Werror $CXXFLAGS -I fuzzing-headers/include/ -I $SRC/lame/include/ fuzzer-encoder.cpp $LIB_FUZZING_ENGINE $SRC/lame/libmp3lame/.libs/libmp3lame.a /usr/local/lib/libmpg123.a -lm -o $OUT/fuzzer-encoder cp fuzzer-encoder_seed_corpus.zip $OUT/ cp fuzzer-encoder.dict $OUT/ ================================================ FILE: projects/lame/project.yaml ================================================ homepage: "https://sourceforge.net/projects/lame/" main_repo: "https://svn.code.sf.net/p/lame/svn/trunk/lame" language: c++ primary_contact: "guidovranken@gmail.com" auto_ccs: - "bouvigne@gmail.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory architectures: - x86_64 - i386 fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/lark-parser/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## FROM gcr.io/oss-fuzz-base/base-builder-python RUN pip3 install --upgrade pip RUN git clone https://github.com/lark-parser/lark lark COPY *.sh *py $SRC/ WORKDIR $SRC/lark ================================================ FILE: projects/lark-parser/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## pip3 install . # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/lark-parser/fuzz_parse.py ================================================ #!/usr/bin/python3 # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################## import sys import atheris # Auto-fuzz heuristics used: py-autofuzz-heuristics-4.1.1 # Imports by the generated code import lark def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) grammar = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1,4096)) text = fdp.ConsumeUnicodeNoSurrogates(fdp.ConsumeIntInRange(1,4096)) # Class target. try: c1 = lark.lark.Lark(grammar) c1.parse(text) except(lark.exceptions.LarkError,): pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/lark-parser/project.yaml ================================================ homepage: https://github.com/lark-parser/lark main_repo: https://github.com/lark-parser/lark language: python fuzzing_engines: - libfuzzer sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/lcms/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/mm2/Little-CMS.git lcms RUN mkdir $SRC/seeds && \ cd seeds && \ cp $SRC/lcms/testbed/bad.icc . && \ cp $SRC/lcms/testbed/toosmall.icc . && \ cp $SRC/lcms/testbed/test1.icc . && \ cp $SRC/lcms/testbed/crayons.icc . && \ cp $SRC/lcms/testbed/ibm-t61.icc . && \ #add more seeds from the testbed dir cp $SRC/lcms/testbed/bad_mpe.icc . && \ cp $SRC/lcms/testbed/new.icc . && \ cp $SRC/lcms/testbed/test2.icc . && \ cp $SRC/lcms/testbed/test3.icc . && \ cp $SRC/lcms/testbed/test4.icc . && \ cp $SRC/lcms/testbed/test5.icc . && \ zip -rj $SRC/seed_corpus.zip $SRC/seeds/* WORKDIR lcms COPY build.sh run_tests.sh *.c *.options *.dict $SRC/ ================================================ FILE: projects/lcms/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build the target. ./configure --enable-shared=no make -j$(nproc) all # build your fuzzer(s) FUZZERS="cmsIT8_load_fuzzer \ cms_transform_fuzzer \ cms_overwrite_transform_fuzzer \ cms_transform_all_fuzzer \ cms_profile_fuzzer \ cms_universal_transform_fuzzer \ cms_transform_extended_fuzzer \ cms_md5_fuzzer \ cms_dict_fuzzer \ cms_postscript_fuzzer \ cms_cie_cam02_fuzzer \ cms_gdb_fuzzer \ cms_cgats_fuzzer \ cms_virtual_profile_fuzzer \ cms_devicelink_fuzzer" for F in $FUZZERS; do $CC $CFLAGS -c -Iinclude \ $SRC/$F.c -o $SRC/$F.o $CXX $CXXFLAGS \ $SRC/$F.o -o $OUT/$F \ $LIB_FUZZING_ENGINE src/.libs/liblcms2.a done cp $SRC/*.dict $SRC/*.options $OUT/ cp $SRC/icc.dict $OUT/cms_transform_all_fuzzer.dict cp $SRC/icc.dict $OUT/cms_transform_extended_fuzzer.dict cp $SRC/icc.dict $OUT/cms_universal_transform_fuzzer.dict cp $SRC/icc.dict $OUT/cms_profile_fuzzer.dict cp $SRC/icc.dict $OUT/cms_postscript_fuzzer.dict cp $SRC/icc.dict $OUT/cms_virtual_profile_fuzzer.dict cp $SRC/icc.dict $OUT/cms_md5_fuzzer.dict cp $SRC/seed_corpus.zip $OUT/cms_postscript_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_profile_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_universal_transform_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_transform_all_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_transform_extended_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_transform_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_virtual_profile_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cmsIT8_load_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_md5_fuzzer_seed_corpus.zip cp $SRC/seed_corpus.zip $OUT/cms_overwrite_transform_fuzzer_seed_corpus.zip ================================================ FILE: projects/lcms/cmsIT8_load_fuzzer.c ================================================ // Copyright 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include "lcms2.h" // The main sink int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) return 0; cmsHANDLE handle = cmsIT8LoadFromMem(0, (void *)data, size); if (handle) { char filename[256]; sprintf(filename, "/tmp/fuzzer-it.%d.it8", getpid()); cmsIT8SaveToFile(handle, filename); cmsIT8Free(handle); } return 0; } ================================================ FILE: projects/lcms/cmsIT8_load_fuzzer.options ================================================ [libfuzzer] dict = icc.dict ================================================ FILE: projects/lcms/cms_cgats_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 8){ return 0; } cmsContext context = cmsCreateContext(NULL, (void *)data); uint32_t Row = *((uint32_t *)data); uint32_t Col = *((uint32_t *)data+1); /* Write */ cmsHANDLE it8; cmsInt32Number i; it8 = cmsIT8Alloc(0); if (it8 == NULL) return 0; cmsIT8SetSheetType(it8, "LCMS/TESTING"); cmsIT8SetPropertyStr(it8, "ORIGINATOR", "1 2 3 4"); cmsIT8SetPropertyUncooked(it8, "DESCRIPTOR", "1234"); cmsIT8SetPropertyStr(it8, "MANUFACTURER", "3"); cmsIT8SetPropertyDbl(it8, "CREATED", data[0] / 255.0); cmsIT8SetPropertyDbl(it8, "SERIAL", data[1] / 255.0); cmsIT8SetPropertyHex(it8, "MATERIAL", 0x123); cmsIT8SetPropertyDbl(it8, "NUMBER_OF_SETS", 10); cmsIT8SetPropertyDbl(it8, "NUMBER_OF_FIELDS", Row); cmsIT8SetDataFormat(it8, 0, "SAMPLE_ID"); cmsIT8SetDataFormat(it8, 1, "RGB_R"); cmsIT8SetDataFormat(it8, 2, "RGB_G"); cmsIT8SetDataFormat(it8, 3, "RGB_B"); for (i=0; i < 10; i++) { char Patch[20]; sprintf(Patch, "P%d", i); cmsIT8SetDataRowCol(it8, i, 0, Patch); cmsIT8SetDataRowColDbl(it8, i, 1, i); cmsIT8SetDataRowColDbl(it8, i, 2, i); cmsIT8SetDataRowColDbl(it8, i, 3, i); } cmsIT8SaveToFile(it8, "TEST.IT8"); cmsIT8Free(it8); it8 = cmsIT8LoadFromFile(0, "TEST.IT8"); if (it8 == NULL) return 0; /* Read */ cmsIT8GetDataRowColDbl(it8,Row,Col); cmsIT8GetPropertyDbl(it8, "DESCRIPTOR"); cmsIT8GetDataDbl(it8, "P3", "RGB_G"); cmsIT8Free(it8); return 1; } ================================================ FILE: projects/lcms/cms_cie_cam02_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < sizeof(cmsViewingConditions)) { return 0; } // Define and initialize the viewing conditions structure cmsViewingConditions viewingConditions; viewingConditions.whitePoint.X = data[0]/ 255.0; viewingConditions.whitePoint.Y = data[1]/ 255.0; viewingConditions.whitePoint.Z = data[2]/ 255.0; viewingConditions.Yb = data[3] / 255.0; viewingConditions.La = data[4]/ 255.0; viewingConditions.surround = data[5] % 4 + 1; //from 1 to 4 viewingConditions.D_value = data[6] / 255.0; cmsContext context = cmsCreateContext(NULL, NULL); cmsHANDLE hModel = cmsCIECAM02Init(context, &viewingConditions); if (hModel) { // Perform forward and reverse CAM02 transformations with appropriate input data cmsCIEXYZ inputXYZ; inputXYZ.X = data[0]/ 255.0; // Random value between 0 and 1 inputXYZ.Y = data[1] / 255.0; inputXYZ.Z = data[2] / 255.0; cmsJCh outputJCh; cmsCIEXYZ outputXYZ; cmsCIECAM02Forward(hModel, &inputXYZ, &outputJCh); cmsCIECAM02Reverse(hModel, &outputJCh, &outputXYZ); cmsCIECAM02Done(hModel); } cmsDeleteContext(context); return 0; } ================================================ FILE: projects/lcms/cms_devicelink_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "lcms2.h" #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 4) { return 0; } // cmsCreateInkLimitingDeviceLink cmsFloat64Number limit = *((const uint32_t *)data) % 401; cmsHPROFILE limitingDeviceLinkProfile = cmsCreateInkLimitingDeviceLink(cmsSigCmykData, limit); if (limitingDeviceLinkProfile) { cmsCloseProfile(limitingDeviceLinkProfile); } return 0; } ================================================ FILE: projects/lcms/cms_dict_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include "lcms2.h" wchar_t* generateWideString(const char* characters, const uint8_t *data){ if (!characters){ return NULL; } char stringToWide[10]; for (int i = 0; i < 9; i++){ stringToWide[i] = characters[data[i] % 95]; } stringToWide[9] = '\0'; int requiredSize = mbstowcs(NULL, stringToWide, 0); wchar_t* wideString = (wchar_t *)malloc((requiredSize + 1) * sizeof(wchar_t)); mbstowcs(wideString, stringToWide, requiredSize + 1); return wideString; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 27){ return 0; } cmsContext context = cmsCreateContext(NULL, (void *)data); if (!context) { return 0; } // Create a Dictionary handle cmsHANDLE hDict = cmsDictAlloc(context); if (!hDict) { return 0; } cmsMLU *mlu = cmsMLUalloc(hDict, 0); if (!mlu) { return 0; } char* characters = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; wchar_t* wideString = generateWideString(characters, data); cmsMLUsetWide(mlu, "en", "US", wideString); free(wideString); char ObtainedLanguage[3], ObtainedCountry[3]; ObtainedLanguage[0] = characters[*(data+1) % 95]; ObtainedLanguage[1] = characters[*(data+2) % 95]; ObtainedLanguage[2] = characters[*(data) % 95]; ObtainedCountry[0] = characters[*(data+2) % 95]; ObtainedCountry[1] = characters[*data % 95]; ObtainedCountry[2] = characters[*(data+1) % 95]; cmsMLUgetTranslation(mlu, "en", "US",ObtainedLanguage,ObtainedCountry); cmsMLUtranslationsCount(mlu); cmsMLUtranslationsCodes(mlu, *((uint32_t *)data), ObtainedLanguage, ObtainedCountry); cmsMLU* displayName = mlu; cmsMLU* displayValue = mlu; //cmsDictAddEntry wchar_t* name = generateWideString(characters, data + 9); wchar_t* value = generateWideString(characters, data + 18); cmsDictAddEntry(hDict, name, value, displayName, displayValue); free(name); free(value); //cmsDictDup cmsHANDLE ResultDictDup = cmsDictDup(hDict); if (ResultDictDup) { cmsDictFree(ResultDictDup); } // Iterate over the Dictionary entries const cmsDICTentry* entry = cmsDictGetEntryList(hDict); cmsDictNextEntry(entry); cmsMLUfree(mlu); cmsDictFree(hDict); return 0; } ================================================ FILE: projects/lcms/cms_gdb_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 16) { return 0; } //cmsGBDAlloc cmsHANDLE hGDB = cmsGBDAlloc(NULL); if (!hGDB){ return 0; } //cmsGDBAddPoint cmsCIELab Lab; Lab.L = *((const uint32_t *)data); Lab.a = *((const uint32_t *)data+1); Lab.b = *((const uint32_t *)data+2); cmsGDBAddPoint(hGDB, &Lab); //cmsGDBCheckPoint cmsGDBCheckPoint(hGDB, &Lab); //cmsGDBCompute cmsGDBCompute(hGDB, *((const uint32_t *)data+3)); //cmsGBDFree cmsGBDFree(hGDB); return 0; } ================================================ FILE: projects/lcms/cms_md5_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { cmsHPROFILE hProfile = cmsOpenProfileFromMem(data, size); if (!hProfile){ return 0; } //cmsMD5computeID cmsMD5computeID(hProfile); cmsCloseProfile(hProfile); return 0; } ================================================ FILE: projects/lcms/cms_overwrite_transform_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 2) { return 0; } size_t mid = size / 2; cmsHPROFILE hInProfile, hOutProfile; cmsHTRANSFORM hTransform; hInProfile = cmsOpenProfileFromMem(data, mid); hOutProfile = cmsOpenProfileFromMem(data + mid, size - mid); hTransform = cmsCreateTransform(hInProfile, TYPE_BGR_8, hOutProfile, TYPE_BGR_8, INTENT_PERCEPTUAL, 0); cmsCloseProfile(hInProfile); cmsCloseProfile(hOutProfile); if (hTransform) { cmsDeleteTransform(hTransform); } return 0; } ================================================ FILE: projects/lcms/cms_overwrite_transform_fuzzer.options ================================================ [libfuzzer] dict = icc.dict ================================================ FILE: projects/lcms/cms_postscript_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 16) { return 0; } cmsContext context = cmsCreateContext(NULL, (void *)data); if (!context){ return 0; } cmsHPROFILE hProfile = cmsOpenProfileFromMem(data, size); if (!hProfile){ return 0; } uint32_t flags = *((const uint32_t *)data+2); uint32_t intent = *((const uint32_t *)data+3) % 16; /* cmsGetPostScriptCSA */ cmsUInt32Number result1 = cmsGetPostScriptCSA(context, hProfile, intent, flags, NULL, size); /* cmsGetPostScriptCRD */ cmsUInt32Number result2 = cmsGetPostScriptCRD(context, hProfile, intent, flags, NULL, size); cmsCloseProfile(hProfile); cmsDeleteContext(context); return 0; } ================================================ FILE: projects/lcms/cms_profile_fuzzer.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include "lcms2.h" cmsTagSignature tagsToRead[] = { cmsSigGreenColorantTag, cmsSigGreenMatrixColumnTag, cmsSigGreenTRCTag, cmsSigMeasurementTag, cmsSigNamedColorTag, cmsSigPreview1Tag, cmsSigPs2CRD2Tag, cmsSigPs2CRD3Tag, cmsSigRedTRCTag, }; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) return 0; char filename[256]; sprintf(filename, "/tmp/libfuzzer.%d.icc", getpid()); FILE *fp = fopen(filename, "wb"); if (!fp) { return 0; } fwrite(data, size, 1, fp); fclose(fp); cmsHPROFILE hProfile = cmsOpenProfileFromFile(filename, "r"); // If we have a profile, perform a set of operations if (hProfile) { char tagBuffer[4]; // Perform multiple tag reads. Read tags twice as behavior matters // if tags have been read before. for (int j = 0; j < 2; j++) { for (int i = 0; i < sizeof(tagsToRead)/sizeof(tagsToRead[0]); i++) { cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadRawTag(hProfile, tagsToRead[i], NULL, 0); cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadTag(hProfile, tagsToRead[i]); } } // Read profile info cmsInfoType info = data[0] % 4; char outBuffer[100]; cmsGetProfileInfoASCII(hProfile, info, "DEN", "DEN", outBuffer, 100); cmsGetTagCount(hProfile); if (size > 2) { cmsGetTagSignature(hProfile, (cmsUInt32Number)data[1]); } if (size > 40) { cmsTagSignature tag = *((uint32_t *)(data+5)); cmsTagLinkedTo(hProfile, tag); } // Save to random file cmsSaveProfileToFile(hProfile, "random.icc"); cmsCloseProfile(hProfile); } // Let's write the profile now. hProfile = cmsOpenProfileFromFile(filename, "w"); if (hProfile) { char tagBuffer[4] = {'a', 'a', 'a', 'a'}; // Perform multiple tag reads for (int j = 0; j < 2; j++) { for (int i = 0; i < sizeof(tagsToRead)/sizeof(tagsToRead[0]); i++) { cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadRawTag(hProfile, tagsToRead[i], NULL, 0); cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadTag(hProfile, tagsToRead[i]); } } for (int i = 0; i < sizeof(tagsToRead)/sizeof(tagsToRead[0]); i++) { cmsWriteRawTag(hProfile, tagsToRead[i], tagBuffer, 4); } for (int j = 0; j < 2; j++) { for (int i = 0; i < sizeof(tagsToRead)/sizeof(tagsToRead[0]); i++) { cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadRawTag(hProfile, tagsToRead[i], NULL, 0); cmsReadRawTag(hProfile, tagsToRead[i], tagBuffer, 4); cmsReadTag(hProfile, tagsToRead[i]); } } for (int i = 0; i < sizeof(tagsToRead)/sizeof(tagsToRead[0]); i++) { cmsWriteRawTag(hProfile, tagsToRead[i], tagBuffer, 4); } // Save to random file cmsSaveProfileToFile(hProfile, "random.icc"); cmsCloseProfile(hProfile); } unlink(filename); return 0; } ================================================ FILE: projects/lcms/cms_transform_all_fuzzer.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" void run_test(const uint8_t *data, size_t size, uint32_t intent_id, uint32_t input_format, uint32_t output_format, uint32_t flags) { if (size < 2) { return; } size_t mid = size / 2; cmsHPROFILE hInProfile, hOutProfile; cmsHTRANSFORM hTransform; hInProfile = cmsOpenProfileFromMem(data, mid); hOutProfile = cmsOpenProfileFromMem(data + mid, size - mid); hTransform = cmsCreateTransform(hInProfile, input_format, hOutProfile, output_format, intent_id, flags); cmsCloseProfile(hInProfile); cmsCloseProfile(hOutProfile); if (hTransform) { cmsDeleteTransform(hTransform); } } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 16) { return 0; } // Generate a random set of args for cmsCreateTransform uint32_t input_format = *((const uint32_t *)data); uint32_t output_format = *((const uint32_t *)data+1); uint32_t flags = *((const uint32_t *)data+2); uint32_t intent = *((const uint32_t *)data+3) % 16; data += 16; size -= 16; run_test(data, size, intent, input_format, output_format, flags); return 0; } ================================================ FILE: projects/lcms/cms_transform_extended_fuzzer.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" // An extended cmsDoTransform fuzzer. The idea is to include a range of // input/output source formats. void run_test(const uint8_t *data, size_t size, uint32_t intent, uint32_t flags, int dstVal) { if (size < 2) { return; } cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size); if (!srcProfile) return; // Select dstProfile and dstFormat cmsHPROFILE dstProfile; uint32_t dstFormat; if (dstVal == 1) { dstProfile = cmsCreateLab4Profile(NULL); dstFormat = TYPE_Lab_8; } else if (dstVal == 2) { dstProfile = cmsCreateLab2Profile(NULL); dstFormat = TYPE_LabV2_8; } else if (dstVal == 3) { cmsToneCurve* gamma18; gamma18 = cmsBuildGamma(0, 1.8); dstProfile = cmsCreateGrayProfile(NULL, gamma18); cmsFreeToneCurve(gamma18); dstFormat = TYPE_GRAY_FLT | EXTRA_SH(1); } else if (dstVal == 4) { dstProfile = cmsCreateXYZProfile(); dstFormat = TYPE_XYZ_16; } else if (dstVal == 5) { dstProfile = cmsCreateXYZProfile(); dstFormat = TYPE_XYZ_DBL; } else if (dstVal == 6) { dstProfile = cmsCreateLab4Profile(NULL); dstFormat = TYPE_Lab_DBL; } else if (dstVal == 7) { dstProfile = cmsCreateLab4Profile(NULL); dstFormat = TYPE_Lab_DBL; } else if (dstVal == 8){ dstProfile = cmsCreate_OkLabProfile(NULL); dstFormat = (FLOAT_SH(1)|COLORSPACE_SH(PT_MCH3)|CHANNELS_SH(3)|BYTES_SH(0)); } else if (dstVal == 9){ dstProfile = cmsCreateNULLProfile(); dstFormat = 0; } else if (dstVal == 10){ dstProfile = cmsCreateBCHSWabstractProfile(17, 0, 1.2, 0, 3, 5000, 5000); dstFormat = TYPE_Lab_DBL; } else { dstProfile = cmsCreate_sRGBProfile(); dstFormat = TYPE_RGB_8; } if (!dstProfile) { cmsCloseProfile(srcProfile); return; } // Extract srcFormat from the random src profile cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile); cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS); cmsUInt32Number srcFormat; if (srcCS == cmsSigLabData) { if (dstVal != 7) { srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0); } else { srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0) | FLOAT_SH(1); } } else { srcFormat = COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1); } // Create the transform cmsContext ctx = cmsCreateContext(NULL, NULL); cmsHTRANSFORM hTransform = cmsCreateTransformTHR( ctx, srcProfile, srcFormat, dstProfile, dstFormat, intent, flags); cmsCloseProfile(srcProfile); cmsCloseProfile(dstProfile); if (!hTransform) return; // Do transformation. // The output buffer type depends on the dstFormat // The input buffer type depends on the srcFormat. if (T_BYTES(srcFormat) == 0) { // 0 means double // Ensure output is large enough long long output[nSrcComponents*4]; double input[nSrcComponents]; for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 0.5f; cmsDoTransform(hTransform, input, output, 1); } else { uint8_t input[nSrcComponents]; for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128; if (dstFormat == TYPE_XYZ_16) { cmsCIEXYZ output_XYZ = { 0, 0, 0 }; cmsDoTransform(hTransform, input, &output_XYZ, 1); } else if (dstFormat == TYPE_XYZ_DBL) { cmsCIEXYZTRIPLE out[4]; cmsDoTransform(hTransform, input, out, 1); } else if (dstFormat == TYPE_Lab_DBL || dstFormat == (FLOAT_SH(1)|COLORSPACE_SH(PT_MCH3)|CHANNELS_SH(3)|BYTES_SH(0))) { cmsCIELab Lab1; cmsDoTransform(hTransform, input, &Lab1, 1); } else { uint8_t output[4]; cmsDoTransform(hTransform, input, output, 1); } } cmsDeleteTransform(hTransform); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 12) { return 0; } uint32_t flags = *((const uint32_t *)data+0); uint32_t intent = *((const uint32_t *)data+1) % 16; int decider = *((int*)data+2) % 11; data += 12; size -= 12; // Transform using various output formats. run_test(data, size, intent, flags, decider); return 0; } ================================================ FILE: projects/lcms/cms_transform_fuzzer.c ================================================ // Copyright 2016 The PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { cmsHPROFILE srcProfile = cmsOpenProfileFromMem(data, size); if (!srcProfile) return 0; cmsHPROFILE dstProfile = cmsCreate_sRGBProfile(); if (!dstProfile) { cmsCloseProfile(srcProfile); return 0; } cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile); cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS); cmsUInt32Number srcFormat; if (srcCS == cmsSigLabData) { srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0); } else { srcFormat = COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1); } cmsUInt32Number intent = 0; cmsUInt32Number flags = 0; cmsHTRANSFORM hTransform = cmsCreateTransform( srcProfile, srcFormat, dstProfile, TYPE_BGR_8, intent, flags); cmsCloseProfile(srcProfile); cmsCloseProfile(dstProfile); if (!hTransform) return 0; uint8_t output[4]; if (T_BYTES(srcFormat) == 0) { // 0 means double double input[nSrcComponents]; for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 0.5f; cmsDoTransform(hTransform, input, output, 1); } else { uint8_t input[nSrcComponents]; for (uint32_t i = 0; i < nSrcComponents; i++) input[i] = 128; cmsDoTransform(hTransform, input, output, 1); } cmsDeleteTransform(hTransform); return 0; } ================================================ FILE: projects/lcms/cms_transform_fuzzer.options ================================================ [libfuzzer] dict = icc.dict ================================================ FILE: projects/lcms/cms_universal_transform_fuzzer.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include "lcms2.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 2) { return 0; } size_t mid = size / 2; cmsHPROFILE hInProfile, hOutProfile; cmsHTRANSFORM hTransform; hInProfile = cmsOpenProfileFromMem(data, mid); hOutProfile = cmsOpenProfileFromMem(data + mid, size - mid); hTransform = cmsCreateTransform(hInProfile, TYPE_BGR_8, hOutProfile, TYPE_BGR_8, INTENT_PERCEPTUAL, 0); cmsCloseProfile(hInProfile); cmsCloseProfile(hOutProfile); if (hTransform) { cmsDeleteTransform(hTransform); } return 0; } ================================================ FILE: projects/lcms/cms_virtual_profile_fuzzer.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include "lcms2.h" #include int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 16) { return 0; } cmsHPROFILE hInProfile = cmsOpenProfileFromMem(data, size); if (!hInProfile) { return 0; } cmsHPROFILE hOutProfile = cmsCreate_sRGBProfile(); if (!hOutProfile) { cmsCloseProfile(hInProfile); return 0; } cmsColorSpaceSignature srcCS = cmsGetColorSpace(hInProfile); cmsUInt32Number nSrcComponents = cmsChannelsOf(srcCS); cmsUInt32Number srcFormat; if (srcCS == cmsSigLabData) { srcFormat = COLORSPACE_SH(PT_Lab) | CHANNELS_SH(nSrcComponents) | BYTES_SH(0); } else { srcFormat = COLORSPACE_SH(PT_ANY) | CHANNELS_SH(nSrcComponents) | BYTES_SH(1); } cmsHTRANSFORM hTransform = cmsCreateTransform( hInProfile, srcFormat, hOutProfile, TYPE_BGR_8, *((const uint32_t *)data + 3) % 16, *((const uint32_t *)data + 2)); cmsCloseProfile(hInProfile); cmsCloseProfile(hOutProfile); if (!hTransform) { return 0; } cmsFloat64Number version; if (*((const uint32_t *)data + 3) % 2 == 0) { version = 3.4; } else { version = 4.4; } // cmsTransform2DeviceLink cmsHPROFILE devicelinkProfile = cmsTransform2DeviceLink( hTransform, version, *((const uint32_t *)data + 2)); // clean up cmsDeleteTransform(hTransform); if (devicelinkProfile) { cmsCloseProfile(devicelinkProfile); } // cmsCreateLinearizationDeviceLink cmsToneCurve *tone = cmsBuildGamma(NULL, *((const uint32_t *)data + 3)); if (!tone) { return 0; } // 15 curves, so it can handle all color spaces cmsToneCurve *rgb_curves[15] = {tone, tone, tone, tone, tone, tone, tone, tone, tone, tone, tone, tone, tone, tone, tone}; cmsHPROFILE linearizationDeviceLinkProfile = cmsCreateLinearizationDeviceLink(srcCS, rgb_curves); cmsFreeToneCurve(tone); if (linearizationDeviceLinkProfile) { cmsCloseProfile(linearizationDeviceLinkProfile); } return 0; } ================================================ FILE: projects/lcms/icc.dict ================================================ # Fuzzing dictionary for icc # Extracted from lcms2.h of Little-CMS project 2.8. magic="acsp" sig="lcms" # Base ICC type definitions "chrm" "clro" "clrt" "crdi" "curv" "data" "dict" "dtim" "devs" "mft2" "mft1" "mAB " "mBA " "meas" "mluc" "mpet" "ncol" "ncl2" "para" "pseq" "psid" "rcs2" "sf32" "scrn" "sig " "text" "desc" "uf32" "bfd " "ui16" "ui32" "ui64" "ui08" "vcgt" "view" "XYZ " # Base ICC tag definitions "A2B0" "A2B1" "A2B2" "bXYZ" "bXYZ" "bTRC" "B2A0" "B2A1" "B2A2" "calt" "targ" "chad" "chrm" "clro" "clrt" "clot" "ciis" "cprt" "crdi" "data" "dtim" "dmnd" "dmdd" "devs" "D2B0" "D2B1" "D2B2" "D2B3" "B2D0" "B2D1" "B2D2" "B2D3" "gamt" "kTRC" "gXYZ" "gXYZ" "gTRC" "lumi" "meas" "bkpt" "wtpt" "ncol" "ncl2" "resp" "rig0" "pre0" "pre1" "pre2" "desc" "dscm" "pseq" "psid" "psd0" "psd1" "psd2" "psd3" "ps2s" "ps2i" "rXYZ" "rXYZ" "rTRC" "rig2" "scrd" "scrn" "tech" "bfd " "vued" "view" "vcgt" "meta" "arts" # ICC Technology tag "dcam" "fscn" "rscn" "ijet" "twax" "epho" "esta" "dsub" "rpho" "fprn" "vidm" "vidc" "pjtv" "CRT " "PMD " "AMD " "KPCD" "imgs" "grav" "offs" "silk" "flex" "mpfs" "mpfr" "dmpc" "dcpj" # ICC Color spaces "XYZ " "Lab " "Luv " "YCbr" "Yxy " "RGB " "GRAY" "HSV " "HLS " "CMYK" "CMY " "MCH1" "MCH2" "MCH3" "MCH4" "MCH5" "MCH6" "MCH7" "MCH8" "MCH9" "MCHA" "MCHB" "MCHC" "MCHD" "MCHE" "MCHF" "nmcl" "1CLR" "2CLR" "3CLR" "4CLR" "5CLR" "6CLR" "7CLR" "8CLR" "9CLR" "ACLR" "BCLR" "CCLR" "DCLR" "ECLR" "FCLR" "LuvK" # ICC Profile Class "scnr" "mntr" "prtr" "link" "abst" "spac" "nmcl" # ICC Platforms "APPL" "MSFT" "SUNW" "SGI " "TGNT" "*nix" # Reference gamut "prmg" # For cmsSigColorimetricIntentImageStateTag "scoe" "sape" "fpce" "rhoc" "rpoc" # Multi process elements types "cvst" "matf" "clut" "bACS" "eACS" "l2x " "x2l " "ncl " "2 4 " "4 2 " "idn " "d2l " "l2d " "d2x " "x2d " "clp " # Types of CurveElements "parf" "samf" "curf" # Used in ResponseCurveType "StaA" "StaE" "StaI" "StaT" "StaM" "DN " "DN P" "DNN " "DNNP" ================================================ FILE: projects/lcms/project.yaml ================================================ main_repo: "https://github.com/mm2/Little-CMS" homepage: "http://www.littlecms.com/" language: c++ primary_contact: "marti.maria.s@gmail.com" auto_ccs: - "david@adalogics.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory architectures: - x86_64 - i386 ================================================ FILE: projects/lcms/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/leptonica/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make automake libtool \ pkg-config cmake nasm # Install autoconf 2.71+ required by libtiff RUN curl -LO http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz && \ tar xzf autoconf-2.71.tar.gz && \ cd autoconf-2.71 && \ ./configure && \ make && \ make install && \ cd .. && \ rm -rf autoconf-2.71 autoconf-2.71.tar.gz RUN git clone --depth 1 https://github.com/DanBloomberg/leptonica.git leptonica RUN git clone --depth 1 https://github.com/madler/zlib.git zlib RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff libtiff RUN git clone --depth 1 https://github.com/glennrp/libpng.git libpng RUN git clone --depth 1 https://chromium.googlesource.com/webm/libwebp libwebp RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit jbigkit RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo libjpeg-turbo RUN git clone --depth 1 https://github.com/facebook/zstd zstd WORKDIR leptonica COPY build.sh $SRC/ ================================================ FILE: projects/leptonica/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/leptonica/prog/fuzzing/oss-fuzz-build.sh ================================================ FILE: projects/leptonica/project.yaml ================================================ homepage: "http://www.leptonica.com" language: c++ primary_contact: "taking@google.com" auto_ccs: - "kusano@google.com" - "dbloomberg@google.com" - "dan.bloomberg@gmail.com" - "stjoweil@googlemail.com" - "Adam@adalogics.com" - "ballbach@google.com" sanitizers: - address - undefined - memory labels: pix_rotate_shear_fuzzer: - sundew main_repo: 'https://github.com/DanBloomberg/leptonica.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/leveldb/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y build-essential cmake gettext make RUN git clone --recurse-submodules https://github.com/google/leveldb.git WORKDIR $SRC/ # Copy in our files COPY build.sh $SRC/ COPY *.cc $SRC/leveldb/ COPY *.options $SRC/ ================================================ FILE: projects/leveldb/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # Copyright 2020 Luca Boccassi # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Avoid: clang++: error: invalid argument '-fsanitize=vptr' not allowed with '-fno-rtti' CFLAGS="$CFLAGS -fno-sanitize=vptr" CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" # Pick C++17 due to use of std::filesystem CXXFLAGS="$CXXFLAGS -std=c++17" cd $SRC/leveldb mkdir -p build && cd build cmake -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_TESTS=0 \ -DLEVELDB_BUILD_BENCHMARKS=0 -DCMAKE_CXX_STANDARD=17 .. && cmake --build . for fuzzer in fuzz_db; do # Compile $CXX $CXXFLAGS -c ../${fuzzer}.cc -o ${fuzzer}.o \ -DLEVELDB_PLATFORM_POSIX=1 -Wall \ -I$SRC/leveldb/build/include -I$SRC/leveldb/ -I$SRC/leveldb/include # Link $CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${fuzzer}.o -o $OUT/${fuzzer} $SRC/leveldb/build/libleveldb.a done # Copy options to out cp $SRC/*options $OUT/ ================================================ FILE: projects/leveldb/fuzz_db.cc ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include "leveldb/db.h" #include "leveldb/iterator.h" #include "leveldb/options.h" #include "leveldb/status.h" #include namespace { // Deletes the database directory when going out of scope. class AutoDbDeleter { public: static constexpr char kDbPath[] = "/tmp/testdb"; AutoDbDeleter() = default; AutoDbDeleter(const AutoDbDeleter&) = delete; AutoDbDeleter& operator=(const AutoDbDeleter&) = delete; ~AutoDbDeleter() { std::filesystem::remove_all(kDbPath); } }; // static constexpr char AutoDbDeleter::kDbPath[]; // Returns nullptr (a falsey unique_ptr) if opening fails. std::unique_ptr OpenDB() { leveldb::Options options; options.create_if_missing = true; leveldb::DB* db_ptr; leveldb::Status status = leveldb::DB::Open(options, AutoDbDeleter::kDbPath, &db_ptr); if (!status.ok()) return nullptr; return std::unique_ptr(db_ptr); } enum class FuzzOp { kPut = 0, kGet = 1, kDelete = 2, kGetProperty = 3, kIterate = 4, kGetReleaseSnapshot = 5, kReopenDb = 6, kCompactRange = 7, // Add new values here. // When adding new values, update to the last value above. kMaxValue = kCompactRange, }; } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Must occur before `db` so the deletion doesn't happen while the DB is open. AutoDbDeleter db_deleter; std::unique_ptr db = OpenDB(); if (!db.get()) return 0; // Perform a sequence of operations on the database. FuzzedDataProvider fuzzed_data(data, size); while (fuzzed_data.remaining_bytes() != 0) { FuzzOp fuzz_op = fuzzed_data.ConsumeEnum(); switch (fuzz_op) { case FuzzOp::kPut: { std::string key = fuzzed_data.ConsumeRandomLengthString(); std::string value = fuzzed_data.ConsumeRandomLengthString(); db->Put(leveldb::WriteOptions(), key, value); break; } case FuzzOp::kGet: { std::string key = fuzzed_data.ConsumeRandomLengthString(); std::string value; db->Get(leveldb::ReadOptions(), key, &value); break; } case FuzzOp::kDelete: { std::string key = fuzzed_data.ConsumeRandomLengthString(); db->Delete(leveldb::WriteOptions(), key); break; } case FuzzOp::kGetProperty: { std::string name = fuzzed_data.ConsumeRandomLengthString(); std::string value; db->GetProperty(name, &value); break; } case FuzzOp::kIterate: { std::unique_ptr it( db->NewIterator(leveldb::ReadOptions())); for (it->SeekToFirst(); it->Valid(); it->Next()) continue; } case FuzzOp::kGetReleaseSnapshot: { leveldb::ReadOptions snapshot_options; snapshot_options.snapshot = db->GetSnapshot(); std::unique_ptr it(db->NewIterator(snapshot_options)); db->ReleaseSnapshot(snapshot_options.snapshot); } case FuzzOp::kReopenDb: { // The database must be closed before attempting to reopen it. Otherwise, // the open will fail due to exclusive locking. db.reset(); db = OpenDB(); if (!db) return 0; // Reopening the database failed. break; } case FuzzOp::kCompactRange: { std::string begin_key = fuzzed_data.ConsumeRandomLengthString(); std::string end_key = fuzzed_data.ConsumeRandomLengthString(); leveldb::Slice begin_slice(begin_key); leveldb::Slice end_slice(end_key); db->CompactRange(&begin_slice, &end_slice); break; } } } return 0; } ================================================ FILE: projects/leveldb/fuzz_db.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/leveldb/project.yaml ================================================ homepage: "https://github.com/google/leveldb" language: c++ primary_contact: "costan@google.com" auto_ccs : - "cmumford@google.com" - "david@adalogics.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory main_repo: 'https://github.com/google/leveldb.git' file_github_issue: True fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libaom/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake yasm wget RUN git clone https://aomedia.googlesource.com/aom ADD https://storage.googleapis.com/aom-test-data/fuzzer/dec_fuzzer_seed_corpus.zip $SRC/ COPY build.sh $SRC/ WORKDIR aom ================================================ FILE: projects/libaom/README.md ================================================ # Submit a Patch to oss-fuzz repo ## One-time Setup 1. Create github account if needed (with @google.com email address, preferably) and log in. 1. To allow “git push” to work, you’ll have to add an SSH key: https://help.github.com/articles/connecting-to-github-with-ssh/ 1. Go to https://github.com/google/oss-fuzz and click on “Fork”. 1. Go to your own fork of the repo, which will be at https://github.com/\/oss-fuzz 1. Click on “clone or download” and pick “Clone with SSH” method (I found that easier to use for “git push”). Then copy that URL and run “git clone \” in terminal. Now you have a local repo, and **your fork** of the remote repo will be called “**origin**” in your git config. 1. Configure a remote repo pointing to the **upstream repo** (https://github.com/google/oss-fuzz) so that it’s called “**upstream**”: * cd \/oss-fuzz * git remote add upstream git@github.com:google/oss-fuzz.git * git remote -v NOTE: For trivial changes it's possible to edit the files in the web UI on the main project and create a commit + pull request from that. ## Workflow for a Pull Request (Patch) 1. Go to your repo: * cd \/oss-fuzz 1. Create a new branch: * git checkout master * git checkout -b new_feature_xyz 1. Make your changes and commit them locally with “git commit” 1. Push your changes to your fork on github * git push -u origin HEAD * (This will create a branch of the same name “new_feature_xyz” on your fork “origin”). 1. Open your fork in browser and click on “Compare & pull request” and follow the prompts. 1. If changes are requested to the patch: * make changes to the same local branch * commit them locally with “git commit” (but DO NOT amend!) * git push -u origin HEAD 1. Once pull request is closed: * Delete “new_feature_xyz” branch on your fork using the “Delete branch” button on the pull request * Delete local “new_feature_xyz” branch locally with “git checkout master && git branch -D new_feature_xyz” * Sync your local repo and your fork with upstream repo: * git checkout master * git fetch upstream * git merge upstream/master * git push origin master ================================================ FILE: projects/libaom/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build libaom build_dir=$WORK/build mkdir -p ${build_dir} pushd ${build_dir} # Remove files generated by the previous build. rm -rf ./* # oss-fuzz has 2 GB total memory allocation limit. So, we limit per-allocation # limit in libaom to 1 GB to avoid OOM errors. A smaller per-allocation is # needed for MemorySanitizer (see bug oss-fuzz:9497 and bug oss-fuzz:9499). if [[ $CFLAGS = *sanitize=memory* ]]; then extra_c_flags='-DAOM_MAX_ALLOCABLE_MEMORY=536870912' else extra_c_flags='-DAOM_MAX_ALLOCABLE_MEMORY=1073741824' fi # Also, enable DO_RANGE_CHECK_CLAMP to suppress the noise of integer overflows # in the transform functions. extra_c_flags+=' -DDO_RANGE_CHECK_CLAMP=1' extra_cmake_flags= # MemorySanitizer requires that all program code is instrumented. Therefore we # need to replace all inline assembly code that writes to memory with pure C # code. Disable all assembly code for MemorySanitizer. if [[ $CFLAGS = *sanitize=memory* ]]; then extra_cmake_flags+="-DAOM_TARGET_CPU=generic" fi cmake $SRC/aom -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE='-O3 -g' \ -DCMAKE_CXX_FLAGS_RELEASE='-O3 -g' -DCONFIG_PIC=1 -DCONFIG_LOWBITDEPTH=1 \ -DCONFIG_AV1_ENCODER=0 -DENABLE_EXAMPLES=0 -DENABLE_DOCS=0 -DENABLE_TESTS=0 \ -DCONFIG_SIZE_LIMIT=1 -DDECODE_HEIGHT_LIMIT=12288 -DDECODE_WIDTH_LIMIT=12288 \ -DAOM_EXTRA_C_FLAGS="${extra_c_flags}" -DENABLE_TOOLS=0 \ -DAOM_EXTRA_CXX_FLAGS="${extra_c_flags}" ${extra_cmake_flags} make -j$(nproc) popd # build fuzzers fuzzer_src_name=av1_dec_fuzzer fuzzer_name=${fuzzer_src_name} $CXX $CXXFLAGS -std=c++11 \ -I$SRC/aom \ -I${build_dir} \ -Wl,--start-group \ $LIB_FUZZING_ENGINE \ $SRC/aom/examples/${fuzzer_src_name}.cc -o $OUT/${fuzzer_name} \ ${build_dir}/libaom.a -Wl,--end-group # copy seed corpus. cp $SRC/dec_fuzzer_seed_corpus.zip $OUT/${fuzzer_name}_seed_corpus.zip cp $SRC/aom/examples/av1_dec_fuzzer.dict $OUT/${fuzzer_name}.dict ================================================ FILE: projects/libaom/project.yaml ================================================ homepage: "https://aomedia.org/av1-features/get-started/" language: c++ primary_contact: "wtc@google.com" sanitizers: - address - memory - undefined auto_ccs: - jianj@google.com - jingning@google.com - jzern@google.com - wtc@google.com - yunqingwang@google.com vendor_ccs: - twsmith@mozilla.com main_repo: 'https://aomedia.googlesource.com/aom' ================================================ FILE: projects/libarchive/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf libtool pkg-config \ libbz2-dev liblzo2-dev liblzma-dev liblz4-dev libz-dev \ libssl-dev libacl1-dev libattr1-dev lrzip liblzo2-dev \ liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk sharutils RUN curl -LO http://mirrors.kernel.org/ubuntu/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ apt install ./automake_1.16.5-1.3_all.deb RUN git clone --depth 1 https://github.com/libarchive/libarchive.git RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git # compile libxml2 from source so we can statically link RUN mkdir /deps && \ cd $SRC/libxml2 && \ ./autogen.sh \ --without-debug \ --without-ftp \ --without-http \ --without-legacy \ --without-python \ --enable-static && \ make -j$(nproc) && \ make install && \ cp .libs/libxml2.a /deps/ COPY run_tests.sh build.sh libarchive_fuzzer.cc $SRC/ WORKDIR $SRC ================================================ FILE: projects/libarchive/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # For fuzz-introspector. This is to exclude all libxml2 code from the # fuzz-introspector reports. export FUZZ_INTROSPECTOR_CONFIG=$SRC/fuzz_introspector_exclusion.config cat > $FUZZ_INTROSPECTOR_CONFIG < #include #include #include "archive.h" #include "archive_entry.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { struct archive *a = archive_read_new(); archive_read_support_filter_all(a); archive_read_support_format_all(a); archive_read_support_format_empty(a); archive_read_support_format_raw(a); archive_read_support_format_gnutar(a); if (ARCHIVE_OK != archive_read_set_options(a, "zip:ignorecrc32,tar:read_concatenated_archives,tar:mac-ext")) { return 0; } archive_read_add_passphrase(a, "secret"); if (ARCHIVE_OK != archive_read_open_memory(a, buf, len)) { archive_read_free(a); return 0; } while(1) { std::vector data_buffer(getpagesize(), 0); struct archive_entry *entry; int ret = archive_read_next_header(a, &entry); if (ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL) break; if (ret == ARCHIVE_RETRY) continue; (void)archive_entry_pathname(entry); (void)archive_entry_pathname_utf8(entry); (void)archive_entry_pathname_w(entry); (void)archive_entry_atime(entry); (void)archive_entry_birthtime(entry); (void)archive_entry_ctime(entry); (void)archive_entry_dev(entry); (void)archive_entry_digest(entry, ARCHIVE_ENTRY_DIGEST_SHA1); (void)archive_entry_filetype(entry); (void)archive_entry_gid(entry); (void)archive_entry_is_data_encrypted(entry); (void)archive_entry_is_encrypted(entry); (void)archive_entry_is_metadata_encrypted(entry); (void)archive_entry_mode(entry); (void)archive_entry_mtime(entry); (void)archive_entry_size(entry); (void)archive_entry_uid(entry); ssize_t r; while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0) ; if (r == ARCHIVE_FATAL) break; } archive_read_has_encrypted_entries(a); archive_read_format_capabilities(a); archive_file_count(a); archive_seek_data(a, 0, SEEK_SET); archive_read_free(a); return 0; } ================================================ FILE: projects/libarchive/project.yaml ================================================ homepage: "https://github.com/libarchive/libarchive" language: c++ primary_contact: "joerg.sonnenberger@googlemail.com" auto_ccs: - "kientzle@gmail.com" - "martin@matuska.org" sanitizers: - address - memory: experimental: True - undefined main_repo: 'https://github.com/libarchive/libarchive.git' ================================================ FILE: projects/libarchive/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Skip leak sanitizer and disable possible null return from allocator export ASAN_OPTIONS="detect_leaks=0:allocator_may_return_null=1" # Run unit test and disable those tests that are failing or not able to run without network connection ctest --test-dir libarchive/build2 -j$(nproc) -E \ "libarchive_test_compat_zip_4|libarchive_test_read_format_cpio_bin*|libarchive_test_read_pax_truncated|bsdcpio_test_basic|bsdcpio_test_option_0|bsdcpio_test_option_L_upper|bsdcpio_test_option_d|bsdcpio_test_option_f|bsdcpio_test_option_m|bsdcpio_test_option_t" ================================================ FILE: projects/libass/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libfontconfig1-dev libfreetype-dev libfribidi-dev python3-pip && \ pip3 install meson==0.60.0 ninja RUN git clone --depth 1 https://github.com/libass/libass.git RUN git clone --depth 1 https://github.com/harfbuzz/harfbuzz.git COPY build.sh *.options $SRC/ ================================================ FILE: projects/libass/build.sh ================================================ #!/bin/bash -eux # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/harfbuzz # setup build=$WORK/build # # cleanup rm -rf $build mkdir -p $build # disable sanitize=vptr for harfbuzz since it compiles without rtti CFLAGS="$CFLAGS -fno-sanitize=vptr" \ CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" \ meson --default-library=static --wrap-mode=nodownload \ -Dfuzzer_ldflags="$(echo $LIB_FUZZING_ENGINE)" \ -Dtests=disabled \ --prefix=/work/ --libdir=lib $build \ || (cat build/meson-logs/meson-log.txt && false) meson install -C $build cd $SRC/libass export PKG_CONFIG_PATH=/work/lib/pkgconfig ./autogen.sh ./configure \ FUZZ_CPPFLAGS="-DASS_FUZZMODE=2 -DASSFUZZ_MAX_LEN=8192" \ --disable-asm --disable-shared --enable-fuzz make -j "$(nproc)" fuzz/fuzz_ossfuzz cp fuzz/fuzz_ossfuzz $OUT/libass_fuzzer cp fuzz/ass.dict $OUT/ass.dict cp $SRC/*.options $OUT/ ================================================ FILE: projects/libass/libass_fuzzer.options ================================================ [libfuzzer] dict = ass.dict max_len = 8192 ================================================ FILE: projects/libass/project.yaml ================================================ homepage: "https://github.com/libass/libass" language: c++ primary_contact: "chortos@inbox.lv" auto_ccs: - "greg@kinoho.net" - "rcombs@rcombs.me" - "vabnick@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/libass/libass.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libavc/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake RUN git clone https://github.com/ittiam-systems/libavc.git ADD https://storage.googleapis.com/android_media/external/libavc/fuzzer/avc_dec_fuzzer_seed_corpus.zip $SRC/ COPY build.sh $SRC/ WORKDIR libavc ================================================ FILE: projects/libavc/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. $SRC/libavc/fuzzer/ossfuzz.sh ================================================ FILE: projects/libavc/project.yaml ================================================ homepage: "https://github.com/ittiam-systems/libavc" language: c++ primary_contact: "harish.mahendrakar@ittiam.com" sanitizers: - address - memory - undefined auto_ccs: - aadithya.kamath@ittiam.com - harish.mahendrakar@ittiam.com - mallikarjun.kamble@ittiam.com - ram.mohan@ittiam.com - saurabh.agrawal@ittiam.com - umang.saini@ittiam.com - vaibhav.valvaiker@ittiam.com - vijayakumar.gr@ittiam.com - essick@google.com - lajos@google.com vendor_ccs: - adambacchus@google.com - ailport@google.com - bcreasey@google.com - cunefare@google.com - ejorgensen@google.com - faerber@google.com - greendonald@google.com - hamzeh@google.com - jaredkidd@google.com - kimtony@google.com - lindsaywells@google.com - maverickm@google.com - swansonr@google.com - warrenwright@google.com architectures: - x86_64 - i386 main_repo: 'https://github.com/ittiam-systems/libavc.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libavif/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel cmake git nasm && \ pip3 install meson ninja RUN git clone --depth 1 https://github.com/AOMediaCodec/libavif.git libavif WORKDIR libavif COPY build.sh avif_decode_seed_corpus.zip $SRC/ ================================================ FILE: projects/libavif/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ bash tests/oss-fuzz/build.sh # show contents of $OUT/ for sanity checking find $OUT/ ================================================ FILE: projects/libavif/project.yaml ================================================ homepage: "https://github.com/AOMediaCodec/libavif" language: c++ primary_contact: "wtc@google.com" fuzzing_engines: - libfuzzer auto_ccs: - "fgalligan@google.com" - "joedrago@gmail.com" - "jzern@google.com" - "yguyon@google.com" - "maryla@google.com" - "vrabaud@google.com" - "david@adalogics.com" - "vigneshv@google.com" main_repo: 'https://github.com/AOMediaCodec/libavif.git' sanitizers: - address - memory - undefined ================================================ FILE: projects/libbpf/Dockerfile ================================================ # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN sed -i -e '/^#\s*deb-src.*\smain\s\+restricted/s/^#//' /etc/apt/sources.list && \ apt-get update && \ # libelf build dependencies \ apt-get build-dep -y --no-install-recommends libelf-dev && \ apt-get install -y --no-install-recommends pkg-config && \ # libbpf build dependencies \ apt-get install -y --no-install-recommends libz-dev libz-dev:i386 RUN git clone --depth 1 https://github.com/libbpf/libbpf WORKDIR libbpf COPY build.sh $SRC/ ================================================ FILE: projects/libbpf/build.sh ================================================ #!/bin/bash -e # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./scripts/build-fuzzers.sh ================================================ FILE: projects/libbpf/project.yaml ================================================ homepage: "https://github.com/libbpf/libbpf" language: c primary_contact: "andrii.nakryiko@gmail.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 auto_ccs: - hengqi.chen@gmail.com - yulia.kartseva@gmail.com - evverx@gmail.com - shunghsiyu@gmail.com - eddyz87@gmail.com main_repo: "https://github.com/libbpf/libbpf" builds_per_day: 4 view_restrictions: none file_github_issue: True fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libcacard/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y pkg-config libglib2.0-dev gyp libsqlite3-dev mercurial python3-pip python # Because Ubuntu has really ancient meson out there RUN pip3 install meson ninja RUN git clone --depth 1 --single-branch --branch master https://gitlab.freedesktop.org/spice/libcacard.git libcacard RUN git clone --depth 1 https://github.com/nss-dev/nss.git nss RUN hg clone https://hg.mozilla.org/projects/nspr WORKDIR libcacard COPY build.sh $SRC/ ================================================ FILE: projects/libcacard/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Compile NSS mkdir $SRC/nss-nspr mv $SRC/nss $SRC/nss-nspr/ mv $SRC/nspr $SRC/nss-nspr/ cd $SRC/nss-nspr/ # We do not need NSS to be built with address sanitizer CFLAGS="" CXXFLAGS="" nss/build.sh --static --disable-tests # Create a package config for NSS cp dist/Debug/lib/pkgconfig/{nspr,nss}.pc sed -i "s/Debug//g" dist/Debug/lib/pkgconfig/nss.pc sed -i "s/\/lib/\/lib\/Debug/g" dist/Debug/lib/pkgconfig/nss.pc sed -i "s/include\/nspr/public\/nss/g" dist/Debug/lib/pkgconfig/nss.pc sed -i "s/NSPR/NSS/g" dist/Debug/lib/pkgconfig/nss.pc LIBS="-lssl -lsmime -lnssdev -lnss_static -lpk11wrap_static -lcryptohi" LIBS="$LIBS -lcerthi -lcertdb -lnssb -lnssutil -lnsspki -ldl -lm -lsqlite" LIBS="$LIBS -lsoftokn_static -lsha-x86_c_lib -lfreebl_static" LIBS="$LIBS -lgcm-aes-x86_c_lib -lhw-acc-crypto-avx -lhw-acc-crypto-avx2" sed -i "s/Libs:.*/Libs: -L\${libdir} $LIBS/g" dist/Debug/lib/pkgconfig/nss.pc echo "Requires: nspr" >> dist/Debug/lib/pkgconfig/nss.pc export NSS_NSPR_PATH=$(realpath $SRC/nss-nspr/) export PKG_CONFIG_PATH=$NSS_NSPR_PATH/dist/Debug/lib/pkgconfig export LD_LIBRARY_PATH=$NSS_NSPR_PATH/dist/Debug/lib # compile libcacard BUILD=$WORK/meson rm -rf $BUILD mkdir $BUILD cd $SRC/libcacard # Drop the tests as they are not needed and require too much dependencies meson $BUILD -Ddefault_library=static -Ddisable_tests=true ninja -C $BUILD # We need nss db to work cp -r tests/db $OUT/ echo "XXXXXXXX" > $WORK/testinput fuzzers=$(find $BUILD/fuzz/ -executable -type f) for f in $fuzzers; do fuzzer=$(basename $f) cp $f $OUT/ # Check if it runs at least in build image $OUT/$fuzzer $WORK/testinput #zip -j $OUT/${fuzzer}_seed_corpus.zip fuzz/corpora/${fuzzer}/* done rm $WORK/testinput ================================================ FILE: projects/libcacard/project.yaml ================================================ homepage: "https://gitlab.freedesktop.org/spice/libcacard" language: c primary_contact: "jjelen@redhat.com" auto_ccs: - "jakuje@gmail.com" sanitizers: - address - undefined main_repo: 'https://gitlab.freedesktop.org/spice/libcacard.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libcbor/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake libcmocka-dev RUN git clone --depth 1 https://github.com/PJK/libcbor WORKDIR libcbor COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libcbor/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./oss-fuzz/build.sh ================================================ FILE: projects/libcbor/project.yaml ================================================ homepage: "https://github.com/PJK/libcbor" language: c++ primary_contact: "me@pavelkalvoda.com" auto_ccs: - alex.gaynor@gmail.com fuzzing_engines: - afl - libfuzzer - honggfuzz sanitizers: - address - undefined - memory main_repo: 'https://github.com/PJK/libcbor' ================================================ FILE: projects/libcbor/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir oss_fuzz_build -j$(nproc) ================================================ FILE: projects/libcoap/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool \ pkg-config libcunit1 libcunit1-doc libcunit1-dev RUN git clone --depth 1 https://github.com/obgm/libcoap.git libcoap WORKDIR libcoap COPY *.sh $SRC/ ================================================ FILE: projects/libcoap/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ "$SANITIZER" == "introspector" ]; then export WARNING_CFLAGS="${CFLAGS}" fi ./autogen.sh && ./configure --disable-doxygen --disable-manpages \ --with-openssl --enable-tests \ --disable-thread-safe \ && make -j$(nproc) # build all fuzzer targets make -C tests/oss-fuzz -f Makefile.oss-fuzz ================================================ FILE: projects/libcoap/project.yaml ================================================ homepage: "https://libcoap.net/" language: c++ primary_contact: "bergmann@tzi.org" auto_ccs: - "libcoap@gmail.com" - "supjps-libcoap@jpshallow.com" - "arthur.chan@adalogics.com" - "david@adalogics.com" - "adam@adalogics.com" main_repo: 'https://github.com/obgm/libcoap.git' ================================================ FILE: projects/libcoap/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ./tests/testdriver ================================================ FILE: projects/libconfig/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/hyperrealm/libconfig.git libconfig \ && cp libconfig/fuzz/build.sh $SRC/ RUN sed -i 's/-DBUILD_TESTS=Off/-DBUILD_TESTS=On/g' $SRC/build.sh COPY run_tests.sh $SRC WORKDIR libconfig ================================================ FILE: projects/libconfig/project.yaml ================================================ homepage: "https://hyperrealm.github.io/libconfig/" language: c primary_contact: "hyperrealm@gmail.com" auto_ccs: - "capuanobailey@gmail.com" main_repo: "https://github.com/hyperrealm/libconfig.git" fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/libconfig/run_tests.sh ================================================ ##!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build ================================================ FILE: projects/libcst/Dockerfile ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. FROM gcr.io/oss-fuzz-base/base-builder-python RUN git clone https://github.com/instagram/libcst libcst RUN apt-get install build-essential libssl-dev libffi-dev pkg-config python3-dev cargo -y RUN pip3 install --upgrade pip RUN curl https://sh.rustup.rs -sSf | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}" RUN rustup install nightly RUN rustup default stable COPY *.sh *py $SRC/ WORKDIR $SRC/libcst ================================================ FILE: projects/libcst/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export RUSTFLAGS="" python3 -m pip install -U hatch python3 -m pip uninstall -y libcst python3 -m pip install . # Change directory to force pyinstaller to load in the package we build cd ../ mkdir fuzzbuild cd fuzzbuild if [ "$SANITIZER" = "address" ] then # Enable pysecsan export ENABLE_PYSECSAN="1" fi # Build fuzzers in $OUT. for fuzzer in $(find $SRC -name 'fuzz_*.py'); do compile_python_fuzzer $fuzzer done ================================================ FILE: projects/libcst/fuzz_transformer.py ================================================ #!/usr/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import atheris import libcst from libcst import parse_module from libcst import PartialParserConfig, ParserSyntaxError from libcst.codemod._context import CodemodContext from libcst.codemod._runner import SkipFile from libcst.codemod.commands.unnecessary_format_string import UnnecessaryFormatString def TestOneInput(data): fdp = atheris.FuzzedDataProvider(data) context = CodemodContext() transform_instance = UnnecessaryFormatString(context) inp = fdp.ConsumeUnicodeNoSurrogates(sys.maxsize) try: input_tree = parse_module( inp, config=PartialParserConfig() ) try: output_tree = transform_instance.transform_module(input_tree) except SkipFile: pass except ParserSyntaxError: pass except RecursionError: pass def main(): atheris.instrument_all() atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) atheris.Fuzz() if __name__ == "__main__": main() ================================================ FILE: projects/libcst/project.yaml ================================================ fuzzing_engines: - libfuzzer homepage: https://github.com/instagram/libcst language: python main_repo: https://github.com/instagram/libcst sanitizers: - address - undefined vendor_ccs: - david@adalogics.com ================================================ FILE: projects/libcue/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool bison flex RUN git clone --depth 1 https://github.com/lipnitsk/libcue.git libcue WORKDIR libcue COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libcue/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/libcue/oss-fuzz/build.sh ================================================ FILE: projects/libcue/project.yaml ================================================ homepage: "https://github.com/lipnitsk/libcue" main_repo: "https://github.com/lipnitsk/libcue.git" language: c primary_contact: "ilya.lipnitskiy@gmail.com" auto_ccs: - "aleksandrosansan@gmail.com" sanitizers: - address - memory - undefined fuzzing_engines: - libfuzzer - honggfuzz - afl # - centipede disabled until https://github.com/lipnitsk/libcue/pull/31/ ================================================ FILE: projects/libcue/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd $WORK make test ================================================ FILE: projects/libcups/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool build-essential libavahi-client-dev libgnutls28-dev libnss-mdns zlib1g-dev libsystemd-dev RUN git clone --depth 1 https://github.com/OpenPrinting/libcups.git RUN git clone --depth 1 https://github.com/OpenPrinting/fuzzing.git COPY build.sh $SRC/ WORKDIR $SRC/libcups ================================================ FILE: projects/libcups/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/fuzzing/projects/libcups/oss_fuzz_build.sh ================================================ FILE: projects/libcups/project.yaml ================================================ homepage: "https://github.com/OpenPrinting/libcups" main_repo: "https://github.com/OpenPrinting/libcups.git" # help_url: language: c++ primary_contact: "jiongchiyu@gmail.com" auto_ccs: - "till.kamppeter@gmail.com" - "ossfuzz@iosifache.me" - "pushinliu@gmail.com" # - "msweet@msweet.org" # - "jsmeix@suse.de" # - "debian@alteholz.de" # - "zdohnal@redhat.com" # - "basu.aveek@gmail.com" # vendor_ccs: architectures: - x86_64 # - i386 sanitizers: - address - memory # - undefined fuzzing_engines: - libfuzzer # - honggfuzz # - afl # builds_per_day: 2 ================================================ FILE: projects/libdwarf/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get -qq update && apt-get install -qq -y cmake make zlib1g-dev RUN git clone --depth=1 https://github.com/davea42/libdwarf-code $SRC/libdwarf RUN git clone --depth=1 https://github.com/davea42/libdwarf-binary-samples $SRC/libdwarf-binary-samples WORKDIR libdwarf COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libdwarf/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build corpus for fuzzing export BINARY_SAMPLES_DIR="$SRC/libdwarf-binary-samples" export BINARY_SAMPLES_V1="$BINARY_SAMPLES_DIR/binary-samples" export BINARY_SAMPLES_V2="$BINARY_SAMPLES_DIR/binary-samples-v2" export FUZZER_DIR="$SRC/libdwarf/fuzz" mkdir $SRC/corp cp $BINARY_SAMPLES_V1/elf* $SRC/corp cp $BINARY_SAMPLES_V1/Mach* $SRC/corp cp $BINARY_SAMPLES_V1/pe* $SRC/corp cp $BINARY_SAMPLES_V1/lib* $SRC/corp for file in $BINARY_SAMPLES_V2/{linux,windows}/*_DWARF*/* $BINARY_SAMPLES_V2/macOS-arm/*/*; do export newfile=$(echo $file | sed 's/ /_/g') # e.g. cp "..." /out/windows_gcc11_DWARF2_cross-platform.exe cp "$file" $SRC/corp/$(echo "$newfile" | cut -d/ -f5,6 | sed 's/\//_/g')_$(basename "$newfile") done zip -r -j $OUT/fuzz_seed_corpus.zip $SRC/corp for fuzzFile in $FUZZER_DIR/fuzz*.c; do fuzzName=$(basename "$fuzzFile" '.c') cp $OUT/fuzz_seed_corpus.zip $OUT/${fuzzName}_seed_corpus.zip done rm $OUT/fuzz_seed_corpus.zip # Build fuzzers mkdir build cd build cmake ../ -DDO_TESTING=ON make for fuzzFile in $FUZZER_DIR/fuzz*.c; do fuzzName=$(basename "$fuzzFile" '.c') $CC $CFLAGS $LIB_FUZZING_ENGINE -I../src/lib/libdwarf/ \ "$FUZZER_DIR/${fuzzName}.c" -o "$OUT/${fuzzName}" ./src/lib/libdwarf/libdwarf.a -lz done ================================================ FILE: projects/libdwarf/project.yaml ================================================ homepage: "https://www.prevanders.net/dwarf.html" language: c primary_contact: "davea42@gmail.com" main_repo: "https://github.com/davea42/libdwarf-code" auto_ccs: - "david@adalogics.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libdwarf/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # The unit test of selftied is failing, thus excluded temporarily ctest --test-dir build -C Release -E selftied -j$(nproc) ================================================ FILE: projects/libecc/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e # ! Project pinned after a clang update and an afl link error. Log: https://oss-fuzz-gcb-logs.storage.googleapis.com/log-bca72181-cfb2-4b2f-98f1-c2addee0aa4b.txt RUN apt-get update && apt-get install -y make autoconf automake libtool wget python bison flex texinfo lzip bsdmainutils RUN git clone --depth 1 --branch cryptofuzz https://github.com/libecc/libecc.git RUN git clone --depth 1 https://github.com/randombit/botan.git RUN git clone https://github.com/wolfssl/wolfssl RUN git clone --depth 1 https://github.com/wolfssl/wolfsm RUN git clone --depth 1 https://github.com/MozillaSecurity/cryptofuzz RUN wget -q https://ftp.gnu.org/gnu/gmp/gmp-6.2.1.tar.lz RUN test "$(sha256sum gmp-6.2.1.tar.lz)" = "2c7f4f0d370801b2849c48c9ef3f59553b5f1d3791d070cffb04599f9fc67b41 gmp-6.2.1.tar.lz" RUN wget -q https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 COPY build.sh $SRC/ ================================================ FILE: projects/libecc/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL" export LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ # Build libecc cd $SRC/libecc python3 scripts/expand_libecc.py --name="secp112r2" --prime=0xdb7c2abf62e35e668076bead208b --order=0x36df0aafd8b8d7597ca10520d04b --a=0x6127c24c05f38a0aaaf65c0ef02c --b=0x51def1815db5ed74fcc34c85d709 --gx=0x4ba30ab5e892b4e1649dd0928643 --gy=0xadcd46f5882e3747def36e956e97 --cofactor=4 python3 scripts/expand_libecc.py --name="secp128r2" --prime=0xfffffffdffffffffffffffffffffffff --order=0x3fffffff7fffffffbe0024720613b5a3 --a=0xd6031998d1b3bbfebf59cc9bbff9aee1 --b=0x5eeefca380d02919dc2c6558bb6d8a5d --gx=0x7b6aa5d85e572983e6fb32a7cdebc140 --gy=0x27b6916a894d3aee7106fe805fc34b44 --cofactor=4 export CFLAGS="$CFLAGS -DUSE_CRYPTOFUZZ" make -j$(nproc) build/libsign.a export LIBECC_PATH=$(realpath .) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBECC" # Build Botan cd $SRC/botan if [[ $CFLAGS != *-m32* ]] then if [[ $CFLAGS != *sanitize=memory* ]] then ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509 --build-targets=static --without-documentation else ./configure.py --disable-asm --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509 --build-targets=static --without-documentation fi else ./configure.py --cpu=x86_32 --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509 --build-targets=static --without-documentation fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN -DCRYPTOFUZZ_BOTAN_IS_ORACLE" export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a" export BOTAN_INCLUDE_PATH="$SRC/botan/build/include" # Compile libgmp cd $SRC/ tar --lzip -xvf gmp-6.2.1.tar.lz cd $SRC/gmp-6.2.1/ autoreconf -ivf if [[ $CFLAGS = *-m32* ]] then setarch i386 ./configure --enable-maintainer-mode --enable-assert elif [[ $CFLAGS = *sanitize=memory* ]] then ./configure --enable-maintainer-mode --enable-assert --disable-assembly else ./configure --enable-maintainer-mode --enable-assert fi make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_LIBGMP" export LIBGMP_INCLUDE_PATH=$(realpath .) export LIBGMP_A_PATH=$(realpath .libs/libgmp.a) cd $SRC/wolfssl/ # Checkout at commit that's known to be bug-free git checkout b7b20ededda4cea208fb7745629904fda64c7524 # Install support for wolfCrypt SM algorithms cd $SRC/wolfsm/ ./install.sh # Compile wolfSSL cd $SRC/wolfssl/ # Note (to self): # Compiling wolfCrypt with SP math instead of normal math due to symbol collisions (specifically fp_* functions) between libecc and wolfCrypt otherwise. export CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DHAVE_ECC_BRAINPOOL -DHAVE_ECC_KOBLITZ -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DWOLFSSL_SP_INT_NEGATIVE" autoreconf -ivf export WOLFCRYPT_CONFIGURE_PARAMS="--enable-static --enable-md2 --enable-md4 --enable-ripemd --enable-blake2 --enable-blake2s --enable-pwdbased --enable-scrypt --enable-hkdf --enable-cmac --enable-arc4 --enable-camellia --enable-aesccm --enable-aesctr --enable-xts --enable-des3 --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --enable-aessiv --enable-keygen --enable-curve25519 --enable-curve448 --enable-shake256 --disable-crypttests --disable-examples --enable-compkey --enable-ed448 --enable-ed25519 --enable-ecccustcurves --enable-xchacha --enable-cryptocb --enable-eccencrypt --enable-smallstack --enable-ed25519-stream --enable-ed448-stream --enable-sp-math-all --enable-aesgcm-stream --enable-shake128 --enable-siphash --enable-sm2 --enable-sm3" if [[ $CFLAGS = *sanitize=memory* ]] then export WOLFCRYPT_CONFIGURE_PARAMS="$WOLFCRYPT_CONFIGURE_PARAMS -disable-asm" fi ./configure $WOLFCRYPT_CONFIGURE_PARAMS make -j$(nproc) export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_WOLFCRYPT" export WOLFCRYPT_LIBWOLFSSL_A_PATH=`realpath src/.libs/libwolfssl.a` export WOLFCRYPT_INCLUDE_PATH=`realpath .` # Build Cryptofuzz cd $SRC/cryptofuzz python gen_repository.py rm extra_options.h echo -n '"' >>extra_options.h echo -n '--force-module=libecc ' >>extra_options.h echo -n '--operations=Digest,HMAC,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,ECGDSA_Sign,ECGDSA_Verify,ECRDSA_Sign,ECRDSA_Verify,ECDH_Derive,ECC_Point_Add,ECC_Point_Mul,ECC_Point_Dbl,ECC_Point_Neg,BignumCalc ' >>extra_options.h echo -n '--curves=brainpool192r1,brainpool192t1,brainpool224r1,brainpool224t1,brainpool256r1,brainpool256t1,brainpool320r1,brainpool320t1,brainpool384r1,brainpool384t1,brainpool512r1,brainpool512t1,secp112r2,secp128r2,secp192r1,secp192k1,secp224r1,secp224k1,secp256r1,secp256k1,secp384r1,secp521r1,frp256v1,secp256k1,sm2p256v1,gost_256A,gost_512A,gostr3410_2001_cryptopro_a,gostr3410_2001_cryptopro_b,gostr3410_2001_cryptopro_c,gostr3410_2001_cryptopro_xcha,gostr3410_2001_cryptopro_xchb,gostr3410_2001_test,tc26_gost_3410_12_256_a,tc26_gost_3410_12_256_b,tc26_gost_3410_12_256_c,tc26_gost_3410_12_256_d,tc26_gost_3410_12_512_a,tc26_gost_3410_12_512_b,tc26_gost_3410_12_512_c,tc26_gost_3410_12_512_test ' >>extra_options.h echo -n '--digests=NULL,SHA224,SHA256,SHA3-224,SHA3-256,SHA3-384,SHA3-512,SHA384,SHA512,SHA512-224,SHA512-256,SM3,SHAKE256_114,STREEBOG-256,STREEBOG-512,RIPEMD160,BASH224,BASH256,BASH384,BASH512 ' >>extra_options.h echo -n '--calcops=Add,AddMod,And,Bit,Cmp,CondAdd,CondSub,Div,ExpMod,ExtGCD_X,ExtGCD_Y,GCD,InvMod,IsOdd,IsOne,IsZero,LRot,LShift1,Mod,Mul,MulMod,NegMod,NumBits,One,Or,RRot,RShift,RandMod,Sqr,Sub,SubMod,Xor,Zero ' >>extra_options.h echo -n '"' >>extra_options.h cd modules/libecc/ make -B -j$(nproc) cd ../botan/ make -B -j$(nproc) cd ../libgmp/ make -B -j$(nproc) cd ../wolfcrypt/ make -B -j$(nproc) cd ../../ make -B -j$(nproc) cp cryptofuzz $OUT/cryptofuzz-libecc ================================================ FILE: projects/libecc/project.yaml ================================================ homepage: "https://github.com/ANSSI-FR/libecc" language: c++ primary_contact: "guidovranken@gmail.com" main_repo: "https://github.com/ANSSI-FR/libecc.git" auto_ccs: - "dev.libecc@gmail.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 ================================================ FILE: projects/libevent/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/libevent/libevent.git libevent RUN git clone --depth 1 https://github.com/google/fuzzing fuzzing WORKDIR libevent COPY build.sh *.cc *.c $SRC/ ================================================ FILE: projects/libevent/buffer_add_file_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include extern "C" { #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/buffer_compat.h" #include "libevent/include/event2/event.h" #include "libevent/include/event2/util.h" #include "util-internal.h" } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider data_provider(data, size); std::string s1 = data_provider.ConsumeRandomLengthString(); uint32_t int1 = data_provider.ConsumeIntegral(); char bufferFile[50]; struct stat st; sprintf(bufferFile, "/tmp/buffer.%d", getpid()); FILE *fp = fopen(bufferFile, "wb"); if (!fp) { return 0; } fwrite(s1.c_str(), s1.size(), 1, fp); fclose(fp); fp = fopen(bufferFile, "rb"); if (!fp) { return 0; } int fd = fileno(fp); fstat(fd, &st); struct evbuffer *buf = evbuffer_new(); evbuffer_set_flags(buf, int1); evbuffer_add_file(buf, fd, 0, st.st_size); fclose(fp); close(fd); unlink(bufferFile); evbuffer_free(buf); return 0; } ================================================ FILE: projects/libevent/buffer_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include extern "C" { #include "libevent/include/event2/event.h" #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/buffer_compat.h" #include "libevent/include/event2/util.h" #include "util-internal.h" } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider data_provider(data, size); std::string s1 = data_provider.ConsumeRandomLengthString(); std::string s2 = data_provider.ConsumeRandomLengthString(); std::string s3 = data_provider.ConsumeRandomLengthString(); std::string s4 = data_provider.ConsumeRandomLengthString(); struct evbuffer *buf = evbuffer_new(); size_t sz; evbuffer_add(buf, s1.c_str(), s1.size()); char *cp = NULL; cp = evbuffer_readln(buf, &sz, EVBUFFER_EOL_ANY); if (cp != NULL) { free(cp); cp = NULL; } struct evbuffer *buf2 = evbuffer_new(); struct evbuffer *buf3 = evbuffer_new(); struct evbuffer_iovec vec[1]; evbuffer_add(buf2, s1.c_str(), s1.size()); evbuffer_add_reference(buf2, s2.c_str(), s2.size(), NULL, NULL); evbuffer_add_buffer(buf, buf2); evbuffer_expand(buf, 2000); evbuffer_pullup(buf, 2); evbuffer_prepend(buf, s3.c_str(), s3.size()); evbuffer_prepend_buffer(buf, buf2); evbuffer_find(buf2, (const unsigned char *)s4.c_str(), s4.size()); evbuffer_commit_space(buf, vec, 1); evbuffer_add_buffer_reference(buf, buf2); evbuffer_remove_buffer(buf, buf3, 10); evbuffer_free(buf); evbuffer_free(buf2); evbuffer_free(buf3); return 0; } ================================================ FILE: projects/libevent/bufferevent_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include extern "C" { #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/bufferevent.h" #include "libevent/include/event2/event.h" } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider data_provider(data, size); std::string s1 = data_provider.ConsumeRandomLengthString(); std::string s2 = data_provider.ConsumeRandomLengthString(); size_t int1 = data_provider.ConsumeIntegral(); size_t int2 = data_provider.ConsumeIntegral(); size_t int3 = data_provider.ConsumeIntegral(); size_t int4 = data_provider.ConsumeIntegral(); int use_pair = int1 % 2; int read_write = int2 % 2; int use_filter = int4 % 2; int options1 = int2 % 16; int options2 = int3 % 16; struct bufferevent *bev1 = NULL, *bev2 = NULL, *bev3 = NULL, *bev4 = NULL, *pair[2]; struct event_base *base = NULL; struct evbuffer *evbuf = NULL; static struct ev_token_bucket_cfg *conn_bucket_cfg = NULL; struct bufferevent_rate_limit_group *bev_rate_group = NULL; char buf[128]; /*create a buffer event*/ base = event_base_new(); if (use_pair == 0) { if (bufferevent_pair_new(base, options1, pair) == -1) { event_base_free(base); return 0; } bev1 = pair[0]; bev2 = pair[1]; assert(bufferevent_pair_get_partner(bev1) != NULL); } else { bev1 = bufferevent_socket_new(base, -1, options1); bev2 = bufferevent_socket_new(base, -1, options2); } /*bufferevent_filter_new*/ if (use_filter == 0) { /*we cannot use BEV_OPT_CLOSE_ON_FREE when freeing bufferevents*/ bev3 = bufferevent_filter_new( bev1, NULL, NULL, options1 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL); bev4 = bufferevent_filter_new( bev2, NULL, NULL, options2 & (~BEV_OPT_CLOSE_ON_FREE), NULL, NULL); if (bev1) { bufferevent_free(bev1); } if (bev2) { bufferevent_free(bev2); } } else { bev3 = bev1; bev4 = bev2; } if (!bev3 || !bev4) { goto cleanup; } if (bufferevent_priority_set(bev3, options2) == 0) { assert(bufferevent_get_priority(bev3) == options2); } /*set rate limits*/ assert(bufferevent_set_rate_limit(bev3, NULL) != -1); static struct timeval cfg_tick = {static_cast<__time_t>(int1), static_cast<__suseconds_t>(int2)}; conn_bucket_cfg = ev_token_bucket_cfg_new(int1, int2, int3, int4, &cfg_tick); if (!conn_bucket_cfg) { goto cleanup; } bev_rate_group = bufferevent_rate_limit_group_new(base, conn_bucket_cfg); assert(bufferevent_add_to_rate_limit_group(bev4, bev_rate_group) != -1); /*write and read from buffer events*/ bufferevent_write(bev3, s1.c_str(), s1.size()); bufferevent_write(bev4, s2.c_str(), s2.size()); bufferevent_write_buffer(bev3, bufferevent_get_input(bev4)); evbuf = evbuffer_new(); bufferevent_read_buffer(bev3, evbuf); evbuffer_free(evbuf); bufferevent_read(bev3, buf, sizeof(buf) - 1); bufferevent_remove_from_rate_limit_group(bev4); /*watermarks*/ if (read_write == 0) { bufferevent_setwatermark(bev4, EV_READ, int1, int2); bufferevent_getwatermark(bev4, EV_READ, &int3, NULL); bufferevent_getwatermark(bev4, EV_READ, NULL, &int4); } else { bufferevent_setwatermark(bev4, EV_WRITE, int1, int2); bufferevent_getwatermark(bev4, EV_WRITE, &int3, NULL); bufferevent_getwatermark(bev4, EV_WRITE, NULL, &int4); } assert(int1 == int3); assert(int2 == int4); /*clean up*/ cleanup: if (bev3) { bufferevent_free(bev3); } if (bev4) { bufferevent_free(bev4); } if (conn_bucket_cfg) { ev_token_bucket_cfg_free(conn_bucket_cfg); conn_bucket_cfg = NULL; } if (bev_rate_group) { bufferevent_rate_limit_group_free(bev_rate_group); } event_base_free(base); return 0; } ================================================ FILE: projects/libevent/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project mkdir build cd build cmake -DEVENT__DISABLE_MBEDTLS=ON \ -DEVENT__DISABLE_OPENSSL=ON \ -DEVENT__LIBRARY_TYPE=STATIC \ -DEVENT__DISABLE_TESTS=ON \ -DEVENT__DISABLE_SAMPLES=ON \ ../ make -j$(nproc) make install # build fuzzer for fuzzers in $(find $SRC -name '*_fuzzer.cc'); do fuzz_basename=$(basename -s .cc $fuzzers) $CXX $CXXFLAGS -std=c++17 -I../ -Iinclude \ $fuzzers $LIB_FUZZING_ENGINE ./lib/libevent.a ./lib/libevent_core.a \ ./lib/libevent_pthreads.a ./lib/libevent_extra.a \ -o $OUT/$fuzz_basename done if [[ "$FUZZING_ENGINE" == "honggfuzz" ]] then fuzz_basename=$(basename -s .cc $fuzzers) $CC $CFLAGS $LIB_HFND "$HFND_CFLAGS" -Iinclude \ $SRC/fuzz_request_cb.c $LIB_FUZZING_ENGINE ./lib/libevent.a ./lib/libevent_core.a \ ./lib/libevent_pthreads.a ./lib/libevent_extra.a \ -o $OUT/fuzz_request fi # The dictionary is not compatible with AFL if [ "$FUZZING_ENGINE" != 'afl' ]; then cp $SRC/fuzzing/dictionaries/http.dict $OUT/http_fuzzer.dict fi ================================================ FILE: projects/libevent/dns_config_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include extern "C" { #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/bufferevent.h" #include "libevent/include/event2/dns.h" #include "libevent/include/event2/event.h" } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider data_provider(data, size); uint32_t flags = data_provider.ConsumeIntegral(); std::string s1 = data_provider.ConsumeRandomLengthString(); std::string s2 = data_provider.ConsumeRandomLengthString(); struct event_base *base = NULL; struct evdns_base *dns = NULL; base = event_base_new(); dns = evdns_base_new(base, flags % 65537); /* Create resolv.conf file*/ char resolvFilename[50]; sprintf(resolvFilename, "/tmp/resolv.%d", getpid()); FILE *fp = fopen(resolvFilename, "wb"); if (!fp) { goto cleanup; } fwrite(s1.c_str(), s1.size(), 1, fp); fclose(fp); evdns_base_resolv_conf_parse(dns, flags % 17, resolvFilename); /* Create /etc/hosts file*/ char hostsFilename[50]; sprintf(hostsFilename, "/tmp/hosts.%d", getpid()); fp = fopen(hostsFilename, "wb"); if (!fp) { unlink(resolvFilename); goto cleanup; } fwrite(s2.c_str(), s2.size(), 1, fp); fclose(fp); evdns_base_load_hosts(dns, hostsFilename); evdns_base_search_ndots_set(dns, flags); unlink(resolvFilename); unlink(hostsFilename); evdns_base_search_clear(dns); evdns_base_clear_host_addresses(dns); /*clean up*/ cleanup: evdns_base_free(dns, 0); event_base_free(base); return 0; } ================================================ FILE: projects/libevent/fuzz_request_cb.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * Uses the Honggfuzz netdriver logic: * - https://github.com/google/honggfuzz/tree/master/libhfnetdriver * This fuzzer can only be compiled with Honggfuzz (and not libFuzzer of AFL). */ #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/event.h" #include "libevent/include/event2/http.h" static void handle_request(struct evhttp_request *req, void *arg) { const char *uri = evhttp_request_get_uri(req); struct evbuffer *buf = evbuffer_new(); evbuffer_add_printf(buf, "From fuzzer cb, %s!", uri); evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf); } HFND_FUZZING_ENTRY_FUNCTION(int argc, char **argv) { struct event_base *base = event_base_new(); struct evhttp *http = evhttp_new(base); evhttp_bind_socket(http, "0.0.0.0", 8666); evhttp_set_gencb(http, handle_request, NULL); event_base_dispatch(base); return 0; } ================================================ FILE: projects/libevent/http_fuzzer.cc ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include extern "C" { #include "libevent/include/event2/event.h" #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/buffer_compat.h" #include "libevent/include/event2/util.h" #include "libevent/include/event2/event.h" #include "libevent/include/event2/http.h" #include "libevent/include/event2/http_struct.h" #include "libevent/include/event2/buffer.h" #include "libevent/include/event2/bufferevent.h" #include "libevent/http-internal.h" } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 5) { return 0; } // Decider to determine which request type to parse. uint8_t decider = data[0]; data++; size--; int maxHeaderSize = *(int*)data; data += 4; size -= 4; if (maxHeaderSize < 0) { return 0; } // Prepare in case it's used. struct evhttp_connection evcon; evcon.ext_method_cmp = NULL; evcon.max_headers_size = maxHeaderSize % 2048; struct evhttp *http_val = NULL; http_val = evhttp_new(NULL); if (http_val == NULL) { return 0; } evcon.http_server = http_val; FuzzedDataProvider data_provider(data, size); std::string s1 = data_provider.ConsumeRandomLengthString(); struct evbuffer *buf = evbuffer_new(); evbuffer_add(buf, s1.c_str(), s1.size()); struct evhttp_request *req = evhttp_request_new(NULL, NULL); // Use either the defailt request type or EVHTTP_REQUEST if (decider % 2 == 1) { req->kind=EVHTTP_REQUEST; req->evcon = &evcon; } enum message_read_status data_read; data_read = evhttp_parse_firstline_(req, buf); if (data_read != ALL_DATA_READ) { data_read = evhttp_parse_headers_(req, buf); if (data_read != ALL_DATA_READ) { data_read = evhttp_parse_headers_(req, buf); if (data_read != ALL_DATA_READ) { evhttp_request_get_input_headers(req); } } } evhttp_request_get_host(req); char *encoded = evhttp_encode_uri(s1.c_str()); if (encoded != NULL) { free(encoded); } // Minor utils function char *tmp_escaped = evhttp_htmlescape(s1.c_str()); if (tmp_escaped != NULL) { free(tmp_escaped); } // URI utils struct evhttp_uri *uri; uri = evhttp_uri_parse(s1.c_str()); if (uri != NULL) { char uri_buf[256]; evhttp_uri_join(uri, uri_buf, 256); evhttp_uri_free(uri); } // Cleanup evhttp_request_free(req); evbuffer_free(buf); evhttp_free(http_val); return 0; } ================================================ FILE: projects/libevent/parse_query_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include "libevent/include/event2/http.h" #include "libevent/include/event2/keyvalq_struct.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { std::string fuzz_string(reinterpret_cast(data), size); struct evkeyvalq headers; if (evhttp_parse_query(fuzz_string.c_str(), &headers) == 0) { evhttp_clear_headers(&headers); } if (size > 4) { uint32_t flags = *(uint32_t *)data; data += 4; size -= 4; std::string fuzz_string2(reinterpret_cast(data), size); if (evhttp_parse_query_str_flags(fuzz_string2.c_str(), &headers, flags) == 0) { evhttp_clear_headers(&headers); } } return 0; } ================================================ FILE: projects/libevent/project.yaml ================================================ homepage: "https://github.com/libevent/libevent" language: c++ primary_contact: "a3at.mail@gmail.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/libevent/libevent.git' auto_ccs: - "david@adalogics.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libevent/utils_fuzzer.cc ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include "libevent/include/event2/event.h" #include "libevent/include/event2/util.h" #include "util-internal.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int r; int len; char out_buf[128]; struct sockaddr_storage ss; FuzzedDataProvider data_provider(data, size); std::string fuzz_string = data_provider.ConsumeRandomLengthString(); len = sizeof(out_buf); r = evutil_parse_sockaddr_port( fuzz_string.c_str(), (struct sockaddr*)&ss, &len); if (r == 0) { evutil_format_sockaddr_port_((struct sockaddr*)&ss, out_buf, sizeof(out_buf)); } struct evutil_addrinfo *addr_info = NULL; std::string s1 = data_provider.ConsumeRandomLengthString(); evutil_getaddrinfo(s1.c_str(), NULL, NULL, &addr_info); if (addr_info != NULL) { evutil_freeaddrinfo(addr_info); } int portnum=-1; struct evutil_addrinfo *res = NULL; struct evutil_addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; evutil_getaddrinfo_common_(NULL, s1.c_str(), &hints, &res, &portnum); if (res != NULL) { evutil_freeaddrinfo(res); } res = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; evutil_getaddrinfo_common_(s1.c_str(), NULL, &hints, &res, &portnum); if (res != NULL) { evutil_freeaddrinfo(res); } return 0; } ================================================ FILE: projects/libexif/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool gettext autopoint RUN git clone --depth 1 https://github.com/libexif/libexif RUN git clone --depth 1 https://github.com/ianare/exif-samples WORKDIR libexif COPY exif_loader_fuzzer.cc exif_from_data_fuzzer.cc run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libexif/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ autoreconf -fiv ./configure --disable-docs --enable-shared=no --prefix="$WORK" make -j$(nproc) make install pushd $SRC mkdir -p exif_corpus find exif-samples -type f -name '*.jpg' -exec mv -n {} exif_corpus/ \; -o -name '*.tiff' -exec mv -n {} exif_corpus/ \; cp libexif/test/testdata/*.jpg exif_corpus zip -r "$WORK/exif_seed_corpus.zip" exif_corpus/ popd for fuzzer in $(find $SRC/ -name '*_fuzzer.cc'); do fuzzer_basename=$(basename -s .cc $fuzzer) $CXX $CXXFLAGS \ -std=c++11 \ -I"$WORK/include" \ $fuzzer \ -o $OUT/$fuzzer_basename \ $LIB_FUZZING_ENGINE \ "$WORK/lib/libexif.a" cp $WORK/exif_seed_corpus.zip "${OUT}/${fuzzer_basename}_seed_corpus.zip" done ================================================ FILE: projects/libexif/exif_from_data_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include /* Extract all MakerNote tags */ static void mnote_dump(ExifData *data) { ExifMnoteData *mn = exif_data_get_mnote_data(data); if (mn) { int num = exif_mnote_data_count(mn); /* Loop through all MakerNote tags */ for (int i=0; i < num; ++i) { char buf[1024]; exif_mnote_data_get_value(mn, i, buf, sizeof(buf)); } } } static void dump_value(ExifEntry *entry, void *user_data) { char buf[1024]; exif_entry_get_value(entry, buf, sizeof(buf)); } static void data_func(ExifContent *content, void *user_data) { exif_content_foreach_entry(content, dump_value, NULL); } /* This is like exif_data_dump but without writing to stdout */ static void data_dump(ExifData *data) { exif_data_foreach_content(data, data_func, NULL); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Parse tags using (ultimately) exif_data_load_data() auto image = exif_data_new_from_data(data, size); if (image) { // Exercise the EXIF tag manipulation code exif_data_get_mnote_data(image); data_dump(image); mnote_dump(image); unsigned char *buf; unsigned int sz; exif_data_save_data(image, &buf, &sz); free(buf); exif_data_fix(image); exif_data_unref(image); } return 0; } ================================================ FILE: projects/libexif/exif_loader_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include void content_func(ExifEntry *entry, void *user_data) { char buf[10000]; exif_entry_get_value(entry, buf, sizeof(buf)); } void data_func(ExifContent *content, void *user_data) { exif_content_foreach_entry(content, content_func, NULL); } static void test_exif_data (ExifData *d) { unsigned int i, c; char v[1024], *p; ExifMnoteData *md; md = exif_data_get_mnote_data (d); if (!md) { return; } exif_mnote_data_ref (md); exif_mnote_data_unref (md); c = exif_mnote_data_count (md); for (i = 0; i < c; i++) { const char *name = exif_mnote_data_get_name (md, i); if (!name) { break; } exif_mnote_data_get_title (md, i); exif_mnote_data_get_description (md, i); exif_mnote_data_get_value (md, i, v, sizeof (v)); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ExifLoader *loader = exif_loader_new(); ExifData *exif_data; if (!loader) { return 0; } exif_loader_write(loader, const_cast(data), size); exif_data = exif_loader_get_data(loader); if(!exif_data) { exif_loader_unref(loader); return 0; } exif_data_foreach_content(exif_data, data_func, NULL); test_exif_data (exif_data); exif_loader_unref(loader); exif_data_unref(exif_data); return 0; } ================================================ FILE: projects/libexif/project.yaml ================================================ homepage: "https://libexif.github.io" language: c++ primary_contact: "dan@coneharvesters.com" auto_ccs: - paul.l.kehrer@gmail.com - marcus@jet.franken.de - marcusmeissner@googlemail.com fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory main_repo: 'https://github.com/libexif/libexif' ================================================ FILE: projects/libexif/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/libfdk-aac/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://android.googlesource.com/platform/external/aac/ COPY build.sh *.cpp $SRC/ ================================================ FILE: projects/libfdk-aac/aacDecoder_ConfigRaw.cpp ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "aacdecoder_lib.h" #include #define FILEREAD_MAX_LAYERS 1 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { HANDLE_AACDECODER aacDecoderInfo = NULL; UCHAR *conf[FILEREAD_MAX_LAYERS]; UINT confSize[FILEREAD_MAX_LAYERS]; if (Size > 255) return 0; aacDecoderInfo = aacDecoder_Open(TT_MP4_ADIF, FILEREAD_MAX_LAYERS); FDK_ASSERT(aacDecoderInfo != NULL); for (UINT layer = 0; layer < FILEREAD_MAX_LAYERS; layer++) { conf[layer] = const_cast(Data); confSize[layer] = Size; } aacDecoder_ConfigRaw(aacDecoderInfo, conf, confSize); aacDecoder_Close(aacDecoderInfo); return 0; } ================================================ FILE: projects/libfdk-aac/aacDecoder_DecodeFrame.cpp ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "aacdecoder_lib.h" #include #define FILEREAD_MAX_LAYERS 1 #define OUT_BUF_SIZE (8 * 2048 * 4) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { HANDLE_AACDECODER aacDecoderInfo = NULL; INT_PCM TimeData[OUT_BUF_SIZE]; AAC_DECODER_ERROR err; aacDecoderInfo = aacDecoder_Open(TT_MP4_LOAS, FILEREAD_MAX_LAYERS); FDK_ASSERT(aacDecoderInfo != NULL); const uint8_t *start = Data; UINT valid, buffer_size; do { valid = buffer_size = Data + Size - start; err = aacDecoder_Fill(aacDecoderInfo, const_cast(&start), &buffer_size, &valid); start += buffer_size - valid; if (err == AAC_DEC_OK) { do { err = aacDecoder_DecodeFrame(aacDecoderInfo, TimeData, OUT_BUF_SIZE, 0); if (err != AAC_DEC_OK && err != AAC_DEC_NOT_ENOUGH_BITS) { aacDecoder_Close(aacDecoderInfo); aacDecoderInfo = NULL; return 0; } } while (err != AAC_DEC_NOT_ENOUGH_BITS); } } while (valid > 0); aacDecoder_Close(aacDecoderInfo); aacDecoderInfo = NULL; return 0; } ================================================ FILE: projects/libfdk-aac/aacDecoder_Open.cpp ================================================ // Copyright 2019 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "aacdecoder_lib.h" #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { HANDLE_AACDECODER aacDecoderInfo = NULL; TRANSPORT_TYPE transportType; INT nrOfLayers; if (Size != 8) return 0; transportType = (TRANSPORT_TYPE)(Data[0] + (Data[1] << 8) + (Data[2] << 16) + (Data[3] << 24)); nrOfLayers = (UINT)(Data[4] + (Data[5] << 8) + (Data[6] << 16) + (Data[7] << 24)); aacDecoderInfo = aacDecoder_Open(transportType, nrOfLayers); if (aacDecoderInfo != NULL) { aacDecoder_Close(aacDecoderInfo); } return 0; } ================================================ FILE: projects/libfdk-aac/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build the lib. INCLUDES=$(for f in $(find aac -name include); do echo -I $f; done) # exclude -fno-sanitize=shift-base as there are shallow errors. EXTRA_FLAGS=-fno-sanitize=shift-base for f in aac/*/src/*.cpp; do $CXX $CXXFLAGS $INCLUDES $EXTRA_FLAGS -c $f & done wait # Build the fuzz targets. for target_cpp in *.cpp; do target=$(basename $target_cpp .cpp) $CXX $CXXFLAGS $EXTRA_FLAGS $target_cpp $INCLUDES *.o -lm $LIB_FUZZING_ENGINE -o $OUT/$target done ================================================ FILE: projects/libfdk-aac/project.yaml ================================================ homepage: https://android.googlesource.com/platform/external/aac/ main_repo: 'https://android.googlesource.com/platform/external/aac/' language: c++ primary_contact: audio-fdk@iis.fraunhofer.de auto_ccs: - jmtrivi@google.com vendor_ccs: - adambacchus@google.com - ailport@google.com - bcreasey@google.com - cunefare@google.com - ejorgensen@google.com - faerber@google.com - greendonald@google.com - hamzeh@google.com - jaredkidd@google.com - kimtony@google.com - lindsaywells@google.com - maverickm@google.com - swansonr@google.com - warrenwright@google.com fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory architectures: - x86_64 - i386 ================================================ FILE: projects/libfido2/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN apt-get install -y cmake libpcsclite-dev libudev-dev pkg-config chrpath RUN git clone --depth 1 --branch v0.11.0 https://github.com/PJK/libcbor RUN git clone --depth 1 --branch openssl-3.0 https://github.com/openssl/openssl RUN git clone --depth 1 --branch v1.3.1 https://github.com/madler/zlib RUN git clone --depth 1 https://github.com/Yubico/libfido2 # CIFuzz will replace the libfido directory so put the corpus outside ADD https://storage.googleapis.com/yubico-libfido2/corpus.tgz corpus.tgz WORKDIR libfido2 COPY build.sh $SRC/ ================================================ FILE: projects/libfido2/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build libcbor, taken from oss-fuzz/projects/libcbor/build.sh # Note SANITIZE=OFF since it gets taken care of by $CFLAGS set by oss-fuzz cd ${SRC}/libcbor patch -l -p0 < ${SRC}/libfido2/fuzz/README mkdir build && cd build cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=${WORK} -DSANITIZE=OFF .. make -j$(nproc) VERBOSE=1 make install # Build OpenSSL, taken from oss-fuzz/projects/openssl/build.sh cd ${SRC}/openssl CONFIGURE_FLAGS="" if [[ ${SANITIZER} = memory ]] then CONFIGURE_FLAGS="no-asm" fi ./config --debug no-tests ${CFLAGS} --prefix=${WORK} \ --openssldir=${WORK}/openssl --libdir=lib ${CONFIGURE_FLAGS} make -j$(nproc) LDCMD="${CXX} ${CXXFLAGS}" make install_sw # Build zlib, taken from oss-fuzz/projects/zlib.sh cd ${SRC}/zlib ./configure --prefix=${WORK} make -j$(nproc) all make install # Building libfido2 with ${LIB_FUZZING_ENGINE} and chosen sanitizer cd ${SRC}/libfido2 mkdir build && cd build cmake -DFUZZ=1 -DFUZZ_LDFLAGS="${LIB_FUZZING_ENGINE}" \ -DFUZZ_LINKER_LANGUAGE=CXX \ -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=1 \ -DCMAKE_PREFIX_PATH=${WORK} \ -DCMAKE_INSTALL_PREFIX=${WORK} \ -DCMAKE_BUILD_TYPE=Debug .. make -j$(nproc) make install # Prepare ${OUT} with instrumented libs mkdir -p ${OUT}/lib for lib in `ls ${WORK}/lib/lib*.so*`; do cp ${lib} ${OUT}/lib; done # Place libpcsclite in ${OUT}; needed by fuzz_pcsc if [ -x fuzz/fuzz_pcsc ]; then for lib in `ldd fuzz/fuzz_pcsc | awk '/libpcsclite.so.*=>/ { print $3 }'`; do cp ${lib} ${OUT}/lib; done fi # Fixup rpath in the fuzzers so they use our libs for f in `ls fuzz/fuzz_*`; do cp ${f} ${OUT}/ fuzzer=$(basename $f) chrpath -r '$ORIGIN/lib' ${OUT}/${fuzzer} done # Prepare seed corpora tar xzf ${SRC}/corpus.tgz (set -e ; cd fuzz_assert/corpus ; zip -r ${OUT}/fuzz_assert_seed_corpus.zip .) (set -e ; cd fuzz_attobj/corpus ; zip -r ${OUT}/fuzz_attobj_seed_corpus.zip .) (set -e ; cd fuzz_bio/corpus ; zip -r ${OUT}/fuzz_bio_seed_corpus.zip .) (set -e ; cd fuzz_cred/corpus ; zip -r ${OUT}/fuzz_cred_seed_corpus.zip .) (set -e ; cd fuzz_credman/corpus ; zip -r ${OUT}/fuzz_credman_seed_corpus.zip .) (set -e ; cd fuzz_hid/corpus ; zip -r ${OUT}/fuzz_hid_seed_corpus.zip .) (set -e ; cd fuzz_largeblob/corpus ; zip -r ${OUT}/fuzz_largeblob_seed_corpus.zip .) (set -e ; cd fuzz_mgmt/corpus ; zip -r ${OUT}/fuzz_mgmt_seed_corpus.zip .) (set -e ; cd fuzz_netlink/corpus ; zip -r ${OUT}/fuzz_netlink_seed_corpus.zip .) (set -e ; cd fuzz_pcsc/corpus ; zip -r ${OUT}/fuzz_pcsc_seed_corpus.zip .) ================================================ FILE: projects/libfido2/project.yaml ================================================ homepage: https://github.com/Yubico/libfido2 language: c++ primary_contact: "kostas@yubico.com" auto_ccs: - "pedro@ambientworks.net" - "marissa.nishimoto@yubico.com" - "pedro.ossfuzz@gmail.com" - "ludvig.michaelsson@yubico.com" - "alex.geana@yubico.com" sanitizers: - address - undefined - memory fuzzing_engines: - libfuzzer - honggfuzz - afl # - centipede disabled due to https://github.com/google/oss-fuzz/pull/10248#issuecomment-1579657163 main_repo: 'https://github.com/Yubico/libfido2' ================================================ FILE: projects/libfuse/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ make autoconf automake libtool libudev-dev pkg-config \ udev python3-pip && \ python3 -m pip install meson==0.60.0 ninja RUN git clone --depth 1 https://github.com/AdaLogics/fuzz-headers fuzz-headers RUN git clone --depth 1 https://github.com/libfuse/libfuse libfuse WORKDIR libfuse COPY build.sh *.c $SRC/ ================================================ FILE: projects/libfuse/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build meson setup .. meson configure -D default_library=static ninja $CC $CFLAGS -c $SRC/fuzz_optparse.c -o fuzz_optparse.o \ -I$SRC/libfuse/lib/ -I$SRC/libfuse/include -I./ \ -I$SRC/fuzz-headers/lang/c \ -Wincompatible-pointer-types-discards-qualifiers $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_optparse.o \ -o $OUT/fuzz_optparse lib/libfuse3.a ================================================ FILE: projects/libfuse/fuzz_optparse.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #define FUSE_USE_VERSION 31 #include #include #include #include #include #include // To make some fuzz data operations easier. #include "ada_fuzz_header.h" static char *my_argv[10]; static struct options { const char *char_opt1; const char *char_opt2; int int_opt3; } options; #define OPTION(t, p) \ { t, offsetof(struct options, p), 1 } static const struct fuse_opt option_spec[] = { OPTION("--char_opt1=%s", char_opt1), OPTION("--char_opt2=%s", char_opt2), OPTION("-i", int_opt3), OPTION("--intopt3", int_opt3), FUSE_OPT_END}; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { af_safe_gb_init(data, size); char *opt1 = ada_safe_get_char_p(); char *opt2 = ada_safe_get_char_p(); for (int i = 0; i < 10; i++) { my_argv[i] = ada_safe_get_char_p(); } struct fuse_args args = {10, my_argv, 0}; options.char_opt1 = strdup(opt1); options.char_opt2 = strdup(opt2); options.int_opt3 = ada_safe_get_int(); if (fuse_opt_parse(&args, &options, option_spec, NULL) == -1) { free(options.char_opt1); free(options.char_opt2); af_safe_gb_cleanup(); return 0; } free(options.char_opt1); free(options.char_opt2); fuse_opt_free_args(&args); af_safe_gb_cleanup(); return 0; } ================================================ FILE: projects/libfuse/project.yaml ================================================ homepage: "https://github.com/libfuse/libfuse" main_repo: "https://github.com/libfuse/libfuse" language: c vendor_ccs: - david@adalogics.com ================================================ FILE: projects/libgd/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y make autoconf automake libtool pkg-config libz-dev RUN git clone --depth 1 https://github.com/libgd/libgd ADD https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz $SRC/afl_testcases.tgz WORKDIR libgd COPY run_tests.sh build.sh *.cc $SRC/ ================================================ FILE: projects/libgd/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ sed -i 's/-Werror//g' ./configure.ac ./bootstrap.sh # Limit the size of buffer allocations to avoid bogus OOM issues # https://github.com/libgd/libgd/issues/422 sed -i'' -e 's/INT_MAX/100000/' "$SRC/libgd/src/gd_security.c" ./configure --prefix="$WORK" --disable-shared make -j$(nproc) install export CXXFLAGS="${CXXFLAGS} -std=c++17" for target in Bmp Gd Gd2 Gif Jpeg Png Tga Tiff WBMP Webp; do lowercase=$(echo $target | tr "[:upper:]" "[:lower:]") $CXX $CXXFLAGS -I"$WORK/include" -L"$WORK/lib" \ -DFUZZ_GD_FORMAT=$target \ $SRC/parser_target.cc -o $OUT/${lowercase}_target \ $LIB_FUZZING_ENGINE -lgd -Wl,-Bstatic -lz -Wl,-Bdynamic done for fuzzers in $(find $SRC -name '*_fuzzer.cc'); do fuzz_basename=$(basename -s .cc $fuzzers) $CXX $CXXFLAGS -I"$WORK/include" -L"$WORK/lib" \ $fuzzers -o $OUT/$fuzz_basename \ $LIB_FUZZING_ENGINE -lgd -Wl,-Bstatic -lz -Wl,-Bdynamic done mkdir afl_testcases (cd afl_testcases; tar xvf "$SRC/afl_testcases.tgz") for format in bmp gif png webp; do mkdir $format find afl_testcases -type f -name '*.'$format -exec mv -n {} $format/ \; zip -rj $format.zip $format/ cp $format.zip "$OUT/${format}_target_seed_corpus.zip" done # Build unit testing by cmake # UBSan crashes with the unit testing build, thus unset the CXXFLAGS # when UBSan is used for the unit testing build. if [[ "$SANITIZER" == "undefined" ]] then unset CXXFLAGS fi cmake . -DBUILD_TEST=ON make -C tests -j$(nproc) ================================================ FILE: projects/libgd/gd_image_string_fuzzer.cc ================================================ // Copyright 2020 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ///////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "gd.h" #include "gdfontg.h" #include "gdfontl.h" #include "gdfontmb.h" #include "gdfonts.h" #include "gdfontt.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider stream(data, size); const uint8_t slate_width = stream.ConsumeIntegral(); const uint8_t slate_height = stream.ConsumeIntegral(); gdImagePtr slate_image = gdImageCreateTrueColor(slate_width, slate_height); if (slate_image == nullptr) { return 0; } const int x_position = stream.ConsumeIntegral(); const int y_position = stream.ConsumeIntegral(); const int text_color = stream.ConsumeIntegral(); const gdFontPtr font_ptr = stream.PickValueInArray( {gdFontGetGiant(), gdFontGetLarge(), gdFontGetMediumBold(), gdFontGetSmall(), gdFontGetTiny()}); const std::string text = stream.ConsumeRemainingBytesAsString(); gdImageString(slate_image, font_ptr, x_position, y_position, reinterpret_cast(const_cast(text.c_str())), text_color); gdImageDestroy(slate_image); return 0; } ================================================ FILE: projects/libgd/parser_target.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ///////////////////////////////////////////////////////////////////////////// #include #include "gd.h" #define PASTE(x) gdImageCreateFrom ## x ## Ptr #define CREATE_IMAGE(FORMAT) PASTE(FORMAT) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { gdImagePtr im = CREATE_IMAGE(FUZZ_GD_FORMAT)(Size, (void*) Data); if (im) gdImageDestroy(im); return 0; } ================================================ FILE: projects/libgd/project.yaml ================================================ homepage: "https://libgd.org" language: c++ primary_contact: "security@libgd.org" auto_ccs: - vapier@gmail.com - tim@tim-smith.us - cmbecker69@gmx.de main_repo: 'https://github.com/libgd/libgd' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libgd/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Skip segfault and failed cases and run the remaining unit testing ctest --test-dir $SRC/libgd -j$(nproc) -E \ "test_gdimagecolormatch_cve_2019_6977|test_gdimagetruecolortopalette_php_bug_72512|test_gdinterpolatedscale_gdTrivialResize|test_gdimagecopyrotated_bug00320|test_gdinterpolatedscale_gdModesAndPalettes" ================================================ FILE: projects/libgit2/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/libgit2/libgit2 libgit2 WORKDIR libgit2 COPY *.sh $SRC/ ================================================ FILE: projects/libgit2/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Some of the tests do not work in the OSS-Fuzz environment, patch these out # here: sed -i "s/add_clar_test(libgit2_tests online /#add_clar_test(libgit2_tests online/g" tests/libgit2/CMakeLists.txt sed -i "s/add_clar_test(libgit2_tests prox/#add_clar_test(libgit2_tests prox/g" tests/libgit2/CMakeLists.txt sed -i "s/add_clar_test(libgit2_tests auth_clone/#add_clar_test(libgit2_tests auth_clone/g" tests/libgit2/CMakeLists.txt # build project mkdir -p build cd build cmake .. -DCMAKE_INSTALL_PREFIX="$WORK" \ -DBUILD_SHARED_LIBS=OFF \ -DBUILD_CLAR=OFF \ -DUSE_HTTPS=OFF \ -DUSE_AUTH_NTLM=OFF \ -DUSE_SSH=OFF \ -DUSE_BUNDLED_ZLIB=ON \ make -j$(nproc) make install # Compile the shared fuzzer_utils.c $CC $CFLAGS -c \ -I./src -I./src/util -I./include/ -I./include/git2 \ -I../src/libgit2 -I../src/util -I../include \ -I../fuzzers \ ../fuzzers/fuzzer_utils.c -o "$WORK/fuzzer_utils.o" for fuzzer in ../fuzzers/*_fuzzer.c do fuzzer_name=$(basename "${fuzzer%.c}") $CC $CFLAGS -c \ -I./src -I./src/util -I./include/ -I./include/git2 \ -I../src/libgit2 -I../src/util -I../include \ -I../fuzzers \ "$fuzzer" -o "$WORK/$fuzzer_name.o" $CXX $CXXFLAGS -std=c++11 -o "$OUT/$fuzzer_name" \ $LIB_FUZZING_ENGINE "$WORK/$fuzzer_name.o" "$WORK/fuzzer_utils.o" "$WORK/lib/libgit2.a" zip -j "$OUT/${fuzzer_name}_seed_corpus.zip" \ ../fuzzers/corpora/${fuzzer_name%_fuzzer}/* done ================================================ FILE: projects/libgit2/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://libgit2.github.com/" language: c++ primary_contact: "ps@pks.im" auto_ccs: - "nelhage@nelhage.com" main_repo: 'https://github.com/libgit2/libgit2' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libgit2/run_tests.sh ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### cd build ctest ================================================ FILE: projects/libheif/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone \ --depth 1 \ --branch master \ https://github.com/strukturag/libheif.git \ libheif WORKDIR libheif COPY build.sh $SRC/ ================================================ FILE: projects/libheif/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Delegate actual building to the script provided by libheif. ./scripts/build-oss-fuzz.sh ================================================ FILE: projects/libheif/project.yaml ================================================ homepage: "https://github.com/strukturag/libheif" language: c++ primary_contact: "dirk.farin@gmail.com" auto_ccs: - "mail@joachim-bauch.de" architectures: - i386 - x86_64 main_repo: 'https://github.com/strukturag/libheif.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libhevc/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake RUN git clone https://github.com/ittiam-systems/libhevc.git ADD https://storage.googleapis.com/android_media/external/libhevc/fuzzer/hevc_dec_fuzzer_seed_corpus.zip $SRC/ COPY build.sh $SRC/ WORKDIR libhevc ================================================ FILE: projects/libhevc/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. $SRC/libhevc/fuzzer/ossfuzz.sh ================================================ FILE: projects/libhevc/project.yaml ================================================ homepage: "https://github.com/ittiam-systems/libhevc" language: c++ primary_contact: "harish.mahendrakar@ittiam.com" sanitizers: - address - memory - undefined auto_ccs: - aadithya.kamath@ittiam.com - harish.mahendrakar@ittiam.com - ram.mohan@ittiam.com - umang.saini@ittiam.com - essick@google.com - lajos@google.com vendor_ccs: - adambacchus@google.com - ailport@google.com - bcreasey@google.com - cunefare@google.com - ejorgensen@google.com - faerber@google.com - greendonald@google.com - hamzeh@google.com - jaredkidd@google.com - kimtony@google.com - lindsaywells@google.com - maverickm@google.com - swansonr@google.com - warrenwright@google.com architectures: - x86_64 - i386 main_repo: 'https://github.com/ittiam-systems/libhevc.git' ================================================ FILE: projects/libhtp/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust RUN apt-get update && apt-get install -y make autoconf automake libtool zlib1g-dev liblzma-dev RUN git clone --depth 1 https://github.com/OISF/libhtp.git libhtp WORKDIR $SRC/libhtp COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libhtp/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project sh autogen.sh ./configure make -j$(nproc) $CC $CFLAGS -I. -c test/fuzz/fuzz_htp.c -o fuzz_htp.o $CC $CFLAGS -I. -c test/test.c -o test.o $CXX $CXXFLAGS fuzz_htp.o test.o -o $OUT/fuzz_htp_c ./htp/.libs/libhtp.a $LIB_FUZZING_ENGINE -lz -llzma # builds corpus zip -r $OUT/fuzz_htp_seed_corpus.zip test/files/*.t ================================================ FILE: projects/libhtp/project.yaml ================================================ homepage: "https://github.com/OISF/libhtp" language: c primary_contact: "vjulien@openinfosecfoundation.org" auto_ccs : - "p.antoine@catenacyber.fr" - "jish@openinfosecfoundation.org" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory fuzzing_engines: - libfuzzer main_repo: 'https://github.com/OISF/libhtp.git' ================================================ FILE: projects/libhtp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/libical/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Install OpenJDK RUN apt-get update && \ apt-get install -y openjdk-11-jdk && \ rm -rf /var/lib/apt/lists/* RUN git clone --depth 1 https://github.com/libical/libical.git COPY run_tests.sh build.sh $SRC/ COPY *.cc $SRC/ WORKDIR libical ================================================ FILE: projects/libical/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cmake . -DSTATIC_ONLY=ON -DLIBICAL_GLIB=False -DLIBICAL_GLIB_BUILD_DOCS=False -DLIBICAL_GOBJECT_INTROSPECTION=False -DLIBICAL_JAVA_BINDINGS=False -DLIBICAL_BUILD_TESTING=True make install -j$(nproc) $CXX $CXXFLAGS -std=c++11 $SRC/libical_fuzzer.cc $LIB_FUZZING_ENGINE /usr/local/lib/libical.a -o $OUT/libical_fuzzer $CXX $CXXFLAGS -std=c++11 $SRC/libical_extended_fuzzer.cc $LIB_FUZZING_ENGINE /usr/local/lib/libical.a -o $OUT/libical_extended_fuzzer $CXX $CXXFLAGS -std=c++11 $SRC/libicalvcard_fuzzer.cc $LIB_FUZZING_ENGINE /usr/local/lib/libicalvcard.a /usr/local/lib/libical.a -o $OUT/libicalvcard_fuzzer find . -name *.ics -print | zip -q $OUT/libical_fuzzer_seed_corpus.zip -@ ================================================ FILE: projects/libical/libical_extended_fuzzer.cc ================================================ /* # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ /* Usage: python infra/helper.py build_image libical python infra/helper.py build_fuzzers --sanitizer undefined|address|memory libical python infra/helper.py run_fuzzer libical libical_extended_fuzzer */ #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *ical_string1 = (char*)malloc(size + 1); memcpy(ical_string1, data, size); ical_string1[size] = '\0'; icalcomponent *ical1 = icalcomponent_new_from_string(ical_string1); if (ical1 != NULL) { icalcomponent_normalize(ical1); } icalcomponent_free(ical1); free(ical_string1); return 0; } ================================================ FILE: projects/libical/libical_fuzzer.cc ================================================ /* # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ /* Usage: python infra/helper.py build_image libical python infra/helper.py build_fuzzers --sanitizer undefined|address|memory libical python infra/helper.py run_fuzzer libical libical_fuzzer */ #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *ical_string = (char*)malloc(size + 1); memcpy(ical_string, data, size); ical_string[size] = '\0'; icalcomponent *component = icalparser_parse_string(ical_string); icalcomponent_free(component); free(ical_string); return 0; } ================================================ FILE: projects/libical/libicalvcard_fuzzer.cc ================================================ /* # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ /* Usage: python infra/helper.py build_image libical python infra/helper.py build_fuzzers --sanitizer undefined|address|memory libical python infra/helper.py run_fuzzer libical libicalvcard_fuzzer */ #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char *vcard_string = (char*)malloc(size + 1); memcpy(vcard_string, data, size); vcard_string[size] = '\0'; vcardcomponent *card = vcardparser_parse_string(vcard_string); vcardcomponent_free(card); free(vcard_string); return 0; } ================================================ FILE: projects/libical/project.yaml ================================================ homepage: https://github.com/libical/libical language: c++ primary_contact: tsdgeos@gmail.com auto_ccs: - allen.d.winter@gmail.com - kent.sutherland@gmail.com - ksmurchison@gmail.com sanitizers: - address - memory - undefined main_repo: 'https://github.com/libical/libical.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libical/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir $SRC/libical -j$(nproc) ================================================ FILE: projects/libidn/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ pkg-config \ autopoint \ autoconf \ autoconf-archive \ automake \ libtool \ gettext gengetopt curl gperf wget RUN git clone https://git.savannah.gnu.org/git/libidn.git WORKDIR libidn COPY build.sh $SRC/ ================================================ FILE: projects/libidn/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite) export ASAN_OPTIONS=detect_leaks=0 ./bootstrap --skip-po ./configure --enable-static --disable-doc make -j make -j check cd fuzz make oss-fuzz find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' for fuzzer in *_fuzzer; do cp -p "${fuzzer}" "$OUT" if [ -f "$SRC/${fuzzer}_seed_corpus.zip" ]; then cp "$SRC/${fuzzer}_seed_corpus.zip" "$OUT/" fi if [ -d "${fuzzer}.in/" ]; then zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${fuzzer}.in/" fi done ================================================ FILE: projects/libidn/project.yaml ================================================ homepage: "https://www.gnu.org/software/libidn/" language: c++ primary_contact: "rockdaboot@gmail.com" auto_ccs: - "tim.ruehsen@gmx.de" - "simon@josefsson.org" main_repo: 'https://git.savannah.gnu.org/git/libidn.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libidn2/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake gettext libtool autopoint pkg-config gengetopt curl gperf rsync wget RUN git clone --recursive https://gitlab.com/libidn/libidn2.git WORKDIR libidn2 COPY build.sh replay_build.sh $SRC/ ================================================ FILE: projects/libidn2/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./bootstrap # switch off leak detection for ./configure run to detect iconv() correctly ASAN_OPTIONS=detect_leaks=0 ./configure --enable-static --disable-shared --disable-doc --disable-gcc-warnings make clean make -j$(nproc) check VERBOSE=t cd fuzz make oss-fuzz find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' for dir in *_fuzzer.in; do fuzzer=$(basename $dir .in) zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/" done ================================================ FILE: projects/libidn2/project.yaml ================================================ homepage: "https://gitlab.com/libidn/libidn2" language: c++ primary_contact: "rockdaboot@gmail.com" auto_ccs: - "simon@josefsson.org" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory main_repo: 'https://gitlab.com/libidn/libidn2.git' ================================================ FILE: projects/libidn2/replay_build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # This script is useful for OSS-Fuzz infrastructure which is used to rebuild # code from cached images. This is to support various ongoing efforts in # OSS-Fuzz. cd $SRC/libidn2 make -j$(nproc) cd fuzz make oss-fuzz find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' ================================================ FILE: projects/libiec61850/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone https://github.com/mz-automation/libiec61850 WORKDIR $SRC COPY build.sh $SRC/ COPY fuzz_decode.options $SRC/fuzz_decode.options ================================================ FILE: projects/libiec61850/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd libiec61850 mkdir build && cd build cmake ../ make $CC $CFLAGS $LIB_FUZZING_ENGINE ../fuzz/fuzz_mms_decode.c -c \ -I../src/iec61850/inc -I../src/mms/inc -I../src/common/inc \ -I../hal/inc -I../src/logging $CXX $CXXFLAGS -fuse-ld=lld $LIB_FUZZING_ENGINE fuzz_mms_decode.o -o $OUT/fuzz_mms_decode ./src/libiec61850.a ./hal/libhal.a # Copy over the options file cp $SRC/fuzz_decode.options $OUT/fuzz_decode.options ================================================ FILE: projects/libiec61850/fuzz_decode.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/libiec61850/project.yaml ================================================ homepage: "https://github.com/mz-automation/libiec61850" primary_contact: "support@mz-automation.de" auto_ccs: - "david@adalogics.com" language: c main_repo: 'https://github.com/mz-automation/libiec61850' ================================================ FILE: projects/libigl/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make libgmp-dev libmpfr-dev RUN git clone --depth 1 https://github.com/libigl/libigl WORKDIR $SRC/libigl COPY igl_fuzzer.cpp \ run_tests.sh \ build.sh \ $SRC/ ================================================ FILE: projects/libigl/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build-dir && cd build-dir cmake -DLIBIGL_OPENGL=OFF \ -DLIBIGL_GLFW=OFF \ -DLIBIGL_IMGUI=OFF \ -DLIBIGL_COMISO=OFF \ -DLIBIGL_EMBREE=OFF \ -DLIBIGL_PNG=OFF \ -DLIBIGL_COPYLEFT_CORE=OFF \ -DLIBIGL_COPYLEFT_CGAL=OFF \ -DLIBIGL_COPYLEFT_TETGEN=OFF \ -DLIBIGL_COPYLEFT_COMISO=OFF \ -DLIBIGL_RESTRICTED_TRIANGLE=OFF \ -DLIBIGL_PREDICATES=OFF \ -DLIBIGL_XML=OFF \ -DLIBIGL_RESTRICTED_MATLAB=OFF \ -DLIBIGL_BUILD_TESTS=ON \ .. make -j$(nproc) $CXX $CXXFLAGS -DIGL_STATIC_LIBRARY \ -I/src/libigl/include \ -isystem /src/libigl/cmake/../include \ -isystem /src/libigl/cmake/../external/eigen \ -c $SRC/igl_fuzzer.cpp -o fuzzer.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzzer.o \ -o $OUT/igl_fuzzer $SRC/libigl/build-dir/lib/libigl.a ================================================ FILE: projects/libigl/igl_fuzzer.cpp ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){ char *nullt_string = (char *)malloc(size+1); if (nullt_string == NULL){ return 0; } memcpy(nullt_string, data, size); nullt_string[size] = '\0'; std::ofstream fuzz_file; fuzz_file.open ("fuzz_file.msh"); fuzz_file << nullt_string; fuzz_file.close(); try { igl::MshLoader msh_loader("fuzz_file.msh"); } catch (...) {} free(nullt_string); return 0; } ================================================ FILE: projects/libigl/project.yaml ================================================ homepage: "https://libigl.github.io" language: c++ primary_contact: "alecjacobson@gmail.com" auto_ccs: - "Adam@adalogics.com" sanitizers: - address - undefined - memory main_repo: "https://github.com/libigl/libigl" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libigl/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ cd build-dir # TODO: Skipping some failing tests for now. ctest \ -j $(nproc) \ -E "(AABB: intersect|\ boundary_facets: single_tri|\ increment_ulp: dense|\ signed_distance: single_tet|\ signed_distance: single_triangle|\ signed_distance: dimension-templates)" ================================================ FILE: projects/libjpeg-turbo/Dockerfile ================================================ # Copyright 2016 Google Inc. # Copyright 2022-2023 D. R. Commander # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make yasm cmake RUN git clone --depth 1 https://github.com/libjpeg-turbo/fuzz && \ cat fuzz/branches.txt | while read branch; do \ git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo -b $branch libjpeg-turbo.$branch; \ done RUN git clone --depth 1 https://github.com/libjpeg-turbo/seed-corpora RUN cd seed-corpora && zip -r ../decompress_fuzzer_seed_corpus.zip afl-testcases/jpeg* bugs/decompress* RUN cat fuzz/branches.txt | while read branch; do \ zip -r decompress_fuzzer_seed_corpus.zip libjpeg-turbo.$branch/testimages/*.jpg; \ done RUN cd seed-corpora && zip -r ../compress_fuzzer_seed_corpus.zip afl-testcases/bmp afl-testcases/gif* afl-testcases/targa bugs/compress* RUN cat fuzz/branches.txt | while read branch; do \ zip -r compress_fuzzer_seed_corpus.zip libjpeg-turbo.$branch/testimages/*.bmp libjpeg-turbo.$branch/testimages/*.ppm libjpeg-turbo.$branch/testimages/*.pgm; \ done RUN rm -rf seed-corpora COPY build.sh $SRC/ ================================================ FILE: projects/libjpeg-turbo/build.sh ================================================ # Copyright 2022-2023 D. R. Commander # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -e set -u cat fuzz/branches.txt | while read branch; do pushd libjpeg-turbo.$branch if [ "$branch" = "main" ]; then sh fuzz/build.sh else sh fuzz/build.sh _$branch fi popd done ================================================ FILE: projects/libjpeg-turbo/project.yaml ================================================ homepage: "https://libjpeg-turbo.org" language: c primary_contact: "drc@virtualgl.org" vendor_ccs: - "aosmond@mozilla.com" - "tnikkel@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/libjpeg-turbo/libjpeg-turbo' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libjxl/Dockerfile ================================================ # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake ninja-build pkg-config \ libjpeg-dev RUN git clone --depth 1 https://github.com/libjxl/libjxl.git # We only need these sub-projects for the fuzzers. RUN git -C libjxl submodule update --init --recommend-shallow \ third_party/brotli \ third_party/highway \ third_party/libjpeg-turbo \ third_party/skcms RUN git clone --depth 1 https://github.com/libjpeg-turbo/seed-corpora WORKDIR libjxl COPY build.sh $SRC/ ================================================ FILE: projects/libjxl/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ build_args=( -G Ninja -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_DEVTOOLS=ON -DJPEGXL_ENABLE_EXAMPLES=OFF -DJPEGXL_ENABLE_FUZZERS=ON -DJPEGXL_ENABLE_MANPAGES=OFF -DJPEGXL_ENABLE_SJPEG=OFF -DJPEGXL_ENABLE_VIEWERS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON ) # Build and generate a fuzzer corpus in release mode without instrumentation. # This is done in a subshell since we change the environment. ( unset CFLAGS unset CXXFLAGS export AFL_NOOPT=1 rm -rf ${WORK}/libjxl-corpus mkdir -p ${WORK}/libjxl-corpus cd ${WORK}/libjxl-corpus cmake "${build_args[@]}" "${SRC}/libjxl" ninja clean ninja djxl_fuzzer_corpus # Generate fuzzer corpora. fuzzers=( djxl_fuzzer ) for fuzzer in "${fuzzers[@]}"; do mkdir -p "${fuzzer}_corpus" "tools/${fuzzer}_corpus" -q -r "${fuzzer}_corpus" done for fuzzer in "${fuzzers[@]}"; do zip -q -j "${OUT}/${fuzzer}_seed_corpus.zip" "${fuzzer}_corpus"/* done ) # Build the fuzzers in release mode but force the inclusion of JXL_DASSERT() # checks. export CXXFLAGS="${CXXFLAGS} -DJXL_IS_DEBUG_BUILD=1" if [ "$SANITIZER" == "undefined" ]; then build_args[${#build_args[@]}]="-DCXX_NO_RTTI_SUPPORTED=OFF" fi rm -rf ${WORK}/libjxl-fuzzer mkdir -p ${WORK}/libjxl-fuzzer cd ${WORK}/libjxl-fuzzer cmake \ "${build_args[@]}" \ -DJPEGXL_FUZZER_LINK_FLAGS="${LIB_FUZZING_ENGINE}" \ "${SRC}/libjxl" fuzzers=( cjxl_fuzzer color_encoding_fuzzer decode_basic_info_fuzzer djxl_fuzzer fields_fuzzer icc_codec_fuzzer rans_fuzzer set_from_bytes_fuzzer streaming_fuzzer transforms_fuzzer ) ninja clean ninja "${fuzzers[@]}" for fuzzer in "${fuzzers[@]}"; do cp tools/${fuzzer} "${OUT}/" done ================================================ FILE: projects/libjxl/project.yaml ================================================ homepage: "https://github.com/libjxl/libjxl" main_repo: 'https://github.com/libjxl/libjxl.git' language: c++ primary_contact: "libjxl-security@google.com" auto_ccs: - "eustas@google.com" - "jyrki@google.com" - "veluca@google.com" sanitizers: - address - memory - undefined fuzzing_engines: - afl - honggfuzz - libfuzzer architectures: - x86_64 - i386 ================================================ FILE: projects/libldac/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y automake ffmpeg libtool RUN git clone --depth 1 -b master https://android.googlesource.com/platform/external/libldac RUN python3 -m pip install --upgrade pip && python3 -m pip install corpus-replicator RUN corpus-replicator -o corpora audio_pcm_wav_ffmpeg.yml audio WORKDIR libldac COPY build.sh libldac_encode_fuzzer.cc $SRC/ ================================================ FILE: projects/libldac/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $CC $CFLAGS -Iinc -c $SRC/libldac_encode_fuzzer.cc -o libldac_encode_fuzzer.o $CC $CFLAGS -Iinc -c src/ldaclib.c -o src/ldaclib.o $CC $CFLAGS -Iinc -c src/ldacBT.c -o src/ldacBT.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE \ libldac_encode_fuzzer.o \ src/ldaclib.o \ src/ldacBT.o \ -o $OUT/libldac_encode_fuzzer zip -q $OUT/libldac_encode_fuzzer_seed_corpus.zip $SRC/corpora/* ================================================ FILE: projects/libldac/libldac_encode_fuzzer.cc ================================================ // Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include "ldacBT.h" #define TESTFUNC_TYPE extern "C" int TESTFUNC_TYPE LLVMFuzzerTestOneInput(const uint8_t *buf, size_t size) { if (size == 0) { return 0; } HANDLE_LDAC_BT hLdacBt; int pcm_used, stream_sz, frame_num; unsigned char p_stream[1024]; hLdacBt = ldacBT_get_handle(); ldacBT_init_handle_encode( hLdacBt, 679, LDACBT_EQMID_SQ, LDACBT_CHANNEL_MODE_DUAL_CHANNEL, LDACBT_SMPL_FMT_S16, 48000); ldacBT_encode( hLdacBt, (void *)(&buf + 44), &pcm_used, p_stream, &stream_sz, &frame_num); ldacBT_get_sampling_freq(hLdacBt); ldacBT_get_bitrate(hLdacBt); ldacBT_get_version(); ldacBT_close_handle(hLdacBt); ldacBT_free_handle(hLdacBt); return 0; } ================================================ FILE: projects/libldac/project.yaml ================================================ homepage: "https://android.googlesource.com/platform/external/libldac" language: c++ primary_contact: "Chisato.Kenmochi@sony.com" auto_ccs: - twsmith@mozilla.com vendor_ccs: - adambacchus@google.com - ailport@google.com - bcreasey@google.com - cunefare@google.com - ejorgensen@google.com - faerber@google.com - greendonald@google.com - hamzeh@google.com - jaredkidd@google.com - kimtony@google.com - lindsaywells@google.com - maverickm@google.com - swansonr@google.com - warrenwright@google.com fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address main_repo: 'https://android.googlesource.com/platform/external/libldac' ================================================ FILE: projects/liblouis/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool \ pkg-config zlib1g-dev libpci-dev RUN git clone --depth 1 https://github.com/liblouis/liblouis WORKDIR liblouis RUN sed -i 's/main/main2/g' tests/fuzzing/fuzz_backtranslate.c && \ sed -i 's/main/main2/g' tests/fuzzing/fuzz_translate_generic.c && \ sed -i 's/LLVMFuzzerRunDriver(&argc/\/\/LLVMFuzzerRunDriver(&argc/g' tests/fuzzing/fuzz_backtranslate.c && \ sed -i 's/LLVMFuzzerRunDriver(&argc/\/\/LLVMFuzzerRunDriver(&argc/g' tests/fuzzing/fuzz_translate_generic.c COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/liblouis/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/liblouis/tests/fuzzing/build.sh ================================================ FILE: projects/liblouis/project.yaml ================================================ homepage: "https://github.com/liblouis/liblouis" main_repo: "https://github.com/liblouis/liblouis" language: c primary_contact: "christian.egli@sbs.ch" auto_ccs: - "bertfrees@gmail.com" - "david@adalogics.com" - "Adam@adalogics.com" sanitizers: - address - undefined - memory fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/liblouis/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check ================================================ FILE: projects/libmicrohttpd/project.yaml ================================================ homepage: "https://www.gnu.org/s/libmicrohttpd/" main_repo: "https://git.gnunet.org/libmicrohttpd.git" primary_contact: "christian@grothoff.org" auto_ccs: - "k2k@narod.ru" ================================================ FILE: projects/libmicrohttpd2/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && \ apt-get install -y autoconf automake libtool pkg-config texinfo \ gnutls-dev gnutls-bin RUN git clone git://git.gnunet.org/libmicrohttpd2.git mhd2 WORKDIR mhd2 COPY build.sh *.cpp *.h $SRC/ COPY *.options *.dict $SRC/ ================================================ FILE: projects/libmicrohttpd2/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ BINARY=$SRC/mhd2/src/mhd2/.libs/libmicrohttpd2.a # Build libmicrohttpd git pull ./autogen.sh # Compile MHD with the SAME compiler used later. export CC=$CXX # Enable most features, force specific TLS library, and disable symbol hiding ./configure \ --enable-dauth \ --enable-md5=builtin \ --enable-sha256=builtin \ --enable-sha512-256=builtin \ --enable-bauth \ --enable-upgrade \ --enable-https \ --without-openssl \ --enable-messages \ --disable-examples \ mhd_cv_cc_attr_visibility_default="no" \ mhd_cv_cc_attr_visibility_internal="no" \ mhd_cv_cc_attr_visibility_hidden="no" ASAN_OPTIONS=detect_leaks=0 make -j$(nproc) make install # Compile fuzzer FUZZERS="fuzz_response fuzz_daemon fuzz_mhd2 fuzz_str fuzz_crypto_int fuzz_libinfo fuzz_connection fuzz_daemon_connection" for fuzzer in $FUZZERS; do extra_src="" case "$fuzzer" in fuzz_response|fuzz_daemon) extra_src="$SRC/mhd_helper.cpp" ;; esac case "$fuzzer" in fuzz_connection|fuzz_daemon_connection) extra_src="$SRC/connection_helper.cpp" ;; esac $CXX $CXXFLAGS -DHAVE_CONFIG_H "$SRC/$fuzzer.cpp" $extra_src \ -Wno-unused-parameter -Wno-unused-value -pthread \ -I"$SRC" -I"$SRC/mhd2/src/mhd2" -I"$SRC/mhd2/src/include" \ -I"$SRC/mhd2/src/incl_priv" -I"$SRC/mhd2/src/incl_priv/config" \ $LIB_FUZZING_ENGINE "$BINARY" -lgnutls -o "$OUT/$fuzzer" done # Rebuild the binary for external crypto with libgcrypt ./autogen.sh ./configure \ --enable-md5=tlslib \ --enable-sha256=tlslib \ --enable-sha512-256=builtin \ --without-openssl \ --disable-examples \ mhd_cv_cc_attr_visibility_default="no" \ mhd_cv_cc_attr_visibility_internal="no" \ mhd_cv_cc_attr_visibility_hidden="no" make clean make -j$(nproc) make install $CXX $CXXFLAGS $SRC/fuzz_crypto_ext.cpp -DHAVE_CONFIG_H \ -Wno-unused-parameter -Wno-unused-value -I$SRC/mhd2/src/mhd2 \ -I$SRC/mhd2/src/include -I$SRC/mhd2/src/incl_priv \ -I$SRC/mhd2/src/incl_priv/config $LIB_FUZZING_ENGINE $BINARY \ -lgnutls -o $OUT/fuzz_crypto_ext cp $SRC/default.options $OUT/fuzz_daemon.options cp $SRC/*.dict $OUT/ ================================================ FILE: projects/libmicrohttpd2/connection_helper.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "connection_helper.h" #include #include #include "mhd_action.h" #include "http_post_enc.h" #include "mempool_funcs.h" #include "daemon_funcs.h" #include "post_parser_funcs.h" #include "response_funcs.h" #include "stream_process_request.h" #include "stream_funcs.h" // MHD memory pool struct mhd_MemoryPool *g_pool = nullptr; const size_t g_pool_size = 14 * 1024; std::string g_mpart_boundary; // Body status static std::unordered_set g_post_parse_ready; // Helper to clear memory pool void destroy_global_pool() { if (g_pool) { mhd_pool_destroy(g_pool); g_pool = nullptr; } } // Helper to set body parsing ready void mark_post_parse_ready(MHD_Connection& c) { g_post_parse_ready.insert(&c); } // Helper to check parse body status bool is_post_parse_ready(const MHD_Connection& c) { return g_post_parse_ready.find(&c) != g_post_parse_ready.end(); } // Helper to clear parse body status void clear_post_parse_ready(const MHD_Connection& c) { g_post_parse_ready.erase(&c); } // Helper to destroy error response static bool destroy_error_response(MHD_Connection c) { if (c.stage == mhd_HTTP_STAGE_START_REPLY) { MHD_response_destroy(c.rp.response); c.rp.response = nullptr; return true; } return false; } // Helper to randomly choose HTTP methods static std::string pick_method(FuzzedDataProvider& fdp) { static const char* kMethods[] = { "GET","POST","PUT","HEAD","DELETE","CONNECT","OPTIONS","TRACE","*" }; return std::string(fdp.PickValueInArray(kMethods)); } // Helper to randomly choose http versions static std::string pick_http_version(FuzzedDataProvider& fdp) { // Common + a chance to be malformed to trigger version errors. switch (fdp.ConsumeIntegralInRange(0, 5)) { case 0: return "HTTP/1.1"; case 1: return "HTTP/1.0"; case 2: return "HTTP/2.0"; case 3: return "HTTP/0.9"; case 4: return "HTTX/1.1"; default: { std::string s = "HTTP/"; s.push_back(char('0' + fdp.ConsumeIntegralInRange(0,9))); s.push_back('.'); s.push_back(char('0' + fdp.ConsumeIntegralInRange(0,9))); return s; } } } // Helper to check and expand buffer capcaity bool ensure_lbuf_capacity(MHD_Connection& c, size_t min_needed) { if (!c.daemon) { return false; } if (c.rq.cntn.lbuf.data && c.rq.cntn.lbuf.size >= min_needed) { return true; } size_t have = c.rq.cntn.lbuf.size; size_t need = (min_needed > have) ? (min_needed - have) : 0; if (need) { mhd_daemon_extend_lbuf_up_to(c.daemon, need, &c.rq.cntn.lbuf); } return (c.rq.cntn.lbuf.data != nullptr) && (c.rq.cntn.lbuf.size >= min_needed); } // Dummy upload actions const struct MHD_UploadAction kContinueAction = { mhd_UPLOAD_ACTION_CONTINUE, { nullptr } }; const struct MHD_UploadAction kSuspend = { mhd_UPLOAD_ACTION_SUSPEND, { nullptr } }; const struct MHD_UploadAction kAbort = { mhd_UPLOAD_ACTION_ABORT, { nullptr } }; // Dummy reader function const struct MHD_UploadAction * dummy_reader(struct MHD_Request*, void*, const struct MHD_String*, const struct MHD_StringNullable*, const struct MHD_StringNullable*, const struct MHD_StringNullable*, size_t, const void*, uint_fast64_t, enum MHD_Bool) { return &kContinueAction; } // Dummy connection request ending function const struct MHD_UploadAction * dummy_done(struct MHD_Request*, void*, enum MHD_PostParseResult) { return &kContinueAction; } // Dummy request callback function static const struct MHD_Action* dummy_request_cb(void* cls, struct MHD_Request* request, const struct MHD_String* path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { return nullptr; } void init_daemon_connection(FuzzedDataProvider& fdp, MHD_Daemon& d, MHD_Connection& c) { // Basic initialisation d = {}; c = {}; c.daemon = &d; c.pool = g_pool; // Configure daemon memory pool d.conns.cfg.mem_pool_size = g_pool_size; d.conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_ON_RESET; // Confiugre daemon request d.req_cfg.large_buf.space_left = fdp.ConsumeIntegralInRange(256, 65536); d.req_cfg.strictness = static_cast( fdp.ConsumeIntegralInRange(0, 2)); // Safe guard for buffer space if (fdp.ConsumeBool()) { const size_t clamp = fdp.ConsumeIntegralInRange(64, 512); if (d.req_cfg.large_buf.space_left > clamp) d.req_cfg.large_buf.space_left = clamp; } // Configure connection request and general settings c.discard_request = false; c.suspended = false; c.timeout.milsec = fdp.ConsumeIntegralInRange(0, 4096); c.timeout.last_act = 0; // Add dummy callback function d.req_cfg.cb = dummy_request_cb; d.req_cfg.cb_cls = nullptr; } void init_connection_buffer(FuzzedDataProvider& fdp, MHD_Connection& c) { // Prepare connection buffer in memory pool size_t required = 0; const size_t capacity = fdp.ConsumeIntegralInRange(512, 16384); char* buf = static_cast(mhd_pool_try_alloc(c.pool, capacity, &required)); if (!buf) { c.read_buffer = nullptr; c.read_buffer_size = 0; c.read_buffer_offset = 0; return; } // Randomly choose configuration std::string hdrs; const std::string method = pick_method(fdp); const std::string version = pick_http_version(fdp); const std::string target = (method == "*") ? "*" : (fdp.ConsumeBool() ? "/upload" : "/x?y=z"); // Randomly break line endings in request line const bool bare_lf = fdp.ConsumeBool(); const bool bare_cr = (!bare_lf) && fdp.ConsumeBool(); auto EOL = [&](bool final=false) { if (bare_lf) { return std::string("\n"); } if (bare_cr) { return std::string("\r"); } return std::string("\r\n"); }; std::string req = method + " " + target + " " + version + EOL(); // Host headers int host_count = 0; if (version == "HTTP/1.1") { host_count = fdp.ConsumeIntegralInRange(0,2); } else { host_count = fdp.ConsumeIntegralInRange(0,1); } for (int i = 0; i < host_count; ++i) { if (fdp.ConsumeBool()) { hdrs += " Host: fuzz" + std::to_string(i) + EOL(); } else if (fdp.ConsumeBool()) { hdrs += "Host : fuzz" + std::to_string(i) + EOL(); } else { hdrs += "Host: fuzz" + std::to_string(i) + EOL(); } } // Transfer-Encoding and Content-Length headers const bool add_te = fdp.ConsumeBool(); const bool add_cl = fdp.ConsumeBool(); std::string te_val = fdp.PickValueInArray({"chunked","gzip","br","compress"}); if (add_te) { hdrs += "Transfer-Encoding: " + te_val + EOL(); } if (add_cl) { std::string cl; switch (fdp.ConsumeIntegralInRange(0,3)) { case 0: cl = "0"; break; case 1: cl = std::to_string(fdp.ConsumeIntegralInRange(0, 1<<20)); break; case 2: cl = "18446744073709551616"; break; default: cl = "xyz"; break; } hdrs += "Content-Length: " + cl + EOL(); } // Random minimum headers if (fdp.ConsumeBool()) { hdrs += (fdp.ConsumeBool() ? "Expect: 100-continue" : "Expect: something-weird") + EOL(); } bool detect_mpart = false; switch (c.rq.app_act.head_act.data.post_parse.enc) { case MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA: g_mpart_boundary = "fuzz" + std::to_string(fdp.ConsumeIntegral()); hdrs += "Content-Type: multipart/form-data; boundary=" + g_mpart_boundary + EOL(); break; case MHD_HTTP_POST_ENCODING_FORM_URLENCODED: hdrs += "Content-Type: application/x-www-form-urlencoded" + EOL(); break; case MHD_HTTP_POST_ENCODING_TEXT_PLAIN: hdrs += "Content-Type: text/plain" + EOL(); break; default: case MHD_HTTP_POST_ENCODING_OTHER: detect_mpart = fdp.ConsumeBool(); if (detect_mpart) { g_mpart_boundary = "fuzz" + std::to_string(fdp.ConsumeIntegral()); hdrs += "Content-Type: multipart/form-data; boundary=" + g_mpart_boundary + EOL(); } else { hdrs += std::string("Content-Type: ") + (fdp.ConsumeBool() ? "application/x-www-form-urlencoded" : "text/plain") + EOL(); } break; } // Randomly add some chunked headers const bool add_te_chunked = fdp.ConsumeBool(); if (add_te_chunked) { hdrs += "Transfer-Encoding: chunked" + EOL(); } if (fdp.ConsumeBool()) { const uint32_t cl = fdp.ConsumeIntegralInRange(0, 256); hdrs += "Content-Length: " + std::to_string(cl) + EOL(); } if (add_te_chunked && fdp.ConsumeBool()) { if (fdp.ConsumeBool()) hdrs += "Trailer: X-Fuzz-Trace" + EOL(); else hdrs += "Trailer: X-One, X-Two" + EOL(); } if (fdp.ConsumeBool()) { hdrs += (fdp.ConsumeBool() ? "Expect: 100-continue" : "Expect: something-weird") + EOL(); } // Connection ending line hdrs += "Connection: close" + EOL(); std::string end = EOL() + EOL(); // Write into the read buffer std::string full = req + hdrs + end; const size_t n = (full.size() <= capacity) ? full.size() : capacity; memcpy(buf, full.data(), n); c.read_buffer = buf; c.read_buffer_size = capacity; c.read_buffer_offset = n; } void init_parsing_configuration(FuzzedDataProvider& fdp, MHD_Connection& c) { MHD_HTTP_PostEncoding enc; // Configure connection encoding abd methods if (fdp.ConsumeBool()) { c.rq.app_act.head_act.act = mhd_ACTION_POST_PARSE; } else { c.rq.app_act.head_act.act = mhd_ACTION_NO_ACTION; } if (fdp.ConsumeBool()) { enc = MHD_HTTP_POST_ENCODING_TEXT_PLAIN; } else if (fdp.ConsumeBool()) { enc = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; } else if (fdp.ConsumeBool()) { enc = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA; } else { enc = MHD_HTTP_POST_ENCODING_OTHER; } c.rq.app_act.head_act.data.post_parse.buffer_size = fdp.ConsumeIntegralInRange(1, 4096); c.rq.app_act.head_act.data.post_parse.max_nonstream_size = fdp.ConsumeIntegralInRange(1, 4096); // Confiugre head action for connection post parsing process c.rq.app_act.head_act.data.post_parse.enc = enc; c.rq.app_act.head_act.data.post_parse.stream_reader = dummy_reader; c.rq.app_act.head_act.data.post_parse.reader_cls = nullptr; c.rq.app_act.head_act.data.post_parse.done_cb = dummy_done; c.rq.app_act.head_act.data.post_parse.done_cb_cls = nullptr; } void prepare_headers_and_parse(MHD_Connection& connection, size_t size) { // Manually add a parameter for parsing auto add_hdr = [&](const char* name_c, const std::string& val_s) { const size_t nlen = strlen(name_c); const size_t vlen = val_s.size(); char* nbuf = static_cast(mhd_stream_alloc_memory(&connection, nlen + 1)); char* vbuf = static_cast(mhd_stream_alloc_memory(&connection, vlen + 1)); if (!nbuf || !vbuf) { return; } memcpy(nbuf, name_c, nlen); nbuf[nlen] = '\0'; memcpy(vbuf, val_s.data(), vlen); vbuf[vlen] = '\0'; struct MHD_String name; name.len = nlen; name.cstr = nbuf; struct MHD_String value; value.len = vlen; value.cstr = vbuf; mhd_stream_add_field(&connection.h1_stream, MHD_VK_HEADER, &name, &value); }; add_hdr("Host", "fuzz"); if ((size & 3u) == 0u) { add_hdr("Transfer-Encoding", "chunked"); } if ((size & 7u) == 0u) { add_hdr("Content-Length", "0"); } bool force_mpart = (connection.rq.app_act.head_act.data.post_parse.enc == MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA); if (!force_mpart) { force_mpart = ((size & 0x3Fu) == 0u); } if (force_mpart) { if (g_mpart_boundary.empty()) { g_mpart_boundary = "fuzz" + std::to_string(size ^ 0x9e3779b97f4a7c15ULL); } std::string ct = "multipart/form-data; boundary=" + g_mpart_boundary; add_hdr("Content-Type", ct); } // If we wrote a real HTTP header for multipart, parse it so Content-Type is visible connection.stage = mhd_HTTP_STAGE_INIT; bool got_line = mhd_stream_get_request_line(&connection); if (destroy_error_response(connection)) { return; } if (got_line && connection.stage == mhd_HTTP_STAGE_REQ_LINE_RECEIVED) { mhd_stream_switch_to_rq_headers_proc(&connection); } mhd_stream_parse_request_headers(&connection); // Only proceed to post-parse if header parsing did not bail out destroy_error_response(connection); } void prepare_body_and_process(MHD_Connection& connection, std::string& body, size_t body_size, bool use_stream_body) { // Use streaming if boundary is not empty if (!g_mpart_boundary.empty()) { std::string wrapped; wrapped.reserve(body.size() + g_mpart_boundary.size() * 2 + 128); wrapped += "\r\n--"; wrapped += g_mpart_boundary; wrapped += "\r\n"; wrapped += "Content-Disposition: form-data; name=\"x\"; filename=\"f\"\r\n"; wrapped += "Content-Type: application/octet-stream\r\n\r\n"; wrapped += body; wrapped += "\r\n"; wrapped += "--"; wrapped += g_mpart_boundary; wrapped += "--\r\n"; body.swap(wrapped); body_size = body.size(); } if (!use_stream_body) { // Fuzz mhd_stream_prepare_for_post_parse once and mhd_stream_post_parse mhd_stream_prepare_for_post_parse(&connection); mhd_stream_post_parse(&connection, &body_size, &body[0]); mark_post_parse_ready(connection); } else { // Try prepare the body by streaming connection buffer const bool want_chunked = (connection.rq.have_chunked_upload == MHD_YES); std::string to_feed; if (want_chunked) { auto append_chunk = [&](const char* data, size_t len) { char hex[32]; const int n = snprintf(hex, sizeof(hex), "%zx", len); to_feed.append(hex, (size_t)n); if ((len & 3u) == 0u) { to_feed += ";ext=1"; } to_feed += "\r\n"; to_feed.append(data, len); to_feed += "\r\n"; }; if (body_size <= 32) { append_chunk(body.data(), body_size); } else { const size_t mid = body_size / 2; append_chunk(body.data(), mid); append_chunk(body.data() + mid, body_size - mid); } to_feed += "0\r\n"; if (body_size & 1) { to_feed += "X-Fuzz-Trace: 1\r\n\r\n"; } else { to_feed += "\r\n"; } } else { // Non-chunked body is handled as is to_feed.assign(body.data(), body_size); } // Stage into the connection read buffer (allocate if needed). size_t feed_sz = to_feed.size(); bool staged = false; if (connection.read_buffer && connection.read_buffer_size >= feed_sz) { memcpy(connection.read_buffer, to_feed.data(), feed_sz); connection.read_buffer_offset = feed_sz; staged = true; } else { size_t need = 0; char *nb = (char*) mhd_pool_try_alloc(connection.pool, feed_sz, &need); if (nb) { memcpy(nb, to_feed.data(), feed_sz); connection.read_buffer = nb; connection.read_buffer_size = feed_sz; connection.read_buffer_offset = feed_sz; staged = true; } } if (staged) { // Use stream body approach if success const size_t min_needed = body_size + 1; if (ensure_lbuf_capacity(connection, min_needed)) { // Only post parse the request if buffer is enough connection.stage = mhd_HTTP_STAGE_BODY_RECEIVING; connection.rq.have_chunked_upload = MHD_NO; connection.rq.cntn.cntn_size = (uint64_t) body_size; mhd_stream_prepare_for_post_parse(&connection); mhd_stream_process_request_body(&connection); mark_post_parse_ready(connection); } else { // Fall back if not enough buffer size_t tmp = body_size; mhd_stream_prepare_for_post_parse(&connection); mhd_stream_post_parse(&connection, &tmp, body.data()); mark_post_parse_ready(connection); } } else { // Use post prase approach if stream body failed mhd_stream_prepare_for_post_parse(&connection); mhd_stream_post_parse(&connection, &body_size, &body[0]); mark_post_parse_ready(connection); } } } void final_cleanup(MHD_Connection& connection, MHD_Daemon& daemon) { // Post process response mhd_stream_switch_from_recv_to_send(&connection); mhd_stream_process_req_recv_finished(&connection); mhd_stream_release_write_buffer(&connection); // Release buffers in daemon to avoid memory leakage if (connection.rq.cntn.lbuf.data != nullptr || connection.rq.cntn.lbuf.size != 0) { mhd_daemon_free_lbuf(&daemon, &connection.rq.cntn.lbuf); } // Clean post parse body status clear_post_parse_ready(connection); } ================================================ FILE: projects/libmicrohttpd2/connection_helper.h ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include "fuzzer/FuzzedDataProvider.h" #include "mhd_sys_options.h" #include "microhttpd2.h" #include "mhd_connection.h" #include "mhd_daemon.h" #include "mhd_post_parser.h" #include "request_funcs.h" extern struct mhd_MemoryPool *g_pool; extern const size_t g_pool_size; extern std::string g_mpart_boundary; void destroy_global_pool(); extern const struct MHD_UploadAction kContinueAction; extern const struct MHD_UploadAction kSuspend; extern const struct MHD_UploadAction kAbort; const struct MHD_UploadAction * dummy_reader(struct MHD_Request*, void*, const struct MHD_String*, const struct MHD_StringNullable*, const struct MHD_StringNullable*, const struct MHD_StringNullable*, size_t, const void*, uint_fast64_t, enum MHD_Bool); const struct MHD_UploadAction * dummy_done(struct MHD_Request*, void*, enum MHD_PostParseResult); void init_daemon_connection(FuzzedDataProvider& fdp, MHD_Daemon& d, MHD_Connection& c); void init_connection_buffer(FuzzedDataProvider& fdp, MHD_Connection& c); void init_parsing_configuration(FuzzedDataProvider& fdp, MHD_Connection& c); void prepare_headers_and_parse(MHD_Connection& connection, size_t size); void prepare_body_and_process(MHD_Connection& connection, std::string& body, size_t body_size, bool use_stream_body); void final_cleanup(MHD_Connection& connection, MHD_Daemon& daemon); void mark_post_parse_ready(MHD_Connection& connection); bool is_post_parse_ready(const MHD_Connection& connection); void clear_post_parse_ready(const MHD_Connection& connection); ================================================ FILE: projects/libmicrohttpd2/default.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/libmicrohttpd2/fuzz_connection.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "fuzzer/FuzzedDataProvider.h" #include "connection_helper.h" #include "conn_timeout.h" #include "daemon_funcs.h" #include "mempool_funcs.h" #include "post_parser_funcs.h" #include "stream_funcs.h" #include "stream_process_request.h" // Helper to fuzz mhd_stream_process_post_finish static void fuzz_mhd_stream_process_post_finish(MHD_Connection& connection, MHD_Daemon& daemon, const std::string& body) { struct mhd_PostParserData *p = &connection.rq.u_proc.post; size_t pos = p->next_parse_pos; size_t need = ((p->lbuf_used > pos) ? p->lbuf_used : pos) + 1; // +1 for NUL if (connection.rq.cntn.lbuf.size < need) { size_t delta = need - connection.rq.cntn.lbuf.size; if (delta != 0) mhd_daemon_extend_lbuf_up_to(&daemon, delta, &connection.rq.cntn.lbuf); } if (connection.rq.cntn.lbuf.data == nullptr && !body.empty()) { size_t to_copy = (body.size() < (size_t)p->lbuf_limit) ? body.size() : (size_t)p->lbuf_limit; size_t min_needed = to_copy + 1; // 1 byte for \0 terminator if (connection.rq.cntn.lbuf.size < min_needed) { size_t delta = min_needed - connection.rq.cntn.lbuf.size; if (delta != 0) mhd_daemon_extend_lbuf_up_to(&daemon, delta, &connection.rq.cntn.lbuf); } if (connection.rq.cntn.lbuf.data != nullptr) { memcpy(connection.rq.cntn.lbuf.data, body.data(), to_copy); p->lbuf_used = to_copy; } } // Fail back to Text encoding if (p->enc == MHD_HTTP_POST_ENCODING_OTHER) { p->enc = MHD_HTTP_POST_ENCODING_TEXT_PLAIN; } mhd_stream_prepare_for_post_parse(&connection); mhd_stream_process_post_finish(&connection); bool can_finish = (connection.rq.cntn.lbuf.data != nullptr); if (can_finish && connection.rq.u_proc.post.enc == MHD_HTTP_POST_ENCODING_FORM_URLENCODED) { size_t pos = connection.rq.u_proc.post.next_parse_pos; if (pos >= connection.rq.cntn.lbuf.size) { mhd_daemon_extend_lbuf_up_to(&daemon, 1, &connection.rq.cntn.lbuf); if (pos >= connection.rq.cntn.lbuf.size) can_finish = false; } } if (can_finish) { if (connection.rq.u_proc.post.enc == MHD_HTTP_POST_ENCODING_OTHER) { if (connection.rq.app_act.head_act.data.post_parse.enc == MHD_HTTP_POST_ENCODING_OTHER) connection.rq.app_act.head_act.data.post_parse.enc = MHD_HTTP_POST_ENCODING_TEXT_PLAIN; mhd_stream_prepare_for_post_parse(&connection); } mhd_stream_process_post_finish(&connection); } } // Initialising the memory pool extern "C" int LLVMFuzzerInitialize() { g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); atexit(destroy_global_pool); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0 || g_pool == nullptr) { return 0; } FuzzedDataProvider fdp(data, size); // Reseting the memory pool for each iteartion mhd_pool_destroy(g_pool); g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); // Initialising the daemon, connection and other MHD components MHD_Daemon daemon; MHD_Connection connection; init_daemon_connection(fdp, daemon, connection); init_parsing_configuration(fdp, connection); init_connection_buffer(fdp, connection); prepare_headers_and_parse(connection, size); // Randomly choose how many targets to fuzz std::vector selectors; for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 8); i++) { selectors.push_back(fdp.ConsumeIntegralInRange(0, 9)); } // Generate random body and stream it in the connection bool use_stream_body = fdp.ConsumeBool(); // Use remaining bytes to generate random body for fuzzing std::string body = fdp.ConsumeRemainingBytesAsString(); size_t body_size = body.size(); if (body_size == 0) { return 0; } prepare_body_and_process(connection, body, body_size, use_stream_body); // Fuzz random round of target functions for (int selector : selectors) { switch (selector) { case 0: { mhd_conn_is_timeout_expired(&connection); break; } case 1: { mhd_stream_switch_to_rq_headers_proc(&connection); break; } case 2: { const struct MHD_UploadAction* act = &kContinueAction; mhd_stream_process_upload_action(&connection, &kContinueAction, false); mhd_stream_process_upload_action(&connection, &kSuspend, false); mhd_stream_process_upload_action(&connection, &kAbort, true); break; } case 3: { connection.stage = mhd_HTTP_STAGE_REQ_RECV_FINISHED; mhd_stream_process_req_recv_finished(&connection); break; } case 4: { mhd_stream_reset_rq_hdr_proc_state(&connection); break; } case 5: { mhd_stream_alloc_memory(&connection, 1024); break; } case 6: { // Safe guard for out of buffer space if (connection.write_buffer_send_offset > connection.write_buffer_append_offset) { connection.write_buffer_send_offset = connection.write_buffer_append_offset; } mhd_stream_maximize_write_buffer(&connection); break; } case 7: { // Safe guard for out of buffer space connection.write_buffer_send_offset = connection.write_buffer_append_offset; mhd_stream_release_write_buffer(&connection); break; } case 8: { // Safe guard for out of buffer read if (connection.read_buffer_offset > connection.read_buffer_size) { connection.read_buffer_offset = connection.read_buffer_size; } mhd_stream_shrink_read_buffer(&connection); break; } case 9: { mhd_stream_switch_from_recv_to_send(&connection); break; } } } // Fuzz mhd_stream_process_post_finish fuzz_mhd_stream_process_post_finish(connection, daemon, body); // Final cleanup to avoid memory leak final_cleanup(connection, daemon); return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_crypto_ext.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "md5_ext.h" #include "sha256_ext.h" // Fuzzing target function pointer types for the enternal hash APIs template using InitOnceFn = void (*)(HashType*); template using UpdateFn = void (*)(HashType*, size_t, const uint8_t*); template using FinishFn = void (*)(HashType*, uint8_t*); template using DeinitFn = void (*)(HashType*); // Generic hashing flow that fuzz same hashing procedure for different algorithm template static void fuzz_hash_ext_multi(FuzzedDataProvider &fdp, size_t block_size, InitOnceFn init_once, UpdateFn update_fn, FinishFn finish_fn, DeinitFn deinit_fn, size_t digest_size) { if (!fdp.remaining_bytes()) { return; } // Pull a random slice of data for fuzzing size_t take_len = fdp.ConsumeIntegralInRange(0, fdp.remaining_bytes()); std::vector input_bytes = fdp.ConsumeBytes(take_len); // Create 1 to 4 independent hashing contexts with it own digest buffer const unsigned num_contexts = fdp.ConsumeIntegralInRange(1, 4); std::vector contexts(num_contexts); std::vector> digests(num_contexts, std::vector(digest_size)); for (unsigned i = 0; i < num_contexts; i++) { init_once(&contexts[i]); } // Intentionally misalign the data pointer to stress alignment sensitive paths const size_t misalign_pad = fdp.ConsumeIntegralInRange(0, 64); std::vector scratch_buf(misalign_pad + input_bytes.size()); if (!input_bytes.empty()) { memcpy(scratch_buf.data() + misalign_pad, input_bytes.data(), input_bytes.size()); } // Define cursor and remaining bytes counter to keep track of the multiple hash update iterations const uint8_t *cursor = scratch_buf.data() + misalign_pad; size_t remaining = input_bytes.size(); // Perform multiple hash update iterations on the raw data unsigned num_iterations = fdp.ConsumeIntegralInRange(1, 4); while (num_iterations-- && remaining > 0) { // Pick which context to feed this iteration const unsigned ctx_index = (num_contexts == 1) ? 0 : fdp.ConsumeIntegralInRange(0, num_contexts - 1); // Choose a chunking pattern relative to block size. enum Pattern { LESS1, EQ, PLUS1, SMALL, RANDOM, TAIL, HALT }; Pattern pattern = fdp.PickValueInArray({LESS1, EQ, PLUS1, SMALL, RANDOM, TAIL, HALT}); size_t chunk_len = 0; switch (pattern) { case LESS1: { // Consume 1 byte less from block size from the raw data for this iteration if (block_size > 1) { chunk_len = std::min(remaining, block_size - 1); } break; } case EQ: { // Consume block size bytes from the raw data for this iteration chunk_len = std::min(remaining, block_size); break; } case PLUS1: { // Consume 1 byte more from block size from the raw data for this iteration chunk_len = std::min(remaining, block_size + 1); break; } case SMALL: { // Consume 1~32 bytes from the raw data for this iteration size_t small_len = (size_t)fdp.ConsumeIntegralInRange(1, 32); chunk_len = std::min(remaining, small_len); break; } case RANDOM: { // Consume random bytes from the raw data for this iteration chunk_len = (remaining >= 1) ? (size_t)fdp.ConsumeIntegralInRange(1, remaining) : 0; break; } case TAIL: { // Consume all remaining bytes from the raw data for this iteration chunk_len = remaining; break; } case HALT: { // Consume small chunk and consider reinitialisation or early halt of the hash iteration size_t step = std::max(1, fdp.ConsumeIntegralInRange(1, block_size)); size_t loops = fdp.ConsumeIntegralInRange(1, 4); for (size_t j = 0; j < loops && remaining > 0; j++) { size_t w = std::min(remaining, step); update_fn(&contexts[ctx_index], w, cursor); cursor += w; remaining -= w; } // Randomly reinitialise the hash stream if (fdp.ConsumeBool()) { finish_fn(&contexts[ctx_index], digests[ctx_index].data()); } continue; } } if (chunk_len == 0 || chunk_len > remaining) { continue; } // Fuzz the update function update_fn(&contexts[ctx_index], chunk_len, cursor); cursor += chunk_len; remaining -= chunk_len; } // Finalize all active contexts (finish_reset). for (unsigned i = 0; i < num_contexts; i++) { finish_fn(&contexts[i], digests[i].data()); } // Additional fuzzing on special context chaining approach. if (num_contexts >= 2 && digest_size && fdp.ConsumeBool()) { unsigned src_idx = fdp.ConsumeIntegralInRange(0, num_contexts - 1); unsigned dst_idx = fdp.ConsumeIntegralInRange(0, num_contexts - 1); if (src_idx != dst_idx) { size_t offset = fdp.ConsumeIntegralInRange(0, digest_size - 1); size_t max_avail = digest_size - offset; // >= 1 size_t feed_len = fdp.ConsumeIntegralInRange(1, max_avail); update_fn(&contexts[dst_idx], feed_len, digests[src_idx].data() + offset); finish_fn(&contexts[dst_idx], digests[dst_idx].data()); } } // Deinitialise all contexts after this iteration for (unsigned i = 0; i < num_contexts; i++) { deinit_fn(&contexts[i]); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); for (unsigned i = 0; i < fdp.ConsumeIntegralInRange(1, 4); i++) { if (fdp.ConsumeBool()) { fuzz_hash_ext_multi( fdp, 64, mhd_MD5_init_one_time, mhd_MD5_update, mhd_MD5_finish_reset, mhd_MD5_deinit, mhd_MD5_DIGEST_SIZE); } else { fuzz_hash_ext_multi( fdp, 64, mhd_SHA256_init_one_time, mhd_SHA256_update, mhd_SHA256_finish_reset, mhd_SHA256_deinit, mhd_SHA256_DIGEST_SIZE); } } return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_crypto_int.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "md5_int.h" #include "sha256_int.h" #include "sha512_256_int.h" // Fuzzing target function pointer types for the internal hash APIs template using InitFn = void (*)(HashType*); template using UpdateFn = void (*)(HashType*, size_t, const uint8_t*); template using FinishFn = void (*)(HashType*, uint8_t*); // Generic hashing flow that fuzz same hashing procedure for different algorithm template static void fuzz_hash_int_multi(FuzzedDataProvider &fdp, size_t block_size, InitFn init_fn, UpdateFn update_fn, FinishFn finish_fn, size_t digest_size) { if (!fdp.remaining_bytes()) { return; } // Pull a random slice of data for fuzzing size_t take_len = fdp.ConsumeIntegralInRange(0, fdp.remaining_bytes()); std::vector input_bytes = fdp.ConsumeBytes(take_len); // Create 1 to 4 independent hashing contexts with it own digest buffer const unsigned num_contexts = fdp.ConsumeIntegralInRange(1, 4); std::vector contexts(num_contexts); std::vector> digests(num_contexts, std::vector(digest_size)); for (unsigned i = 0; i < num_contexts; i++) { init_fn(&contexts[i]); } // Intentionally misalign the data pointer to stress alignment sensitive paths const size_t misalign_pad = fdp.ConsumeIntegralInRange(0, 64); std::vector scratch_buf(misalign_pad + input_bytes.size()); if (!input_bytes.empty()) { memcpy(scratch_buf.data() + misalign_pad, input_bytes.data(), input_bytes.size()); } // Define cursor and remaining bytes counter to keep track of the multiple hash update iterations const uint8_t *cursor = scratch_buf.data() + misalign_pad; size_t remaining = input_bytes.size(); // Perform multiple hash update iterations on the raw data unsigned num_iterations = fdp.ConsumeIntegralInRange(1, 4); while (num_iterations-- && remaining > 0) { // Pick which context to feed this iteration const unsigned ctx_index = (num_contexts == 1) ? 0 : fdp.ConsumeIntegralInRange(0, num_contexts - 1); // Choose a chunking pattern for this iteration enum Pattern { LESS1, EQ, PLUS1, SMALL, RANDOM, TAIL, HALT }; Pattern pattern = fdp.PickValueInArray({LESS1, EQ, PLUS1, SMALL, RANDOM, TAIL, HALT}); size_t chunk_len = 0; switch (pattern) { case LESS1: { // Consume 1 byte less from block size from the raw data for this iteration if (block_size > 1) { chunk_len = std::min(remaining, block_size - 1); } break; } case EQ: { // Consume block size bytes from the raw data for this iteration chunk_len = std::min(remaining, block_size); break; } case PLUS1: { // Consume 1 byte more from block size from the raw data for this iteration chunk_len = std::min(remaining, block_size + 1); break; } case SMALL: { // Consume 1 to 32 bytes from the raw data for this iteration size_t small_len = (size_t)fdp.ConsumeIntegralInRange(1, 32); chunk_len = std::min(remaining, small_len); break; } case RANDOM: { // Consume random bytes from the raw data for this iteration chunk_len = (remaining >= 1) ? (size_t)fdp.ConsumeIntegralInRange(1, remaining) : 0; break; } case TAIL: { // Consume all remaining bytes from the raw data for this iteration chunk_len = remaining; break; } case HALT: { // Consume small chunk and consider reinitialisation or early halt of the hash iteration size_t step = std::max(1, fdp.ConsumeIntegralInRange(1, block_size)); size_t loops = fdp.ConsumeIntegralInRange(1, 4); for (size_t j = 0; j < loops && remaining > 0; j++) { size_t w = std::min(remaining, step); update_fn(&contexts[ctx_index], w, cursor); cursor += w; remaining -= w; } // Randomly reinitialise the hash stream if (fdp.ConsumeBool()) { finish_fn(&contexts[ctx_index], digests[ctx_index].data()); init_fn(&contexts[ctx_index]); } continue; } } if (chunk_len == 0 || chunk_len > remaining) { continue; } // Occasionally reinitialise a context between update iterations if (fdp.ConsumeBool()) { init_fn(&contexts[ctx_index]); } // Fuzz the update function update_fn(&contexts[ctx_index], chunk_len, cursor); cursor += chunk_len; remaining -= chunk_len; // Randomly halt and reinitialise the stream if (fdp.ConsumeBool()) { finish_fn(&contexts[ctx_index], digests[ctx_index].data()); init_fn(&contexts[ctx_index]); } } // Fuzz the finish function for all contexts for (unsigned i = 0; i < num_contexts; i++) { finish_fn(&contexts[i], digests[i].data()); } // Additional fuzzing on special context chaining approach if (num_contexts >= 2 && digest_size && fdp.ConsumeBool()) { unsigned src_idx = fdp.ConsumeIntegralInRange(0, num_contexts - 1); unsigned dst_idx = fdp.ConsumeIntegralInRange(0, num_contexts - 1); if (src_idx != dst_idx) { init_fn(&contexts[dst_idx]); size_t offset = fdp.ConsumeIntegralInRange(0, digest_size - 1); size_t feed_len = std::min(digest_size - offset, (size_t)fdp.ConsumeIntegralInRange(1, digest_size)); update_fn(&contexts[dst_idx], feed_len, digests[src_idx].data() + offset); finish_fn(&contexts[dst_idx], digests[dst_idx].data()); } } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 4); i++) { switch (fdp.ConsumeIntegralInRange(0, 2)) { case 0: fuzz_hash_int_multi( fdp, mhd_MD5_BLOCK_SIZE, mhd_MD5_init, mhd_MD5_update, mhd_MD5_finish, mhd_MD5_DIGEST_SIZE); break; case 1: fuzz_hash_int_multi( fdp, mhd_SHA256_BLOCK_SIZE, mhd_SHA256_init, mhd_SHA256_update, mhd_SHA256_finish, mhd_SHA256_DIGEST_SIZE); break; case 2: default: fuzz_hash_int_multi( fdp, mhd_SHA512_256_BLOCK_SIZE, mhd_SHA512_256_init, mhd_SHA512_256_update, mhd_SHA512_256_finish, mhd_SHA512_256_DIGEST_SIZE); break; } } return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_daemon.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "mhd_helper.h" static constexpr uint16_t kPort = 54321; static uint16_t g_listen_port = kPort; static struct MHD_Daemon* g_daemon = nullptr; static std::once_flag g_start_once; static void start_daemon_once() { if (g_daemon) { return; } // Add deterministic entropy unsigned char entropy[32]; for (size_t i = 0; i < sizeof(entropy); ++i) { entropy[i] = (unsigned char)(0xA5 ^ (i * 17)); } // Try start the daemon and map to a designated port // Retry to next port if mapping to port fails bool started = false; for (int i = 0; i < 8 && !started; ++i) { const uint16_t try_port = static_cast(kPort + i); if (g_fdp->ConsumeBool()) { g_daemon = MHD_daemon_create(&req_cb, NULL); } else if (g_fdp->ConsumeBool()) { g_daemon = MHD_daemon_create(&req_cb_stream, NULL); } else { g_daemon = MHD_daemon_create(&req_cb_process, NULL); } if (!g_daemon) { continue; } // Configure daemon starting options auto sc = MHD_DAEMON_SET_OPTIONS( g_daemon, MHD_D_OPTION_BIND_PORT(MHD_AF_INET4, try_port), MHD_D_OPTION_RANDOM_ENTROPY(sizeof(entropy), entropy) ); // Safeguard if daemon starting or mapping to port fails and try on next port if (sc != MHD_SC_OK) { MHD_daemon_destroy(g_daemon); g_daemon = nullptr; continue; } if (MHD_daemon_start(g_daemon) != MHD_SC_OK) { MHD_daemon_destroy(g_daemon); g_daemon = nullptr; continue; } // Store the final port used g_listen_port = try_port; started = true; } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { size_t reqs = 0; // Put FuzzedDataProvider to global { std::lock_guard lk(g_fdp_mu); g_fdp = std::make_unique(data, size); } // Start daemon std::call_once(g_start_once, start_daemon_once); if (!g_daemon) { return 0; } // Generate random number to determine number of random request to be sent { std::lock_guard lk(g_fdp_mu); if (g_fdp) { reqs = 1 + g_fdp->ConsumeIntegralInRange(0, 7); } } // Send multiple random requests to daemon for (size_t i = 0; i < reqs; ++i) { std::string method = "GET", path, user, pass, body; bool garble_auth = false; // Prepare HTTP request in locked session with random data { std::lock_guard lk(g_fdp_mu); if (g_fdp) { static const char* kCommon[] = {"GET","POST","PUT","DELETE","HEAD","PATCH","OPTIONS"}; if (g_fdp->ConsumeBool()) { method = g_fdp->PickValueInArray(kCommon); } else { method = g_fdp->ConsumeRandomLengthString(8); if (method.empty()) { method = "GET"; } } path = g_fdp->ConsumeRandomLengthString( g_fdp->ConsumeIntegralInRange(0, 64)); for (char &c : path) { if (c == ' ') { c = '_'; } } user = g_fdp->ConsumeRandomLengthString(16); pass = g_fdp->ConsumeRandomLengthString(16); garble_auth = g_fdp->ConsumeBool(); if (method == "POST" || g_fdp->ConsumeBool()) { body = g_fdp->ConsumeRandomLengthString(2048); } } } // Send request send_http_request_blocking(g_listen_port, method, path, user, pass, body, garble_auth); // Early exit if failed to load more random data { std::lock_guard lk(g_fdp_mu); if (!g_fdp || g_fdp->remaining_bytes() < 8) { break; } } } // Free FDP { std::lock_guard lk(g_fdp_mu); g_fdp.reset(); } return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_daemon.dict ================================================ "GET" "POST" "HEAD" "Authorization:" "Basic" "Host:" "Content-Length:" "Connection:" "HTTP/1.1" "/" method_delete="DELETE" method_get="GET" method_head="HEAD" method_post="POST" method_put="PUT" method_connect="CONNECT" method_options="OPTIONS" method_trace="TRACE" method_copy="COPY" method_lock="LOCK" method_mkcol="MKCOL" method_move="MOVE" method_propfind="PROPFIND" method_proppatch="PROPPATCH" method_search="SEARCH" method_unlock="UNLOCK" method_bind="BIND" method_rebind="REBIND" method_unbind="UNBIND" method_acl="ACL" method_report="REPORT" method_mkactivity="MKACTIVITY" method_checkout="CHECKOUT" method_merge="MERGE" method_m_search="M-SEARCH" method_notify="NOTIFY" method_subscribe="SUBSCRIBE" method_unsubscribe="UNSUBSCRIBE" method_patch="PATCH" method_purge="PURGE" method_mkcalendar="MKCALENDAR" method_link="LINK" method_unlink="UNLINK" header_req_standard_accept="Accept" header_req_standard_accept_charset="Accept-Charset" header_req_standard_accept_encoding="Accept-Encoding" header_req_standard_accept_language="Accept-Language" header_req_standard_accept_datetime="Accept-Datetime" header_req_standard_authorization="Authorization" header_req_standard_cache_control="Cache-Control" header_req_standard_connection="Connection" header_req_standard_cookie="Cookie" header_req_standard_content_length="Content-Length" header_req_standard_content_md5="Content-MD5" header_req_standard_content_type="Content-Type" header_req_standard_date="Date" header_req_standard_expect="Expect" header_req_standard_forwarded="Forwarded" header_req_standard_from="From" header_req_standard_host="Host" header_req_standard_if_match="If-Match" header_req_standard_if_modified_since="If-Modified-Since" header_req_standard_if_none_match="If-None-Match" header_req_standard_if_range="If-Range" header_req_standard_if_unmodified_since="If-Unmodified-Since" header_req_standard_max_forwards="Max-Forwards" header_req_standard_origin="Origin" header_req_standard_pragma="Pragma" header_req_standard_proxy_authorization="Proxy-Authorization" header_req_standard_range="Range" header_req_standard_referer="Referer" header_req_standard_te="TE" header_req_standard_user_agent="User-Agent" header_req_standard_upgrade="Upgrade" header_req_standard_via="Via" header_req_standard_warning="Warning" header_req_nonstandard_x_requested_with="X-Requested-With" header_req_nonstandard_dnt="DNT" header_req_nonstandard_x_forwarded_for="X-Forwarded-For" header_req_nonstandard_x_forwarded_host="X-Forwarded-Host" header_req_nonstandard_x_forwarded_proto="X-Forwarded-Proto" header_req_nonstandard_front_end_https="Front-End-Https" header_req_nonstandard_x_http_method_override ="X-Http-Method-Override" header_req_nonstandard_x_att_deviceid="X-ATT-DeviceId" header_req_nonstandard_x_wap_profile="X-Wap-Profile" header_req_nonstandard_proxy_connection="Proxy-Connection" header_req_nonstandard_x_uidh="X-UIDH" header_req_nonstandard_x_csrf_token="X-Csrf-Token" header_req_nonstandard_x_request_id="X-Request-ID" header_req_nonstandard_x_correlation_id="X-Correlation-ID" header_res_standard_access_control_allow_origin="Access-Control-Allow-Origin" header_res_standard_accept_patch="Accept-Patch" header_res_standard_accept_ranges="Accept-Ranges" header_res_standard_age="Age" header_res_standard_allow="Allow" header_res_standard_alt_svc="Alt-Svc" header_res_standard_cache_control="Cache-Control" header_res_standard_connection="Connection" header_res_standard_content_disposition="Content-Disposition" header_res_standard_content_encoding="Content-Encoding" header_res_standard_content_language="Content-Language" header_res_standard_content_length="Content-Length" header_res_standard_content_location="Content-Location" header_res_standard_content_md5="Content-MD5" header_res_standard_content_range="Content-Range" header_res_standard_content_type="Content-Type" header_res_standard_date="Date" header_res_standard_etag="ETag" header_res_standard_expires="Expires" header_res_standard_last_modified="Last-Modified" header_res_standard_link="Link" header_res_standard_location="Location" header_res_standard_p3p="P3P" header_res_standard_pragma="Pragma" header_res_standard_proxy_authenticate="Proxy-Authenticate" header_res_standard_public_key_pins="Public-Key-Pins" header_res_standard_refresh="Refresh" header_res_standard_retry_after="Retry-After" header_res_standard_server="Server" header_res_standard_set_cookie="Set-Cookie" header_res_standard_strict_transport_security="Strict-Transport-Security" header_res_standard_trailer="Trailer" header_res_standard_transfer_encoding="Transfer-Encoding" header_res_standard_tk="Tk" header_res_standard_upgrade="Upgrade" header_res_standard_vary="Vary" header_res_standard_via="Via" header_res_standard_warning="Warning" header_res_standard_www_authenticate="WWW-Authenticate" header_res_standard_x_frame_options="X-Frame-Options" header_res_nonstandard_status="Status" header_res_nonstandard_x_xss_protection="X-XSS-Protection" header_res_nonstandard_content_security_policy="Content-Security-Policy" header_res_nonstandard_x_content_security_policy="X-Content-Security-Policy" header_res_nonstandard_x_webkit_csp="X-WebKit-CSP" header_res_nonstandard_x_content_type_options="X-Content-Type-Options" header_res_nonstandard_x_powered_by="X-Powered-By" header_res_nonstandard_x_ua_compatible="X-UA-Compatible" header_res_nonstandard_x_content_duration="X-Content-Duration" header_res_nonstandard_upgrade_insecure_requests="Upgrade-Insecure-Requests" header_res_nonstandard_x_request_id="X-Request-ID" header_res_nonstandard_x_correlation_id="X-Correlation-ID" content_encoding_compress="compress" content_encoding_deflate="deflate" content_encoding_exi="exi" content_encoding_gzip="gzip" content_encoding_pack200_gzip="pack200-gzip" content_encoding_br="br" ================================================ FILE: projects/libmicrohttpd2/fuzz_daemon_connection.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "fuzzer/FuzzedDataProvider.h" #include "connection_helper.h" #include "conn_tls_check.h" #include "mempool_funcs.h" #include "mhd_send.h" #include "stream_process_request.h" #include "stream_process_states.h" // Initialising the memory pool extern "C" int LLVMFuzzerInitialize() { g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); atexit(destroy_global_pool); return 0; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0 || g_pool == nullptr) { return 0; } FuzzedDataProvider fdp(data, size); // Reseting the memory pool for each iteartion mhd_pool_destroy(g_pool); g_pool = mhd_pool_create(g_pool_size, MHD_MEMPOOL_ZEROING_ON_RESET); // Initialising the daemon, connection and other MHD components MHD_Daemon daemon; MHD_Connection connection; init_daemon_connection(fdp, daemon, connection); init_parsing_configuration(fdp, connection); init_connection_buffer(fdp, connection); prepare_headers_and_parse(connection, size); // Randomly choose how many targets to fuzz std::vector selectors; for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 8); i++) { selectors.push_back(fdp.ConsumeIntegralInRange(0, 5)); } // Generate random flags bool use_stream_body = fdp.ConsumeBool(); bool is_nodelay = fdp.ConsumeBool(); bool is_cork = fdp.ConsumeBool(); // Use remaining bytes to generate random body for fuzzing std::string body = fdp.ConsumeRemainingBytesAsString(); size_t body_size = body.size(); if (body_size == 0) { return 0; } prepare_body_and_process(connection, body, body_size, use_stream_body); for (int selector : selectors) { switch (selector) { case 0: { mhd_conn_event_loop_state_update(&connection); break; } case 1: { if (connection.rq.app_act.head_act.act == mhd_ACTION_NO_ACTION && connection.daemon && connection.daemon->req_cfg.cb) { mhd_stream_call_app_request_cb(&connection); } break; } case 2: { if (connection.rq.app_act.head_act.act == mhd_ACTION_POST_PARSE && connection.rq.app_act.head_act.data.post_parse.done_cb != nullptr && is_post_parse_ready(connection)) { mhd_stream_process_req_recv_finished(&connection); } break; } default: case 3: { mhd_conn_tls_check(&connection); break; } } } final_cleanup(connection, daemon); return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_libinfo.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "microhttpd2.h" #include "fuzzer/FuzzedDataProvider.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { FuzzedDataProvider fdp(data, size); // Generate random ids int fixed_id = fdp.ConsumeIntegral(); int dynamic_id = fdp.ConsumeIntegral(); // Generate random raw data std::vector raw_data = fdp.ConsumeRemainingBytes(); // Fuzz MHD_lib_get_info_fixed_sz MHD_lib_get_info_fixed_sz( static_cast(fixed_id), raw_data.size() > 0 ? reinterpret_cast(raw_data.data()) : nullptr, raw_data.size()); // Fuzz MHD_lib_get_info_dynamic_sz MHD_lib_get_info_dynamic_sz( static_cast(dynamic_id), raw_data.size() > 0 ? reinterpret_cast(raw_data.data()) : nullptr, raw_data.size()); return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_mhd2.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include "microhttpd2.h" #include "fuzzer/FuzzedDataProvider.h" static inline enum MHD_Bool ToMhdBool(bool b) { return b ? MHD_YES : MHD_NO; } static void dummy_log(void*, enum MHD_StatusCode, const char*, va_list) { // Do nothing } static MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb(void* cls, struct MHD_Request* request, const struct MHD_String* path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { const std::string* body = static_cast(cls); struct MHD_Response* r = MHD_response_from_buffer( MHD_HTTP_STATUS_OK, body->size(), body->c_str(), nullptr, nullptr); if (!r) { return nullptr; } return MHD_action_from_response(request, r); } void fuzz_digest_auth_calc(FuzzedDataProvider& fdp) { std::string realm = fdp.ConsumeRandomLengthString(40); std::string user = fdp.ConsumeRandomLengthString(24); std::string pass = fdp.ConsumeRandomLengthString(24); enum MHD_DigestAuthAlgo alg = fdp.PickValueInArray({ MHD_DIGEST_AUTH_ALGO_MD5, MHD_DIGEST_AUTH_ALGO_SHA256, MHD_DIGEST_AUTH_ALGO_SHA512_256 }); size_t hsz = MHD_digest_get_hash_size(alg); if (hsz > 0 && hsz <= 128) { std::vector bin(hsz); std::vector ud(hsz); std::vector hex(hsz * 2 + 1); (void) MHD_digest_auth_calc_userhash(alg, user.c_str(), realm.c_str(), bin.size(), bin.data()); (void) MHD_digest_auth_calc_userhash_hex(alg, user.c_str(), realm.c_str(), hex.size(), hex.data()); (void) MHD_digest_auth_calc_userdigest(alg, user.c_str(), realm.c_str(), pass.c_str(), ud.size(), ud.data()); } } struct MHD_Response* fuzz_response_creation(FuzzedDataProvider& fdp) { // Create random body string for response const size_t body_len = fdp.ConsumeIntegralInRange(0, std::min(fdp.remaining_bytes(), 2048)); std::string body = fdp.ConsumeBytesAsString(body_len); struct MHD_Response* r = nullptr; enum MHD_HTTP_StatusCode sc = fdp.PickValueInArray({ MHD_HTTP_STATUS_OK, MHD_HTTP_STATUS_CREATED, MHD_HTTP_STATUS_NO_CONTENT, MHD_HTTP_STATUS_PARTIAL_CONTENT, MHD_HTTP_STATUS_BAD_REQUEST, MHD_HTTP_STATUS_UNAUTHORIZED, MHD_HTTP_STATUS_FORBIDDEN, MHD_HTTP_STATUS_NOT_FOUND, MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR }); if (fdp.ConsumeBool()) { r = MHD_response_from_buffer(sc, body.size(), body.data(), nullptr, nullptr); } else if (fdp.ConsumeBool()) { r = MHD_response_from_buffer_static(sc, body.size(), body.c_str()); } else { r = MHD_response_from_empty(sc); } return r; } void fuzz_response_config(FuzzedDataProvider& fdp, struct MHD_Response* r) { std::string header1 = fdp.ConsumeRandomLengthString(24); if (header1.empty()) header1 = "H1"; std::string header2 = fdp.ConsumeRandomLengthString(24); if (header2.empty()) header2 = "H2"; std::string header3 = fdp.ConsumeRandomLengthString(24); if (header3.empty()) header3 = "H3"; std::string val1 = fdp.ConsumeRandomLengthString(64); if (val1.empty()) val1 = "V1"; std::string val2 = fdp.ConsumeRandomLengthString(64); if (val2.empty()) val2 = "V2"; std::string val3 = fdp.ConsumeRandomLengthString(64); if (val3.empty()) val3 = "V3"; // Set random headers MHD_response_add_header(r, "Content-Type", fdp.ConsumeBool() ? "text/plain" : "application/octet-stream"); MHD_response_add_header(r, header1.c_str(), val1.c_str()); MHD_response_add_header(r, header2.c_str(), val2.c_str()); MHD_response_add_header(r, header3.c_str(), val3.c_str()); // Set predefined headers MHD_response_add_predef_header( r, fdp.PickValueInArray({MHD_PREDEF_ACCEPT_CHARSET, MHD_PREDEF_ACCEPT_LANGUAGE}), fdp.ConsumeRandomLengthString(32).c_str() ); // Set boolean configurations { auto opt = MHD_R_OPTION_REUSABLE( ToMhdBool(fdp.ConsumeBool())); (void) MHD_response_set_option(r, &opt); } { auto opt = MHD_R_OPTION_HEAD_ONLY_RESPONSE( ToMhdBool(fdp.ConsumeBool())); (void) MHD_response_set_option(r, &opt); } { auto opt = MHD_R_OPTION_CHUNKED_ENC( ToMhdBool(fdp.ConsumeBool())); (void) MHD_response_set_option(r, &opt); } { auto opt = MHD_R_OPTION_CONN_CLOSE( ToMhdBool(fdp.ConsumeBool())); (void) MHD_response_set_option(r, &opt); } // Create random data for response generation char tmpl[] = "/tmp/mhd2_fuzz_XXXXXX"; int fd = mkstemp(tmpl); if (fd >= 0) { std::string bytes = fdp.ConsumeRandomLengthString(512); if (!bytes.empty()) { write(fd, bytes.data(), bytes.size()); } off_t sz = lseek(fd, 0, SEEK_END); if (sz > 0) { uint_fast64_t off = fdp.ConsumeIntegralInRange(0, (uint_fast64_t)sz); uint_fast64_t len = fdp.ConsumeIntegralInRange(0, (uint_fast64_t)(sz - off)); struct MHD_Response* rf = MHD_response_from_fd( fdp.PickValueInArray({ MHD_HTTP_STATUS_OK, MHD_HTTP_STATUS_PARTIAL_CONTENT, MHD_HTTP_STATUS_NO_CONTENT }), fd, off, len); if (rf) MHD_response_destroy(rf); else close(fd); } else { close(fd); } unlink(tmpl); } // Pipe random response int pfd[2]; if (0 == pipe(pfd)) { std::string pbytes = fdp.ConsumeRandomLengthString(256); if (!pbytes.empty()) (void)!write(pfd[1], pbytes.data(), pbytes.size()); close(pfd[1]); struct MHD_Response* rp = MHD_response_from_pipe( fdp.PickValueInArray({ MHD_HTTP_STATUS_OK, MHD_HTTP_STATUS_NO_CONTENT }), pfd[0]); if (rp) { MHD_response_destroy(rp); } else { close(pfd[0]); } } } void daemon_configuration(FuzzedDataProvider& fdp, MHD_Daemon* d) { using PollEnum = decltype(MHD_SPS_AUTO); static constexpr PollEnum kPollChoices[] = { MHD_SPS_AUTO, MHD_SPS_SELECT, MHD_SPS_POLL, MHD_SPS_EPOLL, }; PollEnum ps = fdp.PickValueInArray(kPollChoices); auto opt1 = MHD_D_OPTION_POLL_SYSCALL(ps); MHD_daemon_set_option(d, &opt1); using AddrEnum = decltype(MHD_AF_NONE); static constexpr AddrEnum kAddrChoices[] = { MHD_AF_NONE, MHD_AF_AUTO, MHD_AF_INET4, MHD_AF_INET6, }; uint_least16_t port = fdp.ConsumeIntegralInRange(0, 65535); AddrEnum af = fdp.PickValueInArray(kAddrChoices); auto opt2 = MHD_D_OPTION_BIND_PORT(af, port); (void) MHD_daemon_set_option(d, &opt2); auto opt3 = MHD_D_OPTION_DEFAULT_TIMEOUT_MILSEC(fdp.ConsumeIntegralInRange(0, 10000)); MHD_daemon_set_option(d, &opt3); auto opt4 = MHD_D_OPTION_CONN_MEMORY_LIMIT(fdp.ConsumeIntegralInRange(0, 1<<16)); MHD_daemon_set_option(d, &opt4); auto opt5 = MHD_D_OPTION_LOG_CALLBACK(&dummy_log, nullptr); MHD_daemon_set_option(d, &opt5); std::vector ent = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, 32)); auto opt6 = MHD_D_OPTION_RANDOM_ENTROPY(ent.size(), const_cast(static_cast(ent.data())) ); MHD_daemon_set_option(d, &opt6); auto opt7 = MHD_D_OPTION_REREGISTER_ALL(ToMhdBool(fdp.ConsumeBool())); MHD_daemon_set_option(d, &opt7); } void fuzz_daemon_lifecycle(FuzzedDataProvider& fdp) { // Create random body string for response const size_t body_len = fdp.ConsumeIntegralInRange(0, std::min(fdp.remaining_bytes(), 2048)); std::string body = fdp.ConsumeBytesAsString(body_len); struct MHD_Daemon* d = MHD_daemon_create(&req_cb, &body); if (!d) { return; } // Fuzz with random fixed queries union MHD_DaemonInfoFixedData dfix{}; const int n = fdp.ConsumeIntegralInRange(1, 6); using FixedEnum = decltype(MHD_DAEMON_INFO_FIXED_POLL_SYSCALL); static constexpr FixedEnum kFixedChoices[] = { MHD_DAEMON_INFO_FIXED_POLL_SYSCALL, MHD_DAEMON_INFO_FIXED_AGGREAGATE_FD, MHD_DAEMON_INFO_FIXED_NUM_WORK_THREADS, MHD_DAEMON_INFO_FIXED_BIND_PORT, MHD_DAEMON_INFO_FIXED_LISTEN_SOCKET, MHD_DAEMON_INFO_FIXED_TLS_BACKEND, MHD_DAEMON_INFO_FIXED_DEFAULT_TIMEOUT_MILSEC, MHD_DAEMON_INFO_FIXED_GLOBAL_CONNECTION_LIMIT, MHD_DAEMON_INFO_FIXED_PER_IP_LIMIT, MHD_DAEMON_INFO_FIXED_SUPPRESS_DATE_HEADER, MHD_DAEMON_INFO_FIXED_CONN_MEMORY_LIMIT, MHD_DAEMON_INFO_FIXED_FD_NUMBER_LIMIT, }; for (int i = 0; i < n; ++i) { daemon_configuration(fdp, d); FixedEnum which = fdp.PickValueInArray(kFixedChoices); MHD_daemon_get_info_fixed(d, which, &dfix); } // Fuzz with random dynamic queries union MHD_DaemonInfoDynamicData ddyn{}; const int m = fdp.ConsumeIntegralInRange(1, 6); using DynEnum = decltype(MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT); static constexpr DynEnum kDynChoices[] = { MHD_DAEMON_INFO_DYNAMIC_MAX_TIME_TO_WAIT, MHD_DAEMON_INFO_DYNAMIC_HAS_CONNECTIONS, }; for (int i = 0; i < m; ++i) { daemon_configuration(fdp, d); DynEnum which = fdp.PickValueInArray(kDynChoices); MHD_daemon_get_info_dynamic(d, which, &ddyn); } MHD_daemon_destroy(d); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size <= 0) { return 0; } FuzzedDataProvider fdp(data, size); // Fuzz digest_auth_calc targets fuzz_digest_auth_calc(fdp); // Create responses with random choices struct MHD_Response* r = fuzz_response_creation(fdp); // Fuzz response configurations if (r) { fuzz_response_config(fdp, r); MHD_response_destroy(r); } // Fuzz daemon lifecycle fuzz_daemon_lifecycle(fdp); return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_response.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include "mhd_helper.h" static void request_ended_cb(void *cls, const struct MHD_RequestEndedData *data, void *request_app_context) { // Do nothing } static enum MHD_HTTP_StatusCode pick_status_code(FuzzedDataProvider &fdp) { // Randomly pick a valid or invalid HTTP response status code return fdp.ConsumeBool() ? fdp.PickValueInArray({ MHD_HTTP_STATUS_OK, MHD_HTTP_STATUS_CREATED, MHD_HTTP_STATUS_NO_CONTENT, MHD_HTTP_STATUS_PARTIAL_CONTENT, MHD_HTTP_STATUS_BAD_REQUEST, MHD_HTTP_STATUS_UNAUTHORIZED, MHD_HTTP_STATUS_FORBIDDEN, MHD_HTTP_STATUS_NOT_FOUND, MHD_HTTP_STATUS_INTERNAL_SERVER_ERROR }) : (enum MHD_HTTP_StatusCode)(fdp.ConsumeIntegralInRange(0, 999)); } static MHD_Response* create_response(FuzzedDataProvider &fdp, enum MHD_HTTP_StatusCode sc) { struct MHD_Response* r = nullptr; // Generate random response body const size_t body_len = fdp.ConsumeIntegralInRange( 0, std::min(fdp.remaining_bytes(), 8192)); std::string body = fdp.ConsumeBytesAsString(body_len); // Randomly select which constructing function to use for respone object creation enum CtorKind { EMPTY, BUF_STATIC, BUF_COPY, IOVEC, FROM_FD, FROM_PIPE }; CtorKind ctor = fdp.PickValueInArray( {EMPTY, BUF_STATIC, BUF_COPY, IOVEC, FROM_FD, FROM_PIPE}); switch (ctor) { default: case EMPTY: { // Create empty response r = MHD_response_from_empty(sc); break; } case BUF_STATIC: { // Create response with random body and static buffer status r = MHD_response_from_buffer_static(sc, body.size(), body.c_str()); break; } case BUF_COPY: { // Create response with random body and copy buffer in r = MHD_response_from_buffer_copy(sc, body.size(), body.data()); break; } case IOVEC: { // Create response from random IO vector unsigned cnt = fdp.ConsumeIntegralInRange(0, 6); std::vector iov(cnt); std::vector chunks; chunks.reserve(cnt); for (unsigned i=0;i(0, 1024))); iov[i].iov_base = chunks.back().data(); iov[i].iov_len = chunks.back().size(); } r = MHD_response_from_iovec(sc, cnt ? cnt : 0, cnt ? iov.data() : nullptr, nullptr, nullptr); break; } case FROM_FD: { // Create response from file with random data char path[] = "/tmp/mhdrespXXXXXX"; int fd = mkstemp(path); if (fd >= 0) { unlink(path); if (!body.empty()) (void) ::write(fd, body.data(), body.size()); uint64_t sz = (uint64_t)body.size(); uint64_t off = 0; if (fdp.ConsumeBool()) { off = std::min(sz, fdp.ConsumeIntegral() % (sz + 1)); } uint64_t len = (sz > off) ? (fdp.ConsumeIntegral() % (sz - off + 1)) : 0; r = MHD_response_from_fd(sc, fd, off, len); if (!r) { close(fd); } } break; } case FROM_PIPE: { // Create response by piping in random data int pfd[2]; if (0 == pipe(pfd)) { std::string pbytes = fdp.ConsumeBytesAsString( fdp.ConsumeIntegralInRange(0, 2048)); if (!pbytes.empty()) { ::write(pfd[1], pbytes.data(), pbytes.size()); } close(pfd[1]); r = MHD_response_from_pipe(sc, pfd[0]); if (!r) { close(pfd[0]); } } break; } } return r; } static void add_headers(FuzzedDataProvider &fdp, MHD_Response *r) { const char* ct = fdp.ConsumeBool() ? "text/plain" : "application/octet-stream"; MHD_response_add_header(r, "Content-Type", ct); // Add random standard headers size_t num_headers = fdp.ConsumeIntegralInRange(0, 10); for (size_t i = 0; i < num_headers; i++) { std::string name = safe_ascii(fdp.ConsumeRandomLengthString(20), false); std::string val = safe_ascii(fdp.ConsumeRandomLengthString(60), true); MHD_response_add_header(r, name.c_str(), val.c_str()); } // Add random predefined header enum MHD_PredefinedHeader which = fdp.PickValueInArray( { MHD_PREDEF_ACCEPT_CHARSET, MHD_PREDEF_ACCEPT_LANGUAGE }); std::string value = safe_ascii(fdp.ConsumeRandomLengthString(32)); MHD_response_add_predef_header(r, which, value.c_str()); } static void randomise_response_options(FuzzedDataProvider &fdp, MHD_Response *r) { if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_REUSABLE(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_HEAD_ONLY_RESPONSE(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_CHUNKED_ENC(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_CONN_CLOSE(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_HTTP_1_0_SERVER(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_HTTP_1_0_COMPATIBLE_STRICT(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_INSANITY_HEADER_CONTENT_LENGTH(ToMhdBool(fdp.ConsumeBool())); MHD_response_set_option(r, &o); } if (fdp.ConsumeBool()) { auto o = MHD_R_OPTION_TERMINATION_CALLBACK(&request_ended_cb, nullptr); MHD_response_set_option(r, &o); } } static void add_auth(FuzzedDataProvider &fdp, MHD_Response *r, enum MHD_HTTP_StatusCode sc) { if (sc == MHD_HTTP_STATUS_UNAUTHORIZED) { // Randomly add different challenge under 401 status code if (fdp.ConsumeBool()) { // Use digest challenge std::string realm = safe_ascii(fdp.ConsumeRandomLengthString(24)); MHD_response_add_auth_basic_challenge(r, realm.c_str(), ToMhdBool(fdp.ConsumeBool())); if (fdp.ConsumeBool()) { std::string drealm = safe_ascii(fdp.ConsumeRandomLengthString(24)); const char* opaque = fdp.ConsumeBool() ? "opaque" : nullptr; const char* domain = fdp.ConsumeBool() ? "/a /b" : nullptr; enum MHD_DigestAuthMultiQOP mqop = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_QOP_AUTH : MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT; enum MHD_DigestAuthMultiAlgo malgo = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_ALGO_ANY : MHD_DIGEST_AUTH_MULT_ALGO_MD5; MHD_response_add_auth_digest_challenge( r, drealm.c_str(), opaque, domain, ToMhdBool(fdp.ConsumeBool()), mqop, malgo, ToMhdBool(fdp.ConsumeBool()), ToMhdBool(fdp.ConsumeBool())); } } else { // Use basic challenge std::string realm = safe_ascii(fdp.ConsumeRandomLengthString(24)); const char* opaque = fdp.ConsumeBool() ? "opaque" : nullptr; const char* domain = fdp.ConsumeBool() ? "/a /b" : nullptr; enum MHD_DigestAuthMultiQOP mqop = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_QOP_AUTH : MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT; enum MHD_DigestAuthMultiAlgo malgo = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_ALGO_ANY : MHD_DIGEST_AUTH_MULT_ALGO_MD5; MHD_response_add_auth_digest_challenge( r, realm.c_str(), opaque, domain, ToMhdBool(fdp.ConsumeBool()), mqop, malgo, ToMhdBool(fdp.ConsumeBool()), ToMhdBool(fdp.ConsumeBool())); if (fdp.ConsumeBool()) { std::string brealm = safe_ascii(fdp.ConsumeRandomLengthString(24)); MHD_response_add_auth_basic_challenge(r, brealm.c_str(), ToMhdBool(fdp.ConsumeBool())); } } } else { // For all other status code, randomly determine if challenges are added // Randomly choose if basic challenge is used or not if (fdp.ConsumeBool()) { std::string realm = safe_ascii(fdp.ConsumeRandomLengthString(24)); MHD_response_add_auth_basic_challenge(r, realm.c_str(), ToMhdBool(fdp.ConsumeBool())); } // Randomly choose if disgest challenge is used or not if (fdp.ConsumeBool()) { std::string realm = safe_ascii(fdp.ConsumeRandomLengthString(24)); const char* opaque = fdp.ConsumeBool() ? "opaque" : nullptr; const char* domain = fdp.ConsumeBool() ? "/a /b" : nullptr; enum MHD_DigestAuthMultiQOP mqop = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_QOP_AUTH : MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT; enum MHD_DigestAuthMultiAlgo malgo = fdp.ConsumeBool()? MHD_DIGEST_AUTH_MULT_ALGO_ANY : MHD_DIGEST_AUTH_MULT_ALGO_MD5; MHD_response_add_auth_digest_challenge( r, realm.c_str(), opaque, domain, ToMhdBool(fdp.ConsumeBool()), mqop, malgo, ToMhdBool(fdp.ConsumeBool()), ToMhdBool(fdp.ConsumeBool())); } } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size == 0) { return 0; } FuzzedDataProvider fdp(data, size); // Pick a random response status code enum MHD_HTTP_StatusCode sc = pick_status_code(fdp); // Create a random response object struct MHD_Response* r = create_response(fdp, sc); if (!r) { return 0; } // Add random headers into the response object add_headers(fdp, r); // Set random options for the response object randomise_response_options(fdp, r); // Add authentication challenges to response add_auth(fdp, r, sc); // Fuzz additional targets on response status MHD_HTTP_status_code_to_string(sc); MHD_status_code_to_string((enum MHD_StatusCode)sc); // Destory the response object MHD_response_destroy(r); return 0; } ================================================ FILE: projects/libmicrohttpd2/fuzz_str.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include "mhd_str.h" #include "microhttpd2.h" static void fuzz_tokens(FuzzedDataProvider& fdp) { // Prepare random string for string comparison std::string payload1 = fdp.ConsumeRandomLengthString(1024); std::string payload2 = fdp.ConsumeRandomLengthString(1024); std::string payload3 = fdp.ConsumeRandomLengthString(1024); const char *payload_str1 = payload1.c_str(); const char *payload_str2 = payload2.c_str(); const char *payload_str3 = payload3.c_str(); size_t payload_size1 = payload1.size(); size_t payload_size2 = payload2.size(); size_t payload_size3 = payload3.size(); // Fuzz mhd_str_equal_caseless mhd_str_equal_caseless(payload_str1, payload_str2); // Fuzz mhd_str_equal_caseless_n mhd_str_equal_caseless_n(payload_str1, payload_str2, fdp.ConsumeIntegral()); // Fuzz mhd_str_equal_caseless_bin_n const size_t min_len = std::min(payload_size1, payload_size2); if (min_len) { mhd_str_equal_caseless_bin_n(payload_str1, payload_str2, min_len); } // Fuzz mhd_str_has_token_caseless mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size1); mhd_str_has_token_caseless(payload_str1, payload_str2, payload_size2); // Fuzz mhd_str_remove_token_caseless ssize_t out_sz = (ssize_t)fdp.ConsumeIntegralInRange(1, 1024); char *out_buf = (char*) malloc((size_t)out_sz); mhd_str_remove_token_caseless(payload_str1, payload_size1, payload_str2, payload_size2, out_buf, &out_sz); free(out_buf); // Fuzz mhd_str_starts_with_token_opt_param struct MHD_String mhd_str1 { payload_size1, payload_str1 }; struct MHD_String mhd_str2 { payload_size2, payload_str2 }; mhd_str_starts_with_token_opt_param(&mhd_str1, &mhd_str2); // Fuzz mhd_str_starts_with_token_req_param bool needs_uni = fdp.ConsumeBool(); struct MHD_String mhd_str3 { payload_size3, payload_str3 }; struct mhd_BufferConst str3_buf { 0, nullptr }; mhd_str_starts_with_token_req_param(&mhd_str1, &mhd_str2, &mhd_str3, &str3_buf, &needs_uni); } static void fuzz_conversion(FuzzedDataProvider& fdp) { // Prepare random string for string/int conversion std::string payload = fdp.ConsumeRandomLengthString(1024); const char *payload_str = payload.c_str(); size_t payload_size = payload.size(); uint_fast32_t u32 = 0; uint_fast64_t u64 = 0; char small[4], big[128]; size_t max_len = fdp.ConsumeIntegralInRange(0, payload_size); // Fuzz conversion between string and uint64 with random payload mhd_str_to_uint64(payload_str, &u64); mhd_str_to_uint64_n(payload_str, max_len, &u64); mhd_strx_to_uint64(payload_str, &u64); mhd_strx_to_uint64_n(payload_str, max_len, &u64); mhd_uint64_to_str((uint_fast64_t)fdp.ConsumeIntegral(), small, sizeof(small)); mhd_uint64_to_str((uint_fast64_t)fdp.ConsumeIntegral(), big, sizeof(big)); // Fuzz string to uint32 conversion with random payload string mhd_strx_to_uint32(payload_str, &u32); mhd_strx_to_uint32_n(payload_str, max_len, &u32); mhd_uint32_to_strx((uint_fast32_t)fdp.ConsumeIntegral(), small, sizeof(small)); mhd_uint32_to_strx((uint_fast32_t)fdp.ConsumeIntegral(), big, sizeof(big)); // Fuzz uint16 to string conversion with random payload mhd_uint16_to_str((uint_least16_t)fdp.ConsumeIntegralInRange(0, 65535), small, sizeof(small)); mhd_uint16_to_str((uint_least16_t)fdp.ConsumeIntegralInRange(0, 65535), big, sizeof(big)); // Fuzz uint8 to string conversion with random payload uint8_t min_digits = fdp.ConsumeIntegralInRange(0, 5); mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral(), min_digits, small, sizeof(small)); mhd_uint8_to_str_pad((uint8_t)fdp.ConsumeIntegral(), min_digits, big, sizeof(big)); } static void fuzz_decode(FuzzedDataProvider& fdp) { // Prepare random data for string decode bool ignored = false; std::string payload = fdp.ConsumeRandomLengthString(1024); char *payload_str = payload.data(); size_t payload_size = payload.size(); // Fuzz decode functions with random payload char *out1 = (char*) malloc(payload_size); char *out2 = (char*) malloc(payload_size); if (out1) { mhd_str_pct_decode_strict_n(payload_str, payload_size, out1, payload_size); } if (out2) { mhd_str_pct_decode_lenient_n(payload_str, payload_size, out2, payload_size, &ignored); } // Fuzz decode in place functions with random payload mhd_str_pct_decode_in_place_strict(payload_str); mhd_str_pct_decode_in_place_lenient(payload_str, &ignored); free(out1); free(out2); } static void fuzz_quoted(FuzzedDataProvider& fdp) { // Prepare random data for quote and equality check std::string payload1 = fdp.ConsumeRandomLengthString(1024); std::string payload2 = fdp.ConsumeRandomLengthString(1024); const char *payload_str1 = payload1.c_str(); const char *payload_str2 = payload2.c_str(); size_t payload_size1 = payload1.size(); size_t payload_size2 = payload2.size(); // Fuzz mhd_str_equal_quoted_bin_n with random string payload as binary mhd_str_equal_quoted_bin_n(payload_str1, payload_size1, payload_str2, payload_size2); // Fuzz mhd_str_equal_caseless_quoted_bin_n with random string payload as binary mhd_str_equal_caseless_quoted_bin_n(payload_str1, payload_size1, payload_str2, payload_size2); // Fuzz mhd_str_quote and mhd_str_unquote with random string payload size_t max_out = payload_size1 * 2; char *out = (char*) malloc(max_out); if (out) { mhd_str_quote(payload_str1, payload_size1, out, max_out); mhd_str_unquote(payload_str1, payload_size1, out); } free(out); max_out = payload_size2 * 2; out = (char*) malloc(max_out); if (out) { mhd_str_quote(payload_str2, payload_size2, out, max_out); mhd_str_unquote(payload_str2, payload_size2, out); } free(out); } static void fuzz_base64(FuzzedDataProvider& fdp) { // Prepare random data for base64 conversion std::string payload = fdp.ConsumeRandomLengthString(1024); char *payload_str = payload.data(); size_t payload_size = payload.size(); // Prepare a valid base64 string from random payload static const char valid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; for (size_t i = 0; i < payload_size; i++) { payload_str[i] = valid_chars[((uint8_t)i) % 64]; } // Fuzz mhd_base64_to_bin_n with the random base64 string size_t max_out = (payload.size() / 4) * 4; uint8_t* out = (uint8_t*) malloc(payload_size); if (out) { mhd_base64_to_bin_n(payload_str, payload_size, out, max_out); free(out); } } static void fuzz_transformation(FuzzedDataProvider& fdp) { // Fuzz targets in multiple rounds for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 8); i++) { // Generate random integer int value = fdp.ConsumeIntegral(); // Fuzz conversion functions MHD_http_method_to_string(static_cast(value)); MHD_protocol_version_to_string(static_cast(value)); } } static void fuzz_hex_conversion(FuzzedDataProvider& fdp) { // Prepare random data for hex conversion std::string payload = fdp.ConsumeRandomLengthString(1024); char *payload_str = payload.data(); size_t payload_size = payload.size(); // Fuzz mhd_hex_to_bin with random payload uint8_t *bin_out = (uint8_t*) malloc(payload_size); if (bin_out) { mhd_hex_to_bin(payload_str, payload_size, bin_out); free(bin_out); } // Fuzz mhd_bin_to_hex with random payload char *hex_out = (char *) malloc(payload_size * 2); if (hex_out) { if (!payload.empty()) { mhd_bin_to_hex(payload_str, payload_size, hex_out); } free(hex_out); } char *hexz_out = (char *) malloc(payload_size * 2 + 1); if (hexz_out) { if (!payload.empty()) { mhd_bin_to_hex_z(payload_str, payload_size, hexz_out); } free(hexz_out); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); for (int i = 0; i < fdp.ConsumeIntegralInRange(1, 6); i++) { switch (fdp.ConsumeIntegralInRange(0, 7)) { case 0: fuzz_tokens(fdp); break; case 1: fuzz_conversion(fdp); break; case 2: fuzz_decode(fdp); break; case 3: fuzz_quoted(fdp); break; case 4: fuzz_base64(fdp); break; case 5: fuzz_transformation(fdp); break; case 6: fuzz_hex_conversion(fdp); break; } } return 0; } ================================================ FILE: projects/libmicrohttpd2/mhd_helper.cpp ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #include "mhd_helper.h" #include #include #include #include #include #include #include #include #include std::unique_ptr g_fdp; std::mutex g_fdp_mu; std::string b64encode(const std::string &in) { static const char* tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string out; size_t i = 0; while (i + 2 < in.size()) { unsigned v = (unsigned((unsigned char)in[i]) << 16) | (unsigned((unsigned char)in[i+1]) << 8) | (unsigned((unsigned char)in[i+2])); out.push_back(tbl[(v >> 18) & 63]); out.push_back(tbl[(v >> 12) & 63]); out.push_back(tbl[(v >> 6) & 63]); out.push_back(tbl[(v) & 63]); i += 3; } if (i + 1 == in.size()) { unsigned v = (unsigned((unsigned char)in[i]) << 16); out.push_back(tbl[(v >> 18) & 63]); out.push_back(tbl[(v >> 12) & 63]); out.push_back('='); out.push_back('='); } else if (i + 2 == in.size()) { unsigned v = (unsigned((unsigned char)in[i]) << 16) | (unsigned((unsigned char)in[i+1]) << 8); out.push_back(tbl[(v >> 18) & 63]); out.push_back(tbl[(v >> 12) & 63]); out.push_back(tbl[(v >> 6) & 63]); out.push_back('='); } return out; } enum MHD_Bool ToMhdBool(bool b) { return b ? MHD_YES : MHD_NO; } std::string safe_ascii(const std::string& in, bool allow_space) { std::string out; out.reserve(in.size()); for (unsigned char c : in) { if (!c || c=='\r' || c=='\n' || c<32 || c>=127 || (!allow_space && c==' ')) { continue; } out.push_back((char)c); } if (out.empty()) { out = "x"; } return out; } // Dummy functions static enum MHD_Bool kv_cb(void*, enum MHD_ValueKind, const struct MHD_NameAndValue*) { return MHD_YES; } static enum MHD_Bool post_cb(void*, const struct MHD_PostField* pf) { return MHD_YES; } /* Start of internal helpers for sending http message to daemon through localhost socket */ static int create_socket(uint16_t port) { int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { return -1; } // Use flag to avoid blocking on socket int flags = fcntl(fd, F_GETFL, 0); if (flags >= 0) { fcntl(fd, F_SETFL, flags | O_NONBLOCK); } struct linger lg{1, 0}; setsockopt(fd, SOL_SOCKET, SO_LINGER, &lg, sizeof(lg)); // configure the socket to target the daemon sockaddr_in addr{}; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // Try connect to the daemon on the binded port in localhost int rc = connect(fd, (sockaddr*)&addr, sizeof(addr)); if (rc == 0) { return fd; } // Early exit for invalid connection if (errno != EINPROGRESS) { close(fd); return -1; } pollfd p{fd, POLLOUT, 0}; if (poll(&p, 1, 5) <= 0) { close(fd); return -1; } int err = 0; socklen_t elen = sizeof(err); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &elen) != 0 || err != 0) { close(fd); return -1; } // Return the created socket return fd; } static void generate_daemon_options(const std::string& method, DaemonOpts& opts) { std::lock_guard lk(g_fdp_mu); if (!g_fdp) { return; } // Generate general daemon options opts.omit_host = g_fdp->ConsumeBool(); opts.bad_cl = g_fdp->ConsumeBool() && g_fdp->ConsumeBool(); opts.keep_alive = g_fdp->ConsumeBool(); opts.extra_headers = g_fdp->ConsumeBool(); opts.use_digest = g_fdp->ConsumeBool(); opts.send_malformed_digest = g_fdp->ConsumeBool(); if (g_fdp->ConsumeBool()) { opts.realm_hint = g_fdp->ConsumeRandomLengthString(16); if (opts.realm_hint.empty()) opts.realm_hint = "hint"; } // Generate specific daemon options with specific method if (!method.empty() && (method == "POST" || g_fdp->ConsumeBool())) { opts.te_chunked = g_fdp->ConsumeBool(); opts.as_multipart = g_fdp->ConsumeBool(); if (g_fdp->ConsumeBool()) { opts.boundary = safe_ascii(g_fdp->ConsumeRandomLengthString(24), false); if (opts.boundary.empty()) opts.boundary = "b"; } } } static std::string generate_auth_header(const DaemonOpts& opts, const std::string& method, const std::string& path, const std::string& auth_user, const std::string& auth_pass, bool garble_auth) { // For basic auth only request if (!opts.use_digest) { if (!garble_auth) { std::string up = auth_user + ":" + auth_pass; return "Authorization: Basic " + b64encode(up) + "\r\n"; } static const char* kBad[] = { "Authorization: Basic\r\n", "Authorization: Basic =\r\n", "Authorization: Bearer ???\r\n", "Authorization:\r\n" }; unsigned idx = (auth_user.empty() ? 0u : (unsigned char)auth_user[0]) % (unsigned)(sizeof(kBad)/sizeof(kBad[0])); return std::string(kBad[idx]); } // For digest auth with malformed headers if (!opts.send_malformed_digest) { std::string u = auth_user.empty() ? "user" : auth_user; std::string r = opts.realm_hint; std::string uri = (path.empty() || path[0] != '/') ? ("/" + path) : path; if (uri.empty()) uri = "/"; std::string h = "Authorization: Digest "; h += "username=\"" + u + "\", "; h += "realm=\"" + r + "\", "; h += "nonce=\"deadbeef\", "; h += "uri=\"" + uri + "\", "; h += "response=\"00000000000000000000000000000000\", "; h += "opaque=\"cafebabe\", "; h += "qop=auth, "; h += "nc=00000001, cnonce=\"0123456789abcdef\"\r\n"; return h; } // For digest auth with correctly formatted headers with random data static const char* kBadDigest[] = { "Authorization: Digest\r\n", "Authorization: Digest username=\r\n", "Authorization: Digest realm=\"\", uri=/, response=\r\n", "Authorization: Digest nonce=,opaque=\r\n" }; unsigned idx = (unsigned char)(auth_user.empty()?0:auth_user[0]) % (unsigned)(sizeof(kBadDigest)/sizeof(kBadDigest[0])); return std::string(kBadDigest[idx]); } static void append_headers(std::string& req, const DaemonOpts& opts, const std::string& auth_header) { // Set host if (!opts.omit_host) { req += "Host: 127.0.0.1\r\n"; } // Append auth headers req += auth_header; // Append general headers if (opts.extra_headers) { req += "User-Agent: fuzz\r\n"; req += "Accept: */*\r\n"; req += "X-Fuzz: 1\r\n"; req += "X-Dup: a\r\nX-Dup: b\r\n"; } } static std::string make_multipart(const DaemonOpts& opts, const std::string& body, std::string& content_type_line_out) { // Do nothing for non-multipart iteration if (!opts.as_multipart) { content_type_line_out.clear(); return body; } // Configure the request body to be multipart format std::string b = opts.boundary.empty() ? "b" : opts.boundary; std::string mp; mp += "--" + b + "\r\n"; mp += "Content-Disposition: form-data; name=\"f\"; filename=\"x\"\r\n"; if (!body.empty()) mp += "Content-Type: application/octet-stream\r\n"; mp += "\r\n"; mp += body; mp += "\r\n--" + b + "--\r\n"; content_type_line_out = "Content-Type: multipart/form-data; boundary=" + b + "\r\n"; return mp; } static void append_request_headers(std::string& req, const DaemonOpts& opts, size_t payload_size, const std::string& content_type_line) { // Append content type header if (!content_type_line.empty()) { req += content_type_line; } if (payload_size == 0) { return; } // Append encoding and payload size headers if (opts.te_chunked) { req += "Transfer-Encoding: chunked\r\n"; } else { if (!opts.bad_cl) { req += "Content-Length: " + std::to_string(payload_size) + "\r\n"; } else { req += "Content-Length: " + std::to_string(payload_size + 5) + "\r\n"; } } // Append connection lifeline header req += opts.keep_alive ? "Connection: keep-alive\r\n" : "Connection: close\r\n"; } static void append_chunked_payload(std::string& req, const std::string& payload) { // End the request body gracefully for empty payload if (payload.empty()) { req += "0\r\n\r\n"; return; } // Continue to write all the body data chunk by chunk to the request size_t off = 0; while (off < payload.size()) { char szbuf[32]; size_t remain = payload.size() - off; size_t chunk = std::min(remain > 1 ? remain / 2 : 1, size_t(4096)); int n = snprintf(szbuf, sizeof(szbuf), "%zx\r\n", chunk); if (n > 0) { req.append(szbuf, (size_t)n); } req.append(payload.data() + off, chunk); req += "\r\n"; off += chunk; } req += "0\r\n\r\n"; } static void send_request(int fd, const std::string& req) { // Configure sent parameters and max timeout size_t off = 0; const int kSendStepMs = 2; const int kSendMaxMs = 8; int waited = 0; // Continue to send data though the socket until all data is sent or timeout is reached while (off < req.size()) { ssize_t s = send(fd, req.data() + off, req.size() - off, 0); if (s > 0) { off += (size_t)s; continue; } if (s < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) { pollfd p{fd, POLLOUT, 0}; if (poll(&p, 1, kSendStepMs) <= 0) { waited += kSendStepMs; if (waited >= kSendMaxMs) { break; } } continue; } break; } shutdown(fd, SHUT_WR); } static void wait_for_response(int fd) { // Configure response waiting parameters and timeout static const int kStepMs = 2; static const int kMaxMs = 8; static const size_t kMaxRead = 64 * 1024; int waited = 0; size_t total = 0; // Continue to receive data from daemon throug the socket until max data threshold or timeout is reached while (true) { pollfd p{fd, POLLIN, 0}; int pr = poll(&p, 1, kStepMs); if (pr <= 0) { waited += kStepMs; if (waited >= kMaxMs) { break; } continue; } char buf[1024]; ssize_t r = recv(fd, buf, sizeof(buf), 0); if (r > 0) { total += (size_t)r; if (total >= kMaxRead) break; continue; } if (r == 0) { break; } if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { continue; } break; } } /* End of internal helpers for sending http message to daemon through localhost socket */ void send_http_request_blocking(uint16_t port, const std::string& method, const std::string& path, const std::string& auth_user, const std::string& auth_pass, const std::string& body, bool garble_auth) { // Create and connect to the daemon with HTTP localhost socket int fd = create_socket(port); if (fd < 0) { return; } // Generate options for the daemon connection and request DaemonOpts opts; generate_daemon_options(method, opts); // Build the request body for the random request std::string req; req.reserve(512 + body.size()); const std::string& m = method.empty() ? std::string("GET") : method; req += m; req += " "; std::string full_path = (path.empty() || path[0] != '/') ? ("/" + path) : path; if (full_path.empty()) full_path = "/"; req += full_path; req += " HTTP/1.1\r\n"; // Generate auth headers std::string auth_header = generate_auth_header(opts, m, path, auth_user, auth_pass, garble_auth); // Append headers into the daemon request append_headers(req, opts, auth_header); // Randomly make the request with multipart data std::string content_type_line; std::string payload = make_multipart(opts, body, content_type_line); // Append additional request specific headers append_request_headers(req, opts, payload.size(), content_type_line); req += "\r\n"; // Add random body content to the request object depends on the content type chosen if (opts.te_chunked) { append_chunked_payload(req, payload); } else { req += payload; } // Sending the request to the daemon through the localhost socket send_request(fd, req); // Wait for a while for daemon response wait_for_response(fd); // Close the socket close(fd); } /* Start of internal helpers for daemon request handling */ static void generate_daemon_req_opts(DaemonReqOpts& o, enum MHD_HTTP_Method method) { std::lock_guard lk(g_fdp_mu); if (!g_fdp) { o.realm = "realm"; return; } // Generate basic daemon request options o.realm = g_fdp->ConsumeRandomLengthString(16); if (o.realm.empty()) { o.realm = "realm"; } o.allowed_user = g_fdp->ConsumeRandomLengthString(12); o.allowed_pass = g_fdp->ConsumeRandomLengthString(12); o.force_challenge = g_fdp->ConsumeBool(); o.force_bad = g_fdp->ConsumeBool(); o.flip_ok_to_forbidden = g_fdp->ConsumeBool(); o.prefer_utf8 = ToMhdBool(g_fdp->ConsumeBool()); o.use_digest = g_fdp->ConsumeBool(); o.qop = g_fdp->ConsumeBool() ? MHD_DIGEST_AUTH_MULT_QOP_AUTH : MHD_DIGEST_AUTH_MULT_QOP_AUTH_INT; o.algo = g_fdp->ConsumeBool() ? MHD_DIGEST_AUTH_MULT_ALGO_ANY : MHD_DIGEST_AUTH_MULT_ALGO_MD5; o.send_stale = g_fdp->ConsumeBool() ? MHD_YES : MHD_NO; o.allow_userhash = g_fdp->ConsumeBool() ? MHD_YES : MHD_NO; o.use_opaque = g_fdp->ConsumeBool(); // Generate daemon request options for form encoded request o.buf_sz = 64 + g_fdp->ConsumeIntegralInRange(0, 8192); o.max_nonstream = g_fdp->ConsumeIntegralInRange(0, 64 * 1024); o.enc = g_fdp->PickValueInArray({ MHD_HTTP_POST_ENCODING_FORM_URLENCODED, MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, MHD_HTTP_POST_ENCODING_TEXT_PLAIN, MHD_HTTP_POST_ENCODING_OTHER }); o.do_parse_post = g_fdp->ConsumeBool() || (method == MHD_HTTP_METHOD_POST); o.do_process_upload = g_fdp->ConsumeBool(); } static const struct MHD_UploadAction* post_done_cb(struct MHD_Request *req, void *cls, enum MHD_PostParseResult pr) { return MHD_upload_action_continue(req); } static const struct MHD_UploadAction* post_reader(struct MHD_Request *req, void *cls, const struct MHD_String *name, const struct MHD_StringNullable *filename, const struct MHD_StringNullable *content_type, const struct MHD_StringNullable *encoding, size_t size, const void *data, uint_fast64_t off, enum MHD_Bool final_data) { return MHD_upload_action_continue(req); } static const struct MHD_UploadAction* upload_cb(void *upload_cls, struct MHD_Request *request, size_t content_data_size, void *content_data) { enum MHD_HTTP_StatusCode sc = content_data_size ? MHD_HTTP_STATUS_OK : MHD_HTTP_STATUS_NO_CONTENT; struct MHD_Response *r = MHD_response_from_empty(sc); if (!r) { return NULL; } return MHD_upload_action_from_response(request, r); } static const struct MHD_Action* request_parsing(struct MHD_Request* request, const DaemonReqOpts& o) { // Handle parsing of post request with form data or general parameters if (o.do_parse_post) { const struct MHD_Action *a = MHD_action_parse_post(request, o.buf_sz, o.max_nonstream, o.enc, &post_reader, nullptr, &post_done_cb, nullptr); if (a) { MHD_request_get_post_data_cb( request, [](void *cls, const struct MHD_PostField *pf)->enum MHD_Bool { std::lock_guard lk(g_fdp_mu); if (!g_fdp) { return MHD_YES; } return ToMhdBool(g_fdp->ConsumeBool()); }, nullptr); return a; } } // Handle parsing of upload request if (o.do_process_upload) { const struct MHD_Action *a = MHD_action_process_upload(request, o.buf_sz, &upload_cb, nullptr, &upload_cb, nullptr); if (a) { return a; } } return nullptr; } static const struct MHD_Action* handle_basic_auth(struct MHD_Request* request, const DaemonReqOpts& o) { union MHD_RequestInfoDynamicData req_data; enum MHD_StatusCode res = MHD_request_get_info_dynamic( request, MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS, &req_data); // Send bad header response if (o.force_bad || (MHD_SC_REQ_AUTH_DATA_BROKEN == res)) { return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_BAD_REQUEST, 10, "bad_header")); } // Send unauthorized response if (o.force_challenge || (MHD_SC_AUTH_ABSENT == res)) { const char* realm_cstr = o.realm.c_str(); return MHD_action_basic_auth_challenge_a( request, realm_cstr, o.prefer_utf8, MHD_response_from_buffer_static( MHD_HTTP_STATUS_UNAUTHORIZED, 4, "auth")); } // Fail safe to abort request if unknown request status is provided if (MHD_SC_OK != res) { return MHD_action_abort_request(request); } // Prepeare and perform basic auth check const struct MHD_AuthBasicCreds *creds = req_data.v_auth_basic_creds; bool user_ok = (creds->username.len == o.allowed_user.size()) && (0 == memcmp(o.allowed_user.data(), creds->username.cstr, creds->username.len)); bool pass_ok = (creds->password.len == o.allowed_pass.size()) && (0 == memcmp(o.allowed_pass.data(), creds->password.cstr, creds->password.len)); bool ok = user_ok && pass_ok; // Try randomly flip the result if (o.flip_ok_to_forbidden) { ok = false; } // Return result with status in response if (ok) { return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_OK, 2, "OK")); } return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_FORBIDDEN, 9, "FORBIDDEN")); } static const struct MHD_Action* handle_digest_auth(struct MHD_Request* request, const DaemonReqOpts& o) { union MHD_RequestInfoDynamicData req_data; enum MHD_StatusCode res = MHD_request_get_info_dynamic( request, MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO, &req_data); const char* opaque_opt = o.use_opaque ? "opaque-token" : nullptr; // Early exit for missing auth in request if (MHD_SC_AUTH_ABSENT == res || o.force_challenge) { return MHD_action_digest_auth_challenge_a( request, o.realm.c_str(), "0", opaque_opt, o.send_stale, o.qop, o.algo, o.allow_userhash, MHD_YES, MHD_response_from_buffer_static( MHD_HTTP_STATUS_UNAUTHORIZED, 4, "auth")); } // Early exit for invalid or malformed request headers if (MHD_SC_REQ_AUTH_DATA_BROKEN == res || o.force_bad) { return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_BAD_REQUEST, 15, "Header Invalid.")); } // Fail safe to abort request if unknown response status is provided if (MHD_SC_OK != res) { return MHD_action_abort_request(request); } // Prepeare and perform digest auth check const struct MHD_AuthDigestInfo *di = req_data.v_auth_digest_info; bool user_ok = (di->username.len == o.allowed_user.size()) && (0 == memcmp(o.allowed_user.data(), di->username.cstr, di->username.len)); if (user_ok) { enum MHD_DigestAuthResult auth_res = MHD_digest_auth_check(request, o.realm.c_str(), o.allowed_user.c_str(), o.allowed_pass.c_str(), 0, o.qop, o.algo); // Return auth result or randomly flip the result if (MHD_DAUTH_OK == auth_res) { if (!o.flip_ok_to_forbidden) { return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_OK, 2, "OK")); } return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_FORBIDDEN, 9, "FORBIDDEN")); } if (MHD_DAUTH_NONCE_STALE == auth_res) { return MHD_action_digest_auth_challenge_a( request, o.realm.c_str(), "0", opaque_opt, MHD_YES, o.qop, o.algo, o.allow_userhash, MHD_YES, MHD_response_from_buffer_static( MHD_HTTP_STATUS_UNAUTHORIZED, 4, "auth")); } return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_FORBIDDEN, 9, "FORBIDDEN")); } return MHD_action_from_response( request, MHD_response_from_buffer_static( MHD_HTTP_STATUS_FORBIDDEN, 9, "FORBIDDEN")); } /* End of internal helpers for daemon request handling */ MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb(void* cls, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { DaemonReqOpts opts; generate_daemon_req_opts(opts, method); // Try parinsg or streaming request if (const struct MHD_Action* a = request_parsing(request, opts)) { return a; } // Perform basic or digest auth on the request if (!opts.use_digest) { return handle_basic_auth(request, opts); } return handle_digest_auth(request, opts); } MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb_stream(void*, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { struct MHD_StringNullable out; // Fuzz MHD_request_get_value for different parameters on random request MHD_request_get_value(request, MHD_VK_HEADER, "host", &out); MHD_request_get_value(request, MHD_VK_HEADER, "content-type", &out); MHD_request_get_value(request, MHD_VK_COOKIE, "cookie", &out); MHD_request_get_value(request, MHD_VK_URI_QUERY_PARAM, "q", &out); MHD_request_get_values_cb(request, MHD_VK_HEADER, kv_cb, nullptr); MHD_request_get_values_cb(request, MHD_VK_COOKIE, kv_cb, nullptr); MHD_request_get_values_cb(request, MHD_VK_URI_QUERY_PARAM, kv_cb, nullptr); // Fuzz MHD_request_get_post_data_cb on random request MHD_request_get_post_data_cb(request, post_cb, nullptr); // Fuzz MHD_request_get_info_fixed for different parameters on random request union MHD_RequestInfoFixedData fix; MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_HTTP_VER, &fix); MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_HTTP_METHOD, &fix); MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_DAEMON, &fix); MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_CONNECTION, &fix); MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_STREAM, &fix); MHD_request_get_info_fixed(request, MHD_REQUEST_INFO_FIXED_APP_CONTEXT, &fix); // Fuzz MHD_request_get_info_dynamic for different parameters on random request union MHD_RequestInfoDynamicData dyn; MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STRING, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_URI, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_URI_PARAMS, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_POST_PARAMS, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_PRESENT, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_CHUNKED, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_TOTAL, &dyn); MHD_request_get_info_dynamic(request, MHD_REQUEST_INFO_DYNAMIC_UPLOAD_SIZE_RECIEVED, &dyn); // Fuzz response creation from random request processing struct MHD_Response* resp = MHD_response_from_empty(MHD_HTTP_STATUS_NO_CONTENT); if (!resp) { return MHD_action_abort_request(request); } // Fuzz response and request abortion MHD_response_add_header(resp, "x-fuzz", "values"); const struct MHD_Action* act = MHD_action_from_response(request, resp); MHD_response_destroy(resp); return act ? act : MHD_action_abort_request(request); } MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb_process(void*, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size) { // Create info unions union MHD_RequestInfoFixedData f; union MHD_RequestInfoDynamicData d; // Fuzz MHD_request_get_info_fixed_sz for different parameters on random request MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_HTTP_VER, &f, sizeof(f)); MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_HTTP_METHOD, &f, sizeof(f)); MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_DAEMON, &f, sizeof(f)); MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_CONNECTION, &f, sizeof(f)); MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_STREAM, &f, sizeof(f)); MHD_request_get_info_fixed_sz(request, MHD_REQUEST_INFO_FIXED_APP_CONTEXT, &f, sizeof(f)); // Fuzz MHD_request_get_info_dynamic_sz for different parameters on random request MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_HTTP_METHOD_STRING, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_URI, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_URI_PARAMS, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_NUMBER_COOKIES, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_HEADER_SIZE, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_AUTH_DIGEST_INFO, &d, sizeof(d)); MHD_request_get_info_dynamic_sz(request, MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS, &d, sizeof(d)); { static const char realm[] = "fuzz-realm"; static const char user[] = "u"; static const char pass[] = "p"; enum MHD_DigestAuthAlgo algos[] = { MHD_DIGEST_AUTH_ALGO_MD5, MHD_DIGEST_AUTH_ALGO_SHA256, MHD_DIGEST_AUTH_ALGO_SHA512_256 }; for (unsigned i = 0; i < (unsigned)(sizeof(algos)/sizeof(algos[0])); ++i) { size_t sz = MHD_digest_get_hash_size(algos[i]); if (sz == 0 || sz > 64) { continue; } unsigned char ha1[64]; if (MHD_SC_OK == MHD_digest_auth_calc_userdigest(algos[i], user, realm, pass, sz, ha1)) { MHD_digest_auth_check_digest( request, realm, user, sz, ha1, 0, MHD_DIGEST_AUTH_MULT_QOP_AUTH_ANY, MHD_DIGEST_AUTH_MULT_ALGO_ANY_NON_SESSION); } } } // Force OK response struct MHD_Response* r = MHD_response_from_empty(MHD_HTTP_STATUS_OK); return MHD_action_from_response(request, r); } ================================================ FILE: projects/libmicrohttpd2/mhd_helper.h ================================================ // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// #pragma once #include #include #include #include #include "microhttpd2.h" #include // Forward declaration extern std::unique_ptr g_fdp; extern std::mutex g_fdp_mu; // Daemon options struct DaemonOpts { bool omit_host = false; bool bad_cl = false; bool keep_alive = false; bool extra_headers = false; bool use_digest = false; bool send_malformed_digest = false; bool te_chunked = false; bool as_multipart = false; std::string realm_hint = "hint"; std::string boundary = "----fuzz----"; }; // Daemon request handling options struct DaemonReqOpts { std::string realm; std::string allowed_user; std::string allowed_pass; bool force_challenge = false; bool force_bad = false; bool flip_ok_to_forbidden = false; enum MHD_Bool prefer_utf8 = MHD_NO; bool use_digest = false; MHD_DigestAuthMultiQOP qop = MHD_DIGEST_AUTH_MULT_QOP_AUTH; MHD_DigestAuthMultiAlgo algo = MHD_DIGEST_AUTH_MULT_ALGO_ANY; enum MHD_Bool send_stale = MHD_NO; enum MHD_Bool allow_userhash = MHD_NO; bool use_opaque = false; size_t buf_sz = 4096; size_t max_nonstream = 16384; enum MHD_HTTP_PostEncoding enc = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; bool do_parse_post = false; bool do_process_upload = false; }; // Helper for sending request to daemon void send_http_request_blocking(uint16_t port, const std::string& method, const std::string& path, const std::string& auth_user, const std::string& auth_pass, const std::string& body, bool garble_auth); // Request handling and processing functions for the daemon MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb(void* cls, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size); MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb_stream(void* cls, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size); MHD_FN_PAR_NONNULL_(2) MHD_FN_PAR_NONNULL_(3) const struct MHD_Action* req_cb_process(void* cls, struct MHD_Request* MHD_RESTRICT request, const struct MHD_String* MHD_RESTRICT path, enum MHD_HTTP_Method method, uint_fast64_t upload_size); // Provide base64 encoding for the response/request std::string b64encode(const std::string &in); // Helper to transform bool to MHD_Bool enum MHD_Bool ToMhdBool(bool b); // Helper to convert random string to safe ascii characters only std::string safe_ascii(const std::string& in, bool allow_space = true); ================================================ FILE: projects/libmicrohttpd2/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://www.gnu.org/s/libmicrohttpd/" main_repo: "git://git.gnunet.org/libmicrohttpd2.git" primary_contact: "grothoff@gmail.com" language: c vendor_ccs: - "arthur.chan@adalogics.com" - "david@adalogics.com" - "adam@adalogics.com" fuzzing_engines: - libfuzzer sanitizers: - address architectures: - x86_64 builds_per_day: 1 ================================================ FILE: projects/libmodbus/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool libtool-bin RUN git clone https://github.com/stephane/libmodbus.git RUN git clone https://github.com/pkillarjun/oss-fuzz-bloat.git COPY build.sh $SRC/ COPY fuzz/ $SRC/libmodbus/fuzz/ WORKDIR $SRC/libmodbus/ ================================================ FILE: projects/libmodbus/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd fuzz make all cp FuzzClient $OUT/FuzzClient cp FuzzServer $OUT/FuzzServer pushd $SRC/oss-fuzz-bloat/libmodbus/ cp FuzzClient_seed_corpus.zip $OUT/FuzzClient_seed_corpus.zip cp FuzzServer_seed_corpus.zip $OUT/FuzzServer_seed_corpus.zip popd ================================================ FILE: projects/libmodbus/fuzz/FuzzClient.c ================================================ /* Copyright 2022 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "unit-test.h" #define PORT 8080 #define kMinInputLength 9 #define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH struct Fuzzer{ uint16_t port; char* file; FILE* inFile; uint64_t size; uint8_t* buffer; pthread_t thread; int socket; }; typedef struct Fuzzer Fuzzer; int client(Fuzzer *fuzzer); void fuzzinit(Fuzzer *fuzzer){ struct sockaddr_in server_addr; fuzzer->socket = socket(AF_INET, SOCK_STREAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(fuzzer->port); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); setsockopt(fuzzer->socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); bind(fuzzer->socket, (struct sockaddr*)&server_addr, sizeof(server_addr)); listen(fuzzer->socket,1); } void *Server(void *args){ Fuzzer *fuzzer = (Fuzzer*)args; { int client; char clientData[10240]; struct sockaddr_in clientAddr; uint32_t clientSZ = sizeof(clientAddr); client = accept(fuzzer->socket, (struct sockaddr*)&clientAddr, &clientSZ); send(client, fuzzer->buffer, fuzzer->size, 0); recv(client, clientData, sizeof(clientData), 0); send(client, fuzzer->buffer, fuzzer->size, 0); recv(client, clientData, sizeof(clientData), 0); shutdown(client,SHUT_RDWR); close(client); } pthread_exit(NULL); } void clean(Fuzzer *fuzzer){ {//Server shutdown(fuzzer->socket,SHUT_RDWR); close(fuzzer->socket); } free(fuzzer); } extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < kMinInputLength || size > kMaxInputLength){ return 0; } Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer)); fuzzer->port = PORT; fuzzer->size = size; fuzzer->buffer = data; fuzzinit(fuzzer); pthread_create(&fuzzer->thread, NULL,Server,fuzzer); client(fuzzer); pthread_join(fuzzer->thread, NULL);/* To Avoid UAF*/ clean(fuzzer); return 0; } int client(Fuzzer *fuzzer){ uint8_t *tab_rp_bits = NULL; uint16_t *tab_rp_registers = NULL; modbus_t *ctx = NULL; int nb_points; int rc; ctx = modbus_new_tcp("127.0.0.1", fuzzer->port); if (ctx == NULL) { fprintf(stderr, "Unable to allocate libmodbus context\n"); return -1; } if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } /* Allocate and initialize the memory to store the bits */ nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB; tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t)); memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t)); /* Allocate and initialize the memory to store the registers */ nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ? UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB; tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t)); memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t)); //Read rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB, tab_rp_bits); rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB, tab_rp_registers); /* Free the memory */ free(tab_rp_bits); free(tab_rp_registers); /* Close the connection */ modbus_close(ctx); modbus_free(ctx); return rc; } ================================================ FILE: projects/libmodbus/fuzz/FuzzServer.c ================================================ /* Copyright 2021 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "unit-test.h" #define PORT 8080 #define kMinInputLength 9 #define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH struct Fuzzer{ uint16_t port; char* file; FILE* inFile; uint64_t size; uint8_t* buffer; pthread_t thread; int socket; }; typedef struct Fuzzer Fuzzer; int server(Fuzzer *fuzzer); void *client(void *args){ Fuzzer *fuzzer = (Fuzzer*)args; int sockfd; struct sockaddr_in serv_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(fuzzer->port); serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); while(1){/* Try until connect*/ if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ continue; }else{ break; } } send(sockfd,fuzzer->buffer,fuzzer->size,0); close(sockfd); pthread_exit(NULL); } extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < kMinInputLength || size > kMaxInputLength){ return 0; } Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer)); fuzzer->port = PORT; fuzzer->size = size; fuzzer->buffer = data; pthread_create(&fuzzer->thread, NULL,client,fuzzer); server(fuzzer); pthread_join(fuzzer->thread, NULL); /* Avoid UAF*/ free(fuzzer); return 0; } int server(Fuzzer *fuzzer) { int s = -1; modbus_t *ctx; modbus_mapping_t *mb_mapping; int rc; int i; uint8_t *query; ctx = modbus_new_tcp("127.0.0.1", fuzzer->port); query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); mb_mapping = modbus_mapping_new_start_address( UT_BITS_ADDRESS, UT_BITS_NB, UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB, UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX, UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB); if (mb_mapping == NULL) { fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } /* Initialize input values that's can be only done server side. */ modbus_set_bits_from_bytes(mb_mapping->tab_input_bits, 0, UT_INPUT_BITS_NB, UT_INPUT_BITS_TAB); /* Initialize values of INPUT REGISTERS */ for (i=0; i < UT_INPUT_REGISTERS_NB; i++) { mb_mapping->tab_input_registers[i] = UT_INPUT_REGISTERS_TAB[i]; } s = modbus_tcp_listen(ctx, 1); modbus_tcp_accept(ctx, &s); rc = modbus_receive(ctx, query); if (s != -1) { close(s); } modbus_mapping_free(mb_mapping); free(query); /* For RTU */ modbus_close(ctx); modbus_free(ctx); return rc; } ================================================ FILE: projects/libmodbus/fuzz/Makefile ================================================ TARGET=Fuzzer #File CLIENTEXE=FuzzClient SERVEREXE=FuzzServer #Compiler Flags SET=cd ../ && INC=-I../src/ LIB=../src/libmodbus.la EXTCFLAGS= -Wall -Wextra LIBTOOL=libtool --mode=link --tag=CXX all: $(TARGET) #SETUP INIT: $(SET) ./autogen.sh CONF: $(SET) ./configure --disable-shared CC=$(CC) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" MAKEALL: $(SET) make -j$(nproc) CPFILE: cp ../tests/unit-test.h . $(TARGET): INIT CONF MAKEALL CPFILE $(CC) $(EXTCFLAGS) $(CFLAGS) $(INC) -c $(CLIENTEXE).c $(LIBTOOL) $(CXX) $(LDFLAGS) $(CFLAGS) $(LIB) $(LIB_FUZZING_ENGINE) $(CLIENTEXE).o -o $(CLIENTEXE) $(CC) $(EXTCFLAGS) $(CFLAGS) $(INC) -c $(SERVEREXE).c $(LIBTOOL) $(CXX) $(LDFLAGS) $(CFLAGS) $(LIB) $(LIB_FUZZING_ENGINE) $(SERVEREXE).o -o $(SERVEREXE) clean: rm $(CLIENTEXE) $(SERVEREXE) *.o .PHONY: all clean ================================================ FILE: projects/libmodbus/project.yaml ================================================ homepage: "https://libmodbus.org" language: c primary_contact: "stephane.raimbault@gmail.com" auto_ccs: - "ajsinghyadav00@gmail.com" vendor_ccs: - "libmodbus@googlegroups.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined main_repo: 'https://github.com/stephane/libmodbus' ================================================ FILE: projects/libmpeg2/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake RUN git clone https://github.com/ittiam-systems/libmpeg2.git ADD https://storage.googleapis.com/android_media/external/libmpeg2/fuzzer/mpeg2_dec_fuzzer_seed_corpus.zip $SRC/ COPY build.sh $SRC/ WORKDIR libmpeg2 ================================================ FILE: projects/libmpeg2/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. $SRC/libmpeg2/fuzzer/ossfuzz.sh ================================================ FILE: projects/libmpeg2/project.yaml ================================================ homepage: "https://github.com/ittiam-systems/libmpeg2" language: c++ primary_contact: "harish.mahendrakar@ittiam.com" sanitizers: - address - memory - undefined auto_ccs: - aadithya.kamath@ittiam.com - harish.mahendrakar@ittiam.com - ram.mohan@ittiam.com - umang.saini@ittiam.com - essick@google.com - lajos@google.com vendor_ccs: - adambacchus@google.com - ailport@google.com - bcreasey@google.com - cunefare@google.com - ejorgensen@google.com - faerber@google.com - greendonald@google.com - hamzeh@google.com - jaredkidd@google.com - kimtony@google.com - lindsaywells@google.com - maverickm@google.com - swansonr@google.com - warrenwright@google.com architectures: - x86_64 - i386 main_repo: 'https://github.com/ittiam-systems/libmpeg2.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/liboqs/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y cmake ninja-build openssl RUN git clone --depth 1 https://github.com/open-quantum-safe/liboqs.git liboqs WORKDIR liboqs COPY build.sh $SRC/ ================================================ FILE: projects/liboqs/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ mkdir build cd build cmake -GNinja .. -DOQS_BUILD_FUZZ_TESTS=ON ninja -j$(nproc) cp tests/fuzz_* $OUT/ ================================================ FILE: projects/liboqs/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://openquantumsafe.org/" language: c primary_contact: "security@openquantumsafe.org" auto_ccs: - nathaniel.brough@gmail.com main_repo: "https://github.com/open-quantum-safe/liboqs.git" fuzzing_engines: - libfuzzer - afl - honggfuzz ================================================ FILE: projects/libpcap/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake flex bison RUN git clone --depth 1 https://github.com/the-tcpdump-group/libpcap.git libpcap # for corpus as wireshark RUN git clone --depth=1 https://github.com/the-tcpdump-group/tcpdump.git tcpdump WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/libpcap/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd libpcap # build project mkdir build cd build cmake .. make # build fuzz targets for target in pcap filter both do $CC $CFLAGS -I.. -c ../testprogs/fuzz/fuzz_$target.c -o fuzz_$target.o $CXX $CXXFLAGS fuzz_$target.o -o $OUT/fuzz_$target libpcap.a $LIB_FUZZING_ENGINE done # export other associated stuff cd .. cp testprogs/fuzz/fuzz_*.options $OUT/ # builds corpus cd $SRC/tcpdump/ zip -r fuzz_pcap_seed_corpus.zip tests/ cp fuzz_pcap_seed_corpus.zip $OUT/ cd $SRC/libpcap/testprogs/BPF mkdir corpus ls *.txt | while read i; do tail -1 $i > corpus/$i; done zip -r fuzz_filter_seed_corpus.zip corpus/ cp fuzz_filter_seed_corpus.zip $OUT/ ================================================ FILE: projects/libpcap/project.yaml ================================================ homepage: "https://www.tcpdump.org" language: c++ primary_contact: "security@tcpdump.org" auto_ccs : - "p.antoine@catenacyber.fr" - "infra.station@gmail.com" - "gharris@sonic.net" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/the-tcpdump-group/libpcap.git' ================================================ FILE: projects/libpg_query/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/pganalyze/libpg_query libpg_query WORKDIR libpg_query COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libpg_query/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make build $CC $CFLAGS -c ./test/fuzz/fuzz_parser.c ./libpg_query.a -I./ $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_parser.o ./libpg_query.a -I./ -o $OUT/fuzz_parser ================================================ FILE: projects/libpg_query/project.yaml ================================================ homepage: "https://pganalyze.com/" language: c primary_contact: "team@pganalyze.com" main_repo: "https://github.com/pganalyze/pg_query" auto_ccs: - "marko@pganalyze.com" - "lukas@pganalyze.com" - "david@adalogics.com" ================================================ FILE: projects/libpg_query/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/libpg_query make clean test ================================================ FILE: projects/libphonenumber/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf automake \ cmake cmake-curses-gui libre2-dev \ libicu-dev libboost-dev libboost-thread-dev libboost-system-dev \ libgflags-dev libgoogle-glog-dev libssl-dev \ protobuf-compiler libtool wget default-jre icu-devtools RUN git clone --depth 1 https://github.com/google/googletest && \ cd $SRC/googletest && \ mkdir build && \ cd build && \ cmake .. && \ make -j$(nproc) && \ make install RUN wget https://github.com/unicode-org/icu/releases/download/release-66-rc/icu4c-66rc-src.tgz && \ tar xzvf icu4c-66rc-src.tgz RUN git clone https://github.com/google/protobuf.git && \ cd protobuf && \ git checkout tags/v3.14.0 RUN git clone https://github.com/google/libphonenumber RUN git clone https://github.com/abseil/abseil-cpp && \ cd abseil-cpp && \ git checkout 273292d COPY build.sh $SRC/ ================================================ FILE: projects/libphonenumber/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CXXFLAGS="$CXXFLAGS -std=c++17" # For coverage build we need to remove some flags when building protobuf and icu if [ "$SANITIZER" = "coverage" ] then export OCX=$CXXFLAGS export OC=$CFLAGS CF1=${CFLAGS//-fprofile-instr-generate/} export CFLAGS=${CF1//-fcoverage-mapping/} CXF1=${CXXFLAGS//-fprofile-instr-generate/} export CXXFLAGS=${CXF1//-fcoverage-mapping/} fi cd $SRC/abseil-cpp mkdir build && cd build cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ../ && make -j$(nproc) && make install ldconfig # Build Protobuf mkdir $SRC/protobuf-install cd $SRC/protobuf-install cmake $SRC/protobuf/cmake -Dprotobuf_BUILD_TESTS=OFF -DABSL_ROOT_DIR=$SRC/abseil-cpp make -j$(nproc) make install cp $SRC/protobuf/src/google/protobuf/*.inc /usr/local/include/google/protobuf/ # Build icu export DEPS_PATH=/src/deps/ mkdir $DEPS_PATH # build ICU for linking statically. cd $SRC/icu/source ./configure --disable-shared --enable-static --disable-layoutex \ --disable-tests --disable-samples --with-data-packaging=static --prefix=$DEPS_PATH make install -j$(nproc) # Ugly ugly hack to get static linking to work for icu. cd $DEPS_PATH/lib ls *.a | xargs -n1 ar x rm *.a ar r libicu.a *.{ao,o} ln -s libicu.a libicudata.a ln -s libicu.a libicuuc.a ln -s libicu.a libicui18n.a if [ "$SANITIZER" = "coverage" ] then export CFLAGS=$OC export CXXFLAGS=$OCX fi # Build libphonenumber cd $SRC/libphonenumber/cpp sed -i 's/set (BUILD_SHARED_LIB true)/set (BUILD_SHARED_LIB false)/g' CMakeLists.txt sed -i 's/set(CMAKE_CXX_STANDARD 11/set(CMAKE_CXX_STANDARD 17/g' CMakeLists.txt sed -i 's/list (APPEND CMAKE_C_FLAGS "-pthread")/string (APPEND CMAKE_C_FLAGS " -pthread")/g' CMakeLists.txt sed -i 's/# Safeguarding/find_package(absl REQUIRED) # Safeguarding/g' CMakeLists.txt mkdir build cd build cmake -DUSE_BOOST=OFF -DBUILD_GEOCODER=OFF \ -DBUILD_STATIC_LIB=ON -DBUILD_SHARED_LIBS=OFF \ -DPROTOBUF_LIB="/src/protobuf-install/libprotobuf.a" \ -DBUILD_TESTING=OFF \ -DICU_UC_INCLUDE_DIR=$SRC/icu/source/comon \ -DICU_UC_LIB=$DEPS_PATH/lib/libicuuc.a \ -DICU_I18N_INCLUDE_DIR=$SRC/icu/source/i18n/ \ -DICU_I18N_LIB=$DEPS_PATH/lib/libicui18n.a \ -DREGENERATE_METADATA=OFF \ ../ make -j$(nproc) # list of fuzz targets FUZZ_TARGETS=( "fuzz_phone" "fuzz_shortnumberinfo" "fuzz_asyoutypeformatter" "fuzz_matcher" ) # libraries for building the fuzzers LIBS=( "./libphonenumber.a" "$SRC/protobuf-install/libprotobuf.a" "/usr/local/lib/libabsl_cord.a" "/usr/local/lib/libabsl_cordz_info.a" "/usr/local/lib/libabsl_cord_internal.a" "/usr/local/lib/libabsl_cordz_functions.a" "/usr/local/lib/libabsl_cordz_handle.a" "/usr/local/lib/libabsl_hash.a" "/usr/local/lib/libabsl_city.a" "/usr/local/lib/libabsl_bad_variant_access.a" "/usr/local/lib/libabsl_low_level_hash.a" "/usr/local/lib/libabsl_raw_hash_set.a" "/usr/local/lib/libabsl_bad_optional_access.a" "/usr/local/lib/libabsl_hashtablez_sampler.a" "/usr/local/lib/libabsl_exponential_biased.a" "/usr/local/lib/libabsl_synchronization.a" "/usr/local/lib/libabsl_graphcycles_internal.a" "/usr/local/lib/libabsl_stacktrace.a" "/usr/local/lib/libabsl_symbolize.a" "/usr/local/lib/libabsl_malloc_internal.a" "/usr/local/lib/libabsl_debugging_internal.a" "/usr/local/lib/libabsl_demangle_internal.a" "/usr/local/lib/libabsl_time.a" "/usr/local/lib/libabsl_strings.a" "/usr/local/lib/libabsl_strings_internal.a" "/usr/local/lib/libabsl_throw_delegate.a" "/usr/local/lib/libabsl_int128.a" "/usr/local/lib/libabsl_civil_time.a" "/usr/local/lib/libabsl_time_zone.a" "/usr/local/lib/libabsl_base.a" "/usr/local/lib/libabsl_raw_logging_internal.a" "/usr/local/lib/libabsl_log_severity.a" "/usr/local/lib/libabsl_spinlock_wait.a" "$DEPS_PATH/lib/libicu.a" ) # build fuzzers for target in "${FUZZ_TARGETS[@]}"; do $CXX -I$SRC/libphonenumber/cpp/src $CXXFLAGS -o ${target}.o -c ../test/phonenumbers/${target}.cc $CXX $CXXFLAGS $LIB_FUZZING_ENGINE ${target}.o -o $OUT/${target} \ ${LIBS[@]} \ -lrt -lpthread done ================================================ FILE: projects/libphonenumber/project.yaml ================================================ homepage: "https://github.com/google/libphonenumber/" primary_contact: "penmetsaa@google.com" language: c++ auto_ccs: - "david@adalogics.com" sanitizers: - address main_repo: 'https://github.com/google/libphonenumber' file_github_issue: True ================================================ FILE: projects/libplist/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config RUN git clone --depth 1 https://github.com/libimobiledevice/libplist WORKDIR libplist COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libplist/build.sh ================================================ #!/bin/bash -eu # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [[ "$SANITIZER" != "coverage" && "$SANITIZER" != "introspector" ]] then ./autogen.sh --without-cython --enable-debug else ./autogen.sh --without-cython --enable-debug --without-tests fi make -j$(nproc) clean make -j$(nproc) all for fuzzer in bplist_fuzzer xplist_fuzzer jplist_fuzzer oplist_fuzzer; do $CXX $CXXFLAGS -std=c++11 -Iinclude/ \ fuzz/$fuzzer.cc -o $OUT/$fuzzer \ $LIB_FUZZING_ENGINE src/.libs/libplist-2.0.a done zip -j $OUT/bplist_fuzzer_seed_corpus.zip test/data/*.bplist zip -j $OUT/xplist_fuzzer_seed_corpus.zip test/data/*.plist zip -j $OUT/jplist_fuzzer_seed_corpus.zip test/data/*.json zip -j $OUT/oplist_fuzzer_seed_corpus.zip test/data/*.ostep cp fuzz/*.dict fuzz/*.options $OUT/ ================================================ FILE: projects/libplist/project.yaml ================================================ homepage: "https://github.com/libimobiledevice/libplist" language: c++ primary_contact: "nikias.bassen@gmail.com" auto_ccs: - "nikias@gmx.li" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://github.com/libimobiledevice/libplist' ================================================ FILE: projects/libplist/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Disable leak sanitizer export ASAN_OPTIONS="detect_leaks=0" # Skip json3.test that is failing and run unit testing make check -C test -j$(nproc) TESTS="$(cd test && ls *.test | grep -v 'json3.test')" ================================================ FILE: projects/libpng/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y make autoconf automake libtool zlib1g-dev RUN git clone --depth 1 https://github.com/madler/zlib.git RUN git clone -b master --depth 1 https://github.com/pnggroup/libpng.git RUN cp libpng/contrib/oss-fuzz/build.sh $SRC WORKDIR libpng ================================================ FILE: projects/libpng/project.yaml ================================================ homepage: "http://www.libpng.org/pub/png/libpng.html" language: c++ primary_contact: "ctruta@gmail.com" auto_ccs: - "barbaro.alberto@gmail.com" - "oss-fuzz@jbowler.com" vendor_ccs: - "aosmond@mozilla.com" - "tnikkel@mozilla.com" - "twsmith@mozilla.com" sanitizers: - address - memory - undefined architectures: - x86_64 main_repo: 'https://github.com/pnggroup/libpng.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libpng-proto/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update -y && \ apt-get install -y make autoconf automake libtool zlib1g-dev \ binutils cmake ninja-build liblzma-dev libz-dev pkg-config RUN git clone --depth 1 https://github.com/glennrp/libpng.git RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git RUN git clone --depth 1 https://github.com/google/fuzzer-test-suite RUN (mkdir LPM && cd LPM && cmake ../libprotobuf-mutator -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON -DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release && ninja) COPY build.sh png_fuzz_proto.proto png_proto_fuzzer_example.cc libpng_transforms_fuzzer.cc png_proto_mutator.cc $SRC/ ================================================ FILE: projects/libpng-proto/build.sh ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #!/bin/bash # build libpng using the upstream-provided build.sh. # it will also build the vanilla (non-proto) fuzz target, # but we discard it. (cd libpng/ && contrib/oss-fuzz/build.sh && rm -rf $OUT/*) # Compile png_fuzz_proto.proto; should produce two files in genfiles/: # png_fuzz_proto.pb.cc png_fuzz_proto.pb.h rm -rf genfiles && mkdir genfiles && LPM/external.protobuf/bin/protoc png_fuzz_proto.proto --cpp_out=genfiles # compile the upstream-provided vanilla fuzz target # but replace LLVMFuzzerTestOneInput with FuzzPNG so that # png_proto_fuzzer_example.cc can call FuzzPNG from its own # LLVMFuzzerTestOneInput. $CXX $CXXFLAGS -c -DLLVMFuzzerTestOneInput=FuzzPNG libpng/contrib/oss-fuzz/libpng_read_fuzzer.cc -I libpng # compile & link the rest $CXX $CXXFLAGS -DNDEBUG png_proto_fuzzer_example.cc libpng_read_fuzzer.o genfiles/png_fuzz_proto.pb.cc \ -I genfiles -I. -I libprotobuf-mutator/ -I LPM/external.protobuf/include \ -fuse-ld=lld -lz \ LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ LPM/src/libprotobuf-mutator.a \ LPM/external.protobuf/lib/lib*.a \ libpng/.libs/libpng16.a \ $LIB_FUZZING_ENGINE \ -o $OUT/png_proto_fuzzer_example # custom png proto mutator $CXX $CXXFLAGS -DNDEBUG png_proto_fuzzer_example.cc png_proto_mutator.cc libpng_read_fuzzer.o genfiles/png_fuzz_proto.pb.cc \ -I genfiles -I. -I libprotobuf-mutator/ -I LPM/external.protobuf/include \ -fuse-ld=lld -lz \ LPM/src/libfuzzer/libprotobuf-mutator-libfuzzer.a \ LPM/src/libprotobuf-mutator.a \ LPM/external.protobuf/lib/lib*.a \ libpng/.libs/libpng16.a \ $LIB_FUZZING_ENGINE \ -o $OUT/png_proto_fuzzer_example_custom_mutator echo > dummy.cc # A target, w/o protos but with a specialized custom mutator. $CXX $CXXFLAGS -c libpng/contrib/oss-fuzz/libpng_read_fuzzer.cc -I libpng $CXX $CXXFLAGS dummy.cc \ -include fuzzer-test-suite/libpng-1.2.56/png_mutator.h \ -D PNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR \ libpng_read_fuzzer.o \ -lz \ libpng/.libs/libpng16.a \ $LIB_FUZZING_ENGINE \ -o $OUT/png_custom_mutator_fuzzer_example # An experimental out-of-tree target, with a specialized custom mutator. $CXX $CXXFLAGS libpng_transforms_fuzzer.cc \ -include fuzzer-test-suite/libpng-1.2.56/png_mutator.h \ -D PNG_MUTATOR_DEFINE_LIBFUZZER_CUSTOM_MUTATOR \ -I libpng \ -lz \ libpng/.libs/libpng16.a \ $LIB_FUZZING_ENGINE \ -o $OUT/png_transforms_fuzzer ================================================ FILE: projects/libpng-proto/libpng_transforms_fuzzer.cc ================================================ #include #include #include #include #include #include "png.h" namespace { struct PngReader { png_structp png_ptr = nullptr; png_infop info_ptr = nullptr; png_infop end_info = nullptr; }; struct PngArrayStream { const uint8_t *data; size_t size; size_t pos; }; void PngArrayStreamCallback(png_structp png_ptr, png_bytep data, png_size_t size) { PngArrayStream *stream = static_cast(png_get_io_ptr(png_ptr)); if (stream->pos + size > stream->size) { memset(data, 0, size); stream->pos = size; } else { memcpy(data, &stream->data[stream->pos], size); stream->pos += size; } } static bool PngVerboseWarnings = getenv("PNG_VERBOSE_WARNINGS") != nullptr; void PngErrorHandler(png_structp png_ptr, png_const_charp error_message) { if (PngVerboseWarnings) fprintf(stderr, "%s\n", error_message); longjmp(png_jmpbuf(png_ptr), 1); } void PngWarningHandler(png_structp png_ptr, png_const_charp warning_message) { if (PngVerboseWarnings) fprintf(stderr, "%s\n", warning_message); longjmp(png_jmpbuf(png_ptr), 1); } } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const size_t kPngSignatureSize = 8; const size_t kIHDRSize = 4 + 4 + 13 + 4; const size_t kMaxImageSize = 1 << 20; const size_t kMaxHeight = 1 << 10; auto Read32 = [&](const uint8_t *p) { uint32_t res; assert(p >= data); assert(p + sizeof(res) < data + size); memcpy(&res, p, sizeof(res)); return res; }; if (size < kPngSignatureSize + kIHDRSize) return 0; if (png_sig_cmp(data, 0, kPngSignatureSize)) return 0; uint32_t width = __builtin_bswap32(Read32(data + kPngSignatureSize + 8)); uint32_t height = __builtin_bswap32(Read32(data + kPngSignatureSize + 12)); // Reject too large images because they will OOM. // Also reject images with a too large height, because large height // will cause too many mallocs. // These two heuristics are far from optimal and may cause us to lose some // coverage. But w/o them fuzzing is way too slow. if ((uint64_t)width * height > kMaxImageSize) return 0; if (height > kMaxHeight) return 0; // Find the fUZz chunk and it's contents. const size_t fUZz_chunk_size = 16; const uint8_t fUZz_signature[8] = {0, 0, 0, fUZz_chunk_size, 'f', 'U', 'Z', 'z'}; const uint8_t *fUZz_beg = std::search(data, data + size, fUZz_signature, fUZz_signature + sizeof(fUZz_signature)); if (fUZz_beg + sizeof(fUZz_signature) + fUZz_chunk_size < data + size) fUZz_beg += sizeof(fUZz_signature); else fUZz_beg = nullptr; PngReader reader; reader.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(reader.png_ptr); reader.info_ptr = png_create_info_struct(reader.png_ptr); assert(reader.info_ptr); reader.end_info = png_create_info_struct(reader.png_ptr); assert(reader.end_info); png_set_error_fn(reader.png_ptr, png_get_error_ptr(reader.png_ptr), PngErrorHandler, PngWarningHandler); PngArrayStream stream{data, size, 0}; if (setjmp(png_jmpbuf(reader.png_ptr)) == 0) { png_set_read_fn(reader.png_ptr, &stream, PngArrayStreamCallback); // Take transforms from the fUZz chunk. By default, enable all. int transforms = fUZz_beg ? Read32(fUZz_beg) : ~0; png_read_png(reader.png_ptr, reader.info_ptr, transforms, nullptr); } png_destroy_read_struct(&reader.png_ptr, &reader.info_ptr, &reader.end_info); // Run the same image through another libpng API. // There is probably some redundancy here (I don't know what I am doing!) png_image image; memset(&image, 0, sizeof(image)); image.version = PNG_IMAGE_VERSION; if (png_image_begin_read_from_memory(&image, data, size)) { const size_t kMaxBufferSize = 64 << 20; image.format = fUZz_beg ? Read32(fUZz_beg + 4) : PNG_FORMAT_RGBA; size_t image_size = PNG_IMAGE_SIZE(image); if (image_size <= kMaxBufferSize) { png_bytep buffer = new png_byte[image_size]; const size_t kColorMapSize = 256 * 4; // Do we need to take color & colormap from the fuzzed input? png_color color = {1, 2, 3}; png_uint_16 colormap[256*4] = {0}; for (size_t i = 0; i < kColorMapSize; i++) colormap[i] = i; png_image_finish_read(&image, &color, buffer, 0, colormap); delete[] buffer; } } png_image_free(&image); return 0; } extern "C" const char *__asan_default_options() { // TODO: remove this once // https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12716 // is fixed. return "detect_leaks=0"; } ================================================ FILE: projects/libpng-proto/png_fuzz_proto.proto ================================================ syntax = "proto2"; // Very simple proto description of the PNG format, // described at https://en.wikipedia.org/wiki/Portable_Network_Graphics message IHDR { required uint32 width = 1; required uint32 height = 2; required uint32 other1 = 3; required uint32 other2 = 4; // Only 1 byte used. } message PLTE { required bytes data = 1; } message IDAT { required bytes data = 1; } message iCCP { required bytes data = 2; } message OtherChunk { oneof type { uint32 known_type = 1; uint32 unknown_type = 2; } required bytes data = 3; } message PngChunk { oneof chunk { PLTE plte = 1; IDAT idat = 2; iCCP iccp = 3; OtherChunk other_chunk = 10000; } } message PngProto { required IHDR ihdr = 1; repeated PngChunk chunks = 2; } // package fuzzer_examples; ================================================ FILE: projects/libpng-proto/png_proto_fuzzer_example.cc ================================================ // Example fuzzer for PNG using protos. #include #include #include #include // for crc32 #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" #include "png_fuzz_proto.pb.h" static void WriteInt(std::stringstream &out, uint32_t x) { x = __builtin_bswap32(x); out.write((char *)&x, sizeof(x)); } static void WriteByte(std::stringstream &out, uint8_t x) { out.write((char *)&x, sizeof(x)); } static std::string Compress(const std::string &s) { std::string out(s.size() + 100, '\0'); size_t out_len = out.size(); compress((uint8_t *)&out[0], &out_len, (uint8_t *)s.data(), s.size()); out.resize(out_len); return out; } // Chunk is written as: // * 4-byte length // * 4-byte type // * the data itself // * 4-byte crc (of type and data) static void WriteChunk(std::stringstream &out, const char *type, const std::string &chunk, bool compress = false) { std::string compressed; const std::string *s = &chunk; if (compress) { compressed = Compress(chunk); s = &compressed; } uint32_t len = s->size(); uint32_t crc = crc32(crc32(0, (const unsigned char *)type, 4), (const unsigned char *)s->data(), s->size()); WriteInt(out, len); out.write(type, 4); out.write(s->data(), s->size()); WriteInt(out, crc); } std::string ProtoToPng(const PngProto &png_proto) { std::stringstream all; const unsigned char header[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}; all.write((const char*)header, sizeof(header)); std::stringstream ihdr_str; auto &ihdr = png_proto.ihdr(); // Avoid large images. // They may have interesting bugs, but OOMs are going to kill fuzzing. uint32_t w = std::min(ihdr.width(), 4096U); uint32_t h = std::min(ihdr.height(), 4096U); WriteInt(ihdr_str, w); WriteInt(ihdr_str, h); WriteInt(ihdr_str, ihdr.other1()); WriteByte(ihdr_str, ihdr.other2()); WriteChunk(all, "IHDR", ihdr_str.str()); for (size_t i = 0, n = png_proto.chunks_size(); i < n; i++) { auto &chunk = png_proto.chunks(i); if (chunk.has_plte()) { WriteChunk(all, "PLTE", chunk.plte().data()); } else if (chunk.has_idat()) { WriteChunk(all, "IDAT", chunk.idat().data(), true); } else if (chunk.has_iccp()) { std::stringstream iccp_str; iccp_str << "xyz"; // don't fuzz iCCP name field. WriteByte(iccp_str, 0); WriteByte(iccp_str, 0); auto compressed_data = Compress(chunk.iccp().data()); iccp_str.write(compressed_data.data(), compressed_data.size()); WriteChunk(all, "iCCP", iccp_str.str()); } else if (chunk.has_other_chunk()) { auto &other_chunk = chunk.other_chunk(); char type[5] = {0}; if (other_chunk.has_known_type()) { static const char * known_chunks[] = { "bKGD", "cHRM", "dSIG", "eXIf", "gAMA", "hIST", "iCCP", "iTXt", "pHYs", "sBIT", "sPLT", "sRGB", "sTER", "tEXt", "tIME", "tRNS", "zTXt", "sCAL", "pCAL", "oFFs", }; size_t known_chunks_size = sizeof(known_chunks) / sizeof(known_chunks[0]); size_t chunk_idx = other_chunk.known_type() % known_chunks_size; memcpy(type, known_chunks[chunk_idx], 4); } else if (other_chunk.has_unknown_type()) { uint32_t unknown_type_int = other_chunk.unknown_type(); memcpy(type, &unknown_type_int, 4); } else { continue; } type[4] = 0; WriteChunk(all, type, other_chunk.data()); } } WriteChunk(all, "IEND", ""); std::string res = all.str(); if (const char *dump_path = getenv("PROTO_FUZZER_DUMP_PATH")) { // With libFuzzer binary run this to generate a PNG file x.png: // PROTO_FUZZER_DUMP_PATH=x.png ./a.out proto-input std::ofstream of(dump_path); of.write(res.data(), res.size()); } return res; } // The actual fuzz target that consumes the PNG data. extern "C" int FuzzPNG(const uint8_t* data, size_t size); DEFINE_PROTO_FUZZER(const PngProto &png_proto) { auto s = ProtoToPng(png_proto); FuzzPNG((const uint8_t*)s.data(), s.size()); } ================================================ FILE: projects/libpng-proto/png_proto_mutator.cc ================================================ /* * Copyright 2020 Google Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h" #include "png_fuzz_proto.pb.h" template using FuzzMutatorCallback = std::function; template struct PngProtoCBRegistration { PngProtoCBRegistration(FuzzMutatorCallback const& _callback) { static protobuf_mutator::libfuzzer::PostProcessorRegistration reg = {_callback}; } }; /// Custom mutation: Otherchunk unknown_type -> known_type static PngProtoCBRegistration addCustomChunk = { [](OtherChunk* message, unsigned int seed) { // Mutate with a probability of roughly 1/47 // 47 has been chosen ad-hoc if (seed % 47 == 0) { // If otherChunk is unknown type, mutate // it to known type if (message->has_unknown_type()) { // This is our custom mutation // We assume (k * 47 mod N) distribute // uniformly, where // - N is total number of known // chunks defined by png proto converter // - k is a factor of seed message->set_known_type(seed); } } } }; ================================================ FILE: projects/libpng-proto/project.yaml ================================================ homepage: "http://www.libpng.org/pub/png/libpng.html" main_repo: "https://git.code.sf.net/p/libpng/code libpng-code" language: c++ primary_contact: "kcc@google.com" sanitizers: - undefined - address fuzzing_engines: - libfuzzer ================================================ FILE: projects/libprotobuf-mutator/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config cmake \ ninja-build liblzma-dev libz-dev docbook2x RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git WORKDIR libprotobuf-mutator COPY build.sh *.dict *.options $SRC/ ================================================ FILE: projects/libprotobuf-mutator/build.sh ================================================ #!/bin/bash -eu # # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp -f $SRC/*.dict $SRC/*.options $OUT/ mkdir -p build pushd build rm -rf * cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release \ -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \ -DLIB_PROTO_MUTATOR_EXAMPLES_USE_LATEST=ON \ -DLIB_PROTO_MUTATOR_FUZZER_LIBRARIES=FuzzingEngine ninja libxml2_example expat_example cp -f examples/libxml2/libxml2_example $OUT/ cp -f examples/expat/expat_example $OUT/ popd ================================================ FILE: projects/libprotobuf-mutator/expat_example.options ================================================ [libfuzzer] dict = xml.dict max_len=1024 ================================================ FILE: projects/libprotobuf-mutator/libxml2_example.options ================================================ [libfuzzer] dict = xml.dict max_len=1000 detect_leaks=0 ================================================ FILE: projects/libprotobuf-mutator/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://github.com/google/libprotobuf-mutator" language: c++ primary_contact: "vitalybuka@chromium.org" main_repo: 'https://github.com/google/libprotobuf-mutator.git' file_github_issue: True fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libprotobuf-mutator/xml.dict ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ "" "" "&a;" "<" "1.0" "ANY" "ATTLIST" "CDATA" "DOCTYPE" "EBCDIC" "ELEMENT" "EMPTY" "ENTITIES" "ENTITY" "FIXED" "ID" "IDREF" "IDREFS" "IGNORE" "IMPLIED" "INCLUDE" "ISO-8859-1" "NDATA" "NMTOKENS" "NOTATION" "PCDATA" "PUBLIC" "REQUIRED" "SYSTEM" "UCS-4" "US-ASCII" "UTF-16" "UTF-16BE" "UTF-16LE" "UTF-8" "\"http://www.w3.org/1999/xhtml\"" "\"http://www.w3.org/2000/xmlns\"" "\"http://www.w3.org/XML/1998/namespace\"" "fallback" "http://" "https://" "include" "schema" "xml" "xml:lang" "xml:space" "xmlns" "xmlns:" ================================================ FILE: projects/libproxy/project.yaml ================================================ homepage: https://libproxy.github.io/libproxy/ main_repo: https://github.com/libproxy/libproxy language: c vendor_ccs: [] primary_contact: "jan.brummer@tabos.org" auto_ccs: - "dimstar@opensuse.org" - "herrvorragend81@gmail.com" fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libpsl/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y \ make \ pkg-config \ autogen \ autopoint \ autoconf \ autoconf-archive \ automake \ libtool \ texinfo \ bison \ gettext \ gengetopt \ curl \ gperf \ wget \ python RUN git clone git://git.savannah.gnu.org/gnulib.git RUN git clone --depth=1 https://git.savannah.gnu.org/git/libunistring.git RUN git clone --depth=1 https://gitlab.com/libidn/libidn2.git RUN git clone --depth=1 https://git.savannah.gnu.org/git/libidn.git RUN wget https://github.com/unicode-org/icu/releases/download/release-59-2/icu4c-59_2-src.tgz && tar xvfz icu4c-59_2-src.tgz RUN git clone --depth=1 --recursive https://github.com/rockdaboot/libpsl.git WORKDIR libpsl COPY build.sh config.site md5sum run_tests.sh $SRC/ ================================================ FILE: projects/libpsl/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export DEPS_PATH=$SRC/deps export PKG_CONFIG_PATH=$DEPS_PATH/lib/pkgconfig export CPPFLAGS="-I$DEPS_PATH/include" export LDFLAGS="-L$DEPS_PATH/lib" export CONFIG_SITE=$SRC/config.site export GNULIB_SRCDIR=$SRC/gnulib export GNULIB_TOOL=$GNULIB_SRCDIR/gnulib-tool cd $SRC/icu/source UBSAN_OPTIONS=detect_leaks=0 \ CFLAGS="$CFLAGS -fno-sanitize=vptr" \ CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" \ CPPFLAGS="$CPPFLAGS -fno-sanitize=vptr" \ ./configure --disable-shared --enable-static --disable-extras --disable-icuio --disable-layoutex \ --disable-tests --disable-samples --with-data-packaging=static --prefix=$DEPS_PATH # ugly hack to avoid build error echo '#include ' >>i18n/digitlst.h # Hack so that upgrade to Ubuntu 20.04 works. ln -s /usr/include/locale.h /usr/include/xlocale.h make -j make install cd $SRC/libunistring ./autogen.sh ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --prefix=$DEPS_PATH make -j make install cd $SRC/libidn ./bootstrap ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --disable-doc --prefix=$DEPS_PATH make -j make install cd $SRC/libidn2 ./bootstrap ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \ ./configure --enable-static --disable-shared --disable-doc --disable-gcc-warnings --prefix=$DEPS_PATH make -j make install cd $SRC/libpsl ./autogen.sh export CXXFLAGS="$CXXFLAGS -L$DEPS_PATH/lib/" if test $SANITIZER = "undefined"; then # libicu doesn't work with -fsanitizer=undefined, see projects/icu/project.yaml builds="libidn2 libidn none" else builds="libicu libidn2 libidn none" fi for build in $builds; do unset LIBS if test $build = "none"; then BUILD_FLAGS="--disable-runtime --disable-builtin" # convert PSL to NFC cp -p list/public_suffix_list.dat list/public_suffix_list.dat.org LC_ALL=C.UTF-8 python3 -c $'import unicodedata\nimport sys\nfor line in sys.stdin:\n sys.stdout.write(unicodedata.normalize("NFC", line))' list/public_suffix_list.dat else BUILD_FLAGS="--enable-runtime=$build --enable-builtin=$build" if test $build = "libicu"; then export LIBS="-lstdc++" fi fi # older m4 iconv detection has memleaks, so switch leak detection off ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \ ./configure --enable-fuzzing --enable-static --disable-shared --disable-gtk-doc $BUILD_FLAGS --prefix=$DEPS_PATH make clean make -j make -j check make -C fuzz oss-fuzz find fuzz -name '*_fuzzer' -exec cp -v '{}' $OUT ';' done cd fuzz find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' for dir in *_fuzzer.in; do fuzzer=$(basename $dir .in) zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/" done ================================================ FILE: projects/libpsl/config.site ================================================ if test "$cache_file" = /dev/null; then hash=`echo $LIBS $CPPFLAGS CXXFLAGS $CFLAGS $LDFLAGS $build_alias $host_alias $target_alias \ | $SRC/md5sum` cache_file=$SRC/config.cache.$CC.$hash fi ================================================ FILE: projects/libpsl/md5sum ================================================ #!/usr/local/bin/python3 # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import hashlib BUFSIZE = 4096 if __name__ == "__main__": sys.stdin = sys.stdin.detach() m = hashlib.md5() while True: data = sys.stdin.read(BUFSIZE) if not data: break m.update(data) print(m.hexdigest()) ================================================ FILE: projects/libpsl/project.yaml ================================================ homepage: "https://github.com/rockdaboot/libpsl" language: c++ primary_contact: "rockdaboot@gmail.com" auto_ccs: - "tim.ruehsen@gmx.de" main_repo: 'https://github.com/rockdaboot/libpsl.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libpsl/run_tests.sh ================================================ #!/bin/bash -eux # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### make check ================================================ FILE: projects/libra/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # google oss-fuzz stuff FROM gcr.io/oss-fuzz-base/base-builder-rust:ubuntu-24-04 # install other tools we might need RUN apt-get update && apt-get install -y cmake curl # get libra RUN git clone --depth 1 https://github.com/libra/libra $SRC/libra WORKDIR $SRC/libra # building script for fuzzers COPY build.sh $SRC/ ================================================ FILE: projects/libra/build.sh ================================================ #!/bin/bash -eux # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Note: This project creates Rust fuzz targets exclusively # recipe: # ------- # 1. we list all the fuzzers and save to a file fuzzer_list # 2. we build the corpus for each fuzzer # 3. we build all the fuzzers # reset flags of OSS-Fuzz export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" export CXXFLAGS_EXTRA="-stdlib=libc++" export CXXFLAGS="$CFLAGS $CXXFLAGS_EXTRA" # correct workdir cd $SRC/libra/testsuite/libra-fuzzer # fetch all dependencies (needed for patching rocksdb) cargo fetch # patch rocksdb to not link libc++ statically sed -i "s/link_cpp(&mut build)/build.cpp_link_stdlib(None)/" \ /rust/git/checkouts/rust-rocksdb-a9a28e74c6ead8ef/72e45c3/librocksdb_sys/build.rs # so now we need to link libc++ at the end export RUSTFLAGS="-C link-arg=-L/usr/local/lib -C link-arg=-lc++" # 1. list fuzzers cargo run --bin libra-fuzzer list --no-desc > fuzzer_list # 2. build corpus and move to $OUT cat fuzzer_list | while read -r line do cargo run --bin libra-fuzzer generate -n 128 $line zip -r $OUT/"$line"_seed_corpus.zip fuzz/corpus/$line rm -r fuzz/corpus/$line done # rust libfuzzer flags (https://github.com/rust-fuzz/libfuzzer/blob/master/build.rs#L12) export CUSTOM_LIBFUZZER_PATH="$LIB_FUZZING_ENGINE_DEPRECATED" export CUSTOM_LIBFUZZER_STD_CXX=c++ # export CUSTOM_LIBFUZZER_STD_CXX=none # export fuzzing flags RUSTFLAGS="$RUSTFLAGS --cfg fuzzing" # used to change code logic RUSTFLAGS="$RUSTFLAGS -Cdebug-assertions" # to get debug_assert in rust RUSTFLAGS="$RUSTFLAGS -Zsanitizer=address" # address sanitizer (ASAN) RUSTFLAGS="$RUSTFLAGS -Cdebuginfo=1" RUSTFLAGS="$RUSTFLAGS -Cforce-frame-pointers" RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-level=4" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-trace-compares" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-inline-8bit-counters" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-trace-geps" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-prune-blocks=0" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-pc-table" RUSTFLAGS="$RUSTFLAGS -Clink-dead-code" RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-stack-depth" RUSTFLAGS="$RUSTFLAGS -Ccodegen-units=1" export RUSTFLAGS # 3. build all the fuzzers! cat fuzzer_list | while read -r line do # build export SINGLE_FUZZ_TARGET="$line" cargo build --manifest-path fuzz/Cargo.toml --bin fuzzer_builder --release --target x86_64-unknown-linux-gnu # move fuzzer to $OUT mv $SRC/libra/target/x86_64-unknown-linux-gnu/release/fuzzer_builder $OUT/$SINGLE_FUZZ_TARGET done ================================================ FILE: projects/libra/project.yaml ================================================ base_os_version: ubuntu-24-04 disabled: true fuzzing_engines: - libfuzzer homepage: https://github.com/libra/libra language: rust main_repo: https://github.com/libra/libra sanitizers: - address vendor_ccs: - david@adalogics.com ================================================ FILE: projects/libraw/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config zlib1g-dev RUN git clone --depth 1 https://github.com/libraw/libraw WORKDIR libraw ADD http://oss-fuzz-corpus.storage.googleapis.com/libraw/libraw_cr2_fuzzer_seed_corpus.zip $SRC/ ADD http://oss-fuzz-corpus.storage.googleapis.com/libraw/libraw_nef_fuzzer_seed_corpus.zip $SRC/ ADD http://oss-fuzz-corpus.storage.googleapis.com/libraw/libraw_raf_fuzzer_seed_corpus.zip $SRC/ COPY build.sh libraw_fuzzer.cc $SRC/ ================================================ FILE: projects/libraw/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # copy corpuses cp $SRC/libraw_cr2_fuzzer_seed_corpus.zip \ $SRC/libraw_nef_fuzzer_seed_corpus.zip \ $SRC/libraw_raf_fuzzer_seed_corpus.zip \ $OUT/ # build project autoreconf --install ./configure --disable-examples make # build fuzzers export CXXFLAGS="${CXXFLAGS} -std=c++17" $CXX $CXXFLAGS -Ilibraw \ $SRC/libraw_fuzzer.cc -o $OUT/libraw_fuzzer \ $LIB_FUZZING_ENGINE -lz lib/.libs/libraw.a $CXX $CXXFLAGS -Ilibraw \ $SRC/libraw_fuzzer.cc -o $OUT/libraw_cr2_fuzzer \ $LIB_FUZZING_ENGINE -lz lib/.libs/libraw.a $CXX $CXXFLAGS -Ilibraw \ $SRC/libraw_fuzzer.cc -o $OUT/libraw_nef_fuzzer \ $LIB_FUZZING_ENGINE -lz lib/.libs/libraw.a $CXX $CXXFLAGS -Ilibraw \ $SRC/libraw_fuzzer.cc -o $OUT/libraw_raf_fuzzer \ $LIB_FUZZING_ENGINE -lz lib/.libs/libraw.a ================================================ FILE: projects/libraw/libraw_fuzzer.cc ================================================ /* Copyright 2020 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include enum InterpolationOptions { Linear = 0, Vng = 1, Ppg = 2, Ahd = 3, Dcb = 4, Dht = 11, AhdModified = 12 }; static const InterpolationOptions options[] = {Linear, Vng, Ppg, Ahd, Dcb, Dht, AhdModified}; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Input less than 15mb if (size > 15000000) { return 0; } FuzzedDataProvider fdp(data, size); LibRaw lib_raw; for(int i =0; i < 4; i++) lib_raw.output_params_ptr()->aber[i] = fdp.ConsumeFloatingPoint(); for(int i =0; i < 4; i++) lib_raw.output_params_ptr()->user_mul[i] = fdp.ConsumeFloatingPoint(); for(int i =0; i < 2; i++) lib_raw.output_params_ptr()->gamm[i] = fdp.ConsumeFloatingPoint(); lib_raw.output_params_ptr()->bright = fdp.ConsumeFloatingPoint(); lib_raw.output_params_ptr()->threshold = fdp.ConsumeFloatingPoint(); lib_raw.output_params_ptr()->use_auto_wb = fdp.ConsumeIntegral(); lib_raw.output_params_ptr()->output_color = fdp.ConsumeIntegralInRange(0, 6); lib_raw.output_params_ptr()->user_flip = fdp.ConsumeIntegralInRange(0, 7); lib_raw.output_params_ptr()->user_black = fdp.ConsumeIntegral(); lib_raw.output_params_ptr()->user_sat = fdp.ConsumeIntegral(); lib_raw.output_params_ptr()->auto_bright_thr = fdp.ConsumeFloatingPoint(); lib_raw.output_params_ptr()->adjust_maximum_thr = fdp.ConsumeFloatingPointInRange(0.f, 1.f); lib_raw.output_params_ptr()->fbdd_noiserd = fdp.ConsumeIntegralInRange(0, 5); std::vector payload = fdp.ConsumeRemainingBytes(); int result = lib_raw.open_buffer(payload.data(), payload.size()); if (result != LIBRAW_SUCCESS) { return 0; } result = lib_raw.unpack(); if (result != LIBRAW_SUCCESS) { return 0; } result = lib_raw.unpack_thumb(); if (result != LIBRAW_SUCCESS) { return 0; } result = lib_raw.raw2image(); if (result != LIBRAW_SUCCESS) { return 0; } lib_raw.free_image(); for (int i = 0; i < sizeof(options)/sizeof(*options); i++) { lib_raw.output_params_ptr()->user_qual = static_cast(options[i]); result = lib_raw.dcraw_process(); if (result != LIBRAW_SUCCESS) { return 0; } } return 0; } ================================================ FILE: projects/libraw/project.yaml ================================================ homepage: "https://www.libraw.org/" language: c++ primary_contact: "jesteele@google.com" auto_ccs: - "nchusid@google.com" - "pinheirojamie@google.com" - "info@libraw.org" sanitizers: - address - memory - undefined main_repo: 'https://github.com/libraw/libraw' file_github_issue: true fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/librawspeed/Dockerfile ================================================ # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y apt-transport-https ca-certificates gnupg software-properties-common wget && \ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \ apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' && \ apt-get update && apt-get install -y cmake make RUN git clone --depth 1 https://github.com/darktable-org/rawspeed.git librawspeed WORKDIR librawspeed COPY build.sh $SRC/ ================================================ FILE: projects/librawspeed/build.sh ================================================ #!/bin/bash -eu # Copyright 2017 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export CFLAGS="$CFLAGS -Wno-error=nan-infinity-disabled" export CXXFLAGS="$CXXFLAGS -Wno-error=nan-infinity-disabled" $SRC/librawspeed/.ci/oss-fuzz.sh ================================================ FILE: projects/librawspeed/project.yaml ================================================ homepage: "https://github.com/darktable-org/rawspeed" language: c++ primary_contact: "lebedev.ri@gmail.com" sanitizers: - address - undefined - memory main_repo: 'https://github.com/darktable-org/rawspeed.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/librdkafka/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake flex bison zlib1g-dev \ libcurlpp-dev libcurl4-openssl-dev RUN git clone https://github.com/edenhill/librdkafka WORKDIR $SRC COPY build.sh $SRC/ ================================================ FILE: projects/librdkafka/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd librdkafka mkdir build cd build cmake -DRDKAFKA_BUILD_STATIC=ON -DRDKAFKA_BUILD_EXAMPLES=OFF -DHAVE_REGEX=OFF ../ make $CC -g -fPIC $CFLAGS -I$SRC/librdkafka/src -Igenerated/dummy \ -c $SRC/librdkafka/tests/fuzzers/fuzz_regex.c -o fuzz_regex.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -rdynamic fuzz_regex.o -o fuzzer \ ./src-cpp/librdkafka++.a ./src/librdkafka.a -lm -lssl -lcrypto \ -lcrypto -lz -ldl -lpthread -lrt cp fuzzer $OUT/fuzz_regex ================================================ FILE: projects/librdkafka/project.yaml ================================================ homepage: "https://github.com/edenhill/librdkafka" primary_contact: "magnus@edenhill.se" language: c++ auto_ccs: - "david@adalogics.com" main_repo: 'https://github.com/edenhill/librdkafka' ================================================ FILE: projects/libredwg/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf libtool texinfo RUN git clone https://github.com/LibreDWG/libredwg WORKDIR $SRC/libredwg COPY run_tests.sh build.sh $SRC/ COPY llvmfuzz.options $SRC/ ================================================ FILE: projects/libredwg/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Harden build in introspector mode if [[ "$SANITIZER" == introspector ]]; then export CFLAGS="${CFLAGS} -Wno-error" export CXXFLAGS="${CXXFLAGS} -Wno-error" else export CFLAGS="${CFLAGS} -Wno-default-const-init-field-unsafe -Wno-uninitialized-const-pointer" export CXXFLAGS="${CXXFLAGS} -Wno-default-const-init-field-unsafe -Wno-uninitialized-const-pointer" fi sh ./autogen.sh # enable-release to skip unstable preR13. bindings are not fuzzed. ./configure --disable-shared --disable-bindings --enable-release make $CC $CFLAGS src/.libs/libredwg.a -I./include -I./src -c examples/llvmfuzz.c $CXX $CXXFLAGS $LIB_FUZZING_ENGINE llvmfuzz.o src/.libs/libredwg.a \ -o $OUT/llvmfuzz cp $SRC/llvmfuzz.options $OUT/llvmfuzz.options # Build unit test make check-prep -C test/unit-testing/ -j$(nproc) ================================================ FILE: projects/libredwg/llvmfuzz.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/libredwg/project.yaml ================================================ homepage: "https://github.com/LibreDWG/libredwg" primary_contact: "reini.urban@gmail.com" language: c auto_ccs : - "david@adalogics.com" fuzzing_engines: - libfuzzer - honggfuzz main_repo: 'https://github.com/LibreDWG/libredwg' ================================================ FILE: projects/libredwg/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./unit_testing_all.sh ================================================ FILE: projects/libreoffice/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # enable source repos RUN sed -i -e '/^#\s*deb-src.*\smain\s\+restricted/s/^#//' /etc/apt/sources.list #build requirements RUN apt-get update && apt-get build-dep -y libreoffice && \ apt-get install -y lockfile-progs wget yasm locales && \ locale-gen en_US.UTF-8 #until base image contains a sufficiently new meson > = 0.55.0 RUN apt-get update && apt-get install -y python3-pip && \ pip3 install meson ninja #clone source RUN git clone --depth 1 https://git.libreoffice.org/core libreoffice WORKDIR libreoffice RUN ./bin/oss-fuzz-setup.sh COPY build.sh $SRC/ ================================================ FILE: projects/libreoffice/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ $SRC/libreoffice/bin/oss-fuzz-build.sh ================================================ FILE: projects/libreoffice/project.yaml ================================================ homepage: "https://www.libreoffice.org/" language: c++ primary_contact: "caolanm@gmail.com" sanitizers: - address - memory: experimental: True - undefined fuzzing_engines: # see https://github.com/google/oss-fuzz/issues/6233 for missing afl - libfuzzer - honggfuzz builds_per_day: 2 auto_ccs: - "damjan.jov@gmail.com" - "noelgrandin@gmail.com" - "sbergman@redhat.com" main_repo: 'https://git.libreoffice.org/core' ================================================ FILE: projects/libressl/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder@sha256:19782f7fe8092843368894dbc471ce9b30dd6a2813946071a36e8b05f5b1e27e # ! Project pinned after a clang update and an afl link error. Log: https://oss-fuzz-gcb-logs.storage.googleapis.com/log-db180642-1ff0-4223-91e6-3bf060adb174.txt RUN apt-get update && apt-get install -y make cmake wget autoconf automake libtool bison flex texinfo lzip RUN git clone --depth 1 https://github.com/libressl/portable.git libressl RUN git clone --depth 1 https://github.com/libressl/fuzz.git libressl.fuzzers RUN wget https://archives.boost.io/release/1.84.0/source/boost_1_84_0.tar.bz2 WORKDIR libressl RUN ./update.sh COPY build.sh *.options $SRC/ ================================================ FILE: projects/libressl/bignum.options ================================================ [libfuzzer] max_len = 2048 ================================================ FILE: projects/libressl/build.sh ================================================ #!/bin/bash -eux # # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Install Boost headers cd $SRC/ tar jxf boost_1_84_0.tar.bz2 cd boost_1_84_0/ CFLAGS="" CXXFLAGS="" ./bootstrap.sh CFLAGS="" CXXFLAGS="" ./b2 headers cp -R boost/ /usr/include/ mkdir -p $WORK/libressl cd $WORK/libressl CMAKE_DEFINES="" if [[ $CFLAGS = *sanitize=memory* ]] then CMAKE_DEFINES+=" -DOPENSSL_NO_ASM=1" fi cmake -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX \ -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ $CMAKE_DEFINES $SRC/libressl/ make -j$(nproc) LIBRESSL_FUZZERS=$SRC/libressl.fuzzers fuzzerFiles=$(find $LIBRESSL_FUZZERS -name "*.c" | egrep -v 'driver.c|test-corpus.c') find . -name "*.a" $CC -c $CFLAGS \ -o $WORK/driver.o \ $LIBRESSL_FUZZERS/driver.c \ -I $SRC/libressl/include -I $SRC/libressl for F in $fuzzerFiles; do fuzzerName=$(basename $F .c) echo "Building fuzzer $fuzzerName" $CC -c $CFLAGS \ -o $WORK/${fuzzerName}.o \ $F -I $SRC/libressl/include -I $SRC/libressl $CXX $CXXFLAGS \ -o $OUT/${fuzzerName} -fsanitize-recover=address \ $WORK/driver.o $WORK/${fuzzerName}.o ./ssl/libssl.a ./crypto/libcrypto.a ./tls/libtls.a $LIB_FUZZING_ENGINE if [ -d "$LIBRESSL_FUZZERS/corpora/${fuzzerName}/" ]; then zip -j $OUT/${fuzzerName}_seed_corpus.zip $LIBRESSL_FUZZERS/corpora/${fuzzerName}/* fi done cp $SRC/*.options $OUT/ cp $LIBRESSL_FUZZERS/oids.txt $OUT/asn1.dict cp $LIBRESSL_FUZZERS/oids.txt $OUT/x509.dict ================================================ FILE: projects/libressl/project.yaml ================================================ homepage: "https://www.libressl.org/" language: c++ primary_contact: "busterb@gmail.com" auto_ccs: - "beck@obtuse.com" - "theorbuehler@gmail.com" - "joel.sing@gmail.com" - "kinichiro.inoguchi@gmail.com" - "ted.unangst@gmail.com" - "miwaxe@gmail.com" - "guidovranken@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/libressl/portable.git' ================================================ FILE: projects/librosa/project.yaml ================================================ homepage: "https://librosa.org/doc/latest/index.html" language: python primary_contact: "brian.mcfee@nyu.edu" auto_ccs: - "ennamarie19@gmail.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined main_repo: "https://github.com/librosa/librosa.git" ================================================ FILE: projects/librsvg/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder-rust ENV RUSTUP_TOOLCHAIN=nightly-2025-09-15 RUN apt-get update && \ apt-get upgrade -y && \ apt-get install --no-install-recommends -y \ gperf \ pkg-config && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* RUN pip3 install --disable-pip-version-check --no-cache-dir \ pip==25.1.1 RUN pip3 install --disable-pip-version-check --no-cache-dir \ meson==1.8.2 \ ninja==1.11.1.4 \ packaging==25.0 # We have to compile various dependencies because the distro does not have recent enough # versions of packages like Pango. Manual compilation also makes it easier to use static linking: # https://google.github.io/oss-fuzz/further-reading/fuzzer-environment/ RUN git clone --depth=1 --no-tags https://gitlab.gnome.org/GNOME/librsvg.git RUN git clone --depth=1 --branch=2.85.2 https://gitlab.gnome.org/GNOME/glib.git RUN git clone --depth=1 --branch=VER-2-13-3 https://gitlab.freedesktop.org/freetype/freetype.git RUN git clone --depth=1 --branch=v2.14.5 https://gitlab.gnome.org/GNOME/libxml2.git RUN git clone --depth=1 --branch=2.17.1 https://gitlab.freedesktop.org/fontconfig/fontconfig.git RUN git clone --depth=1 --branch=1.18.4 https://gitlab.freedesktop.org/cairo/cairo.git RUN git clone --depth=1 --branch=11.3.2 https://github.com/harfbuzz/harfbuzz.git RUN git clone --depth=1 --branch=1.56.4 https://gitlab.gnome.org/GNOME/pango.git RUN git clone --depth=1 --no-tags https://github.com/google/fuzzing.git COPY build.sh *.options "$SRC/" WORKDIR "$SRC/librsvg" ================================================ FILE: projects/librsvg/build.sh ================================================ #!/bin/bash # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ set -o errexit set -o pipefail set -o nounset PREFIX="/usr" # The OSS-Fuzz 'compile' script automatically adds instrumentation flags to the CFLAGS and CXXFLAGS # environment variables. These flags cause build errors with some of the third-party dependencies, # so we save them for restoration later. CFLAGS_SAVE="$CFLAGS" CXXFLAGS_SAVE="$CXXFLAGS" # Set the non-instrumentation flags manually. -O1 is particularly important for avoiding spurious # timeouts caused by unoptimized dependencies. export CFLAGS="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" export CXXFLAGS="$CFLAGS $CXXFLAGS_EXTRA" # Compile and install GLib cd "$SRC/glib" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir -Dman-pages=disabled -Dtests=false -Dsysprof=disabled ninja -C builddir ninja -C builddir install # Compile and install FreeType cd "$SRC/freetype" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir ninja -C builddir ninja -C builddir install # Compile and install libxml2 cd "$SRC/libxml2" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir ninja -C builddir ninja -C builddir install # Compile and install Fontconfig cd "$SRC/fontconfig" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir -Dtests=disabled -Dtools=disabled ninja -C builddir ninja -C builddir install # Compile and install Cairo cd "$SRC/cairo" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir -Dpixman:tests=disabled -Dtests=disabled ninja -C builddir ninja -C builddir install # Compile and install HarfBuzz cd "$SRC/harfbuzz" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir -Ddocs=disabled -Dtests=disabled ninja -C builddir ninja -C builddir install # Compile and install Pango cd "$SRC/pango" meson setup --prefix="$PREFIX" --buildtype=plain --default-library=static builddir -Dbuild-examples=false -Dbuild-testsuite=false ninja -C builddir ninja -C builddir install # Restore the compiler flag environment variables export CFLAGS="${CFLAGS_SAVE}" export CXXFLAGS="${CXXFLAGS_SAVE}" # Compile and copy the fuzz target(s) cd "$SRC/librsvg" cargo fuzz build -O cp target/x86_64-unknown-linux-gnu/release/render_document "$OUT/" # Copy options files for fuzz targets cp "$SRC"/*.options "$OUT/" # Create dictionary files for fuzz targets cat "$SRC/fuzzing/dictionaries/"{css,svg,xml}.dict > "$OUT/render_document.dict" # Build a seed corpus consisting of all the SVGs from the librsvg repo CORPUS_DIR="$WORK/corpus" mkdir -p "$CORPUS_DIR" FILES=$(find "$SRC/librsvg" -type f -iname "*.svg") for file in $FILES; do cp "$file" "$CORPUS_DIR/$(md5sum "$file" | cut -f 1 -d ' ').svg" done zip -r "$OUT/render_document_seed_corpus.zip" "$CORPUS_DIR"/* ================================================ FILE: projects/librsvg/project.yaml ================================================ homepage: "https://gitlab.gnome.org/GNOME/librsvg/" language: rust primary_contact: "federico.mena@gmail.com" auto_ccs: - "correctmost@gmail.com" main_repo: "https://gitlab.gnome.org/GNOME/librsvg.git" sanitizers: - address fuzzing_engines: - libfuzzer coverage_extra_args: > -ignore-filename-regex=rust/.* -ignore-filename-regex=rustc/.* ================================================ FILE: projects/librsvg/render_document.options ================================================ # Suppress spurious leak reports: # https://gnome.pages.gitlab.gnome.org/librsvg/devel-docs/memory_leaks.html [asan] detect_leaks = 0 [libfuzzer] detect_leaks = 0 ================================================ FILE: projects/libsass/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/sass/libsass.git libsass WORKDIR $SRC COPY build.sh $SRC/ COPY data_context_fuzzer.cc $SRC/ ================================================ FILE: projects/libsass/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd libsass export BUILD='static' make -j$(nproc) popd INSTALL_DIR="$SRC/libsass" $CXX $CXXFLAGS -I${INSTALL_DIR}/include data_context_fuzzer.cc \ $LIB_FUZZING_ENGINE -o $OUT/data_context_fuzzer ${INSTALL_DIR}/lib/libsass.a ================================================ FILE: projects/libsass/data_context_fuzzer.cc ================================================ #include "sass.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { char* sass_data = (char*) malloc(sizeof(char) * size + 1); if (sass_data == NULL) return 0; memcpy(sass_data, data, size); sass_data[size] = '\0'; struct Sass_Data_Context* ctx = sass_make_data_context(sass_data); if (ctx == NULL) { free(sass_data); return 0; } struct Sass_Options* options = sass_make_options(); if (options == NULL) { sass_delete_data_context(ctx); return 0; } sass_option_set_output_style(options, SASS_STYLE_NESTED); sass_option_set_precision(options, 5); sass_data_context_set_options(ctx, options); sass_compile_data_context(ctx); sass_delete_data_context(ctx); sass_delete_options(options); return 0; } ================================================ FILE: projects/libsass/project.yaml ================================================ homepage: "http://libsass.org/" language: c++ primary_contact: "xzyfer@gmail.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined labels: data_context_fuzzer: - sundew main_repo: 'https://github.com/sass/libsass.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libsndfile/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/libsndfile/libsndfile.git /src/libsndfile WORKDIR $SRC/libsndfile COPY build.sh $SRC/ ================================================ FILE: projects/libsndfile/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. apt-get update ./ossfuzz/ossfuzz.sh # To make CIFuzz fast, see here for details: https://github.com/libsndfile/libsndfile/pull/796 for fuzzer in sndfile_alt_fuzzer sndfile_fuzzer; do echo "[libfuzzer]" > ${OUT}/${fuzzer}.options echo "close_fd_mask = 3" >> ${OUT}/${fuzzer}.options done ================================================ FILE: projects/libsndfile/project.yaml ================================================ homepage: "https://github.com/libsndfile/libsndfile" primary_contact: "evpobr@gmail.com" language: c auto_ccs: - "cmeister2@gmail.com" - "erikd@mega-nerd.com" sanitizers: - address - undefined - memory coverage_extra_args: -ignore-filename-regex=/usr/lib/jvm/.* main_repo: 'https://github.com/libsndfile/libsndfile.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libsodium/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make RUN git clone --depth 1 https://github.com/jedisct1/libsodium.git --branch stable libsodium WORKDIR libsodium COPY run_tests.sh build.sh *.cc *.h $SRC/ ================================================ FILE: projects/libsodium/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project ./configure --enable-static LDFLAGS="$CXXFLAGS" make -j$(nproc) all # build fuzzers for f in $SRC/*_fuzzer.cc; do fuzzer=$(basename "$f" _fuzzer.cc) $CXX $CXXFLAGS -std=c++11 -I"$SRC/libsodium/src/libsodium/include" \ "$f" -o "$OUT/${fuzzer}_fuzzer" \ "$SRC/libsodium/src/libsodium/.libs/libsodium.a" $LIB_FUZZING_ENGINE done ================================================ FILE: projects/libsodium/fake_random.h ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef FAKE_RANDOM_H_ #define FAKE_RANDOM_H_ #include #include #include #include #include static const unsigned char * SEED_DATA; static size_t SEED_SIZE; static const char * fake_implementation_name(void) { return "fake_random"; } static void fake_random_buffer(void * const buf, const size_t size) { static unsigned char seed[randombytes_SEEDBYTES]; memset(seed, '0', randombytes_SEEDBYTES); size_t boundary = std::min((size_t) randombytes_SEEDBYTES, SEED_SIZE); memcpy(&seed, SEED_DATA, boundary); randombytes_buf_deterministic(buf, size, seed); } struct randombytes_implementation fake_random = { .implementation_name = fake_implementation_name, .random = NULL, .stir = NULL, .uniform = NULL, .buf = fake_random_buffer, .close = NULL }; void setup_fake_random(const unsigned char * seed, const size_t seed_size) { SEED_DATA = seed; SEED_SIZE = seed_size; int fake_random_set = randombytes_set_implementation(&fake_random); assert(fake_random_set == 0); assert(strcmp(randombytes_implementation_name(), "fake_random") == 0); int initialized = sodium_init(); assert(initialized >= 0); } #endif // FAKE_RANDOM_H_ ================================================ FILE: projects/libsodium/project.yaml ================================================ homepage: "https://libsodium.org" language: c++ primary_contact: "ossfuzzz@gmail.com" auto_ccs: - "chriswwolfe@gmail.com" architectures: - x86_64 main_repo: 'https://github.com/jedisct1/libsodium.git' ================================================ FILE: projects/libsodium/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ################################################################################ cd $SRC/libsodium ASAN_OPTIONS=detect_leaks=0 make check ================================================ FILE: projects/libsodium/secret_key_auth_fuzzer.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "fake_random.h" extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { int initialized = sodium_init(); assert(initialized >= 0); setup_fake_random(data, size); unsigned char key[crypto_auth_KEYBYTES]; unsigned char mac[crypto_auth_BYTES]; // this uses a deterministic generator crypto_auth_keygen(key); crypto_auth(mac, data, size, key); int err = crypto_auth_verify(mac, data, size, key); assert(err == 0); return 0; } ================================================ FILE: projects/libsodium/secretbox_easy_fuzzer.cc ================================================ // Copyright 2018 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "fake_random.h" extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { int initialized = sodium_init(); assert(initialized >= 0); setup_fake_random(data, size); unsigned char key[crypto_secretbox_KEYBYTES]; unsigned char nonce[crypto_secretbox_NONCEBYTES]; // these use a deterministic generator crypto_secretbox_keygen(key); randombytes_buf(nonce, sizeof nonce); size_t ciphertext_len = crypto_secretbox_MACBYTES + size; unsigned char *ciphertext = (unsigned char *) malloc(ciphertext_len); crypto_secretbox_easy(ciphertext, data, size, nonce, key); unsigned char *decrypted = (unsigned char *) malloc(size); int err = crypto_secretbox_open_easy(decrypted, ciphertext, ciphertext_len, nonce, key); assert(err == 0); free((void *) ciphertext); free((void *) decrypted); return 0; } ================================================ FILE: projects/libsoup/Dockerfile ================================================ # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y python3-pip ninja-build libbrotli-dev libkrb5-dev libnghttp2-dev libpsl-dev libidn2-dev libsqlite3-dev RUN pip3 install --root-user-action=ignore --break-system-packages meson # version in 20.04 is too old. RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib.git --branch=glib-2-82 && \ meson setup _build glib --prefix=/usr -Ddefault_library=static -Dtests=false && \ meson install -C _build && \ rm -rf glib _build RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libsoup.git && sed -i -e "s/version : glib_required_version/version : glib_required_version, static: true/" -e "s/subdir('examples')//" libsoup/meson.build WORKDIR libsoup COPY build.sh $SRC/ ================================================ FILE: projects/libsoup/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ MESON_SANITIZER_ARG= if [ "$SANITIZER" = "address" ] || [ "$SANITIZER" = "undefined" ]; then MESON_SANITIZER_ARG="-Db_sanitize=$SANITIZER" fi meson setup "$WORK" --wipe --buildtype=debug -Db_lundef=false -Dtls_check=false -Dsysprof=disabled -Dfuzzing=enabled -Dprefer_static=true -Ddefault_library=static -Dintrospection=disabled -Ddocs=disabled -Dtests=false $MESON_SANITIZER_ARG meson compile -C "$WORK" find "$WORK/fuzzing" -perm /a+x -type f -exec cp {} "$OUT" \; find "$SRC/libsoup/fuzzing" -name '*.dict' -exec cp {} "$OUT" \; ================================================ FILE: projects/libsoup/project.yaml ================================================ base_os_version: ubuntu-24-04 homepage: "https://libsoup.gnome.org" language: c++ primary_contact: "tngpng@gmail.com" auto_ccs: - "pgriffis@igalia.com" - "mcatanzaro@redhat.com" - "philip.withnall@gmail.com" sanitizers: - address - undefined fuzzing_engines: - libfuzzer - afl # FIXME: honggfuzz fails and centipede hangs main_repo: 'https://gitlab.gnome.org/GNOME/libsoup.git' ================================================ FILE: projects/libspdm/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder #ENV http_proxy 'http://proxy.example.com:80/' #ENV https_proxy 'https://proxy.example.com:80/' RUN apt-get update && apt-get install -y make autoconf automake libtool #RUN git config --global http.proxy http://proxy.example.com:80/ #RUN git config --global https.proxy https://proxy.example.com:80/ RUN git clone --depth 1 https://github.com/DMTF/libspdm.git libspdm && cd libspdm && git submodule update --init # or use other version control COPY run_tests.sh build.sh $SRC/ WORKDIR $SRC/libspdm ================================================ FILE: projects/libspdm/build.sh ================================================ #!/bin/bash -eu # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project mkdir build pushd build cmake -DARCH=x64 -DTOOLCHAIN=LIBFUZZER -DTARGET=Release -DCRYPTO=mbedtls -DGCOV=ON .. make copy_sample_key -j$(nproc) make -j$(nproc) cp -r ./bin/* $OUT popd # build unit testing that requires different TOOLCHAIN # Unset CFLAGS that incompatible with unit testing build unset CFLAGS mkdir build-test pushd build-test cmake -DARCH=x64 -DTOOLCHAIN="CLANG" -DTARGET=Release -DCRYPTO=mbedtls .. make -j$(nproc) popd # Prepare sample key and unit testing binary mkdir $SRC/unit_testing cp -r $SRC/libspdm/unit_test/sample_key/* $SRC/unit_testing/ cp $SRC/libspdm/build-test/bin/* $SRC/unit_testing/ ================================================ FILE: projects/libspdm/project.yaml ================================================ homepage: "https://github.com/DMTF/libspdm" language: c primary_contact: "zhiqiang.zhao@intel.com" auto_ccs: - "jiewen.yao@intel.com" - "wenxing.hou@intel.com" - "hanx.xiao@intel.com" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: "https://github.com/DMTF/libspdm.git" ================================================ FILE: projects/libspdm/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/unit_testing # Run all unit testing (excluding failing one ./test_crypt && ./test_spdm_common && ./test_spdm_crypt && \ ./test_spdm_requester && ./test_spdm_responder && ./test_spdm_secured_message # Failing unit testing for reference # ./test_spdm_fips && ./test_spdm_sample ================================================ FILE: projects/libspectre/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y pkg-config make automake libtool wget RUN git clone --depth 1 https://gitlab.freedesktop.org/libspectre/libspectre.git RUN wget -O $SRC/libspectre/ghostscript-9.53.3.tar.gz https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs9533/ghostscript-9.53.3.tar.gz RUN tar xvzf $SRC/libspectre/ghostscript-9.53.3.tar.gz --directory $SRC/libspectre/ RUN mv $SRC/libspectre/ghostscript-9.53.3 $SRC/libspectre/ghostscript WORKDIR $SRC/libspectre/ COPY build.sh $SRC/ ================================================ FILE: projects/libspectre/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project $SRC/libspectre/test/ossfuzz.sh ================================================ FILE: projects/libspectre/project.yaml ================================================ homepage: "https://www.freedesktop.org/wiki/Software/libspectre/" language: c++ primary_contact: "tsdgeos@gmail.com" auto_ccs: - "randy440088@gmail.com" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory main_repo: 'https://gitlab.freedesktop.org/libspectre/libspectre.git' ================================================ FILE: projects/libspng/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && \ apt-get install -y wget tar cmake RUN git clone --depth 1 https://github.com/randy408/libspng.git RUN git clone --depth 1 https://github.com/google/fuzzer-test-suite RUN git clone https://github.com/madler/zlib $SRC/zlib WORKDIR libspng COPY build.sh $SRC/ ================================================ FILE: projects/libspng/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project $SRC/libspng/tests/ossfuzz.sh ================================================ FILE: projects/libspng/project.yaml ================================================ homepage: "https://libspng.org" language: c++ primary_contact: "randy408@protonmail.com" auto_ccs: - "randy440088@gmail.com" architectures: - x86_64 - i386 sanitizers: - address - undefined main_repo: 'https://github.com/randy408/libspng.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libsrtp/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y sudo autoconf build-essential libssl-dev pkg-config RUN git clone --depth 1 https://github.com/cisco/libsrtp COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libsrtp/build.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/libsrtp autoreconf -ivf ./configure --with-crypto-library=internal LIBFUZZER="$LIB_FUZZING_ENGINE" make srtp-fuzzer make test zip -r srtp-fuzzer_seed_corpus.zip fuzzer/corpus cp $SRC/libsrtp/fuzzer/srtp-fuzzer $OUT cp srtp-fuzzer_seed_corpus.zip $OUT ================================================ FILE: projects/libsrtp/project.yaml ================================================ homepage: "https://github.com/cisco/libsrtp" language: c++ primary_contact: "richbarn@cisco.com" auto_ccs: - "guidovranken@gmail.com" sanitizers: - address - memory architectures: - x86_64 - i386 main_repo: 'https://github.com/cisco/libsrtp' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libsrtp/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ pushd $SRC/libsrtp make runtest popd ================================================ FILE: projects/libssh/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake zlib1g-dev libssl-dev libcmocka0 libcmocka-dev RUN git clone --depth=1 https://git.libssh.org/projects/libssh.git WORKDIR libssh COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libssh/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ BUILD=$WORK/build mkdir -p $BUILD # Fix deadlock in ssh_scp_fuzzer: the server thread blocks in # ssh_handle_key_exchange and pthread_join waits forever because the # sockets are only closed after the join. Shut them down first. SCP_FUZZER="$SRC/libssh/tests/fuzz/ssh_scp_fuzzer.c" if [ -f "$SCP_FUZZER" ]; then sed -i 's/^cleanup_thread:/cleanup_thread:\n shutdown(socket_fds[0], SHUT_RDWR);\n shutdown(socket_fds[1], SHUT_RDWR);/' "$SCP_FUZZER" fi pushd $BUILD CFLAGS="$CFLAGS -Wno-error=declaration-after-statement" cmake -DCMAKE_C_COMPILER="$CC" -DCMAKE_CXX_COMPILER="$CXX" \ -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DBUILD_SHARED_LIBS=OFF -DWITH_INSECURE_NONE=ON -DWITH_EXEC=OFF \ -DUNIT_TESTING=ON -DWITH_EXAMPLES=OFF $SRC/libssh make "-j$(nproc)" # Build the shared mock server object (needed by ssh_scp_fuzzer) MOCK_SRC="$SRC/libssh/tests/fuzz/ssh_server_mock.c" if [ -f "$MOCK_SRC" ]; then $CC $CFLAGS -I$SRC/libssh/include/ -I$SRC/libssh/src/ -I$BUILD/ -I$BUILD/include/ \ -c "$MOCK_SRC" -O0 -g fi fuzzers=$(find $SRC/libssh/tests/fuzz/ -name "*_fuzzer.c") for f in $fuzzers; do fuzzerName=$(basename $f .c) echo "Building fuzzer $fuzzerName" $CC $CFLAGS -I$SRC/libssh/include/ -I$SRC/libssh/src/ -I$BUILD/ -I$BUILD/include/ \ -c "$f" -O0 -g # Check if this fuzzer needs ssh_server_mock if [ "$fuzzerName" = "ssh_scp_fuzzer" ] || [ "$fuzzerName" = "ssh_sftp_fuzzer" ]; then echo "Linking $fuzzerName with ssh_server_mock" $CXX $CXXFLAGS $fuzzerName.o ssh_server_mock.o \ -o "$OUT/$fuzzerName" -O0 -g \ $LIB_FUZZING_ENGINE ./src/libssh.a -Wl,-Bstatic -lcrypto -lz -Wl,-Bdynamic -lpthread else $CXX $CXXFLAGS $fuzzerName.o \ -o "$OUT/$fuzzerName" -O0 -g \ $LIB_FUZZING_ENGINE ./src/libssh.a -Wl,-Bstatic -lcrypto -lz -Wl,-Bdynamic fi if [ -d "$SRC/libssh/tests/fuzz/${fuzzerName}_corpus" ]; then zip -j $OUT/${fuzzerName}_seed_corpus.zip $SRC/libssh/tests/fuzz/${fuzzerName}_corpus/* cp $OUT/${fuzzerName}_seed_corpus.zip $OUT/${fuzzerName}_nalloc_seed_corpus.zip fi cp $OUT/${fuzzerName} $OUT/${fuzzerName}_nalloc done popd ================================================ FILE: projects/libssh/project.yaml ================================================ homepage: "https://libssh.org/" language: c primary_contact: "asn@cryptomilk.org" auto_ccs: - "cryptomilk@gmail.com" - "jakuje@gmail.com" - "norbertpocs0@gmail.com" - "arthur.chan@adalogics.com" - "david@adalogics.com" - "adam@adalogics.com" sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined main_repo: 'https://git.libssh.org/projects/libssh.git' ================================================ FILE: projects/libssh/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd /work/build make test ================================================ FILE: projects/libssh2/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN git clone --depth 1 https://github.com/libssh2/libssh2.git /src/libssh2 WORKDIR $SRC/libssh2 COPY build.sh $SRC/ ================================================ FILE: projects/libssh2/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ apt-get update # Run the OSS-Fuzz script in the project. ./tests/ossfuzz/ossfuzz.sh ================================================ FILE: projects/libssh2/project.yaml ================================================ homepage: "https://github.com/libssh2/libssh2" language: c++ primary_contact: "will.cosgrove@gmail.com" auto_ccs: - "cmeister2@gmail.com" sanitizers: - address - undefined main_repo: 'https://github.com/libssh2/libssh2.git' ================================================ FILE: projects/libstdcpp/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN sed -i -e 's/^# deb-src/deb-src/g' /etc/apt/sources.list RUN apt-get update && apt-get install -y make autoconf automake libtool RUN apt build-dep -y g++-10 RUN git clone --depth 1 git://gcc.gnu.org/git/gcc.git libstdcpp WORKDIR libstdcpp COPY build.sh $SRC/ ADD https://raw.githubusercontent.com/pauldreik/stdfuzz/main/format/one-arg.cpp $SRC/ ================================================ FILE: projects/libstdcpp/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ SRCDIR=$SRC/libstdcpp BUILDDIR=$OUT/build.d INSTALLDIR=$OUT/install.d mkdir -p $BUILDDIR $INSTALLDIR ( cd $BUILDDIR CXX= CC= CXXFLAGS= CFLAGS= $SRCDIR/configure \ --disable-bootstrap \ --prefix=$INSTALLDIR \ --enable-languages=c++ make -j$(nproc) make -j$(nproc) install-target-libstdc++-v3 ) for fuzzsrcfile in /src/*.cpp; do targetfile=$(basename $fuzzsrcfile .cpp) $CXX \ $CXXFLAGS \ -std=c++20 \ -nostdinc++ \ -cxx-isystem $( echo $INSTALLDIR/include/c++/*/ ) \ -cxx-isystem $( echo $INSTALLDIR/include/c++/*/x86_64-pc-linux-gnu ) \ $fuzzsrcfile \ -o $OUT/$targetfile \ $LIB_FUZZING_ENGINE \ $INSTALLDIR/lib64/libstdc++.a done ================================================ FILE: projects/libstdcpp/project.yaml ================================================ homepage: "https://gcc.gnu.org/" language: c++ primary_contact: "pauldreikossfuzz@gmail.com" auto_ccs: - "jwakely.gcc@gmail.com" main_repo: "git://gcc.gnu.org/git/gcc.git" file_github_issue: false architectures: - x86_64 sanitizers: - address - undefined fuzzing_engines: - libfuzzer - afl - honggfuzz # - centipede ================================================ FILE: projects/libtasn1/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool bison RUN git clone git://git.savannah.gnu.org/gnulib.git ENV GNULIB_TOOL=$SRC/gnulib/gnulib-tool ENV GNULIB_SRCDIR=$SRC/gnulib RUN git clone https://gitlab.com/gnutls/libtasn1.git WORKDIR libtasn1 COPY run_tests.sh build.sh $SRC/ ================================================ FILE: projects/libtasn1/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./bootstrap # switch off leak detection for ./configure run to detect iconv() correctly ASAN_OPTIONS=detect_leaks=0 ./configure --enable-static --disable-shared --disable-doc --disable-gcc-warnings --enable-fuzzing make clean make -j$(nproc) -C lib make -j$(nproc) -C src make -j$(nproc) -C tests check cd fuzz make oss-fuzz find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.dict' -exec cp -v '{}' $OUT ';' find . -name '*_fuzzer.options' -exec cp -v '{}' $OUT ';' for dir in *_fuzzer.in; do fuzzer=$(basename $dir .in) zip -rj "$OUT/${fuzzer}_seed_corpus.zip" "${dir}/" done ================================================ FILE: projects/libtasn1/project.yaml ================================================ homepage: "https://gitlab.com/gnutls/libtasn1" language: c++ primary_contact: "rockdaboot@gmail.com" auto_ccs: - "dbaryshkov@gmail.com" - "ueno@gnu.org" - "simon@josefsson.org" fuzzing_engines: - afl - libfuzzer - honggfuzz sanitizers: - address - memory - undefined main_repo: 'https://gitlab.com/gnutls/libtasn1.git' ================================================ FILE: projects/libtasn1/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make check -C tests -j$(nproc) ================================================ FILE: projects/libteken/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y pmake RUN svn co https://svn.freebsd.org/base/head/sys/teken libteken WORKDIR libteken COPY build.sh libteken_fuzzer.c $SRC/ ================================================ FILE: projects/libteken/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build the library. pmake -C libteken teken_state.h export CFLAGS="$CFLAGS -D__unused=" $CC $CFLAGS -c teken.c -o teken.o -I./libteken ar -q libteken.a ./teken.o ranlib libteken.a $CC $CFLAGS -c $SRC/libteken_fuzzer.c -o $SRC/libteken_fuzzer.o -I. $CXX $CXXFLAGS $SRC/libteken_fuzzer.o \ -o $OUT/libteken_fuzzer \ $LIB_FUZZING_ENGINE libteken.a ================================================ FILE: projects/libteken/libteken_fuzzer.c ================================================ #include #include #include static void dummy_bell(void *s) {} static void dummy_cursor(void *s, const teken_pos_t *p) {} static void dummy_putchar(void *s, const teken_pos_t *p, teken_char_t c, const teken_attr_t *a) {} static void dummy_fill(void *s, const teken_rect_t *r, teken_char_t c, const teken_attr_t *a) {} static void dummy_copy(void *s, const teken_rect_t *r, const teken_pos_t *p) {} static void dummy_param(void *s, int cmd, unsigned int value) {} static void dummy_respond(void *s, const void *buf, size_t len) {} static teken_funcs_t tf = { .tf_bell = dummy_bell, .tf_cursor = dummy_cursor, .tf_putchar = dummy_putchar, .tf_fill = dummy_fill, .tf_copy = dummy_copy, .tf_param = dummy_param, .tf_respond = dummy_respond, }; int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { teken_t t = { 0 }; teken_init(&t, &tf, NULL); teken_input(&t, data, size); return 0; } ================================================ FILE: projects/libteken/project.yaml ================================================ homepage: "http://svn.freebsd.org/base/head/sys/teken/" language: c++ primary_contact: "ed@nuxi.nl" fuzzing_engines: - libfuzzer - afl - honggfuzz sanitizers: - address - undefined - memory main_repo: 'http://svn.freebsd.org/base/head/sys/teken/' ================================================ FILE: projects/libtheora/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://gitlab.xiph.org/xiph/ogg.git RUN git clone --depth 1 https://gitlab.xiph.org/xiph/theora.git libtheora RUN git clone --depth 1 https://github.com/tmatth/oss-fuzz-fuzzers.git RUN git clone --depth 1 https://github.com/fuzzamos/fuzzing-headers.git COPY build.sh $SRC/ ================================================ FILE: projects/libtheora/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [[ $CFLAGS = *sanitize=address* ]] then export CXXFLAGS="$CXXFLAGS -DASAN" fi if [[ $CFLAGS = *sanitize=memory* ]] then export CXXFLAGS="$CXXFLAGS -DMSAN" fi mkdir $SRC/libogg-install/ cd $SRC/ogg ./autogen.sh ./configure --prefix="$SRC/libogg-install" --enable-static --disable-shared --disable-crc make -j$(nproc) make install cd $SRC/fuzzing-headers/ rm -rf /usr/include/fuzzing cp -R include/fuzzing/ /usr/include/ cd $SRC/libtheora/ # patch configure since the baseimage is using an older autoconf sed -i 's/AC_PREREQ(\[[^]]*\])/AC_PREREQ([2.60])/' configure.ac ./autogen.sh if [[ $CFLAGS = *sanitize=memory* || $CFLAGS = *-m32* ]] then LD_LIBRARY_PATH="$SRC/libogg-install/lib" ./configure --with-ogg="$SRC/libogg-install" --disable-encode --disable-examples --disable-asm --enable-static --disable-shared else LD_LIBRARY_PATH="$SRC/libogg-install/lib" ./configure --with-ogg="$SRC/libogg-install" --disable-encode --disable-examples --enable-static --disable-shared fi make -j$(nproc) cd $SRC/oss-fuzz-fuzzers/libtheora/ $CXX $CXXFLAGS -I $SRC/libtheora/include/ -I $SRC/libogg-install/include fuzzer.cpp $SRC/libtheora/lib/.libs/libtheora.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer-decoder ================================================ FILE: projects/libtheora/project.yaml ================================================ homepage: "https://www.theora.org/" language: c++ primary_contact: "guidovranken@gmail.com" main_repo: "https://git.xiph.org/theora.git" auto_ccs: - "le.businessman@gmail.com" vendor_ccs: - "daede003@umn.edu" - "twsmith@mozilla.com" sanitizers: - address - undefined - memory architectures: - x86_64 - i386 fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libtiff/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool cmake nasm RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff RUN git clone --depth 1 https://github.com/madler/zlib RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit ADD https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz afl_testcases.tgz ADD https://raw.githubusercontent.com/google/AFL/debe27037b9444bbf090a0ffbd5d24889bb887ae/dictionaries/tiff.dict tiff.dict WORKDIR libtiff COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libtiff/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ . contrib/oss-fuzz/build.sh ================================================ FILE: projects/libtiff/project.yaml ================================================ homepage: "http://www.libtiff.org" language: c++ primary_contact: "even.rouault@gmail.com" auto_ccs: - paul.l.kehrer@gmail.com sanitizers: - address # Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294 # - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://gitlab.com/libtiff/libtiff' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libtiff/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ make test ================================================ FILE: projects/libtorrent/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget libssl-dev libboost-tools-dev libboost-dev libboost-system-dev RUN git clone --depth 1 --single-branch --branch RC_2_0 --recurse-submodules https://github.com/arvidn/libtorrent.git WORKDIR libtorrent COPY build.sh $SRC/ ================================================ FILE: projects/libtorrent/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ echo "CXX=$CXX" echo "CXXFLAGS=$CXXFLAGS" echo "using clang : ossfuzz : $CXX : \"$CXXFLAGS\" \"$CXXFLAGS\" \"${LIB_FUZZING_ENGINE}\" ;" >project-config.jam cat project-config.jam cd fuzzers # we don't want sanitizers enabled on b2 itself ASAN_OPTIONS=detect_leaks=0 b2 clang-ossfuzz -j$(nproc) crypto=openssl fuzz=external sanitize=off stage-large logging=off cp fuzzers/* $OUT wget --no-verbose https://github.com/arvidn/libtorrent/releases/download/2.0/corpus.zip unzip -q corpus.zip cd corpus for f in *; do zip -q -r ${OUT}/fuzzer_${f}_seed_corpus.zip ${f} done ================================================ FILE: projects/libtorrent/project.yaml ================================================ homepage: "https://github.com/arvidn/libtorrent.git" language: c++ primary_contact: "pauldreikossfuzz@gmail.com" auto_ccs: - "oss-fuzz-libtorrent@pauldreik.se" - "arvid.norberg@gmail.com" main_repo: 'https://github.com/arvidn/libtorrent.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libtpms/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN \ apt-get update && \ apt-get install -y \ make autoconf automake libtool \ libstdc++-9-dev \ libseccomp-dev pkg-config && \ apt-get remove -y libssl-dev || true # Build OpenSSL 3.x from source (libtpms requires OpenSSL 3.0+ APIs) # Use no-shared to build static libraries only for proper fuzzer linking RUN git clone --depth 1 --branch openssl-3.0 https://github.com/openssl/openssl.git /tmp/openssl && \ cd /tmp/openssl && \ ./Configure --prefix=/usr --openssldir=/etc/ssl --libdir=lib/x86_64-linux-gnu no-shared && \ make -j$(nproc) && \ make install_sw install_ssldirs && \ rm -rf /tmp/openssl RUN git clone --depth 1 https://github.com/stefanberger/libtpms libtpms WORKDIR libtpms COPY build.sh $SRC/ ================================================ FILE: projects/libtpms/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Fix include path for generated headers (tpm_library.h is generated in builddir) # Also add libtpms subdir for relative includes within the headers sed -i 's|AM_CFLAGS = -I$(top_srcdir)/include|AM_CFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/include/libtpms|' tests/Makefile.am tests/oss-fuzz.sh ================================================ FILE: projects/libtpms/project.yaml ================================================ homepage: "https://github.com/stefanberger/libtpms" language: c++ primary_contact: "stefanb@us.ibm.com" auto_ccs: - "mlureau@redhat.com" main_repo: 'https://github.com/stefanberger/libtpms' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libtsm/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config RUN git clone --depth 1 git://people.freedesktop.org/~dvdhrm/libtsm WORKDIR libtsm COPY build.sh libtsm_fuzzer.c $SRC/ ================================================ FILE: projects/libtsm/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build the library. ./autogen.sh make -j$(nproc) clean make -j$(nproc) all # build your fuzzer(s) $CC $CFLAGS -c $SRC/libtsm_fuzzer.c -Isrc/tsm -o $SRC/libtsm_fuzzer.o $CXX $CXXFLAGS \ -o $OUT/libtsm_fuzzer \ $SRC/libtsm_fuzzer.o \ .libs/libtsm.a \ $LIB_FUZZING_ENGINE ================================================ FILE: projects/libtsm/libtsm_fuzzer.c ================================================ // Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "libtsm.h" #define WIDTH 80 #define HEIGHT 24 static void terminal_write_fn(struct tsm_vte *vte, const char *u8, size_t len, void *data) { // try to access the written data static char out[4096]; while (len--) out[len % sizeof(out)] = u8[len]; } static int term_draw_cell(struct tsm_screen *screen, uint32_t id, const uint32_t *ch, size_t len, unsigned int cwidth, unsigned int posx, unsigned int posy, const struct tsm_screen_attr *attr, tsm_age_t age, void *data) { if (posx >= WIDTH || posy >= HEIGHT) abort(); return 0; } // Entry point for LibFuzzer. int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { struct tsm_screen *screen; struct tsm_vte *vte; const int scrollback_size = 200; // frecon use 200 tsm_screen_new(&screen, NULL, NULL); tsm_screen_set_max_sb(screen, scrollback_size); tsm_vte_new(&vte, screen, terminal_write_fn, NULL, NULL, NULL); tsm_screen_resize(screen, WIDTH, HEIGHT); tsm_vte_input(vte, (const char*) data, size); tsm_screen_draw(screen, term_draw_cell, NULL); tsm_vte_unref(vte); tsm_screen_unref(screen); return 0; } ================================================ FILE: projects/libtsm/project.yaml ================================================ homepage: "https://www.freedesktop.org/wiki/Software/kmscon/libtsm/" language: c++ primary_contact: "dh.herrmann@gmail.com" sanitizers: - address - memory - undefined main_repo: 'git://people.freedesktop.org/~dvdhrm/libtsm' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libucl/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make cmake pkg-config libtool automake texinfo RUN cd /tmp && wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz && \ tar xzf autoconf-2.71.tar.gz && cd autoconf-2.71 && \ ./configure && make && make install && cd / && rm -rf /tmp/autoconf-2.71* RUN git clone https://github.com/vstakhov/libucl WORKDIR $SRC/libucl COPY build.sh run_tests.sh $SRC/ COPY ucl_add_string_fuzzer.options $SRC/ucl_add_string_fuzzer.options ================================================ FILE: projects/libucl/build.sh ================================================ #!/bin/bash -eux # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cp $SRC/ucl_add_string_fuzzer.options $OUT/ ./autogen.sh --force && ./configure make $CC $CFLAGS -c tests/fuzzers/ucl_add_string_fuzzer.c \ -DHAVE_CONFIG_H -I./src -I./include src/.libs/libucl.a -I./ \ -o $OUT/ucl_add_string_fuzzer.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $OUT/ucl_add_string_fuzzer.o -DHAVE_CONFIG_H -I./src -I./include src/.libs/libucl.a -I. -o $OUT/ucl_add_string_fuzzer ================================================ FILE: projects/libucl/project.yaml ================================================ homepage: "https://github.com/vstakhov/libucl" primary_contact: "vsevolod@highsecure.ru" auto_ccs: - "adam@adalogics.com" language: c main_repo: 'https://github.com/vstakhov/libucl' ================================================ FILE: projects/libucl/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ export ASAN_OPTIONS="detect_leaks=0" make check -C tests -j$(nproc) ================================================ FILE: projects/libucl/ucl_add_string_fuzzer.options ================================================ [libfuzzer] detect_leaks=0 ================================================ FILE: projects/libultrahdr/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake RUN git clone https://github.com/google/libultrahdr.git COPY build.sh $SRC/ WORKDIR libultrahdr ================================================ FILE: projects/libultrahdr/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. $SRC/libultrahdr/fuzzer/ossfuzz.sh ================================================ FILE: projects/libultrahdr/project.yaml ================================================ homepage: "https://github.com/google/libultrahdr" language: c++ primary_contact: "dichenzhang@google.com" sanitizers: - address - memory - undefined: experimental: True auto_ccs: - arifdikici@google.com - dichenzhang@google.com - harish.mahendrakar@ittiam.com - ram.mohan@ittiam.com - umang.saini@ittiam.com architectures: - x86_64 - i386 main_repo: 'https://github.com/google/libultrahdr.git' ================================================ FILE: projects/libunwind/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth 1 https://github.com/libunwind/libunwind libunwind WORKDIR libunwind COPY run_tests.sh build.sh *.c $SRC/ ================================================ FILE: projects/libunwind/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ autoreconf -i ./configure --enable-shared=no --enable-static=yes make $CC $CFLAGS $LIB_FUZZING_ENGINE -I./include -c $SRC/fuzz_libunwind.c \ -o fuzz_libunwind.o $CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_libunwind.o \ ./src/.libs/libunwind-x86_64.a ./src/.libs/libunwind.a \ -o $OUT/fuzz_libunwind ================================================ FILE: projects/libunwind/fuzz_libunwind.c ================================================ /* Copyright 2023 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* * The main idea behind this fuzzer is the generate arbitrary stack traces * by way of recursive funcitons, and then using various calls to libunwind * apis arbitrarily. */ #define UNW_LOCAL_ONLY #include #include #include #include void get_random_reg(int); void get_proc_name(); void dispatch(const uint8_t *data, size_t size); void check_is_signal(); void get_save_loc(int reg); void recurse1(const uint8_t *data, size_t size); void recurse2(const uint8_t *data, size_t size); void recurse3(const uint8_t *data, size_t size); void recurse4(const uint8_t *data, size_t size); void get_save_loc(int regnum) { unw_cursor_t cursor; unw_context_t uc; unw_word_t reference_reg; unw_getcontext(&uc); unw_init_local(&cursor, &uc); unw_save_loc_t loc; while (unw_step(&cursor) > 0) { unw_get_save_loc(&cursor, regnum, &loc); } } void get_random_reg(int regnum) { unw_cursor_t cursor; unw_context_t uc; unw_word_t reference_reg; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, regnum, &reference_reg); } } void check_is_signal() { unw_cursor_t cursor; unw_context_t uc; unw_word_t reference_reg; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { if (unw_is_signal_frame(&cursor)) { return; } } } void get_proc_name() { unw_cursor_t cursor; unw_context_t uc; unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (unw_step(&cursor) > 0) { unw_word_t offset; char buf[512]; unw_get_proc_name(&cursor, buf, sizeof(buf), &offset); } } void dispatch(const uint8_t *data, size_t size) { if (size < 8) { return; } uint8_t decider = data[0] % 4; data += 2; size -= 2; if (decider == 0) { recurse1(data, size); } else if (decider == 1) { recurse2(data, size); } else if (decider == 2) { recurse3(data, size); } else { recurse4(data, size); } } void recurse1(const uint8_t *data, size_t size) { if (data[0] == 0x01) { get_proc_name(); } data += 2; size -= 2; dispatch(data, size); return; } void recurse2(const uint8_t *data, size_t size) { if (data[0] == 0x01) { get_random_reg((int)data[1]); } data += 2; size -= 2; dispatch(data, size); return; } void recurse3(const uint8_t *data, size_t size) { if (data[0] == 0x01) { check_is_signal((int)data[1]); } data += 2; size -= 2; dispatch(data, size); return; } void recurse4(const uint8_t *data, size_t size) { if (data[0] == 0x01) { get_save_loc((int)data[1]); } data += 2; size -= 2; dispatch(data, size); return; } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Ensure we have a bit of data but not too much to cause stackoverflows. if (size < 12 || size > 512) { return 0; } dispatch(data, size); return 0; } ================================================ FILE: projects/libunwind/project.yaml ================================================ homepage: "https://www.nongnu.org/libunwind/" language: c main_repo: "https://github.com/libunwind/libunwind" vendor_ccs: - david@adalogics.com ================================================ FILE: projects/libunwind/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Only include tests that are not failing TESTS="test-strerror test-proc-info test-static-link test-flush-cache Gtest-bt Ltest-init Ltest-varargs Ltest-sig-context test-init-remote Ltest-bt Ltest-init-local-signal Gtest-init Gtest-resume-sig Ltest-resume-sig-rt test-reg-state Lx64-test-dwarf-expressions Gtest-sig-context Ltest-exc test-setjmp Gx64-test-dwarf-expressions Gtest-exc x64-unwind-badjmp-signal-frame Gtest-resume-sig-rt Ltest-resume-sig Gtest-concurrent Ltest-concurrent Lrs-race test-ptrace test-async-sig" # Temporarily disabled failing unit test cases DISABLED_TESTS="Ltest-nomalloc Gtest-trace test-mem Ltest-trace Ltest-nocalloc SKIP: run-coredump-unwind check-namespace.sh run-ptrace-mapper run-ptrace-misc" # Run unit testing that are success make check -j$(nproc) TESTS="$TESTS" ================================================ FILE: projects/libusb/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool libudev-dev libumockdev-dev RUN git clone --depth 1 https://github.com/libusb/libusb libusb WORKDIR libusb COPY build.sh *.cc $SRC/ ================================================ FILE: projects/libusb/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project ./autogen.sh ./configure make -j$(nproc) all # build fuzzer for fuzzer in $(find $SRC -name '*_fuzzer.cc'); do fuzzer_basename=$(basename -s .cc $fuzzer) $CXX $CXXFLAGS -std=c++17 -I. \ $fuzzer $LIB_FUZZING_ENGINE ./libusb/.libs/libusb-1.0.a \ -lpthread -ludev \ -o $OUT/$fuzzer_basename done ================================================ FILE: projects/libusb/libusb_fuzzer.cc ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include "libusb/libusb.h" #include "libusb/libusbi.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct libusb_transfer *transfer = NULL; FuzzedDataProvider stream(data, size); uint8_t bmRequestType = stream.ConsumeIntegral(); uint8_t bRequest = stream.ConsumeIntegral(); uint16_t wValue = stream.ConsumeIntegral(); uint16_t wIndex = stream.ConsumeIntegral(); uint16_t wLength = stream.ConsumeIntegral(); std::string input = stream.ConsumeRandomLengthString(); const char *d = input.c_str(); transfer = libusb_alloc_transfer(0); if (!transfer) { return LIBUSB_ERROR_NO_MEM; } libusb_fill_control_setup((unsigned char *)d, bmRequestType, bRequest, wValue, wIndex, wLength); // Cleanup. // We cannot call libusb_free_transfer as no callbacks has occurred. Calling // libusb_free_transfer without this will trigger false positive errors. struct usbi_transfer *itransfer = LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer); usbi_mutex_destroy(&itransfer->lock); size_t priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size); unsigned char *ptr = (unsigned char *)itransfer - priv_size; free(ptr); return 0; } ================================================ FILE: projects/libusb/project.yaml ================================================ homepage: "http://libusb.info/" language: c++ primary_contact: "christopher.a.dickens@gmail.com" auto_ccs: - "hjelmn@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 main_repo: 'https://github.com/libusb/libusb' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libvips/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y \ automake \ autopoint \ cmake \ curl \ gettext \ glib2.0-dev \ libbrotli-dev \ libexpat1-dev \ libfftw3-dev \ libtool \ nasm \ python3-pip RUN pip3 install meson ninja RUN mkdir afl-testcases RUN curl https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz | tar xzC afl-testcases RUN mkdir pdfium-latest RUN curl -L https://github.com/bblanchon/pdfium-binaries/releases/latest/download/pdfium-linux-x64.tgz | tar xzC pdfium-latest RUN git clone --depth 1 https://github.com/libvips/libvips.git RUN git clone --depth 1 https://github.com/madler/zlib.git RUN git clone --depth 1 https://github.com/libexif/libexif.git RUN git clone --depth 1 https://github.com/mm2/Little-CMS.git lcms RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo.git RUN git clone --depth 1 https://github.com/pnggroup/libpng.git RUN git clone --depth 1 https://chromium.googlesource.com/webm/libwebp RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff.git RUN git clone --depth 1 https://aomedia.googlesource.com/aom RUN git clone --depth 1 https://github.com/strukturag/libheif.git RUN git clone --depth 1 https://github.com/libjxl/libjxl.git RUN git clone --depth 1 https://github.com/lovell/libimagequant.git RUN git clone --depth 1 https://github.com/dloebl/cgif.git RUN git clone --depth 1 https://github.com/google/highway.git RUN git clone --depth 1 https://github.com/google/libultrahdr.git WORKDIR libvips COPY build.sh $SRC/ ================================================ FILE: projects/libvips/build.sh ================================================ #!/bin/bash -eu # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./fuzz/oss_fuzz_build.sh ================================================ FILE: projects/libvips/project.yaml ================================================ homepage: "https://github.com/libvips/libvips" language: c++ base_os_version: ubuntu-24-04 primary_contact: "jcupitt@gmail.com" auto_ccs: - "kleisauke@gmail.com" - "lovell.fuller@gmail.com" - "dloebl.2000@gmail.com" main_repo: 'https://github.com/libvips/libvips' fuzzing_engines: - afl - honggfuzz - libfuzzer coverage_extra_args: -sources src/libvips ================================================ FILE: projects/libvnc/Dockerfile ================================================ # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake zlib1g-dev RUN git clone --depth 1 https://github.com/LibVNC/libvncserver.git WORKDIR $SRC/libvncserver COPY build.sh $SRC/ ================================================ FILE: projects/libvnc/build.sh ================================================ #!/bin/bash -eu # Copyright 2021 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # build project mkdir build cd build cmake -DWITH_TESTS=ON -DBUILD_SHARED_LIBS=OFF .. cmake --build . cp fuzz* $OUT/ # Adds simple corpus and dictionary echo "RFB 003.008" > rfb_corpus zip -r $OUT/fuzz_server_seed_corpus.zip rfb_corpus echo "\"RFB \"" > $OUT/fuzz_server.dict ================================================ FILE: projects/libvnc/project.yaml ================================================ homepage: "https://libvnc.github.io/" language: c++ primary_contact: "dontmind@sdf.org" auto_ccs: - "p.antoine@catenacyber.fr" - "info@christianbeier.net" - "christian.cb.beier@gmail.com" main_repo: 'https://github.com/LibVNC/libvncserver.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libvpx/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y yasm wget gcc RUN git clone https://chromium.googlesource.com/webm/libvpx ADD https://storage.googleapis.com/downloads.webmproject.org/test_data/fuzzer/vpx_fuzzer_seed_corpus.zip $SRC/ COPY build.sh vpx_dec_fuzzer.dict $SRC/ WORKDIR libvpx ================================================ FILE: projects/libvpx/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Build libvpx build_dir=$WORK/build rm -rf ${build_dir} mkdir -p ${build_dir} pushd ${build_dir} # oss-fuzz has 2 GB total memory allocation limit. So, we limit per-allocation # limit in libvpx to 1 GB to avoid OOM errors. A smaller per-allocation is # needed for MemorySanitizer (see bug oss-fuzz:9497 and bug oss-fuzz:9499). if [[ $CFLAGS = *sanitize=memory* ]]; then extra_c_flags='-DVPX_MAX_ALLOCABLE_MEMORY=536870912' # MemorySanitizer requires that all program code is instrumented. # Disable all assembly code, leaving the optimizations implemented with # compiler intrinsics, to improve sanitizer performance and coverage. extra_configure_flags=(--disable-x86-asm) else extra_c_flags='-DVPX_MAX_ALLOCABLE_MEMORY=1073741824' extra_configure_flags=() fi LDFLAGS="$CXXFLAGS" LD=$CXX $SRC/libvpx/configure \ --enable-vp9-highbitdepth \ --disable-unit-tests \ --disable-examples \ --size-limit=12288x12288 \ --extra-cflags="${extra_c_flags}" \ --disable-webm-io \ --enable-debug \ --enable-vp8-encoder \ --enable-vp9-encoder \ "${extra_configure_flags[@]}" make -j$(nproc) all popd # build fuzzers fuzzer_src_name=vpx_dec_fuzzer fuzzer_decoders=( 'vp9' 'vp8' ) for decoder in "${fuzzer_decoders[@]}"; do fuzzer_name=${fuzzer_src_name}"_"${decoder} $CXX $CXXFLAGS -std=c++11 \ -DDECODER=${decoder} \ -I$SRC/libvpx \ -I${build_dir} \ -Wl,--start-group \ $LIB_FUZZING_ENGINE \ $SRC/libvpx/examples/${fuzzer_src_name}.cc -o $OUT/${fuzzer_name} \ ${build_dir}/libvpx.a \ -Wl,--end-group cp $SRC/vpx_fuzzer_seed_corpus.zip $OUT/${fuzzer_name}_seed_corpus.zip cp $SRC/vpx_dec_fuzzer.dict $OUT/${fuzzer_name}.dict cp $OUT/${fuzzer_name} $OUT/${fuzzer_name}_nalloc done fuzzer_src_name=vpx_enc_fuzzer fuzzer_encoders=( 'vp9' 'vp8' ) for encoder in "${fuzzer_encoders[@]}"; do fuzzer_name=${fuzzer_src_name}"_"${encoder} $CXX $CXXFLAGS -std=c++11 \ -DENCODER=${encoder} \ -I$SRC/libvpx \ -I${build_dir} \ -Wl,--start-group \ $LIB_FUZZING_ENGINE \ $SRC/libvpx/examples/${fuzzer_src_name}.cc -o $OUT/${fuzzer_name} \ ${build_dir}/libvpx.a \ -Wl,--end-group cp $OUT/${fuzzer_name} $OUT/${fuzzer_name}_nalloc done ================================================ FILE: projects/libvpx/project.yaml ================================================ homepage: "https://www.webmproject.org" language: c++ primary_contact: "jzern@google.com" sanitizers: - address - memory - undefined auto_ccs: - jianj@google.com - jingning@google.com - jzern@google.com - wtc@google.com vendor_ccs: - "media-alerts@mozilla.com" - "twsmith@mozilla.com" - "product-security@apple.com" - "dkishore@apple.com" - "phan@apple.com" - "ebanniettis@apple.com" - "jm.park@apple.com" - "james_e_kim@apple.com" - "rding23@apple.com" - "albassam@apple.com" - "youenn@apple.com" - "ddkilzer@apple.com" - "zakr@apple.com" - "roberto_rodriguez2@apple.com" - "k_monsen@apple.com" - "nnothstine@apple.com" main_repo: 'https://chromium.googlesource.com/webm/libvpx' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libvpx/vpx_dec_fuzzer.dict ================================================ # IVF Signature + version (bytes 0-5) kw1="DKIF\x00\x00" # VP9 codec fourCC (bytes 8-11) kw2="VP90" # VP8 codec fourCC (bytes 8-11) kw3="VP80" ================================================ FILE: projects/libwebp/Dockerfile ================================================ # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y autoconf make libgif-dev libjpeg-dev libpng-dev libtool zip RUN git clone https://chromium.googlesource.com/webm/libwebp RUN git clone https://chromium.googlesource.com/webm/libwebp-test-data ADD https://storage.googleapis.com/downloads.webmproject.org/webp/testdata/fuzzer/fuzz_seed_corpus.zip $SRC/ RUN unzip fuzz_seed_corpus.zip -d libwebp-test-data/ RUN rm fuzz_seed_corpus.zip COPY build.sh $SRC/ WORKDIR libwebp ================================================ FILE: projects/libwebp/build.sh ================================================ #!/bin/bash -eu # Copyright 2018 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ bash tests/fuzzer/oss-fuzz/build.sh # show content of $OUT/ for sanity checking find $OUT/ ================================================ FILE: projects/libwebp/project.yaml ================================================ homepage: "https://developers.google.com/speed/webp/" language: c++ primary_contact: "jzern@google.com" fuzzing_engines: - libfuzzer sanitizers: - address - undefined - memory auto_ccs: - pascal.massimino@gmail.com - vrabaud@google.com - yguyon@google.com vendor_ccs: - aosmond@mozilla.com - tnikkel@mozilla.com - twsmith@mozilla.com main_repo: 'https://chromium.googlesource.com/webm/libwebp' ================================================ FILE: projects/libwebsockets/Dockerfile ================================================ # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y libssl-dev RUN git clone --depth 1 https://github.com/warmcat/libwebsockets.git COPY run_tests.sh build.sh $SRC/ COPY lws_upng_inflate_fuzzer.cpp $SRC/libwebsockets/ WORKDIR $SRC/libwebsockets ================================================ FILE: projects/libwebsockets/build.sh ================================================ #!/bin/bash -eu # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ DIR=$SRC/libwebsockets/ cd $DIR sed -i 's/-Werror//g' ./CMakeLists.txt mkdir build && cd build cmake -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ -DCMAKE_EXE_LINKER_FLAGS="$CFLAGS" -DCMAKE_SHARED_LINKER_FLAGS="$CFLAGS" .. make -j8 cd $DIR $CXX $CFLAGS $LIB_FUZZING_ENGINE -I$DIR/build/include \ -o $OUT/lws_upng_inflate_fuzzer lws_upng_inflate_fuzzer.cpp \ -L$DIR/build/lib -l:libwebsockets.a \ -L/usr/lib/x86_64-linux-gnu/ -l:libssl.so -l:libcrypto.so ================================================ FILE: projects/libwebsockets/lws_upng_inflate_fuzzer.cpp ================================================ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /* * This fuzzer is generated by UTopia project based on TEST(Test_Tensorflow, * read_inception). (UTopia Project: https://github.com/Samsung/UTopia) */ #include "libwebsockets.h" #include static void lws_api_test_gunzip(FuzzedDataProvider &provider) { int result = 0; struct inflator_ctx *gunz = nullptr; const uint8_t *outring; size_t outringlen, *opl, *cl = 0; auto input1 = provider.ConsumeRandomLengthString(); gunz = lws_upng_inflator_create(&outring, &outringlen, &opl, &cl); if (!gunz) goto bail; lws_upng_inflate_data(gunz, input1.c_str(), input1.size()); bail: if (gunz) lws_upng_inflator_destroy(&gunz); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, uint32_t size) { FuzzedDataProvider provider(data, size); auto select = provider.ConsumeIntegralInRange(0, 1); switch (select) { case 0: lws_api_test_gunzip(provider); break; } return 0; } ================================================ FILE: projects/libwebsockets/project.yaml ================================================ homepage: "https://libwebsockets.org" language: c primary_contact: "andy.warmcat.com@googlemail.com" sanitizers: - address fuzzing_engines: - libfuzzer main_repo: 'https://libwebsockets.org/repo/libwebsockets' ================================================ FILE: projects/libwebsockets/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # The ss-tf unit test is failing from the latest build thus excluded # The other unit tests are excluded because they require network connection which are not possible in run_tests.sh environment ctest --test-dir $SRC/libwebsockets/build -E "warmcat|ss-smd|ss-tf|mss-lws-minimal-ss-hello_world|api-test-secure-streams" ================================================ FILE: projects/libxaac/Dockerfile ================================================ # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y wget cmake RUN git clone https://github.com/ittiam-systems/libxaac.git ADD https://storage.googleapis.com/android_media/external/libxaac/fuzzer/xaac_dec_fuzzer_seed_corpus.zip $SRC/ COPY build.sh $SRC/ WORKDIR libxaac ================================================ FILE: projects/libxaac/build.sh ================================================ #!/bin/bash -eu # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run the OSS-Fuzz script in the project. $SRC/libxaac/fuzzer/ossfuzz.sh ================================================ FILE: projects/libxaac/project.yaml ================================================ homepage: "https://github.com/ittiam-systems/libxaac" language: c++ primary_contact: "harish.mahendrakar@ittiam.com" sanitizers: - address - memory - undefined auto_ccs: - akshay.ragir@ittiam.com - divya.bm@ittiam.com - harish.mahendrakar@ittiam.com - reshma.rai@ittiam.com - saketh.sathuvalli@ittiam.com - sandesh.venkatesh@ittiam.com - shashank.pathmudi@ittiam.com - shreyas.talwekar@ittiam.com - tripti.tiwari@ittiam.com - yash.patil@ittiam.com architectures: - x86_64 - i386 main_repo: 'https://github.com/ittiam-systems/libxaac.git' ================================================ FILE: projects/libxls/Dockerfile ================================================ # Copyright 2019 Evan Miller # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf autoconf-archive automake gettext libtool RUN git clone --depth 1 https://github.com/libxls/libxls libxls WORKDIR libxls COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libxls/build.sh ================================================ # Copyright 2019 Evan Miller # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ #!/bin/bash -eu if [ -f ./autogen.sh ]; then ./autogen.sh else ./bootstrap fi ./configure --enable-static make clean make zip $OUT/fuzz_xls_seed_corpus.zip test/files/*.xls fuzz/corpus/*.xls make fuzz_xls cp fuzz_xls $OUT/fuzz_xls ================================================ FILE: projects/libxls/project.yaml ================================================ homepage: "https://github.com/libxls/libxls" language: c++ primary_contact: "emmiller@gmail.com" main_repo: 'https://github.com/libxls/libxls' ================================================ FILE: projects/libxls/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ASAN_OPTIONS=detect_leaks=0 make check ================================================ FILE: projects/libxlsxwriter/Dockerfile ================================================ # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y cmake make zlib1g-dev RUN python3 -m pip install pytest RUN git clone --depth 1 https://github.com/jmcnamara/libxlsxwriter.git libxlsxwriter WORKDIR libxlsxwriter COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libxlsxwriter/build.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ # Run upstream build script for fuzzers and unit test sh ./dev/fuzzing/build.sh ================================================ FILE: projects/libxlsxwriter/project.yaml ================================================ homepage: "http://libxlsxwriter.github.io" language: c primary_contact: "jmcnamara@cpan.org" auto_ccs: - "capuanobailey@gmail.com" main_repo: "https://github.com/jmcnamara/libxlsxwriter.git" ================================================ FILE: projects/libxlsxwriter/run_tests.sh ================================================ #!/bin/bash -eu # # Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ctest --test-dir build -j$(nproc) ================================================ FILE: projects/libxml2/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder ARG TARGETPLATFORM RUN apt-get update && \ case "$TARGETPLATFORM" in \ 'linux/arm64') EXTRA_PACKAGES='' ;; \ *) EXTRA_PACKAGES='zlib1g-dev:i386 liblzma-dev:i386' ;; \ esac && \ apt-get install -y --no-install-recommends \ make autoconf libtool pkg-config \ zlib1g-dev liblzma-dev \ $EXTRA_PACKAGES # Build requires automake 1.16.3 RUN curl -LO http://mirrors.kernel.org/ubuntu/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ apt install ./automake_1.16.5-1.3_all.deb RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git WORKDIR libxml2 COPY build.sh $SRC/ ================================================ FILE: projects/libxml2/build.sh ================================================ #!/bin/bash -eu # # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ fuzz/oss-fuzz-build.sh ================================================ FILE: projects/libxml2/project.yaml ================================================ homepage: "https://gitlab.gnome.org/GNOME/libxml2" language: c++ vendor_ccs: - "ddkilzer@apple.com" - "benl@google.com" - "product-security@apple.com" - "dkishore@apple.com" - "phan@apple.com" - "ebanniettis@apple.com" - "jm.park@apple.com" - "james_e_kim@apple.com" - "rding23@apple.com" - "albassam@apple.com" - "zakr@apple.com" - "roberto_rodriguez2@apple.com" - "k_monsen@apple.com" - "nnothstine@apple.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 fuzzing_engines: - libfuzzer - honggfuzz - afl main_repo: 'https://gitlab.gnome.org/GNOME/libxml2.git' ================================================ FILE: projects/libxslt/Dockerfile ================================================ # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder # Note that we don't use the system libxml2 but a custom instrumented build. # libgcrypt is required for the crypto extensions of libexslt. RUN apt-get update && apt-get install -y --no-install-recommends \ make autoconf libtool pkg-config \ libgcrypt-dev # Build requires automake 1.16.3 RUN curl -LO http://mirrors.kernel.org/ubuntu/pool/main/a/automake-1.16/automake_1.16.5-1.3_all.deb && \ apt install ./automake_1.16.5-1.3_all.deb # TODO: Update this when new releases are issued # to keep run_tests.sh working. The reason for this # is https://gitlab.gnome.org/GNOME/libxslt/-/issues/126#note_2273444 ENV LATEST_LIBXML2_RELEASE_TAG=v2.14.4 RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git --branch=$LATEST_LIBXML2_RELEASE_TAG RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxslt.git WORKDIR libxslt COPY build.sh run_tests.sh $SRC/ ================================================ FILE: projects/libxslt/build.sh ================================================ #!/bin/bash -eu # # Copyright 2019 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ if [ "$SANITIZER" = undefined ]; then export CFLAGS="$CFLAGS -fsanitize=integer -fno-sanitize-recover=integer" export CXXFLAGS="$CXXFLAGS -fsanitize=integer -fno-sanitize-recover=integer" fi if [ "$SANITIZER" = memory ]; then # This would require an instrumented libgcrypt build. CRYPTO_CONF=--without-crypto CRYPTO_LIBS= else CRYPTO_CONF=--with-crypto CRYPTO_LIBS=-lgcrypt fi cd ../libxml2 ./autogen.sh \ --disable-shared \ --without-c14n \ --without-push \ --without-python \ --without-reader \ --without-regexps \ --without-sax1 \ --without-schemas \ --without-schematron \ --without-valid \ --without-writer \ --without-zlib \ --without-lzma make -j$(nproc) V=1 cd ../libxslt ./autogen.sh \ --with-libxml-src=../libxml2 \ --disable-shared \ --without-python \ $CRYPTO_CONF \ --without-debug \ --without-debugger \ --without-profiler make -j$(nproc) V=1 cd tests/fuzz rm -rf seed make fuzz.o for fuzzer in xpath xslt; do make $fuzzer.o # Link with $CXX $CXX $CXXFLAGS \ $fuzzer.o fuzz.o \ -o $OUT/$fuzzer \ $LIB_FUZZING_ENGINE \ ../../libexslt/.libs/libexslt.a ../../libxslt/.libs/libxslt.a \ ../../../libxml2/.libs/libxml2.a \ $CRYPTO_LIBS [ -e seed/$fuzzer ] || make seed/$fuzzer.stamp zip -j $OUT/${fuzzer}_seed_corpus.zip seed/$fuzzer/* done cp *.dict $OUT/ ================================================ FILE: projects/libxslt/project.yaml ================================================ homepage: "http://www.xmlsoft.org/libxslt/" language: c++ vendor_ccs: - "ddkilzer@apple.com" - "product-security@apple.com" - "schenney@chromium.org" - "dkishore@apple.com" - "phan@apple.com" - "ebanniettis@apple.com" - "jm.park@apple.com" - "james_e_kim@apple.com" - "rding23@apple.com" - "albassam@apple.com" - "zakr@apple.com" - "roberto_rodriguez2@apple.com" - "k_monsen@apple.com" - "nnothstine@apple.com" sanitizers: - address - memory - undefined main_repo: 'https://gitlab.gnome.org/GNOME/libxslt.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libxslt/run_tests.sh ================================================ #!/bin/bash -eu # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ cd $SRC/libxslt make check ================================================ FILE: projects/libyal/Dockerfile ================================================ # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake autopoint libtool pkg-config flex byacc RUN git clone --depth 1 https://github.com/libyal/libcaes.git libcaes RUN git clone --depth 1 https://github.com/libyal/libfcrypto.git libfcrypto RUN git clone --depth 1 https://github.com/libyal/libfmapi.git libfmapi RUN git clone --depth 1 https://github.com/libyal/libfmos.git libfmos RUN git clone --depth 1 https://github.com/libyal/libfplist.git libfplist RUN git clone --depth 1 https://github.com/libyal/libftxf.git libftxf RUN git clone --depth 1 https://github.com/libyal/libfusn.git libfusn RUN git clone --depth 1 https://github.com/libyal/libfwevt.git libfwevt RUN git clone --depth 1 https://github.com/libyal/libfwnt.git libfwnt RUN git clone --depth 1 https://github.com/libyal/libfwps.git libfwps RUN git clone --depth 1 https://github.com/libyal/libfwsi.git libfwsi RUN git clone --depth 1 https://github.com/libyal/libhmac.git libhmac RUN git clone --depth 1 https://github.com/libyal/libagdb.git libagdb RUN git clone --depth 1 https://github.com/libyal/libcreg.git libcreg RUN git clone --depth 1 https://github.com/libyal/libesedb.git libesedb RUN git clone --depth 1 https://github.com/libyal/libevt.git libevt RUN git clone --depth 1 https://github.com/libyal/libevtx.git libevtx RUN git clone --depth 1 https://github.com/libyal/libexe.git libexe RUN git clone --depth 1 https://github.com/libyal/liblnk.git liblnk RUN git clone --depth 1 https://github.com/libyal/libmdmp.git libmdmp RUN git clone --depth 1 https://github.com/libyal/libmsiecf.git libmsiecf RUN git clone --depth 1 https://github.com/libyal/libnk2.git libnk2 RUN git clone --depth 1 https://github.com/libyal/libolecf.git libolecf RUN git clone --depth 1 https://github.com/libyal/libpff.git libpff RUN git clone --depth 1 https://github.com/libyal/libregf.git libregf RUN git clone --depth 1 https://github.com/libyal/libscca.git libscca RUN git clone --depth 1 https://github.com/libyal/libwrc.git libwrc RUN git clone --depth 1 https://github.com/libyal/libfsapfs.git libfsapfs RUN git clone --depth 1 https://github.com/libyal/libfsext.git libfsext RUN git clone --depth 1 https://github.com/libyal/libfsfat.git libfsfat RUN git clone --depth 1 https://github.com/libyal/libfshfs.git libfshfs RUN git clone --depth 1 https://github.com/libyal/libfsntfs.git libfsntfs RUN git clone --depth 1 https://github.com/libyal/libfsxfs.git libfsxfs RUN git clone --depth 1 https://github.com/libyal/libbde.git libbde RUN git clone --depth 1 https://github.com/libyal/libfvde.git libfvde RUN git clone --depth 1 https://github.com/libyal/libluksde.git libluksde RUN git clone --depth 1 https://github.com/libyal/libvsapm.git libvsapm RUN git clone --depth 1 https://github.com/libyal/libvsbsdl.git libvsbsdl RUN git clone --depth 1 https://github.com/libyal/libvsgpt.git libvsgpt RUN git clone --depth 1 https://github.com/libyal/libvshadow.git libvshadow RUN git clone --depth 1 https://github.com/libyal/libvslvm.git libvslvm RUN git clone --depth 1 https://github.com/libyal/libvsmbr.git libvsmbr RUN git clone --depth 1 https://github.com/libyal/libewf.git libewf RUN git clone --depth 1 https://github.com/libyal/libmodi.git libmodi RUN git clone --depth 1 https://github.com/libyal/libodraw.git libodraw RUN git clone --depth 1 https://github.com/libyal/libphdi.git libphdi RUN git clone --depth 1 https://github.com/libyal/libqcow.git libqcow RUN git clone --depth 1 https://github.com/libyal/libsmraw.git libsmraw RUN git clone --depth 1 https://github.com/libyal/libvhdi.git libvhdi RUN git clone --depth 1 https://github.com/libyal/libvmdk.git libvmdk WORKDIR libyal COPY build.sh $SRC/ ================================================ FILE: projects/libyal/build.sh ================================================ #!/bin/bash -eu # Copyright 2020 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ for PROJECT in ${SRC}/*; do PROJECT=$(basename ${PROJECT}) # A libyal project should have an ossfuzz directory and a synclibs.sh script. if ! test -d ${SRC}/${PROJECT}/ossfuzz || ! test -x ${SRC}/${PROJECT}/synclibs.sh; then continue fi cd ${SRC}/${PROJECT} # OSSFuzz base-image currently uses Ubuntu 20.04 which ships older versions # of autoconf and gettext. The libyal projects are compatible with these # older versions, but should not ship with them. The following edits will # allow ./autogen.sh to generate the correct version for OSSFuzz. sed 's/^AC_PREREQ.*$/AC_PREREQ([2.69])/' -i configure.ac sed 's/^AM_GNU_GETTEXT_VERSION.*$/AM_GNU_GETTEXT_VERSION([0.19])/' -i configure.ac # Prepare the project source for build. ./synclibs.sh ./autogen.sh # OSSFuzz cross-compiles certain architectures which can lead to a partial # installed dependencies. ./configure --enable-shared=no --with-openssl=no --with-zlib=no # Build the project and fuzzer binaries. make -j$(nproc) LIB_FUZZING_ENGINE=${LIB_FUZZING_ENGINE} # Download the test data if supported. if test -x ./synctestdata.sh; then ./synctestdata.sh fi # Copy the fuzzer binaries and test data to the output directory. for FUZZ_TARGET in $(cd ossfuzz && find . -executable -type f); do FUZZ_TARGET=$(basename ${FUZZ_TARGET}) # Prefix the fuzzer binaries with the project name. cp ossfuzz/${FUZZ_TARGET} ${OUT}/${PROJECT}_${FUZZ_TARGET} # Download the test data if supported. LIBYAL_TYPE_NAME=${FUZZ_TARGET/_fuzzer/}; if test -f tests/data/${LIBYAL_TYPE_NAME/}.1; then (cd tests/data && zip ${OUT}/${PROJECT}_${FUZZ_TARGET}_seed_corpus.zip ${LIBYAL_TYPE_NAME}.*) elif test -d tests/input/public; then (cd tests/input/public && zip ${OUT}/${PROJECT}_${FUZZ_TARGET}_seed_corpus.zip *) else echo "Missing test data for seed corpus." exit 1 fi done done ================================================ FILE: projects/libyal/project.yaml ================================================ homepage: "https://github.com/libyal" language: c primary_contact: "joachim.metz@gmail.com" sanitizers: - address - memory - undefined architectures: - x86_64 - i386 main_repo: 'https://github.com/libyal/libfplist.git' fuzzing_engines: - afl - honggfuzz - libfuzzer ================================================ FILE: projects/libyaml/Dockerfile ================================================ # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder RUN apt-get update && apt-get install -y make autoconf automake libtool RUN git clone --depth=1 https://github.com/yaml/libyaml RUN zip $SRC/libyaml_seed_corpus.zip libyaml/examples/* WORKDIR libyaml COPY run_tests.sh build.sh *.h *_fuzzer.c libyaml_fuzzer.options yaml.dict $SRC/ ================================================ FILE: projects/libyaml/build.sh ================================================ #!/bin/bash -eu # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ ./bootstrap ./configure make "-j$(nproc)" for fuzzer in $SRC/*_fuzzer.c; do fuzzer_basename=$(basename -s .c $fuzzer) $CC $CFLAGS \ -I $SRC -Iinclude \ -c $fuzzer -o $fuzzer_basename.o $CXX $CXXFLAGS \ -std=c++11 \ $fuzzer_basename.o \ -o $OUT/$fuzzer_basename \ $LIB_FUZZING_ENGINE \ src/.libs/libyaml.a cp $SRC/libyaml_seed_corpus.zip "${OUT}/${fuzzer_basename}_seed_corpus.zip" cp $SRC/libyaml_fuzzer.options "${OUT}/${fuzzer_basename}.options" done cp $SRC/yaml.dict $OUT/ ================================================ FILE: projects/libyaml/libyaml_deconstructor_alt_fuzzer.c ================================================ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "yaml.h" #include "yaml_write_handler.h" #include #include #include #include #include #include #ifdef NDEBUG #undef NDEBUG #endif int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 2) return 0; bool done = false; bool is_canonical = data[0] & 1; bool is_unicode = data[1] & 1; data += 2; size -= 2; yaml_parser_t parser; yaml_emitter_t emitter; yaml_event_t input_event; yaml_document_t output_document; int root; /* Initialize the parser and emitter objects. */ if (!yaml_parser_initialize(&parser)) { return 1; } if (!yaml_emitter_initialize(&emitter)) { yaml_parser_delete(&parser); return 1; } /* Set the parser parameters. */ yaml_parser_set_input_string(&parser, data, size); /* Set the emitter parameters. */ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0, /*capacity=*/1000}; yaml_emitter_set_output(&emitter, yaml_write_handler, &out); yaml_emitter_set_canonical(&emitter, is_canonical); yaml_emitter_set_unicode(&emitter, is_unicode); /* Create and emit the STREAM-START event. */ if (!yaml_emitter_open(&emitter)) goto error; /* Create a output_document object. */ if (!yaml_document_initialize(&output_document, NULL, NULL, NULL, 0, 0)) goto error; /* Create the root sequence. */ root = yaml_document_add_sequence(&output_document, NULL, YAML_BLOCK_SEQUENCE_STYLE); if (!root) goto error; /* Loop through the input events. */ while (!done) { int properties, key, value, map, seq; /* Get the next event. */ if (!yaml_parser_parse(&parser, &input_event)) goto error; /* Check if this is the stream end. */ done = (input_event.type == YAML_STREAM_END_EVENT); /* Create a mapping node and attach it to the root sequence. */ properties = yaml_document_add_mapping(&output_document, NULL, YAML_BLOCK_MAPPING_STYLE); if (!properties) goto error; if (!yaml_document_append_sequence_item(&output_document, root, properties)) goto error; /* Analyze the event. */ switch (input_event.type) { case YAML_STREAM_START_EVENT: /* Add 'type': 'STREAM-START'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"STREAM-START", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Add 'encoding': . */ if (input_event.data.stream_start.encoding) { yaml_encoding_t encoding = input_event.data.stream_start.encoding; key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"encoding", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, NULL, (encoding == YAML_UTF8_ENCODING ? (yaml_char_t *)"utf-8" : encoding == YAML_UTF16LE_ENCODING ? (yaml_char_t *)"utf-16-le" : encoding == YAML_UTF16BE_ENCODING ? (yaml_char_t *)"utf-16-be" : (yaml_char_t *)"unknown"), -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; } break; case YAML_STREAM_END_EVENT: /* Add 'type': 'STREAM-END'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"STREAM-END", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; break; case YAML_DOCUMENT_START_EVENT: /* Add 'type': 'DOCUMENT-START'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"DOCUMENT-START", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Display the output_document version numbers. */ if (input_event.data.document_start.version_directive) { yaml_version_directive_t *version = input_event.data.document_start.version_directive; char number[64]; /* Add 'version': {}. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"version", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; map = yaml_document_add_mapping(&output_document, NULL, YAML_FLOW_MAPPING_STYLE); if (!map) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, map)) goto error; /* Add 'major': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"major", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; sprintf(number, "%d", version->major); value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_INT_TAG, (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; /* Add 'minor': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"minor", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; sprintf(number, "%d", version->minor); value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_INT_TAG, (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; } /* Display the output_document tag directives. */ if (input_event.data.document_start.tag_directives.start != input_event.data.document_start.tag_directives.end) { yaml_tag_directive_t *tag; /* Add 'tags': []. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"tags", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; seq = yaml_document_add_sequence(&output_document, NULL, YAML_BLOCK_SEQUENCE_STYLE); if (!seq) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, seq)) goto error; for (tag = input_event.data.document_start.tag_directives.start; tag != input_event.data.document_start.tag_directives.end; tag++) { /* Add {}. */ map = yaml_document_add_mapping(&output_document, NULL, YAML_FLOW_MAPPING_STYLE); if (!map) goto error; if (!yaml_document_append_sequence_item(&output_document, seq, map)) goto error; /* Add 'handle': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"handle", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, tag->handle, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; /* Add 'prefix': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"prefix", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, tag->prefix, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; } } /* Add 'implicit': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"implicit", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_BOOL_TAG, (input_event.data.document_start.implicit ? (yaml_char_t *)"true" : (yaml_char_t *)"false"), -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; break; case YAML_DOCUMENT_END_EVENT: /* Add 'type': 'DOCUMENT-END'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"DOCUMENT-END", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Add 'implicit': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"implicit", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_BOOL_TAG, (input_event.data.document_end.implicit ? (yaml_char_t *)"true" : (yaml_char_t *)"false"), -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; break; case YAML_ALIAS_EVENT: /* Add 'type': 'ALIAS'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"ALIAS", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Add 'anchor': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"anchor", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, input_event.data.alias.anchor, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; break; case YAML_SCALAR_EVENT: /* Add 'type': 'SCALAR'. */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"type", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"SCALAR", -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Add 'anchor': . */ if (input_event.data.scalar.anchor) { key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"anchor", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, input_event.data.scalar.anchor, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; } /* Add 'tag': . */ if (input_event.data.scalar.tag) { key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"tag", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar(&output_document, NULL, input_event.data.scalar.tag, -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; } /* Add 'value': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"value", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, NULL, input_event.data.scalar.value, input_event.data.scalar.length, YAML_DOUBLE_QUOTED_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, value)) goto error; /* Display if the scalar tag is implicit. */ /* Add 'implicit': {} */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"version", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; map = yaml_document_add_mapping(&output_document, NULL, YAML_FLOW_MAPPING_STYLE); if (!map) goto error; if (!yaml_document_append_mapping_pair(&output_document, properties, key, map)) goto error; /* Add 'plain': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"plain", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_BOOL_TAG, (input_event.data.scalar.plain_implicit ? (yaml_char_t *)"true" : (yaml_char_t *)"false"), -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; /* Add 'quoted': . */ key = yaml_document_add_scalar(&output_document, NULL, (yaml_char_t *)"quoted", -1, YAML_PLAIN_SCALAR_STYLE); if (!key) goto error; value = yaml_document_add_scalar( &output_document, (yaml_char_t *)YAML_BOOL_TAG, (input_event.data.scalar.quoted_implicit ? (yaml_char_t *)"true" : (yaml_char_t *)"false"), -1, YAML_PLAIN_SCALAR_STYLE); if (!value) goto error; if (!yaml_document_append_mapping_pair(&output_document, map, key, value)) goto error; /* Display the style information. */ if (input_event.data.scalar.style) { yaml_scalar_style_t style = input_event.data.scalar.style; /* Add 'style':