aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2021-10-12 08:56:08 -0700
committerElliott Hughes <enh@google.com>2021-10-12 08:56:08 -0700
commitebda00b748d458bf970296cfe04e470a6139e581 (patch)
tree1986de3b646aa32bbe34a45cd3af0c06cb07afa0
parent75c8dcf71ca8652f671b4ca5fea780a558c86e08 (diff)
parentfd15c6d57aa13667af2521daf6167a2d8cd2ecb7 (diff)
downloadoss-fuzz-ebda00b748d458bf970296cfe04e470a6139e581.tar.gz
Upgrade oss-fuzz to fd15c6d57aa13667af2521daf6167a2d8cd2ecb7android-s-v2-preview-2android-s-v2-preview-1android-s-v2-beta-2android-s-v2-preview-1
Test: make Change-Id: Ib2733efe65798b72a56aa5db61992b878b4c6be1
-rw-r--r--.github/CODEOWNERS1
-rw-r--r--.github/workflows/infra_tests.yml11
-rw-r--r--.github/workflows/presubmit.yml5
-rw-r--r--.github/workflows/project_tests.yml5
-rw-r--r--METADATA6
-rw-r--r--README.md6
-rw-r--r--docs/Gemfile.lock164
-rw-r--r--docs/README.md3
-rw-r--r--docs/advanced-topics/bug_fixing_guidance.md94
-rw-r--r--docs/advanced-topics/code_coverage.md9
-rw-r--r--docs/advanced-topics/reproducing.md7
-rw-r--r--docs/clusterfuzzlite/advanced/adding_ci_support.md12
-rw-r--r--docs/clusterfuzzlite/advanced/architecture.md12
-rw-r--r--docs/clusterfuzzlite/advanced_topics.md10
-rw-r--r--docs/clusterfuzzlite/build_integration.md269
-rw-r--r--docs/clusterfuzzlite/clusterfuzzlite.md27
-rw-r--r--docs/clusterfuzzlite/overview.md29
-rw-r--r--docs/clusterfuzzlite/running-clusterfuzzlite/generic.md17
-rw-r--r--docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md12
-rw-r--r--docs/clusterfuzzlite/running_clusterfuzzlite.md101
-rw-r--r--docs/further-reading/clusterfuzz.md2
-rw-r--r--docs/further-reading/fuzzer_environment.md5
-rw-r--r--docs/getting-started/accepting_new_projects.md8
-rw-r--r--docs/getting-started/continuous_integration.md11
-rw-r--r--docs/getting-started/new-project-guide/bazel.md6
-rw-r--r--docs/getting-started/new-project-guide/go_lang.md2
-rw-r--r--docs/getting-started/new-project-guide/jvm_lang.md15
-rw-r--r--docs/getting-started/new-project-guide/python_lang.md4
-rw-r--r--docs/getting-started/new-project-guide/rust_lang.md46
-rw-r--r--docs/getting-started/new-project-guide/swift.md78
-rw-r--r--docs/getting-started/new_project_guide.md68
-rw-r--r--docs/index.md6
-rw-r--r--docs/oss-fuzz/architecture.md2
-rw-r--r--docs/reference/glossary.md2
-rwxr-xr-xinfra/base-images/all.sh7
-rw-r--r--infra/base-images/base-builder-go/Dockerfile30
-rw-r--r--infra/base-images/base-builder-go/ossfuzz_coverage_runner.go69
-rw-r--r--infra/base-images/base-builder-jvm/Dockerfile (renamed from infra/base-images/base-sanitizer-libs-builder/packages/mesa.py)18
-rw-r--r--infra/base-images/base-builder-python/Dockerfile19
-rw-r--r--infra/base-images/base-builder-rust/Dockerfile25
-rw-r--r--infra/base-images/base-builder-swift/Dockerfile21
-rwxr-xr-xinfra/base-images/base-builder-swift/precompile_swift33
-rw-r--r--infra/base-images/base-builder/Dockerfile91
-rwxr-xr-xinfra/base-images/base-builder/bazel_build_fuzz_tests12
-rw-r--r--infra/base-images/base-builder/bisect_clang_test.py18
-rwxr-xr-xinfra/base-images/base-builder/cargo8
-rwxr-xr-xinfra/base-images/base-builder/compile50
-rw-r--r--infra/base-images/base-builder/compile_afl25
-rwxr-xr-xinfra/base-images/base-builder/compile_go_fuzzer6
-rwxr-xr-x[-rw-r--r--]infra/base-images/base-builder/install_go.sh (renamed from infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py)23
-rwxr-xr-xinfra/base-images/base-builder/install_java.sh37
-rwxr-xr-xinfra/base-images/base-builder/install_python.sh21
-rwxr-xr-xinfra/base-images/base-builder/install_rust.sh21
-rwxr-xr-xinfra/base-images/base-builder/install_swift.sh66
-rw-r--r--infra/base-images/base-builder/llvmsymbol.diff50
-rwxr-xr-xinfra/base-images/base-builder/write_labels.py2
-rw-r--r--infra/base-images/base-clang/Dockerfile2
-rwxr-xr-xinfra/base-images/base-clang/checkout_build_install_llvm.sh28
-rw-r--r--infra/base-images/base-image/Dockerfile4
-rwxr-xr-xinfra/base-images/base-runner/Dockerfile18
-rwxr-xr-xinfra/base-images/base-runner/bad_build_check12
-rwxr-xr-xinfra/base-images/base-runner/coverage120
-rwxr-xr-xinfra/base-images/base-runner/coverage_helper2
-rwxr-xr-xinfra/base-images/base-runner/jacoco_report_converter.py158
-rw-r--r--infra/base-images/base-runner/profraw_update.py123
-rwxr-xr-xinfra/base-images/base-runner/run_fuzzer31
-rwxr-xr-xinfra/base-images/base-runner/targets_list3
-rwxr-xr-xinfra/base-images/base-runner/test_all.py102
-rw-r--r--infra/base-images/base-runner/test_all_test.py8
-rwxr-xr-xinfra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py175
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py42
-rwxr-xr-xinfra/base-images/base-sanitizer-libs-builder/msan_build.py460
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/__init__.py0
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/nettle.py41
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/openssl.py42
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/package.py82
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/pixman.py40
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt1
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py42
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch39
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/packages/systemd.py42
-rwxr-xr-xinfra/base-images/base-sanitizer-libs-builder/patch_build.py143
-rw-r--r--infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py47
-rw-r--r--infra/bisector.py38
-rw-r--r--infra/bisector_test.py4
-rw-r--r--infra/build/functions/base_images.py62
-rwxr-xr-x[-rw-r--r--]infra/build/functions/build_and_run_coverage.py194
-rw-r--r--infra/build/functions/build_and_run_coverage_test.py78
-rw-r--r--infra/build/functions/build_lib.py102
-rwxr-xr-x[-rw-r--r--]infra/build/functions/build_project.py725
-rw-r--r--infra/build/functions/build_project_test.py77
-rwxr-xr-xinfra/build/functions/deploy.sh12
-rw-r--r--infra/build/functions/expected_build_steps.json330
-rw-r--r--infra/build/functions/main.py5
-rw-r--r--infra/build/functions/project_sync.py12
-rw-r--r--infra/build/functions/project_sync_test.py5
-rw-r--r--infra/build/functions/request_build.py63
-rw-r--r--infra/build/functions/request_build_test.py61
-rw-r--r--infra/build/functions/request_coverage_build.py16
-rw-r--r--infra/build/functions/request_coverage_build_test.py90
-rw-r--r--infra/build/functions/test_data/expected_build_steps.json628
-rw-r--r--infra/build/functions/test_data/expected_coverage_build_steps.json (renamed from infra/build/functions/expected_coverage_build_steps.json)34
-rw-r--r--infra/build/functions/test_utils.py48
-rw-r--r--infra/build/functions/update_build_status.py24
-rw-r--r--infra/build/functions/update_build_status_test.py51
-rwxr-xr-xinfra/build_and_push_test_images.py92
-rw-r--r--infra/build_fuzzers.Dockerfile7
-rw-r--r--infra/build_specified_commit.py16
-rw-r--r--infra/build_specified_commit_test.py38
-rwxr-xr-xinfra/ci/build.py20
-rw-r--r--infra/ci/requirements.txt2
-rw-r--r--infra/cifuzz/actions/build_fuzzers/action.yml4
-rw-r--r--infra/cifuzz/actions/run_fuzzers/action.yml21
-rw-r--r--infra/cifuzz/affected_fuzz_targets.py26
-rw-r--r--infra/cifuzz/affected_fuzz_targets_test.py30
-rw-r--r--infra/cifuzz/base_runner_utils.py33
-rw-r--r--infra/cifuzz/build_fuzzers.py197
-rw-r--r--infra/cifuzz/build_fuzzers_entrypoint.py67
-rw-r--r--infra/cifuzz/build_fuzzers_test.py293
-rw-r--r--infra/cifuzz/cifuzz-base/Dockerfile23
-rw-r--r--infra/cifuzz/cifuzz_combined_entrypoint.py53
-rw-r--r--infra/cifuzz/cifuzz_end_to_end_test.py46
-rw-r--r--infra/cifuzz/cloudbuild.yaml39
-rw-r--r--infra/cifuzz/clusterfuzz_deployment.py360
-rw-r--r--infra/cifuzz/clusterfuzz_deployment_test.py266
-rw-r--r--infra/cifuzz/config_utils.py304
-rw-r--r--infra/cifuzz/config_utils_test.py200
-rw-r--r--infra/cifuzz/continuous_integration.py169
-rw-r--r--infra/cifuzz/continuous_integration_test.py87
-rw-r--r--infra/cifuzz/coverage_test.py194
-rw-r--r--infra/cifuzz/docker.py81
-rw-r--r--infra/cifuzz/docker_test.py122
-rw-r--r--infra/cifuzz/environment.py7
-rw-r--r--infra/cifuzz/external-actions/build_fuzzers/action.yml63
-rw-r--r--infra/cifuzz/external-actions/run_fuzzers/action.yml69
-rw-r--r--infra/cifuzz/filestore/__init__.py54
-rw-r--r--infra/cifuzz/filestore/git/__init__.py159
-rw-r--r--infra/cifuzz/filestore/git/git_test.py122
-rw-r--r--infra/cifuzz/filestore/github_actions/__init__.py177
-rw-r--r--infra/cifuzz/filestore/github_actions/github_actions_test.py281
-rw-r--r--infra/cifuzz/filestore/github_actions/github_api.py108
-rw-r--r--infra/cifuzz/filestore/github_actions/github_api_test.py33
-rwxr-xr-xinfra/cifuzz/filestore/github_actions/upload.js33
-rw-r--r--infra/cifuzz/filestore_utils.py31
-rw-r--r--infra/cifuzz/filestore_utils_test.py50
-rw-r--r--infra/cifuzz/fuzz_target.py278
-rw-r--r--infra/cifuzz/fuzz_target_test.py197
-rw-r--r--infra/cifuzz/generate_coverage_report.py48
-rw-r--r--infra/cifuzz/generate_coverage_report_test.py71
-rw-r--r--infra/cifuzz/get_coverage.py (renamed from infra/cifuzz/coverage.py)173
-rw-r--r--infra/cifuzz/get_coverage_test.py239
-rw-r--r--infra/cifuzz/http_utils.py117
-rw-r--r--infra/cifuzz/http_utils_test.py71
-rw-r--r--infra/cifuzz/package-lock.json316
-rw-r--r--infra/cifuzz/package.json10
-rw-r--r--infra/cifuzz/requirements.txt2
-rw-r--r--infra/cifuzz/run_cifuzz.py88
-rw-r--r--infra/cifuzz/run_fuzzers.py153
-rw-r--r--infra/cifuzz/run_fuzzers_entrypoint.py67
-rw-r--r--infra/cifuzz/run_fuzzers_test.py354
-rw-r--r--infra/cifuzz/stack_parser.py40
-rw-r--r--infra/cifuzz/stack_parser_test.py12
-rwxr-xr-xinfra/cifuzz/test_data/build-out/example_crash_fuzzer (renamed from infra/cifuzz/test_data/out/example_crash_fuzzer)bin4375872 -> 4375872 bytes
-rwxr-xr-xinfra/cifuzz/test_data/build-out/example_nocrash_fuzzer (renamed from infra/cifuzz/test_data/out/example_nocrash_fuzzer)bin4376224 -> 4376224 bytes
-rw-r--r--infra/cifuzz/test_data/example_coverage_report_summary.json1
-rw-r--r--infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile (renamed from infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile)4
-rw-r--r--infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh (renamed from infra/cifuzz/test_data/external-project/oss-fuzz/build.sh)0
-rwxr-xr-xinfra/cifuzz/test_data/memory/build-out/curl_fuzzer_memory (renamed from infra/cifuzz/test_data/memory/out/curl_fuzzer_memory)bin9768680 -> 9768680 bytes
-rwxr-xr-xinfra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined (renamed from infra/cifuzz/test_data/undefined/out/curl_fuzzer_undefined)bin14401312 -> 14401312 bytes
-rw-r--r--infra/cifuzz/test_helpers.py116
-rw-r--r--infra/cifuzz/workspace_utils.py75
-rw-r--r--infra/constants.py38
-rwxr-xr-xinfra/helper.py886
-rw-r--r--infra/helper_test.py211
-rwxr-xr-xinfra/presubmit.py141
-rw-r--r--infra/pytest.ini3
-rw-r--r--infra/repo_manager.py8
-rw-r--r--infra/retry.py6
-rw-r--r--infra/run_fuzzers.Dockerfile9
-rwxr-xr-xinfra/templates.py39
-rw-r--r--infra/test_helpers.py39
-rw-r--r--infra/test_repos.py14
-rw-r--r--infra/triage-party/README.md13
-rwxr-xr-xinfra/triage-party/deploy.sh42
-rw-r--r--infra/triage-party/oss-fuzz.yaml172
-rw-r--r--infra/utils.py53
-rw-r--r--infra/utils_test.py26
-rw-r--r--projects/apache-commons/CompressSevenZFuzzer.java39
-rw-r--r--projects/apache-commons/CompressTarFuzzer.java33
-rw-r--r--projects/apache-commons/CompressZipFuzzer.java34
-rw-r--r--projects/apache-commons/Dockerfile61
-rw-r--r--projects/apache-commons/GeometryObjFuzzer.java40
-rw-r--r--projects/apache-commons/GeometryStlBinaryFuzzer.java40
-rw-r--r--projects/apache-commons/GeometryStlTextFuzzer.java55
-rw-r--r--projects/apache-commons/GeometryTextFuzzer.java41
-rw-r--r--projects/apache-commons/ImagingBmpFuzzer.java30
-rw-r--r--projects/apache-commons/ImagingGifFuzzer.java30
-rw-r--r--projects/apache-commons/ImagingJpegFuzzer.java30
-rw-r--r--projects/apache-commons/ImagingPngFuzzer.java30
-rw-r--r--projects/apache-commons/ImagingTiffFuzzer.java30
-rwxr-xr-xprojects/apache-commons/build.sh66
-rw-r--r--projects/apache-commons/project.yaml13
-rw-r--r--projects/apache-httpd/Dockerfile34
-rwxr-xr-xprojects/apache-httpd/build.sh45
-rw-r--r--projects/apache-httpd/fuzz_addr_parse.c (renamed from projects/gpac/fuzz_parse.c)39
-rw-r--r--projects/apache-httpd/fuzz_parse.c70
-rw-r--r--projects/apache-httpd/fuzz_preq.c84
-rw-r--r--projects/apache-httpd/fuzz_request.c138
-rw-r--r--projects/apache-httpd/fuzz_tokenize.c34
-rw-r--r--projects/apache-httpd/fuzz_uri.c65
-rw-r--r--projects/apache-httpd/fuzz_utils.c182
-rw-r--r--projects/apache-httpd/patches.diff44
-rw-r--r--projects/apache-httpd/project.yaml8
-rw-r--r--projects/assimp/Dockerfile2
-rw-r--r--projects/assimp/build.sh14
-rw-r--r--projects/assimp/project.yaml5
-rw-r--r--projects/assimp/project_proposed.yaml10
-rw-r--r--projects/bazel-rules-fuzzing-test-java/Dockerfile21
-rw-r--r--projects/bazel-rules-fuzzing-test-java/build.sh27
-rw-r--r--projects/bazel-rules-fuzzing-test-java/project.yaml13
-rw-r--r--projects/bazel-rules-fuzzing-test/build.sh9
-rw-r--r--projects/bearssl/Dockerfile2
-rw-r--r--projects/bearssl/project.yaml3
-rw-r--r--projects/bignum-fuzzer/Dockerfile6
-rwxr-xr-xprojects/bignum-fuzzer/build.sh6
-rwxr-xr-xprojects/binutils/build.sh23
-rw-r--r--projects/binutils/fuzz_readelf.c24
-rw-r--r--projects/bitcoin-core/Dockerfile37
-rwxr-xr-xprojects/bitcoin-core/build.sh97
-rwxr-xr-xprojects/bitcoin-core/build_cryptofuzz.sh175
-rw-r--r--projects/bitcoin-core/project.yaml22
-rw-r--r--projects/blackfriday/Dockerfile20
-rw-r--r--[-rwxr-xr-x]projects/blackfriday/build.sh (renamed from projects/libjpeg-turbo/build.sh)13
-rw-r--r--projects/blackfriday/project.yaml11
-rw-r--r--projects/blackfriday/render_fuzzer.go21
-rw-r--r--projects/bleach/Dockerfile4
-rw-r--r--projects/bleach/build.sh2
-rw-r--r--projects/bleach/linkify_fuzzer.py3
-rw-r--r--projects/bleach/sanitize_fuzzer.py3
-rw-r--r--projects/bloaty/Dockerfile2
-rw-r--r--projects/bls-signatures/Dockerfile27
-rwxr-xr-xprojects/bls-signatures/build.sh250
-rw-r--r--projects/bls-signatures/project.yaml20
-rw-r--r--projects/boost-json/Dockerfile49
-rwxr-xr-xprojects/boost-json/build.sh28
-rw-r--r--projects/boost-json/project.yaml8
-rw-r--r--projects/boost/Dockerfile2
-rw-r--r--projects/boost/boost_regex_fuzzer.cc19
-rwxr-xr-xprojects/boost/build.sh4
-rw-r--r--projects/botan/project.yaml5
-rw-r--r--projects/bs4/Dockerfile4
-rw-r--r--projects/bs4/bs4_fuzzer.py8
-rw-r--r--projects/bs4/build.sh2
-rw-r--r--projects/caddy/Dockerfile22
-rw-r--r--projects/caddy/build.sh36
-rw-r--r--projects/caddy/project.yaml10
-rw-r--r--projects/cairo/Dockerfile4
-rw-r--r--projects/capnproto/Dockerfile2
-rwxr-xr-xprojects/capnproto/build.sh9
-rw-r--r--projects/capnproto/project.yaml2
-rw-r--r--projects/cascadia/Dockerfile2
-rw-r--r--projects/casync/project.yaml5
-rw-r--r--projects/cel-cpp/Dockerfile3
-rwxr-xr-xprojects/cel-cpp/build.sh16
-rw-r--r--projects/cel-cpp/fuzz_parse.cc5
-rw-r--r--projects/cel-cpp/project.yaml3
-rw-r--r--projects/cel-go/Dockerfile37
-rwxr-xr-xprojects/cel-go/build.sh36
-rw-r--r--projects/cel-go/cel-go-lpm.proto (renamed from projects/rustls/persist.rs)23
-rw-r--r--projects/cel-go/fuzz_compile.go18
-rw-r--r--projects/cel-go/fuzz_eval.go39
-rw-r--r--projects/cel-go/go-lpm.cc31
-rw-r--r--projects/cel-go/project.yaml10
-rw-r--r--projects/cfengine/Dockerfile26
-rwxr-xr-xprojects/cfengine/build.sh28
-rw-r--r--projects/cfengine/project.yaml10
-rw-r--r--projects/cfengine/string_fuzzer.c40
-rw-r--r--projects/cilium/Dockerfile2
-rw-r--r--projects/cilium/project.yaml6
-rwxr-xr-xprojects/civetweb/project.yaml1
-rw-r--r--projects/clamav/Dockerfile2
-rwxr-xr-xprojects/clamav/build.sh2
-rw-r--r--projects/clib/Dockerfile2
-rw-r--r--projects/clib/build.sh4
-rw-r--r--projects/clickhouse/Dockerfile40
-rwxr-xr-xprojects/clickhouse/build.sh107
-rw-r--r--projects/clickhouse/project.yaml14
-rw-r--r--projects/cmake/project.yaml3
-rw-r--r--projects/containerd/Dockerfile21
-rw-r--r--projects/containerd/build.sh19
-rw-r--r--projects/containerd/project.yaml10
-rw-r--r--projects/cosign/Dockerfile3
-rw-r--r--projects/cosmos-sdk/Dockerfile21
-rwxr-xr-xprojects/cosmos-sdk/build.sh18
-rw-r--r--projects/cosmos-sdk/project.yaml11
-rw-r--r--projects/cpp-httplib/project.yaml6
-rw-r--r--projects/cpython3/Dockerfile15
-rw-r--r--projects/cpython3/project.yaml5
-rw-r--r--projects/cras/Dockerfile3
-rwxr-xr-xprojects/cras/build.sh2
-rw-r--r--projects/cras/project.yaml10
-rw-r--r--projects/cryptofuzz/Dockerfile28
-rwxr-xr-xprojects/cryptofuzz/build.sh212
-rw-r--r--projects/dart/project.yaml2
-rw-r--r--projects/dav1d/Dockerfile4
-rw-r--r--projects/dav1d/nasm.list2
-rw-r--r--projects/dav1d/nasm_apt.pin7
-rw-r--r--projects/dav1d/project.yaml3
-rw-r--r--projects/dgraph/Dockerfile20
-rw-r--r--projects/dgraph/build.sh18
-rw-r--r--projects/dgraph/project.yaml14
-rw-r--r--projects/django/Dockerfile3
-rwxr-xr-xprojects/django/build.sh2
-rw-r--r--projects/dlplibs/project.yaml3
-rw-r--r--projects/dng_sdk/Dockerfile21
-rwxr-xr-xprojects/dng_sdk/build.sh30
-rw-r--r--projects/dng_sdk/project.yaml6
-rw-r--r--projects/dnsmasq/Dockerfile25
-rwxr-xr-xprojects/dnsmasq/build.sh57
-rw-r--r--projects/dnsmasq/fuzz_auth.c72
-rw-r--r--projects/dnsmasq/fuzz_dhcp.c87
-rw-r--r--projects/dnsmasq/fuzz_dhcp6.c83
-rw-r--r--projects/dnsmasq/fuzz_header.h579
-rw-r--r--projects/dnsmasq/fuzz_patch.patch170
-rw-r--r--projects/dnsmasq/fuzz_rfc1035.c271
-rw-r--r--projects/dnsmasq/fuzz_util.c66
-rw-r--r--projects/dnsmasq/project.yaml6
-rw-r--r--projects/draco/project.yaml3
-rw-r--r--projects/dragonfly/Dockerfile15
-rw-r--r--projects/duckdb/Dockerfile21
-rwxr-xr-xprojects/duckdb/build.sh23
-rw-r--r--projects/duckdb/parse_fuzz_test.cpp23
-rw-r--r--projects/duckdb/project.yaml7
-rw-r--r--projects/easywsclient/project.yaml5
-rw-r--r--projects/ecc-diff-fuzzer/Dockerfile9
-rwxr-xr-xprojects/ecc-diff-fuzzer/build.sh1
-rw-r--r--projects/eigen/solver_fuzzer.cc1
-rwxr-xr-xprojects/envoy/build.sh57
-rw-r--r--projects/envoy/project.yaml7
-rw-r--r--projects/espeak-ng/Dockerfile21
-rwxr-xr-xprojects/espeak-ng/build.sh25
-rw-r--r--projects/espeak-ng/project.yaml14
-rw-r--r--projects/etcd/Dockerfile20
-rw-r--r--projects/etcd/build.sh20
-rw-r--r--projects/etcd/project.yaml10
-rw-r--r--projects/etcd/wal_fuzzer.go58
-rw-r--r--projects/exiv2/Dockerfile22
-rwxr-xr-xprojects/exiv2/build.sh38
-rw-r--r--projects/exiv2/project.yaml9
-rw-r--r--projects/exprtk/project.yaml3
-rw-r--r--projects/fast-dds/Dockerfile1
-rwxr-xr-xprojects/fast-dds/build.sh2
-rw-r--r--projects/fast-dds/patch.diff74
-rw-r--r--projects/fasthttp/Dockerfile2
-rw-r--r--projects/fastjson/Dockerfile2
-rw-r--r--projects/fastjson2/Dockerfile2
-rw-r--r--projects/fastjson2/build.sh2
-rw-r--r--projects/ffmpeg/Dockerfile5
-rw-r--r--projects/ffmpeg/bionic.list2
-rwxr-xr-xprojects/ffmpeg/build.sh23
-rw-r--r--projects/ffmpeg/nasm_apt.pin7
-rw-r--r--projects/file/project.yaml3
-rw-r--r--projects/firefox/Dockerfile17
-rwxr-xr-xprojects/flac/build.sh2
-rw-r--r--projects/flatbuffers/Dockerfile2
-rw-r--r--projects/flate2-rs/Dockerfile19
-rw-r--r--projects/flate2-rs/build.sh20
-rw-r--r--projects/flate2-rs/project.yaml10
-rwxr-xr-xprojects/fluent-bit/build.sh16
-rwxr-xr-xprojects/fluent-bit/project.yaml1
-rw-r--r--projects/freeradius/Dockerfile37
-rwxr-xr-xprojects/freeradius/build.sh45
-rw-r--r--projects/freeradius/patch.diff64
-rw-r--r--projects/freeradius/project.yaml11
-rw-r--r--projects/freetype2/project.yaml1
-rw-r--r--projects/fribidi/Dockerfile22
-rwxr-xr-x[-rw-r--r--]projects/fribidi/build.sh (renamed from infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py)35
-rw-r--r--projects/fribidi/project.yaml17
-rw-r--r--projects/frr/Dockerfile (renamed from infra/base-images/msan-libs-builder/Dockerfile)39
-rwxr-xr-xprojects/frr/build.sh63
-rw-r--r--projects/frr/project.yaml11
-rw-r--r--projects/gcloud-go/Dockerfile2
-rw-r--r--projects/gdal/project.yaml1
-rw-r--r--projects/gdbm/Dockerfile32
-rw-r--r--projects/gdbm/build.sh33
-rw-r--r--projects/gdbm/project.yaml6
-rw-r--r--projects/geos/Dockerfile23
-rwxr-xr-xprojects/geos/build.sh24
-rw-r--r--projects/geos/patch.diff106
-rw-r--r--projects/geos/project.yaml12
-rw-r--r--projects/ghostscript/project.yaml5
-rw-r--r--projects/git/Dockerfile2
-rw-r--r--projects/gitea/Dockerfile2
-rw-r--r--projects/glib/Dockerfile2
-rw-r--r--projects/glib/project.yaml5
-rw-r--r--projects/gnupg/Dockerfile5
-rw-r--r--projects/gnupg/fuzzgnupg.diff58
-rw-r--r--projects/gnupg/project.yaml3
-rw-r--r--projects/gnutls/Dockerfile2
-rwxr-xr-xprojects/gnutls/build.sh4
-rw-r--r--projects/go-attestation/Dockerfile2
-rw-r--r--projects/go-coredns/Dockerfile2
-rw-r--r--projects/go-dns/Dockerfile2
-rw-r--r--projects/go-ethereum/Dockerfile2
-rw-r--r--projects/go-ethereum/project.yaml2
-rw-r--r--projects/go-json-iterator/Dockerfile2
-rw-r--r--projects/go-redis/Dockerfile2
-rw-r--r--projects/go-redis/build.sh3
-rw-r--r--projects/go-sftp/Dockerfile2
-rw-r--r--projects/go-snappy/Dockerfile2
-rw-r--r--projects/go-snappy/project.yaml1
-rw-r--r--projects/go-sqlite3/Dockerfile2
-rw-r--r--projects/golang-protobuf/Dockerfile2
-rw-r--r--projects/golang/Dockerfile11
-rwxr-xr-xprojects/golang/build.sh66
-rw-r--r--projects/golang/math_big_fuzzer.go63
-rw-r--r--projects/golang/project.yaml4
-rw-r--r--projects/golang/text_fuzzer.go36
-rw-r--r--projects/gonids/Dockerfile6
-rwxr-xr-xprojects/gonids/build.sh1
-rw-r--r--projects/gopacket/Dockerfile2
-rwxr-xr-xprojects/gpac/Dockerfile3
-rwxr-xr-xprojects/gpac/build.sh2
-rw-r--r--projects/graphicsmagick/Dockerfile2
-rw-r--r--projects/graphicsmagick/project.yaml3
-rw-r--r--projects/grpc-gateway/Dockerfile2
-rw-r--r--projects/grpc-go/Dockerfile2
-rw-r--r--projects/grpc-httpjson-transcoding/Dockerfile23
-rwxr-xr-xprojects/grpc-httpjson-transcoding/build.sh21
-rw-r--r--projects/grpc-httpjson-transcoding/project.yaml20
-rw-r--r--projects/grpc-swift/Dockerfile23
-rwxr-xr-xprojects/grpc-swift/build.sh31
-rw-r--r--projects/grpc-swift/project.yaml13
-rw-r--r--projects/grpc/Dockerfile3
-rw-r--r--projects/gstreamer/Dockerfile25
-rw-r--r--projects/gvisor/Dockerfile21
-rw-r--r--projects/gvisor/build.sh19
-rw-r--r--projects/gvisor/project.yaml11
-rw-r--r--projects/gvisor/state_fuzzer.go30
-rwxr-xr-xprojects/h2o/build.sh1
-rw-r--r--projects/h2o/h2o-fuzzer-http3.options4
-rw-r--r--projects/h2o/project.yaml5
-rw-r--r--projects/h3/Dockerfile (renamed from projects/libchewing/Dockerfile)12
-rwxr-xr-xprojects/h3/build.sh34
-rw-r--r--projects/h3/h3_fuzzer.c71
-rw-r--r--projects/h3/project.yaml13
-rwxr-xr-xprojects/harfbuzz/build.sh6
-rw-r--r--projects/hcl/Dockerfile20
-rw-r--r--projects/hcl/build.sh36
-rw-r--r--projects/hcl/project.yaml10
-rw-r--r--projects/hermes/Dockerfile13
-rwxr-xr-xprojects/hermes/build.sh17
-rw-r--r--projects/hermes/project.yaml3
-rw-r--r--projects/hostap/project.yaml5
-rw-r--r--projects/http-pattern-matcher/Dockerfile23
-rwxr-xr-xprojects/http-pattern-matcher/build.sh21
-rw-r--r--projects/http-pattern-matcher/project.yaml20
-rw-r--r--projects/httparse/Dockerfile2
-rw-r--r--projects/httplib2/Dockerfile2
-rw-r--r--projects/httplib2/build.sh4
-rw-r--r--projects/hugo/Dockerfile2
-rw-r--r--projects/hugo/fuzz.go3
-rw-r--r--projects/hunspell/project.yaml5
-rw-r--r--projects/hyperium/Dockerfile22
-rwxr-xr-xprojects/hyperium/build.sh31
-rw-r--r--projects/hyperium/project.yaml12
-rw-r--r--projects/ibmswtpm2/project.yaml5
-rw-r--r--projects/icu/project.yaml5
-rw-r--r--projects/image-png/Dockerfile3
-rw-r--r--projects/image-png/buf_independent.rs74
-rw-r--r--projects/image-rs/Dockerfile21
-rwxr-xr-xprojects/image-rs/build.sh21
-rw-r--r--projects/image-rs/project.yaml11
-rw-r--r--projects/imageio/Dockerfile2
-rw-r--r--projects/imageio/build.sh2
-rw-r--r--projects/imagemagick/project.yaml3
-rw-r--r--projects/influxdb/Dockerfile2
-rw-r--r--projects/ipfs/Dockerfile2
-rw-r--r--projects/istio/Dockerfile2
-rw-r--r--projects/istio/build.sh3
-rw-r--r--projects/jackson-core/Dockerfile2
-rw-r--r--projects/jackson-core/build.sh2
-rw-r--r--projects/jackson-dataformat-xml/Dockerfile39
-rw-r--r--projects/jackson-dataformat-xml/XmlFuzzer.java29
-rw-r--r--projects/jackson-dataformat-xml/build.sh52
-rw-r--r--projects/jackson-dataformat-xml/project.yaml10
-rw-r--r--projects/jackson-dataformats-binary/Dockerfile2
-rw-r--r--projects/jackson-dataformats-binary/build.sh2
-rwxr-xr-xprojects/janet/build.sh4
-rw-r--r--projects/janus-gateway/Dockerfile2
-rw-r--r--projects/janus-gateway/project.yaml3
-rw-r--r--projects/java-example/Dockerfile2
-rw-r--r--projects/java-example/ExampleFuzzerNative.cpp12
-rwxr-xr-xprojects/java-example/build.sh9
-rw-r--r--projects/java-example/default.options3
-rw-r--r--projects/java-example/project.yaml2
-rw-r--r--projects/javaparser/Dockerfile (renamed from infra/base-images/base-sanitizer-libs-builder/packages/tar.py)16
-rwxr-xr-xprojects/javaparser/build.sh49
-rw-r--r--projects/javaparser/parseFuzzer.java41
-rw-r--r--projects/javaparser/project.yaml11
-rw-r--r--projects/jbig2dec/jbig2_fuzzer.cc2
-rw-r--r--projects/json-patch/Dockerfile23
-rwxr-xr-xprojects/json-patch/build.sh19
-rw-r--r--projects/json-patch/fuzz_create_merge.go26
-rw-r--r--projects/json-patch/fuzz_decode_apply.go25
-rw-r--r--projects/json-patch/project.yaml10
-rw-r--r--projects/json-sanitizer/Dockerfile2
-rwxr-xr-xprojects/json-sanitizer/build.sh2
-rw-r--r--projects/json/project.yaml5
-rw-r--r--projects/json5format/Dockerfile2
-rw-r--r--projects/jsoncpp/project.yaml5
-rw-r--r--projects/jsonnet/build.sh3
-rw-r--r--projects/jsonnet/project.yaml4
-rw-r--r--projects/jsonparser/Dockerfile2
-rw-r--r--projects/jsonschema/Dockerfile2
-rw-r--r--projects/jsonschema/build.sh2
-rw-r--r--projects/jsoup/Dockerfile38
-rw-r--r--projects/jsoup/HtmlFuzzer.java25
-rw-r--r--projects/jsoup/XmlFuzzer.java26
-rwxr-xr-xprojects/jsoup/build.sh52
-rw-r--r--projects/jsoup/project.yaml11
-rw-r--r--projects/juju/Dockerfile20
-rw-r--r--projects/juju/build.sh25
-rw-r--r--projects/juju/project.yaml10
-rw-r--r--projects/juju/storage_fuzzer.go24
-rwxr-xr-xprojects/kamailio/build.sh7
-rwxr-xr-xprojects/kamailio/project.yaml2
-rw-r--r--projects/karchive/project.yaml5
-rw-r--r--projects/kcodecs/Dockerfile3
-rw-r--r--projects/kcodecs/build.sh14
-rw-r--r--projects/kcodecs/project.yaml5
-rw-r--r--projects/keystone/project.yaml5
-rw-r--r--projects/kimageformats/Dockerfile4
-rw-r--r--projects/kimageformats/build.sh2
-rw-r--r--projects/kimageformats/project.yaml3
-rwxr-xr-xprojects/knot-dns/build.sh9
-rw-r--r--projects/kryo/DeserializeCollectionsFuzzer.java69
-rw-r--r--projects/kryo/DeserializeNumbersFuzzer.java76
-rw-r--r--projects/kryo/DeserializeStringFuzzer.java45
-rw-r--r--projects/kryo/Dockerfile29
-rw-r--r--projects/kryo/build.sh51
-rw-r--r--projects/kryo/project.yaml12
-rw-r--r--projects/kubernetes/Dockerfile2
-rw-r--r--projects/lame/project.yaml5
-rw-r--r--projects/leveldb/project.yaml5
-rw-r--r--projects/libaom/Dockerfile2
-rw-r--r--projects/libaom/av1_dec_fuzzer.dict5
-rwxr-xr-xprojects/libaom/build.sh2
-rw-r--r--projects/libaom/project.yaml2
-rw-r--r--projects/libarchive/Dockerfile10
-rwxr-xr-xprojects/libarchive/build.sh35
-rw-r--r--projects/libass/Dockerfile3
-rwxr-xr-xprojects/libass/build.sh12
-rw-r--r--projects/libass/libass_fuzzer.cc58
-rw-r--r--projects/libass/project.yaml5
-rw-r--r--projects/libavc/project.yaml6
-rw-r--r--projects/libavif/Dockerfile10
-rw-r--r--projects/libavif/bionic.list2
-rwxr-xr-xprojects/libavif/build.sh2
-rw-r--r--projects/libavif/nasm_apt.pin7
-rw-r--r--projects/libcacard/Dockerfile2
-rwxr-xr-xprojects/libcacard/build.sh6
-rwxr-xr-xprojects/libchewing/build.sh39
-rw-r--r--projects/libchewing/chewing_default_fuzzer.c15
-rw-r--r--projects/libchewing/chewing_dynamic_config_fuzzer.c15
-rw-r--r--projects/libchewing/chewing_fuzzer_common.c32
-rw-r--r--projects/libchewing/chewing_fuzzer_common.h13
-rw-r--r--projects/libchewing/chewing_random_init_fuzzer.c15
-rw-r--r--projects/libchewing/project.yaml5
-rw-r--r--projects/libecc/Dockerfile23
-rwxr-xr-xprojects/libecc/build.sh69
-rw-r--r--projects/libecc/project.yaml14
-rw-r--r--projects/libevent/Dockerfile2
-rw-r--r--projects/libevent/project.yaml5
-rw-r--r--projects/libfdk-aac/project.yaml7
-rw-r--r--projects/libfido2/project.yaml5
-rwxr-xr-xprojects/libheif/build.sh3
-rw-r--r--projects/libhevc/project.yaml6
-rw-r--r--projects/libhtp/project.yaml5
-rw-r--r--projects/libidn/Dockerfile2
-rwxr-xr-xprojects/libidn/build.sh8
-rw-r--r--projects/libigl/Dockerfile24
-rwxr-xr-xprojects/libigl/build.sh39
-rw-r--r--projects/libigl/igl_fuzzer.cpp37
-rw-r--r--projects/libigl/project.yaml10
-rw-r--r--projects/libjpeg-turbo/Dockerfile11
-rw-r--r--projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc67
-rw-r--r--projects/libjpeg-turbo/project.yaml4
-rw-r--r--projects/libjxl/Dockerfile25
-rwxr-xr-xprojects/libjxl/build.sh73
-rw-r--r--projects/libjxl/project.yaml12
-rw-r--r--projects/libldac/project.yaml6
-rw-r--r--projects/liblouis/Dockerfile2
-rw-r--r--projects/libmpeg2/project.yaml6
-rw-r--r--projects/libpg_query/Dockerfile20
-rwxr-xr-xprojects/libpg_query/build.sh19
-rw-r--r--projects/libpg_query/project.yaml7
-rw-r--r--projects/libphonenumber/Dockerfile23
-rwxr-xr-xprojects/libphonenumber/build.sh18
-rw-r--r--projects/libpng/project.yaml5
-rw-r--r--projects/libpsl/Dockerfile6
-rwxr-xr-xprojects/libpsl/build.sh24
-rw-r--r--projects/libra/Dockerfile2
-rw-r--r--projects/librawspeed/Dockerfile2
-rw-r--r--projects/libreoffice/Dockerfile151
-rw-r--r--projects/libreoffice/project.yaml10
-rw-r--r--projects/libressl/Dockerfile2
-rwxr-xr-xprojects/libressl/build.sh3
-rw-r--r--projects/libsass/project.yaml5
-rwxr-xr-xprojects/libspectre/project.yaml2
-rw-r--r--projects/libssh/project.yaml5
-rwxr-xr-xprojects/libssh2/build.sh1
-rw-r--r--projects/libtasn1/project.yaml2
-rw-r--r--projects/libtiff/project.yaml5
-rw-r--r--projects/libtpms/Dockerfile4
-rw-r--r--projects/libusb/libusb_fuzzer.cc22
-rw-r--r--projects/libvips/Dockerfile24
-rwxr-xr-xprojects/libvips/build.sh101
-rw-r--r--projects/libvips/project.yaml1
-rw-r--r--projects/libxml2/project.yaml1
-rw-r--r--projects/libxslt/project.yaml1
-rw-r--r--projects/libyal/Dockerfile3
-rwxr-xr-xprojects/libyang/build.sh2
-rw-r--r--projects/libzip/project.yaml5
-rwxr-xr-xprojects/lighttpd/build.sh2
-rw-r--r--projects/linkerd2-proxy/Dockerfile21
-rwxr-xr-xprojects/linkerd2-proxy/build.sh48
-rw-r--r--projects/linkerd2-proxy/project.yaml12
-rw-r--r--projects/lldb-eval/Dockerfile27
-rw-r--r--projects/lldb-eval/build.sh93
-rw-r--r--projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options2
-rw-r--r--projects/lldb-eval/project.yaml11
-rw-r--r--projects/llhttp/Dockerfile24
-rwxr-xr-xprojects/llhttp/build.sh23
-rw-r--r--projects/llhttp/project.yaml6
-rw-r--r--projects/loki/Dockerfile2
-rw-r--r--projects/lotus/Dockerfile2
-rw-r--r--projects/matio/Dockerfile2
-rw-r--r--projects/mbedtls/Dockerfile2
-rw-r--r--projects/mdbtools/build.sh2
-rw-r--r--projects/mercurial/project.yaml5
-rw-r--r--projects/minify/Dockerfile2
-rw-r--r--projects/monero/Dockerfile6
-rw-r--r--projects/mp4parse-rust/Dockerfile2
-rw-r--r--projects/msgpack-c/Dockerfile2
-rw-r--r--projects/mtail/Dockerfile2
-rwxr-xr-xprojects/mtail/build.sh2
-rw-r--r--projects/muduo/Dockerfile21
-rwxr-xr-xprojects/muduo/build.sh33
-rw-r--r--projects/muduo/muduo_http_fuzzer.cpp35
-rw-r--r--projects/muduo/project.yaml10
-rw-r--r--projects/mupdf/Dockerfile2
-rwxr-xr-xprojects/mupdf/build.sh5
-rw-r--r--projects/myanmar-tools/build.sh7
-rw-r--r--projects/myanmar-tools/project.yaml3
-rw-r--r--projects/mysql-server/build.sh2
-rw-r--r--projects/mysql-server/fix.diff86
-rw-r--r--projects/mysql-server/project.yaml1
-rw-r--r--projects/nats/Dockerfile2
-rwxr-xr-xprojects/nats/build.sh7
-rw-r--r--projects/ndpi/Dockerfile2
-rw-r--r--projects/nestegg/project.yaml2
-rw-r--r--projects/net-snmp/Dockerfile8
-rw-r--r--projects/net-snmp/agentx_parse_fuzzer.c47
-rwxr-xr-xprojects/net-snmp/build.sh21
-rw-r--r--projects/net-snmp/project.yaml1
-rw-r--r--projects/net-snmp/snmp_pdu_parse_fuzzer.c44
-rw-r--r--projects/netcdf/Dockerfile21
-rwxr-xr-xprojects/netcdf/build.sh23
-rw-r--r--projects/netcdf/project.yaml11
-rw-r--r--projects/nettle/Dockerfile4
-rwxr-xr-xprojects/nettle/build.sh32
-rw-r--r--projects/nettle/project.yaml3
-rw-r--r--projects/nginx/build.sh3
-rw-r--r--projects/nginx/fuzz/http_request_fuzzer.cc18
-rw-r--r--projects/nginx/project.yaml5
-rw-r--r--projects/ninja/project.yaml5
-rw-r--r--projects/njs/project.yaml9
-rw-r--r--projects/nom/Dockerfile2
-rw-r--r--projects/nss/Dockerfile2
-rw-r--r--projects/oak/Dockerfile42
-rwxr-xr-xprojects/oak/build.sh64
-rw-r--r--projects/oak/project.yaml8
-rw-r--r--projects/oak/rustc.py28
-rw-r--r--projects/oatpp/Dockerfile21
-rwxr-xr-xprojects/oatpp/build.sh23
-rw-r--r--projects/oatpp/project.yaml7
-rwxr-xr-xprojects/open62541/build.sh2
-rw-r--r--projects/open62541/project.yaml9
-rw-r--r--projects/opencensus-cpp/.bazelrc24
-rw-r--r--projects/opencensus-cpp/Dockerfile24
-rw-r--r--projects/opencensus-cpp/WORKSPACE (renamed from infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py)29
-rwxr-xr-xprojects/opencensus-cpp/build.sh22
-rw-r--r--projects/opencensus-cpp/project.yaml10
-rw-r--r--projects/opencv/project.yaml5
-rw-r--r--projects/opendnp3/project.yaml3
-rwxr-xr-xprojects/openexr/build.sh6
-rw-r--r--projects/openexr/project.yaml1
-rw-r--r--projects/openh264/Dockerfile2
-rw-r--r--projects/opensc/project.yaml1
-rwxr-xr-xprojects/opensips/Dockerfile25
-rwxr-xr-xprojects/opensips/build.sh28
-rw-r--r--projects/opensips/fuzz_csv_parser.c54
-rw-r--r--projects/opensips/fuzz_msg_parser.c41
-rw-r--r--projects/opensips/fuzz_uri_parser.c40
-rw-r--r--projects/opensips/patch.diff57
-rwxr-xr-xprojects/opensips/project.yaml10
-rw-r--r--projects/opensk/Dockerfile (renamed from infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py)25
-rwxr-xr-xprojects/opensk/build.sh40
-rw-r--r--projects/opensk/project.yaml13
-rw-r--r--projects/openssh/Dockerfile2
-rw-r--r--projects/openssh/project.yaml2
-rw-r--r--projects/openthread/project.yaml1
-rw-r--r--projects/openvpn/Dockerfile28
-rwxr-xr-xprojects/openvpn/build.sh83
-rw-r--r--projects/openvpn/crypto_patch.txt109
-rw-r--r--projects/openvpn/fuzz.h47
-rw-r--r--projects/openvpn/fuzz_base64.c43
-rw-r--r--projects/openvpn/fuzz_buffer.c266
-rw-r--r--projects/openvpn/fuzz_crypto.c257
-rw-r--r--projects/openvpn/fuzz_dhcp.c37
-rw-r--r--projects/openvpn/fuzz_forward.c228
-rw-r--r--projects/openvpn/fuzz_header.h79
-rw-r--r--projects/openvpn/fuzz_list.c135
-rw-r--r--projects/openvpn/fuzz_misc.c70
-rw-r--r--projects/openvpn/fuzz_mroute.c70
-rw-r--r--projects/openvpn/fuzz_packet_id.c104
-rw-r--r--projects/openvpn/fuzz_proxy.c144
-rw-r--r--projects/openvpn/fuzz_randomizer.cpp107
-rw-r--r--projects/openvpn/fuzz_randomizer.h27
-rw-r--r--projects/openvpn/fuzz_route.c201
-rw-r--r--projects/openvpn/fuzz_verify_cert.c167
-rw-r--r--projects/openvpn/fuzz_verify_cert.h1065
-rw-r--r--projects/openvpn/project.yaml6
-rw-r--r--projects/openvswitch/Dockerfile2
-rw-r--r--projects/openvswitch/project.yaml5
-rw-r--r--projects/openweave/Dockerfile27
-rwxr-xr-xprojects/openweave/build.sh66
-rw-r--r--projects/openweave/patch.diff48
-rw-r--r--projects/openweave/project.yaml10
-rwxr-xr-xprojects/osquery/Dockerfile2
-rwxr-xr-xprojects/osquery/build.sh7
-rw-r--r--projects/ots/project.yaml1
-rw-r--r--projects/p11-kit/Dockerfile4
-rw-r--r--projects/p9/Dockerfile2
-rw-r--r--projects/perfetto/project.yaml11
-rw-r--r--projects/pffft/Dockerfile2
-rwxr-xr-xprojects/phmap/Dockerfile22
-rwxr-xr-xprojects/phmap/build.sh19
-rw-r--r--projects/phmap/phashmap_fuzz.cc66
-rwxr-xr-xprojects/phmap/project.yaml6
-rw-r--r--projects/php/Dockerfile1
-rwxr-xr-xprojects/php/build.sh36
-rw-r--r--projects/pidgin/Dockerfile38
-rw-r--r--projects/pidgin/build.sh127
-rw-r--r--projects/pidgin/pidgin_utils_fuzzer.c78
-rw-r--r--projects/pidgin/pidgin_xml_fuzzer.c55
-rw-r--r--projects/pidgin/project.yaml5
-rw-r--r--projects/pillow/Dockerfile22
-rw-r--r--projects/pillow/build.sh31
-rw-r--r--projects/pistache/Dockerfile22
-rwxr-xr-xprojects/pistache/build.sh22
-rw-r--r--projects/pistache/project.yaml10
-rw-r--r--projects/poco/Dockerfile23
-rwxr-xr-xprojects/poco/build.sh37
-rw-r--r--projects/poco/json_parse_fuzzer.cc30
-rw-r--r--projects/poco/project.yaml11
-rw-r--r--projects/poppler/Dockerfile8
-rwxr-xr-xprojects/poppler/build.sh14
-rw-r--r--projects/poppler/project.yaml5
-rw-r--r--projects/postgis/Dockerfile3
-rw-r--r--projects/postgresql/add_fuzzers.diff42
-rw-r--r--projects/postgresql/build.sh9
-rw-r--r--projects/postgresql/fuzzer/fuzzer_initialize.c3
-rw-r--r--projects/postgresql/fuzzer/protocol_fuzzer.c4
-rw-r--r--projects/powerdns/Dockerfile2
-rw-r--r--projects/powerdns/build.sh22
-rw-r--r--projects/proftpd/Dockerfile22
-rwxr-xr-xprojects/proftpd/build.sh46
-rw-r--r--projects/proftpd/fuzzer.c43
-rw-r--r--projects/proftpd/project.yaml9
-rw-r--r--projects/prometheus/Dockerfile2
-rw-r--r--projects/prost/Dockerfile20
-rwxr-xr-xprojects/prost/build.sh21
-rw-r--r--projects/prost/project.yaml10
-rwxr-xr-xprojects/protobuf-c/build.sh3
-rw-r--r--projects/protobuf-c/project.yaml5
-rw-r--r--projects/protobuf-java/Dockerfile34
-rw-r--r--projects/protobuf-java/ProtobufFuzzer.java33
-rwxr-xr-xprojects/protobuf-java/build.sh69
-rw-r--r--projects/protobuf-java/project.yaml14
-rw-r--r--projects/protoreflect/Dockerfile24
-rwxr-xr-xprojects/protoreflect/build.sh20
-rw-r--r--projects/protoreflect/fuzz_dynamic.go33
-rw-r--r--projects/protoreflect/fuzz_protoparse.go21
-rw-r--r--projects/protoreflect/project.yaml10
-rw-r--r--projects/proxygen/Dockerfile12
-rwxr-xr-xprojects/proxygen/build.sh9
-rw-r--r--projects/pulumi/Dockerfile23
-rw-r--r--projects/pulumi/build.sh26
-rw-r--r--projects/pulumi/config_fuzzer.go51
-rw-r--r--projects/pulumi/project.yaml10
-rw-r--r--projects/pulumi/schema_fuzzer.go31
-rw-r--r--projects/pygments/Dockerfile4
-rw-r--r--projects/pygments/build.sh4
-rw-r--r--projects/pygments/fuzz_guesser.py (renamed from projects/pygments/pygments_fuzzer.py)21
-rw-r--r--projects/pygments/fuzz_lexers.py40
-rw-r--r--projects/python-lz4/Dockerfile2
-rw-r--r--projects/python-lz4/build.sh2
-rw-r--r--projects/python-lz4/fuzz_lz4.py3
-rw-r--r--projects/python3-libraries/Dockerfile3
-rw-r--r--projects/pyyaml/Dockerfile2
-rw-r--r--projects/pyyaml/build.sh2
-rw-r--r--projects/pyyaml/fuzz_loader.py6
-rw-r--r--projects/pyyaml/fuzz_reader.py6
-rw-r--r--projects/qcms/Dockerfile2
-rw-r--r--projects/qemu/Dockerfile13
-rwxr-xr-xprojects/qemu/build.sh20
-rw-r--r--projects/qemu/default.options3
-rw-r--r--projects/qemu/project.yaml1
-rw-r--r--projects/qpdf/project.yaml3
-rw-r--r--projects/qt/project.yaml4
-rw-r--r--projects/quic-go/Dockerfile2
-rw-r--r--projects/quick-xml/Dockerfile22
-rwxr-xr-xprojects/quick-xml/build.sh20
-rw-r--r--projects/quick-xml/fuzz_target_1.rs58
-rw-r--r--projects/quick-xml/project.yaml10
-rw-r--r--projects/quickjs/project.yaml2
-rw-r--r--projects/radare2/Dockerfile4
-rwxr-xr-xprojects/radare2/build.sh2
-rw-r--r--projects/radare2/project.yaml4
-rw-r--r--projects/radon/Dockerfile2
-rw-r--r--projects/rdkit/Dockerfile8
-rw-r--r--projects/re2/project.yaml5
-rw-r--r--projects/relic/Dockerfile2
-rwxr-xr-xprojects/relic/build.sh6
-rw-r--r--projects/relic/project.yaml3
-rw-r--r--projects/resiprocate/Dockerfile7
-rwxr-xr-xprojects/rnp/Dockerfile2
-rwxr-xr-xprojects/rnp/build.sh2
-rwxr-xr-xprojects/rocksdb/build.sh1
-rw-r--r--projects/runc/Dockerfile2
-rw-r--r--projects/rust-regex/Dockerfile2
-rw-r--r--projects/rustls/Dockerfile3
-rwxr-xr-xprojects/rustls/build.sh6
-rw-r--r--projects/rustls/project.yaml2
-rw-r--r--projects/s2geometry/Dockerfile43
-rwxr-xr-xprojects/s2geometry/build.sh34
-rw-r--r--projects/s2geometry/project.yaml10
-rw-r--r--projects/s2geometry/s2_fuzzer.cc99
-rw-r--r--projects/samba/project.yaml2
-rw-r--r--projects/scapy/Dockerfile2
-rw-r--r--projects/scapy/build.sh2
-rw-r--r--projects/scapy/pcap_fuzzer.py11
-rw-r--r--projects/selinux/Dockerfile2
-rwxr-xr-xprojects/selinux/build.sh11
-rw-r--r--projects/selinux/secilc-fuzzer.c87
-rw-r--r--projects/sentencepiece/project.yaml5
-rw-r--r--projects/serde-yaml/Dockerfile2
-rw-r--r--projects/serde_json/Dockerfile2
-rw-r--r--projects/servo/Dockerfile2
-rw-r--r--projects/simd/Dockerfile21
-rwxr-xr-xprojects/simd/build.sh30
-rw-r--r--projects/simd/project.yaml10
-rw-r--r--projects/simd/simd_load_fuzzer.cpp32
-rw-r--r--projects/simdjson/project.yaml7
-rw-r--r--projects/skia/Dockerfile2
-rw-r--r--projects/skia/build.sh87
-rw-r--r--projects/skia/project.yaml5
-rw-r--r--projects/sleuthkit/Dockerfile2
-rwxr-xr-xprojects/sleuthkit/build.sh14
-rwxr-xr-xprojects/sleuthkit/buildcorpus.sh77
-rw-r--r--projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc60
-rw-r--r--projects/smt/Dockerfile21
-rwxr-xr-xprojects/smt/build.sh18
-rw-r--r--projects/smt/project.yaml12
-rw-r--r--projects/solidity/Dockerfile7
-rwxr-xr-xprojects/solidity/build.sh32
-rw-r--r--projects/sound-open-firmware/project.yaml5
-rw-r--r--projects/spdk/Dockerfile23
-rwxr-xr-xprojects/spdk/build.sh32
-rw-r--r--projects/spdk/parse_json_fuzzer.cc (renamed from infra/base-images/base-sanitizer-libs-builder/Dockerfile)24
-rw-r--r--projects/spdk/project.yaml10
-rw-r--r--projects/spdlog/project.yaml5
-rw-r--r--projects/spice-usbredir/Dockerfile31
-rwxr-xr-xprojects/spice-usbredir/build.sh18
-rw-r--r--projects/spice-usbredir/project.yaml11
-rw-r--r--projects/spidermonkey/Dockerfile3
-rwxr-xr-xprojects/spidermonkey/build.sh3
-rw-r--r--projects/spirv-tools/Dockerfile21
-rwxr-xr-xprojects/spirv-tools/build.sh107
-rw-r--r--projects/spirv-tools/project.yaml15
-rwxr-xr-xprojects/sql-parser/Dockerfile23
-rwxr-xr-xprojects/sql-parser/build.sh22
-rw-r--r--projects/sql-parser/fuzz_sql_parse.cpp26
-rwxr-xr-xprojects/sql-parser/project.yaml7
-rw-r--r--projects/sqlalchemy/Dockerfile20
-rw-r--r--projects/sqlalchemy/build.sh31
-rw-r--r--projects/sqlalchemy/project.yaml11
-rw-r--r--projects/sqlalchemy/sqlalchemy_fuzzer.py52
-rw-r--r--projects/stb/Dockerfile15
-rwxr-xr-xprojects/sudoers/build.sh6
-rwxr-xr-xprojects/sudoers/project.yaml3
-rw-r--r--projects/suricata/Dockerfile7
-rwxr-xr-xprojects/suricata/build.sh30
-rw-r--r--projects/suricata/project.yaml5
-rw-r--r--projects/swift-nio/Dockerfile24
-rw-r--r--projects/swift-nio/Package.swift19
-rwxr-xr-xprojects/swift-nio/build.sh40
-rw-r--r--projects/swift-nio/fuzz_http1.swift21
-rw-r--r--projects/swift-nio/project.yaml14
-rw-r--r--projects/swift-protobuf/Dockerfile21
-rwxr-xr-xprojects/swift-protobuf/build.sh41
-rw-r--r--projects/swift-protobuf/project.yaml13
-rw-r--r--projects/systemd/Dockerfile2
-rw-r--r--projects/syzkaller/Dockerfile2
-rw-r--r--projects/syzkaller/project.yaml1
-rw-r--r--projects/tailscale/Dockerfile20
-rw-r--r--projects/tailscale/build.sh18
-rw-r--r--projects/tailscale/project.yaml12
-rw-r--r--projects/tcmalloc/Dockerfile21
-rwxr-xr-xprojects/tcmalloc/build.sh18
-rw-r--r--projects/tcmalloc/project.yaml10
-rw-r--r--projects/tdengine/Dockerfile22
-rwxr-xr-xprojects/tdengine/build.sh47
-rw-r--r--projects/tdengine/project.yaml6
-rw-r--r--projects/tdengine/sql-fuzzer.options2
-rw-r--r--projects/teleport/Dockerfile2
-rw-r--r--projects/tendermint/Dockerfile21
-rwxr-xr-xprojects/tendermint/build.sh18
-rw-r--r--projects/tendermint/project.yaml15
-rw-r--r--projects/tensorflow-py/Dockerfile2
-rw-r--r--projects/tensorflow-py/build.sh2
-rw-r--r--projects/tensorflow-py/project.yaml1
-rw-r--r--projects/tesseract-ocr/Dockerfile18
-rw-r--r--projects/thrift/Dockerfile25
-rwxr-xr-xprojects/thrift/build.sh4
-rw-r--r--projects/tidb/Dockerfile2
-rwxr-xr-xprojects/tidb/build.sh4
-rw-r--r--projects/tidy-html5/build.sh4
-rw-r--r--projects/tidy-html5/project.yaml2
-rw-r--r--projects/tidy-html5/tidy_general_fuzzer.c160
-rw-r--r--projects/tidy-html5/tidy_parse_file_fuzzer.c64
-rw-r--r--projects/tidy-html5/tidy_parse_string_fuzzer.c57
-rw-r--r--projects/tidy-html5/tidy_xml_fuzzer.c66
-rw-r--r--projects/tint/Dockerfile23
-rwxr-xr-xprojects/tint/build.sh106
-rw-r--r--projects/tint/project.yaml13
-rw-r--r--projects/tinyobjloader/Dockerfile20
-rwxr-xr-xprojects/tinyobjloader/build.sh23
-rw-r--r--projects/tinyobjloader/project.yaml10
-rw-r--r--projects/tmux/build.sh5
-rw-r--r--projects/tor/Dockerfile2
-rw-r--r--projects/tor/build.sh6
-rw-r--r--projects/tpm2-tss/Dockerfile4
-rw-r--r--projects/tpm2-tss/project.yaml8
-rw-r--r--projects/tpm2/Dockerfile2
-rw-r--r--projects/ujson/Dockerfile4
-rwxr-xr-xprojects/ujson/build.sh2
-rw-r--r--projects/ujson/hypothesis_structured_fuzzer.py3
-rwxr-xr-xprojects/ujson/json_differential_fuzzer.py10
-rwxr-xr-xprojects/ujson/ujson_fuzzer.py2
-rw-r--r--projects/unicode-rs/Dockerfile23
-rwxr-xr-xprojects/unicode-rs/build.sh29
-rw-r--r--projects/unicode-rs/project.yaml10
-rw-r--r--projects/unrar/project.yaml5
-rw-r--r--projects/upb/Dockerfile4
-rwxr-xr-xprojects/upb/build.sh14
-rw-r--r--projects/upb/project.yaml2
-rw-r--r--projects/uriparser/project.yaml5
-rw-r--r--projects/urllib3/Dockerfile2
-rw-r--r--projects/urllib3/build.sh2
-rw-r--r--projects/urllib3/fuzz_urlparse.py1
-rw-r--r--projects/usbguard/build.sh7
-rw-r--r--projects/usbguard/project.yaml3
-rw-r--r--projects/usrsctp/project.yaml4
-rw-r--r--projects/uwebsockets/project.yaml5
-rw-r--r--projects/varnish/Dockerfile21
-rwxr-xr-xprojects/varnish/build.sh27
-rw-r--r--projects/varnish/project.yaml11
-rw-r--r--projects/vitess/Dockerfile2
-rw-r--r--projects/vlc/Dockerfile22
-rwxr-xr-xprojects/vlc/build.sh53
-rw-r--r--projects/vlc/project.yaml10
-rw-r--r--projects/wasm3/Dockerfile21
-rwxr-xr-xprojects/wasm3/build.sh21
-rw-r--r--projects/wasm3/project.yaml14
-rw-r--r--projects/wasmtime/Dockerfile8
-rwxr-xr-xprojects/wasmtime/build.sh3
-rw-r--r--projects/wavpack/Dockerfile2
-rwxr-xr-xprojects/wazuh/Dockerfile23
-rwxr-xr-xprojects/wazuh/build.sh25
-rw-r--r--projects/wazuh/fuzz_xml.c72
-rw-r--r--projects/wazuh/fuzz_xml.options2
-rwxr-xr-xprojects/wazuh/project.yaml6
-rw-r--r--projects/wget/Dockerfile1
-rwxr-xr-xprojects/wget/build.sh22
-rw-r--r--projects/wget2/Dockerfile3
-rwxr-xr-xprojects/wget2/build.sh20
-rw-r--r--projects/wolfssl/Dockerfile22
-rwxr-xr-xprojects/wolfssl/build.sh115
-rw-r--r--projects/wolfssl/project.yaml3
-rwxr-xr-xprojects/wuffs/build.sh34
-rw-r--r--projects/xmlsec/Dockerfile2
-rwxr-xr-xprojects/xmlsec/build.sh5
-rw-r--r--projects/xnu/Dockerfile37
-rwxr-xr-xprojects/xnu/build.sh24
-rw-r--r--projects/xnu/project.yaml9
-rwxr-xr-xprojects/xpdf/Dockerfile2
-rw-r--r--projects/yajl-ruby/project.yaml2
-rw-r--r--projects/ygot/Dockerfile2
-rw-r--r--projects/zeek/build.sh2
-rw-r--r--projects/zeek/project.yaml3
-rw-r--r--projects/znc/Dockerfile21
-rwxr-xr-xprojects/znc/build.sh33
-rw-r--r--projects/znc/msg_parse_fuzzer.cpp30
-rw-r--r--projects/znc/project.yaml12
-rw-r--r--projects/zopfli/project.yaml5
-rw-r--r--projects/zxing/Dockerfile29
-rw-r--r--projects/zxing/MultiFormatDecodeFuzzer.java56
-rw-r--r--projects/zxing/MultiFormatEncodeFuzzer.java187
-rw-r--r--projects/zxing/build.sh53
-rw-r--r--projects/zxing/project.yaml11
-rwxr-xr-xprojects/zydis/build.sh3
1024 files changed, 27217 insertions, 6694 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 000000000..50dc55e8b
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+/projects/librawspeed/ @LebedevRI
diff --git a/.github/workflows/infra_tests.yml b/.github/workflows/infra_tests.yml
index 5273adc45..53c1ad54f 100644
--- a/.github/workflows/infra_tests.yml
+++ b/.github/workflows/infra_tests.yml
@@ -3,6 +3,7 @@ on:
pull_request:
paths:
- 'infra/**'
+ - '.github/workflows/**'
jobs:
build:
@@ -15,8 +16,9 @@ jobs:
access_token: ${{ github.token }}
- uses: actions/checkout@v2
- - run: | # Needed for git diff to work.
- git fetch origin master --depth 1
+ 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
@@ -29,12 +31,13 @@ jobs:
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: GoogleCloudPlatform/github-actions/setup-gcloud@master
+ - uses: google-github-actions/setup-gcloud@master
with:
version: '298.0.0'
- run: |
sudo env "PATH=$PATH" gcloud components install beta cloud-datastore-emulator
- name: Run infra tests
- run: sudo env "PATH=$PATH" INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p
+ run: sudo env "PATH=$PATH" END_TO_END_TESTS=1 INTEGRATION_TESTS=1 python infra/presubmit.py infra-tests -p
diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml
index 9a4b8d698..1e80301ab 100644
--- a/.github/workflows/presubmit.yml
+++ b/.github/workflows/presubmit.yml
@@ -16,8 +16,9 @@ jobs:
access_token: ${{ github.token }}
- uses: actions/checkout@v2
- - run: | # Needed for git diff to work.
- git fetch origin master --depth 1
+ 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
diff --git a/.github/workflows/project_tests.yml b/.github/workflows/project_tests.yml
index 55dfb7f39..4d5e4f02a 100644
--- a/.github/workflows/project_tests.yml
+++ b/.github/workflows/project_tests.yml
@@ -48,8 +48,9 @@ jobs:
access_token: ${{ github.token }}
- uses: actions/checkout@v2
- - run: | # Needed for git diff to work.
- git fetch origin master --depth 1
+ 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
diff --git a/METADATA b/METADATA
index dfba61b91..9380fa5d0 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/oss-fuzz.git"
}
- version: "947169dc86572e121c3e138f366a9f39ac6266ae"
+ version: "fd15c6d57aa13667af2521daf6167a2d8cd2ecb7"
license_type: RESTRICTED
last_upgrade_date {
year: 2021
- month: 4
- day: 1
+ month: 10
+ day: 12
}
}
diff --git a/README.md b/README.md
index 4e5474a05..0baf34bf8 100644
--- a/README.md
+++ b/README.md
@@ -44,11 +44,11 @@ Read our [detailed documentation] to learn how to use OSS-Fuzz.
[detailed documentation]: https://google.github.io/oss-fuzz
## Trophies
-As of January 2021, OSS-Fuzz has found over [25,000] bugs in [375] open source
+As of June 2021, OSS-Fuzz has found over [30,000] bugs in [500] open source
projects.
-[25,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
-[375]: https://github.com/google/oss-fuzz/tree/master/projects
+[30,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
+[500]: https://github.com/google/oss-fuzz/tree/master/projects
## Blog posts
* 2016-12-01 - [Announcing OSS-Fuzz: Continuous fuzzing for open source software]
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index a6807df0e..b67c3bc47 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -1,13 +1,13 @@
GEM
remote: https://rubygems.org/
specs:
- activesupport (6.0.3.4)
+ activesupport (6.0.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
- addressable (2.7.0)
+ addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
@@ -16,26 +16,40 @@ GEM
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
- concurrent-ruby (1.1.7)
- dnsruby (1.61.5)
+ concurrent-ruby (1.1.9)
+ dnsruby (1.61.7)
simpleidn (~> 0.1)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
- ethon (0.12.0)
- ffi (>= 1.3.0)
+ ethon (0.14.0)
+ ffi (>= 1.15.0)
eventmachine (1.2.7)
- execjs (2.7.0)
- faraday (1.3.0)
+ execjs (2.8.1)
+ faraday (1.6.0)
+ faraday-em_http (~> 1.0)
+ faraday-em_synchrony (~> 1.0)
+ faraday-excon (~> 1.1)
+ faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
+ faraday-net_http_persistent (~> 1.1)
+ faraday-patron (~> 1.0)
+ faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
- ruby2_keywords
- faraday-net_http (1.0.0)
- ffi (1.14.2)
+ ruby2_keywords (>= 0.0.4)
+ faraday-em_http (1.0.0)
+ faraday-em_synchrony (1.0.0)
+ faraday-excon (1.1.0)
+ faraday-httpclient (1.0.1)
+ faraday-net_http (1.0.1)
+ faraday-net_http_persistent (1.2.0)
+ faraday-patron (1.0.0)
+ faraday-rack (1.0.0)
+ ffi (1.15.3)
forwardable-extended (2.6.0)
gemoji (3.0.1)
- github-pages (209)
- github-pages-health-check (= 1.16.1)
+ github-pages (218)
+ github-pages-health-check (= 1.17.2)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
@@ -50,39 +64,39 @@ GEM
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
- jekyll-remote-theme (= 0.4.2)
+ jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
- jekyll-seo-tag (= 2.6.1)
+ jekyll-seo-tag (= 2.7.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
- jekyll-theme-architect (= 0.1.1)
- jekyll-theme-cayman (= 0.1.1)
- jekyll-theme-dinky (= 0.1.1)
- jekyll-theme-hacker (= 0.1.2)
- jekyll-theme-leap-day (= 0.1.1)
- jekyll-theme-merlot (= 0.1.1)
- jekyll-theme-midnight (= 0.1.1)
- jekyll-theme-minimal (= 0.1.1)
- jekyll-theme-modernist (= 0.1.1)
- jekyll-theme-primer (= 0.5.4)
- jekyll-theme-slate (= 0.1.1)
- jekyll-theme-tactile (= 0.1.1)
- jekyll-theme-time-machine (= 0.1.1)
+ jekyll-theme-architect (= 0.2.0)
+ jekyll-theme-cayman (= 0.2.0)
+ jekyll-theme-dinky (= 0.2.0)
+ jekyll-theme-hacker (= 0.2.0)
+ jekyll-theme-leap-day (= 0.2.0)
+ jekyll-theme-merlot (= 0.2.0)
+ jekyll-theme-midnight (= 0.2.0)
+ jekyll-theme-minimal (= 0.2.0)
+ jekyll-theme-modernist (= 0.2.0)
+ jekyll-theme-primer (= 0.6.0)
+ jekyll-theme-slate (= 0.2.0)
+ jekyll-theme-tactile (= 0.2.0)
+ jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
- kramdown (= 2.3.0)
+ kramdown (= 2.3.1)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.10.4, < 2.0)
- rouge (= 3.23.0)
+ rouge (= 3.26.0)
terminal-table (~> 1.4)
- github-pages-health-check (1.16.1)
+ github-pages-health-check (1.17.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
- public_suffix (~> 3.0)
+ public_suffix (>= 2.0.2, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
activesupport (>= 2)
@@ -136,57 +150,57 @@ GEM
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
- jekyll-remote-theme (0.4.2)
+ jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
- jekyll-seo-tag (2.6.1)
- jekyll (>= 3.3, < 5.0)
+ jekyll-seo-tag (2.7.1)
+ jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
- jekyll-theme-architect (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-architect (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-cayman (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-cayman (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-dinky (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-dinky (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-hacker (0.1.2)
+ jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-leap-day (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-leap-day (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-merlot (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-merlot (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-midnight (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-midnight (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-minimal (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-minimal (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-modernist (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-modernist (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-primer (0.5.4)
+ jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-slate (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-slate (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-tactile (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-tactile (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
- jekyll-theme-time-machine (0.1.1)
- jekyll (~> 3.5)
+ jekyll-theme-time-machine (0.2.0)
+ jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
@@ -196,41 +210,39 @@ GEM
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
- kramdown (2.3.0)
+ kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
- listen (3.4.0)
+ listen (3.6.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
- mini_portile2 (2.5.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
- minitest (5.14.3)
+ minitest (5.14.4)
multipart-post (2.1.1)
- nokogiri (1.11.1)
- mini_portile2 (~> 2.5.0)
+ nokogiri (1.12.5-x86_64-linux)
racc (~> 1.4)
- octokit (4.20.0)
+ octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
- public_suffix (3.1.1)
+ public_suffix (4.0.6)
racc (1.5.2)
- rb-fsevent (0.10.4)
+ rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
- rexml (3.2.4)
- rouge (3.23.0)
- ruby-enum (0.8.0)
+ rexml (3.2.5)
+ rouge (3.26.0)
+ ruby-enum (0.9.0)
i18n
- ruby2_keywords (0.0.2)
- rubyzip (2.3.0)
+ ruby2_keywords (0.0.5)
+ rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -240,7 +252,7 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
- simpleidn (0.1.1)
+ simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
@@ -256,10 +268,10 @@ GEM
zeitwerk (2.4.2)
PLATFORMS
- ruby
+ x86_64-linux
DEPENDENCIES
github-pages
BUNDLED WITH
- 2.1.4
+ 2.2.16
diff --git a/docs/README.md b/docs/README.md
index db0358faa..af2bc4b31 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -5,7 +5,8 @@ Use the following instructions to make documentation changes locally.
## Prerequisites
```bash
$ sudo apt install ruby bundler
-$ bundle install --path vendor/bundle
+$ bundle config set path 'vendor/bundle'
+$ bundle install
```
## Serving locally
diff --git a/docs/advanced-topics/bug_fixing_guidance.md b/docs/advanced-topics/bug_fixing_guidance.md
new file mode 100644
index 000000000..1ba0bd53b
--- /dev/null
+++ b/docs/advanced-topics/bug_fixing_guidance.md
@@ -0,0 +1,94 @@
+---
+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 `python 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.
diff --git a/docs/advanced-topics/code_coverage.md b/docs/advanced-topics/code_coverage.md
index 3b0acc26c..f307ad0e6 100644
--- a/docs/advanced-topics/code_coverage.md
+++ b/docs/advanced-topics/code_coverage.md
@@ -9,9 +9,10 @@ permalink: /advanced-topics/code-coverage/
# Code Coverage
{: .no_toc}
-For projects written in C/C++, you can generate code coverage reports using
-Clang source-based code coverage. This page walks you through the basic steps.
-For more details, see [Clang's documentation].
+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.
@@ -98,7 +99,7 @@ $ python infra/helper.py coverage --fuzz-target=<fuzz_target_name> \
--corpus-dir=<my_local_corpus_dir> $PROJECT_NAME
```
-### Additional arguments for `llvm-cov`
+### Additional arguments for `llvm-cov` (C/C++ 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 `--`:
diff --git a/docs/advanced-topics/reproducing.md b/docs/advanced-topics/reproducing.md
index 95bb09c5c..c2ed147d4 100644
--- a/docs/advanced-topics/reproducing.md
+++ b/docs/advanced-topics/reproducing.md
@@ -38,7 +38,7 @@ the fuzz target with your build and test system, all you have to do is run this
$ ./fuzz_target_binary <testcase_path>
```
-For timeout bugs, add the `-timeout=25` argument. For OOM bugs, add the
+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).
@@ -82,8 +82,11 @@ The `sanitizer` used in the report is the value in the
* **memory** for MemorySanitizer.
* **undefined** for UndefinedBehaviorSanitizer.
-**Note**: The `architecture` argument is only necessary if you want to specify
+**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
diff --git a/docs/clusterfuzzlite/advanced/adding_ci_support.md b/docs/clusterfuzzlite/advanced/adding_ci_support.md
new file mode 100644
index 000000000..2e855edd8
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced/adding_ci_support.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Advanced Topics
+grand_parent: ClusterFuzzLite
+title: Adding Support for a New CI
+nav_order: 1
+permalink: /clusterfuzzlite/advanced-topics/adding-ci-support/
+---
+
+# Adding Support for a New CI
+
+TODO
diff --git a/docs/clusterfuzzlite/advanced/architecture.md b/docs/clusterfuzzlite/advanced/architecture.md
new file mode 100644
index 000000000..a564f378d
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced/architecture.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Advanced Topics
+grand_parent: ClusterFuzzLite
+title: Architecture
+nav_order: 1
+permalink: /clusterfuzzlite/advanced-topics/architecture/
+---
+
+# Architecture
+
+TODO
diff --git a/docs/clusterfuzzlite/advanced_topics.md b/docs/clusterfuzzlite/advanced_topics.md
new file mode 100644
index 000000000..c5b49e125
--- /dev/null
+++ b/docs/clusterfuzzlite/advanced_topics.md
@@ -0,0 +1,10 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Advanced Topics
+has_children: true
+nav_order: 4
+permalink: /clusterfuzzlite/advanced-topics/
+---
+
+# Advanced topics
diff --git a/docs/clusterfuzzlite/build_integration.md b/docs/clusterfuzzlite/build_integration.md
new file mode 100644
index 000000000..7310f7f6d
--- /dev/null
+++ b/docs/clusterfuzzlite/build_integration.md
@@ -0,0 +1,269 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Build Integration
+has_children: true
+nav_order: 2
+permalink: /clusterfuzzlite/build-integration/
+---
+# Build integration
+{: .no_toc}
+
+- TOC
+{:toc}
+---
+
+## Prerequisites
+ClusterFuzzLite supports statically linked
+[libFuzzer targets]({{ site.baseurl }}/reference/glossary/#fuzz-target) on
+Linux.
+
+We re-use the [OSS-Fuzz](https://github.com/google/oss-fuzz) toolchain to make
+building easier. If you are familiar with this, most of the concepts here are
+exactly the same, with one key difference. Rather than checking out the source
+code in the [`Dockerfile`](#dockerfile) using `git clone`, the `Dockerfile`
+copies in the source code directly during `docker build`.
+
+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 TODO.
+- [Install Docker](https://docs.docker.com/engine/installation)
+ [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.
+
+- Clone the OSS-Fuzz repo: `git clone https://github.com/google/oss-fuzz.git`
+
+## Generating an empty build integration
+
+Build integrations consist of three configuration files:
+* [./clusterfuzzlite/project.yaml](#projectyaml) - provides metadata about the project.
+* [./clusterfuzzlite/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).
+* [./clusterfuzzlite/build.sh](#buildsh) - defines the build script that executes inside the Docker container and
+generates the project build.
+
+These must live in the `.clusterfuzzlite` directory in the root of your
+project's source code checkout.
+
+You can generate empty versions of these files with the following command:
+
+```bash
+$ cd /path/to/oss-fuzz
+$ export PATH_TO_PROJECT=<path_to_your_project>
+$ python infra/helper.py generate $PATH_TO_PROJECT --external
+```
+
+Once the configuration files are generated, you should modify them to fit your
+project.
+
+## project.yaml {#projectyaml}
+
+This configuration file stores project metadata. The following attributes are
+supported:
+
+- [language](#language)
+
+### 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/)
+
+## Dockerfile {#dockerfile}
+
+This integration 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
+COPY . $SRC/<project_name> # checkout all sources needed to build your project
+WORKDIR $SRC/<project_name> # current directory for the build script
+COPY ./clusterfuzzlite/build.sh fuzzer.cc $SRC/ # copy build script into src dir
+```
+TODO: Provide examples.
+
+## 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 OSS-Fuzz's compiler.
+- Provide OSS-Fuzz's compiler flags (defined as [environment variables](#Requirements)) to the build system.
+- Build your [fuzz targets]({{ site.baseurl }}/reference/glossary/#fuzz-target)
+ and link your project's build with `$LIB_FUZZING_ENGINE` (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. 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.
+1. 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
+```
+TODO: Figure out if we should include this AFL code.
+
+### 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 <fuzzer/FuzzedDataProvider.h>` 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.
+
+## 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 running ClusterFuzzLite.
+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
+ $ python infra/helper.py build_image $PATH_TO_PROJECT --external
+ $ python infra/helper.py build_fuzzers $PATH_TO_PROJECT --sanitizer <address/undefined/coverage> --external
+ ```
+
+ The built binaries appear in the `/path/to/oss-fuzz/build/out/$PROJECT_NAME`
+ directory on your machine (and `$OUT` in the container). Note that
+ `$PROJECT_NAME` is the name of the directory of your project (e.g. if
+ `$PATH_TO_PROJECT` is `/path/to/systemd`, `$PROJECT_NAME` is systemd.
+
+ **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
+ $ python infra/helper.py check_build $PATH_TO_PROJECT --external
+ ```
+
+3. If you want to test changes against a particular fuzz target, run the following command:
+
+ ```bash
+ $ python infra/helper.py run_fuzzer --external --corpus-dir=<path-to-temp-corpus-dir> $PATH_TO_PROJECT <fuzz_target>
+ ```
+
+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
+ $ python infra/helper.py build_fuzzers --sanitizer coverage $PATH_TO_PROJECT
+ $ python infra/helper.py coverage $PATH_TO_PROJECT --fuzz-target=<fuzz_target> --corpus-dir=<path-to-temp-corpus-dir> --external
+ ```
+
+You may need to run `python 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, ClusterFuzzLite only supports AddressSanitizer (address)
+and UndefinedBehaviorSanitizer (undefined) configurations.
+<b>Make sure to test each
+of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
+
+If everything works locally, it should also work on ClusterFuzzLite. 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, the [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, please read [this section](
+{{ site.baseurl }}/getting-started/new-project-guide/#efficient-fuzzing).
+
+TODO(metzman): We probably want a TOC for lang-specific guides (which we still need to add).
diff --git a/docs/clusterfuzzlite/clusterfuzzlite.md b/docs/clusterfuzzlite/clusterfuzzlite.md
new file mode 100644
index 000000000..9dfd30a2b
--- /dev/null
+++ b/docs/clusterfuzzlite/clusterfuzzlite.md
@@ -0,0 +1,27 @@
+---
+layout: default
+title: ClusterFuzzLite
+has_children: true
+nav_order: 8
+permalink: /clusterfuzzlite/
+<!-- Hide for now by setting "published: false" -->
+published: false
+---
+
+# ClusterFuzzLite
+ClusterFuzzLite is a lightweight, easy-to-use, fuzzing infrastructure that is
+based off [ClusterFuzz]. ClusterFuzzLite is designed to run on [continuous integration] (CI)
+systems, which means it is easy to set up and provides a familiar interface for
+users.
+Currently CIFuzz fully supports [GitHub Actions]. However ClusterFuzzLite is
+designed so that supporting new CI systems is trivial and core features can be
+used on any CI system without any additional effort.
+
+See [Overview] for a more detailed description of how ClusterFuzzLite works and
+how you can use it.
+
+[continous integration]: https://en.wikipedia.org/wiki/Continuous_integration
+[fuzzing]: https://en.wikipedia.org/wiki/Fuzzing
+[ClusterFuzz]: https://google.github.io/clusterfuzz/
+[GitHub Actions]: https://docs.github.com/en/actions
+[Overview]: {{ site.baseurl }}/clusterfuzzlite/overview/
diff --git a/docs/clusterfuzzlite/overview.md b/docs/clusterfuzzlite/overview.md
new file mode 100644
index 000000000..5e1e2497d
--- /dev/null
+++ b/docs/clusterfuzzlite/overview.md
@@ -0,0 +1,29 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Overview
+nav_order: 1
+permalink: /clusterfuzzlite/overview/
+---
+
+# Overview
+
+ClusterFuzzLite makes fuzzing more valuable by:
+* Fuzzing continuously.
+* Catching bugs before they land in your codebase by fuzzing pull
+ requests/commits.
+* Providing coverage reports on which code is fuzzed.
+* Managing your corpus, pruning it daily or a specified-interval.
+
+ClusterFuzzLite supports [libFuzzer], [AddressSanitizer], and
+[UndefinedBehavior].
+ClusterFuzzLite is modular, so you can decide which features you want to use.
+Using ClusterFuzzLite entails two major steps:
+1. [Integrating with ClusterFuzzLite's build system] so ClusterFuzzLite can
+ build your project's fuzzers.
+2. [Running ClusterFuzzLite].
+[libFuzzer]: https://libfuzzer.info
+[AddressSanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html
+[UndefinedBehaviorSanitizer]: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
+[Integrating with ClusterFuzzLite's build system]: {{ site.baseurl }}/clusterfuzzlite/build-integration/
+[Running ClusterFuzzLite]: {{ site.baseurl }}/clusterfuzzlite/running-clusterfuzzlite/
diff --git a/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md b/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md
new file mode 100644
index 000000000..045cd2438
--- /dev/null
+++ b/docs/clusterfuzzlite/running-clusterfuzzlite/generic.md
@@ -0,0 +1,17 @@
+---
+layout: default
+parent: Running ClusterFuzzLite
+grand_parent: ClusterFuzzLite
+title: Running ClusterFuzzLite in a Generic Environment
+nav_order: 2
+permalink: /clusterfuzzlite/running-clusterfuzzlite/generic/
+---
+
+# Running ClusterFuzzLite in a Generic Environment
+TODO: Rename run_cifuzz.py to run_clusterfuzzlite.py
+
+This page describes how to run clusterfuzzlite using the run_clusterfuzzlite.py
+script, a low level script that is used by CI systems to run ClusterFuzzLite.
+This guide is useful if you want to run ClusterFuzzLite outside of CI or if you
+want to run it on a CI system that isn't supported yet.
+TODO
diff --git a/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md b/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md
new file mode 100644
index 000000000..430f67526
--- /dev/null
+++ b/docs/clusterfuzzlite/running-clusterfuzzlite/github_actions.md
@@ -0,0 +1,12 @@
+---
+layout: default
+parent: Running ClusterFuzzLite
+grand_parent: ClusterFuzzLite
+title: GitHub Actions
+nav_order: 1
+permalink: /clusterfuzzlite/running-clusterfuzzlite/github-actions/
+---
+
+# GitHub Actions
+
+TODO
diff --git a/docs/clusterfuzzlite/running_clusterfuzzlite.md b/docs/clusterfuzzlite/running_clusterfuzzlite.md
new file mode 100644
index 000000000..068fc03eb
--- /dev/null
+++ b/docs/clusterfuzzlite/running_clusterfuzzlite.md
@@ -0,0 +1,101 @@
+---
+layout: default
+parent: ClusterFuzzLite
+title: Running ClusterFuzzLite
+has_children: true
+nav_order: 3
+permalink: /clusterfuzzlite/running-clusterfuzzlite/
+---
+# Running ClusterFuzzLite
+{: .no_toc}
+
+- TOC
+{:toc}
+---
+
+## Overview
+TODO: add a diagram.
+
+Once your project's fuzzers can be built and run by the helper script, it is
+ready to be fuzzed by ClusterFuzzLite.
+The exact method for doing this will depend on the how you are running
+ClusterFuzzLite. For guides on how to run ClusterFuzzLite in your particular
+environment (e.g. GitHub Actions) see the subguides.
+The rest of this page will explain concepts configuration options and that are
+agnostic to how ClusterFuzzLite is being run.
+
+## ClusterFuzzLite Tasks
+
+ClusterFuzzLite has the concept of tasks which instruct ClusterFuzzLite what to
+do when running.
+
+### Code Review Fuzzing
+
+TODO(metzman): Work on a generic name for CIFuzz/PR fuzzing.
+
+One of the core ways for ClusterFuzzLite to be used is for fuzzing code that is
+in review that was just commited.
+This use-case is important because it allows ClusterFuzzLite to find bugs before
+they are commited into your code and while they are easiest to fix.
+To use Code Review Fuzzing, set the configuration option `clusterfuzzlite-task`
+to `code-review`.
+If you are familiar with OSS-Fuzz's CIFuzz, this task is similar to CIFuzz.
+Running other ClusterFuzzLite tasks enhances ClusterFuzzLite's ability to do
+Code Review Fuzzing.
+
+If [Batch Fuzzing] is enabled, Code Review Fuzzing will report only newly
+introduced bugs and use the corpus developed during batch fuzzing.
+If [Code Coverage Reporting] is enabled, Code Review Fuzzing will try to only
+run the fuzzers affected by the code change.
+
+### Batch Fuzzing
+
+ClusterFuzzLite can also run in a batch fuzzing mode where all fuzzers are run
+for a long amount of time. Unlike Code Review Fuzzing, this task is not meant to
+be interactive, it is meant to be long-lasting and generally is more similar to
+fuzzing in ClusterFuzz than Code Review Fuzzing. Batch Fuzzing allows
+ClusterFuzzLite to build up a corpus for each of your fuzz targets. This corpus
+will be used in Code Coverage Reporting as well as Code Review Fuzzing.
+
+### Corpus Prune
+
+If multiple Batch Fuzzing tasks are run concurrently then we strongly recommend
+running a pruning task as well. This task is run according to some set schedule
+(once a day is probably sufficient) to prune the corpus of redundant testcases,
+which can happen if multiple Batch Fuzzing jobs are done concurrently.
+
+### Code Coverage Report
+
+The last task ClusterFuzzLite offers is Code Coverage Reports. This task will
+run your fuzzers on the corpus developed during Batch Fuzzing and will generate
+an HTML report that shows you which part of your code is covered by batch
+fuzzing.
+
+## Configuration Options
+
+Below are some configuration options that you can set when running
+ClusterFuzzLite.
+We will explain how to set these in each of the subguides.
+
+`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-time`: Determines how long ClusterFuzzLite spends fuzzing your project in
+seconds. The default is 600 seconds.
+
+`sanitizer`: Determines a sanitizer to build and run fuzz targets with. The
+choices are `'address'`, and `'undefined'`. The default is `'address'`.
+
+`task`: The task for ClusterFuzzLite to execute. `code-review`
+by default. See [ClusterFuzzLite Tasks] for more details on how to run different
+tasks.
+TODO(metzman): change run_fuzzers_mode to this.
+
+`dry-run`: Determines if ClusterFuzzLite surfaces bugs/crashes. The default
+value is `false`. When set to `true`, ClusterFuzzLite 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.
+
+TODO(metzman): We probably want a TOC on this page for subguides.
diff --git a/docs/further-reading/clusterfuzz.md b/docs/further-reading/clusterfuzz.md
index 92d85ff4c..308882c2d 100644
--- a/docs/further-reading/clusterfuzz.md
+++ b/docs/further-reading/clusterfuzz.md
@@ -46,7 +46,7 @@ information, memory usage) on our fuzzer statistics dashboard.
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 usecases.
+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)
diff --git a/docs/further-reading/fuzzer_environment.md b/docs/further-reading/fuzzer_environment.md
index 7c527ec32..c42bf454e 100644
--- a/docs/further-reading/fuzzer_environment.md
+++ b/docs/further-reading/fuzzer_environment.md
@@ -9,8 +9,7 @@ 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) with some
-[security restrictions](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-runner/run_minijail).
+[Google Compute Engine](https://cloud.google.com/compute/) VM (Linux).
- TOC
{:toc}
@@ -43,7 +42,7 @@ 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 surronded
+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 <fuzz_target_name>` and the `check_build` command in `infra/helper.py`.
diff --git a/docs/getting-started/accepting_new_projects.md b/docs/getting-started/accepting_new_projects.md
index b0ae1f989..898d68bce 100644
--- a/docs/getting-started/accepting_new_projects.md
+++ b/docs/getting-started/accepting_new_projects.md
@@ -19,12 +19,12 @@ with a new `projects/<project_name>/project.yaml` file
**Note:** `project_name` can only contain alphanumeric characters,
underscores(_) or dashes(-).
2. In the file, provide the following information:
- - Your project's homepage.
- - An email address for the engineering contact to be CCed on new issues, satisfying the following:
- - The address belongs to an established project committer (according to VCS logs).
+ * Your project's homepage.
+ * An email address for the engineering contact to be CCed on new issues, 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
+ * 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),
diff --git a/docs/getting-started/continuous_integration.md b/docs/getting-started/continuous_integration.md
index 88e6e4b15..7a6a305bb 100644
--- a/docs/getting-started/continuous_integration.md
+++ b/docs/getting-started/continuous_integration.md
@@ -21,11 +21,11 @@ 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 the crash is reproducible (on the PR/commit build).
-* If the crash does not occur on older OSS-Fuzz builds. Because if it does occur
- on older builds that means the crash was not introduced by the PR/commit
- CIFuzz is testing.
+(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.
@@ -39,6 +39,7 @@ fuzzing more effective and gives you regression testing for free.
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
diff --git a/docs/getting-started/new-project-guide/bazel.md b/docs/getting-started/new-project-guide/bazel.md
index 45b942fee..4af640e42 100644
--- a/docs/getting-started/new-project-guide/bazel.md
+++ b/docs/getting-started/new-project-guide/bazel.md
@@ -28,7 +28,7 @@ For Bazel-based projects, we recommend using the
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 dictionaires as part of the fuzz test
+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
@@ -84,12 +84,12 @@ OSS-Fuzz provides a
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 though a set of
+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 overriden to
+* `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"`.
diff --git a/docs/getting-started/new-project-guide/go_lang.md b/docs/getting-started/new-project-guide/go_lang.md
index 600a66665..f64e6913c 100644
--- a/docs/getting-started/new-project-guide/go_lang.md
+++ b/docs/getting-started/new-project-guide/go_lang.md
@@ -59,6 +59,8 @@ sanitizers:
### 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.
diff --git a/docs/getting-started/new-project-guide/jvm_lang.md b/docs/getting-started/new-project-guide/jvm_lang.md
index 19e4ecbfe..5d25d3cbd 100644
--- a/docs/getting-started/new-project-guide/jvm_lang.md
+++ b/docs/getting-started/new-project-guide/jvm_lang.md
@@ -50,8 +50,9 @@ language: jvm
```
The only supported fuzzing engine is libFuzzer (`libfuzzer`). So far the only
-supported sanitizer is AddressSanitizer (`address`), which needs to be
-specified explicitly even for pure Java projects.
+supported sanitizers are AddressSanitizer (`address`) and
+UndefinedBehaviorSanitizer (`undefined`). For pure Java projects, specify
+just `address`:
```yaml
fuzzing_engines:
@@ -62,6 +63,8 @@ sanitizers:
### 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:
@@ -135,12 +138,16 @@ 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=\"-Xmx2048m\" \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $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
diff --git a/docs/getting-started/new-project-guide/python_lang.md b/docs/getting-started/new-project-guide/python_lang.md
index da147803a..117441029 100644
--- a/docs/getting-started/new-project-guide/python_lang.md
+++ b/docs/getting-started/new-project-guide/python_lang.md
@@ -57,6 +57,8 @@ sanitizers:
### 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
@@ -97,7 +99,7 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
```
diff --git a/docs/getting-started/new-project-guide/rust_lang.md b/docs/getting-started/new-project-guide/rust_lang.md
index c28dd7618..11a3b5115 100644
--- a/docs/getting-started/new-project-guide/rust_lang.md
+++ b/docs/getting-started/new-project-guide/rust_lang.md
@@ -61,6 +61,8 @@ fuzzing_engines:
### 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
@@ -100,3 +102,47 @@ do
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
+depedencies 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).
diff --git a/docs/getting-started/new-project-guide/swift.md b/docs/getting-started/new-project-guide/swift.md
new file mode 100644
index 000000000..dbb127b03
--- /dev/null
+++ b/docs/getting-started/new-project-guide/swift.md
@@ -0,0 +1,78 @@
+---
+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/
+---
+
+# 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
+)
+
+```
diff --git a/docs/getting-started/new_project_guide.md b/docs/getting-started/new_project_guide.md
index d2a7d805b..7ac0d2ae0 100644
--- a/docs/getting-started/new_project_guide.md
+++ b/docs/getting-started/new_project_guide.md
@@ -50,10 +50,10 @@ project is located in [`projects/boringssl`](https://github.com/google/oss-fuzz/
Each project directory also contains the following three configuration files:
-* [project.yaml](#project.yaml) - provides metadata about the project.
-* [Dockerfile](#Dockerfile) - defines the container environment with information
+* [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](#build.sh) - defines the build script that executes inside the Docker container and
+* [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
@@ -63,14 +63,15 @@ by running the following commands:
```bash
$ cd /path/to/oss-fuzz
$ export PROJECT_NAME=<project_name>
-$ python infra/helper.py generate $PROJECT_NAME
+$ export LANGUAGE=<project_language>
+$ python 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
+## project.yaml {#projectyaml}
This configuration file stores project metadata. The following attributes are supported:
@@ -98,6 +99,7 @@ Programming language the project is written in. Values you can specify include:
* [`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/)
### 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
@@ -121,9 +123,11 @@ sanitizers (currently ["address"](https://clang.llvm.org/docs/AddressSanitizer.h
[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," first make sure your project's
-runtime dependencies are listed in the OSS-Fuzz
-[msan-libs-builder Dockerfile](https://github.com/google/oss-fuzz/blob/master/infra/base-images/msan-libs-builder/Dockerfile#L20).
+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
@@ -169,6 +173,11 @@ On the testcase page of each oss-fuzz issue is a list of other jobs where the cr
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.
+### fuzzing_engines (optional) {#fuzzing_engines}
+The list of fuzzing engines to use.
+By default, `libfuzzer`, `afl`, and `honggfuzz` 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
@@ -187,9 +196,9 @@ builds_per_day: 2
Will build the project twice per day.
-## Dockerfile
+## Dockerfile {#dockerfile}
-This configuration file defines the Docker image for your project. Your [build.sh](#build.sh) script will be executed in inside the container you define.
+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
@@ -200,12 +209,22 @@ COPY build.sh fuzzer.cc $SRC/ # copy build script and other fuzze
```
In the above example, the git clone will check out the source to `$SRC/<checkout_dir>`.
+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).
-## build.sh
+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
+
+## 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).
@@ -248,11 +267,8 @@ alphanumeric characters, underscore(_) or dash(-). Otherwise, they won't run on
### Temporarily disabling code instrumentation during builds
-Sometimes not every 3rd party library might be needed to be instrumented or
-tools are being compiled that just support the target built.
+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:
-If for any reasons part of the build process should not be instrumented
-then the following code snippit can be used for this:
```
CFLAGS_SAVE="$CFLAGS"
@@ -309,6 +325,14 @@ 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.
@@ -366,9 +390,8 @@ information on code coverage generation.
**Note:** Currently, we only support AddressSanitizer (address) and UndefinedBehaviorSanitizer (undefined)
-configurations. MemorySanitizer is recommended, but needs to be enabled manually once you verify
-that all system dependencies are
-[instrumented](https://github.com/google/oss-fuzz/blob/master/infra/base-images/msan-libs-builder/Dockerfile#L20).
+configurations by default.
+MemorySanitizer is recommended, but needs to be enabled manually since you must build all runtime dependencies with MemorySanitizer.
<b>Make sure to test each
of the supported build configurations with the above commands (build_fuzzers -> run_fuzzer -> coverage).</b>
@@ -387,12 +410,13 @@ following ways:
### Seed Corpus
-OSS-Fuzz uses evolutionary fuzzing algorithms. Supplying 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.
+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. The name of each file in the corpus is the sha1 checksum (which you can get using the `sha1sum` or `shasum` comand) of its contents. You can store the corpus
+archive will be used as starting inputs for mutations. The name of each file in the corpus is the sha1 checksum (which you can get using the `sha1sum` or `shasum` command) of its contents. 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)).
@@ -401,7 +425,7 @@ Seed corpus files will be used for cross-mutations and portions of them might ap
in bug reports or be used for further security research. It is important that corpus
has an appropriate and consistent license.
-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.
+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
diff --git a/docs/index.md b/docs/index.md
index c372e77f0..989836cf6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -56,9 +56,9 @@ other resources are listed on the [useful links] page.
[useful links]: {{ site.baseurl }}/reference/useful-links/#tutorials
## Trophies
-As of January 2021, OSS-Fuzz has found over [25,000] bugs in [375] open source
+As of June 2021, OSS-Fuzz has found over [30,000] bugs in [500] open source
projects.
-[25,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
-[375]: https://github.com/google/oss-fuzz/tree/master/projects
+[30,000]: https://bugs.chromium.org/p/oss-fuzz/issues/list?q=-status%3AWontFix%2CDuplicate%20-component%3AInfra&can=1
+[500]: https://github.com/google/oss-fuzz/tree/master/projects
diff --git a/docs/oss-fuzz/architecture.md b/docs/oss-fuzz/architecture.md
index 56ff29620..c4b13fb16 100644
--- a/docs/oss-fuzz/architecture.md
+++ b/docs/oss-fuzz/architecture.md
@@ -16,7 +16,7 @@ one or more [fuzz targets](http://libfuzzer.info/#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](jenkins.io) builds the project from the committed configs.
+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
diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md
index 7b12995c1..da6da5aa5 100644
--- a/docs/reference/glossary.md
+++ b/docs/reference/glossary.md
@@ -92,7 +92,7 @@ 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 specifiying the `$ARCHITECTURE` build environment variable using the `--architecture` option:
+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
python infra/helper.py build_fuzzers --architecture i386 json
diff --git a/infra/base-images/all.sh b/infra/base-images/all.sh
index 6d012d5aa..8b3571083 100755
--- a/infra/base-images/all.sh
+++ b/infra/base-images/all.sh
@@ -17,6 +17,11 @@
docker build --pull -t gcr.io/oss-fuzz-base/base-image "$@" infra/base-images/base-image
docker build -t gcr.io/oss-fuzz-base/base-clang "$@" infra/base-images/base-clang
-docker build -t gcr.io/oss-fuzz-base/base-builder -t gcr.io/oss-fuzz/base-libfuzzer "$@" infra/base-images/base-builder
+docker build -t gcr.io/oss-fuzz-base/base-builder "$@" infra/base-images/base-builder
+docker build -t gcr.io/oss-fuzz-base/base-builder-go "$@" infra/base-images/base-builder-go
+docker build -t gcr.io/oss-fuzz-base/base-builder-jvm "$@" infra/base-images/base-builder-jvm
+docker build -t gcr.io/oss-fuzz-base/base-builder-python "$@" infra/base-images/base-builder-python
+docker build -t gcr.io/oss-fuzz-base/base-builder-rust "$@" infra/base-images/base-builder-rust
+docker build -t gcr.io/oss-fuzz-base/base-builder-swift "$@" infra/base-images/base-builder-swift
docker build -t gcr.io/oss-fuzz-base/base-runner "$@" infra/base-images/base-runner
docker build -t gcr.io/oss-fuzz-base/base-runner-debug "$@" infra/base-images/base-runner-debug
diff --git a/infra/base-images/base-builder-go/Dockerfile b/infra/base-images/base-builder-go/Dockerfile
new file mode 100644
index 000000000..9d2c61502
--- /dev/null
+++ b/infra/base-images/base-builder-go/Dockerfile
@@ -0,0 +1,30 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+
+RUN install_go.sh
+
+# TODO(jonathanmetzman): Install this file using install_go.sh.
+COPY ossfuzz_coverage_runner.go $GOPATH
+
diff --git a/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go b/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go
new file mode 100644
index 000000000..d433da246
--- /dev/null
+++ b/infra/base-images/base-builder-go/ossfuzz_coverage_runner.go
@@ -0,0 +1,69 @@
+// 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()
+ }
+}
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/mesa.py b/infra/base-images/base-builder-jvm/Dockerfile
index ec2e9d217..f27478b35 100644
--- a/infra/base-images/base-sanitizer-libs-builder/packages/mesa.py
+++ b/infra/base-images/base-builder-jvm/Dockerfile
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,14 +14,11 @@
#
################################################################################
-import package
+FROM gcr.io/oss-fuzz-base/base-builder
+ENV JAVA_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"
-class Package(package.Package):
- """mesa package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('mesa', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- env['DEB_CXXFLAGS_APPEND'] += ' -std=c++11'
+RUN install_java.sh \ No newline at end of file
diff --git a/infra/base-images/base-builder-python/Dockerfile b/infra/base-images/base-builder-python/Dockerfile
new file mode 100644
index 000000000..749b4d59e
--- /dev/null
+++ b/infra/base-images/base-builder-python/Dockerfile
@@ -0,0 +1,19 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
diff --git a/infra/base-images/base-builder-rust/Dockerfile b/infra/base-images/base-builder-rust/Dockerfile
new file mode 100644
index 000000000..a4ec327b6
--- /dev/null
+++ b/infra/base-images/base-builder-rust/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+
+RUN install_rust.sh
diff --git a/infra/base-images/base-builder-swift/Dockerfile b/infra/base-images/base-builder-swift/Dockerfile
new file mode 100644
index 000000000..2b063bb2f
--- /dev/null
+++ b/infra/base-images/base-builder-swift/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/
diff --git a/infra/base-images/base-builder-swift/precompile_swift b/infra/base-images/base-builder-swift/precompile_swift
new file mode 100755
index 000000000..ab855a620
--- /dev/null
+++ b/infra/base-images/base-builder-swift/precompile_swift
@@ -0,0 +1,33 @@
+#!/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
diff --git a/infra/base-images/base-builder/Dockerfile b/infra/base-images/base-builder/Dockerfile
index d802f247a..256e7be56 100644
--- a/infra/base-images/base-builder/Dockerfile
+++ b/infra/base-images/base-builder/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2016 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -61,71 +61,15 @@ RUN export PYTHON_DEPS="\
rm -rf /usr/local/lib/python3.8/test && \
apt-get remove -y $PYTHON_DEPS # https://github.com/google/oss-fuzz/issues/3888
-# Install latest atheris for python fuzzing, pyinstaller for fuzzer packaging,
-# six for Bazel rules.
+# Install six for Bazel rules.
RUN unset CFLAGS CXXFLAGS && pip3 install -v --no-cache-dir \
- atheris pyinstaller==4.1 six==1.15.0 && \
- rm -rf /tmp/*
-
-# Download and install the latest stable Go.
-RUN cd /tmp && \
- curl -O https://storage.googleapis.com/golang/getgo/installer_linux && \
- chmod +x ./installer_linux && \
- SHELL="bash" ./installer_linux && \
- rm -rf ./installer_linux
-
-# 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
-
-# Uses golang 1.14+ cmd/compile's native libfuzzer instrumentation.
-RUN go get -u github.com/mdempsky/go114-fuzz-build && \
- ln -s $GOPATH/bin/go114-fuzz-build $GOPATH/bin/go-fuzz
-
-# Install Rust and cargo-fuzz for libFuzzer instrumentation.
-ENV CARGO_HOME=/rust
-ENV RUSTUP_HOME=/rust/rustup
-ENV PATH=$PATH:/rust/bin
-RUN curl https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal
-RUN cargo install cargo-fuzz && rm -rf /rust/registry
-# Needed to recompile rust std library for MSAN
-RUN rustup component add rust-src --toolchain nightly
-# Set up custom environment variable for source code copy for coverage reports
-ENV OSSFUZZ_RUSTPATH /rust
+ six==1.15.0 && rm -rf /tmp/*
# Install Bazel through Bazelisk, which automatically fetches the latest Bazel version.
-ENV BAZELISK_VERSION 1.7.4
+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
-# Install OpenJDK 15 and trim its size by removing unused components.
-ENV JAVA_HOME=/usr/lib/jvm/java-15-openjdk-amd64
-ENV JVM_LD_LIBRARY_PATH=$JAVA_HOME/lib/server
-ENV PATH=$PATH:$JAVA_HOME/bin
-RUN cd /tmp && \
- curl -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_HOME && \
- tar -xzv --strip-components=1 -f openjdk-15.0.2_linux-x64_bin.tar.gz --directory $JAVA_HOME && \
- rm -f openjdk-15.0.2_linux-x64_bin.tar.gz && \
- rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
-
-# Install the latest Jazzer in $OUT.
-# jazzer_api_deploy.jar is required only at build-time, the agent and the
-# drivers are copied to $OUT as they need to be present on the runners.
-ENV JAZZER_API_PATH "/usr/local/lib/jazzer_api_deploy.jar"
-RUN cd $SRC/ && \
- git clone --depth=1 https://github.com/CodeIntelligenceTesting/jazzer && \
- cd jazzer && \
- bazel build --java_runtime_version=localjdk_15 -c opt --cxxopt="-stdlib=libc++" --linkopt=-lc++ \
- //agent:jazzer_agent_deploy.jar //driver:jazzer_driver //driver:jazzer_driver_asan //agent:jazzer_api_deploy.jar && \
- cp bazel-bin/agent/jazzer_agent_deploy.jar bazel-bin/driver/jazzer_driver bazel-bin/driver/jazzer_driver_asan /usr/local/bin/ && \
- cp bazel-bin/agent/jazzer_api_deploy.jar $JAZZER_API_PATH && \
- rm -rf ~/.cache/bazel ~/.cache/bazelisk && \
- rm -rf $SRC/jazzer
-
# Default build flags for various sanitizers.
ENV SANITIZER_FLAGS_address "-fsanitize=address -fsanitize-address-use-after-scope"
@@ -181,7 +125,7 @@ WORKDIR $SRC
# TODO: switch to -b stable once we can.
RUN git clone https://github.com/AFLplusplus/AFLplusplus.git aflplusplus && \
cd aflplusplus && \
- git checkout 2102264acf5c271b7560a82771b3af8136af9354
+ git checkout 4fe572b80f76ff0b0e916b639d1e04d5af48b157
RUN cd $SRC && \
curl -L -O https://github.com/google/honggfuzz/archive/oss-fuzz.tar.gz && \
@@ -190,14 +134,25 @@ RUN cd $SRC && \
tar -xzv --strip-components=1 -f $SRC/oss-fuzz.tar.gz && \
rm -rf examples $SRC/oss-fuzz.tar.gz
-COPY cargo compile compile_afl compile_dataflow compile_libfuzzer compile_honggfuzz \
- compile_go_fuzzer precompile_honggfuzz precompile_afl debug_afl srcmap \
- write_labels.py bazel_build_fuzz_tests /usr/local/bin/
-
-COPY detect_repo.py /opt/cifuzz/
-COPY ossfuzz_coverage_runner.go $GOPATH
+# Do precompiles before copying other scripts for better cache efficiency.
+COPY precompile_afl /usr/local/bin/
+RUN precompile_afl
+COPY precompile_honggfuzz /usr/local/bin/
RUN precompile_honggfuzz
-RUN precompile_afl
+
+COPY cargo compile compile_afl compile_dataflow compile_libfuzzer compile_honggfuzz \
+ compile_go_fuzzer debug_afl srcmap \
+ write_labels.py bazel_build_fuzz_tests \
+ # Go, java, and swift installation scripts.
+ install_go.sh \
+ install_java.sh \
+ install_python.sh \
+ install_rust.sh \
+ install_swift.sh \
+ /usr/local/bin/
+
+COPY llvmsymbol.diff $SRC
+COPY detect_repo.py /opt/cifuzz/
CMD ["compile"]
diff --git a/infra/base-images/base-builder/bazel_build_fuzz_tests b/infra/base-images/base-builder/bazel_build_fuzz_tests
index 86740ee01..dca79f3f2 100755
--- a/infra/base-images/base-builder/bazel_build_fuzz_tests
+++ b/infra/base-images/base-builder/bazel_build_fuzz_tests
@@ -22,10 +22,17 @@
: "${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
- \$all_fuzz_tests - attr(tags, \"${BAZEL_FUZZ_TEST_EXCLUDE_TAG}\", \$all_fuzz_tests)
+ 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
@@ -42,9 +49,10 @@ done
declare -r BAZEL_BUILD_FLAGS=(
"-c" "opt"
- "--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine" \
+ "--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine" \
"--@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz" \
"--@rules_fuzzing//fuzzing:cc_engine_sanitizer=none" \
+ "--cxxopt=-stdlib=libc++" \
"--linkopt=-lc++" \
"--action_env=CC=${CC}" "--action_env=CXX=${CXX}" \
${BAZEL_EXTRA_BUILD_FLAGS[*]}
diff --git a/infra/base-images/base-builder/bisect_clang_test.py b/infra/base-images/base-builder/bisect_clang_test.py
index edf13e759..a11bf8640 100644
--- a/infra/base-images/base-builder/bisect_clang_test.py
+++ b/infra/base-images/base-builder/bisect_clang_test.py
@@ -127,7 +127,7 @@ def create_mock_popen(
return MockPopen
-def mock_prepare_build(llvm_project_path): # pylint: disable=unused-argument
+def mock_prepare_build_impl(llvm_project_path): # pylint: disable=unused-argument
"""Mocked prepare_build function."""
return '/work/llvm-build'
@@ -138,7 +138,7 @@ class BuildClangTest(BisectClangTestMixin, unittest.TestCase):
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):
+ 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']],
@@ -170,13 +170,13 @@ class GitRepoTest(BisectClangTestMixin, unittest.TestCase):
"""Tests test_start_commit works as intended when the test returns an
unexpected value."""
- def mock_execute(command, *args, **kwargs): # pylint: disable=unused-argument
+ 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):
- with mock.patch('bisect_clang.prepare_build', mock_prepare_build):
+ 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)
@@ -202,13 +202,13 @@ class GitRepoTest(BisectClangTestMixin, unittest.TestCase):
expected value."""
command_args = []
- def mock_execute(command, *args, **kwargs): # pylint: disable=unused-argument
+ 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):
+ 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,
@@ -247,13 +247,13 @@ class GitRepoTest(BisectClangTestMixin, unittest.TestCase):
"""Test test_commit works as intended."""
command_args = []
- def mock_execute(command, *args, **kwargs): # pylint: disable=unused-argument
+ 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):
+ 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)
diff --git a/infra/base-images/base-builder/cargo b/infra/base-images/base-builder/cargo
index bed8e7660..c60c7611b 100755
--- a/infra/base-images/base-builder/cargo
+++ b/infra/base-images/base-builder/cargo
@@ -27,7 +27,7 @@ then
export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix src=$crate_src_abspath/src"
fi
-if [ "$SANITIZER" = "coverage" ] && [ $1 = "fuzz" ]
+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"
@@ -35,7 +35,11 @@ then
# go into fuzz directory if not already the case
cd fuzz || true
fuzz_src_abspath=`pwd`
- export RUSTFLAGS="$RUSTFLAGS --remap-path-prefix fuzz_targets=$fuzz_src_abspath/fuzz_targets"
+ # 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 <<< "$(ls */*.rs | cut -d/ -f1 | 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
diff --git a/infra/base-images/base-builder/compile b/infra/base-images/base-builder/compile
index 78453c98c..c934d3b5b 100755
--- a/infra/base-images/base-builder/compile
+++ b/infra/base-images/base-builder/compile
@@ -27,8 +27,8 @@ if [ "$FUZZING_LANGUAGE" = "jvm" ]; then
echo "ERROR: JVM projects can be fuzzed with libFuzzer engine only."
exit 1
fi
- if [ "$SANITIZER" != "address" ]; then
- echo "ERROR: JVM projects can be fuzzed with AddressSanitizer only."
+ if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "coverage" ] && [ "$SANITIZER" != "undefined" ]; then
+ echo "ERROR: JVM projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer only."
exit 1
fi
if [ "$ARCHITECTURE" != "x86_64" ]; then
@@ -43,7 +43,7 @@ if [ "$FUZZING_LANGUAGE" = "python" ]; then
exit 1
fi
if [ "$SANITIZER" != "address" ] && [ "$SANITIZER" != "undefined" ]; then
- echo "ERROR: Python projects can be fuzzed with AddressSanitizer and UndefinedBehaviorSanitizer only."
+ echo "ERROR: Python projects can be fuzzed with AddressSanitizer or UndefinedBehaviorSanitizer only."
exit 1
fi
if [ "$ARCHITECTURE" != "x86_64" ]; then
@@ -59,7 +59,7 @@ fi
if [[ $ARCHITECTURE == "i386" ]]; then
export CFLAGS="-m32 $CFLAGS"
- cp -R /usr/i386/lib/* /usr/lib
+ cp -R /usr/i386/lib/* /usr/local/lib
fi
# JVM projects are fuzzed with Jazzer, which has libFuzzer built in.
if [[ $FUZZING_ENGINE != "none" ]] && [[ $FUZZING_LANGUAGE != "jvm" ]]; then
@@ -71,15 +71,9 @@ if [[ $SANITIZER_FLAGS = *sanitize=memory* ]]
then
# Take all libraries from lib/msan and MSAN_LIBS_PATH
# export CXXFLAGS_EXTRA="-L/usr/msan/lib $CXXFLAGS_EXTRA"
- cp -R /usr/msan/lib/* /usr/lib/
-
- if [[ -z "${MSAN_LIBS_PATH-}" ]]; then
- echo 'WARNING: Building without MSan instrumented libraries.'
- else
- # Copy all static libraries only. Don't include .so files because they can
- # break non MSan compiled programs.
- (cd "$MSAN_LIBS_PATH" && find . -name '*.a' -exec cp --parents '{}' / ';')
- fi
+ cp -R /usr/msan/lib/* /usr/local/lib/
+
+ echo 'Building without MSan instrumented libraries.'
fi
# Coverage flag overrides.
@@ -118,7 +112,7 @@ export CFLAGS="$CFLAGS $SANITIZER_FLAGS $COVERAGE_FLAGS"
export CXXFLAGS="$CFLAGS $CXXFLAGS_EXTRA"
if [ "$FUZZING_LANGUAGE" = "python" ]; then
- sanitizer_with_fuzzer_lib_dir=`python3 -c "import atheris; import os; print(os.path.dirname(atheris.path()))"`
+ 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
@@ -136,7 +130,20 @@ 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_driver_asan) $OUT/
+ cp $(which jazzer_agent_deploy.jar) $(which jazzer_driver) $OUT/
+ jazzer_driver_with_sanitizer=$OUT/jazzer_driver_with_sanitizer
+ if [ "$SANITIZER" = "address" ]; then
+ cp $(which jazzer_driver_asan) $jazzer_driver_with_sanitizer
+ elif [ "$SANITIZER" = "undefined" ]; then
+ cp $(which jazzer_driver_ubsan) $jazzer_driver_with_sanitizer
+ elif [ "$SANITIZER" = "coverage" ]; then
+ # Coverage builds require no instrumentation.
+ cp $(which jazzer_driver) $jazzer_driver_with_sanitizer
+ fi
+
+ # Disable leak checking since the JVM triggers too many false positives.
+ export CFLAGS="$CFLAGS -fno-sanitize=leak"
+ export CXXFLAGS="$CXXFLAGS -fno-sanitize=leak"
fi
echo "---------------------------------------------------------------"
@@ -144,13 +151,24 @@ echo "CC=$CC"
echo "CXX=$CXX"
echo "CFLAGS=$CFLAGS"
echo "CXXFLAGS=$CXXFLAGS"
+echo "RUSTFLAGS=$RUSTFLAGS"
echo "---------------------------------------------------------------"
BUILD_CMD="bash -eux $SRC/build.sh"
+# 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 $OUT"
+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/
+ cp -r /rust/rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/ /rustc/$rustch/
+fi
if [ "${BUILD_UID-0}" -ne "0" ]; then
adduser -u $BUILD_UID --disabled-password --gecos '' builder
diff --git a/infra/base-images/base-builder/compile_afl b/infra/base-images/base-builder/compile_afl
index dc6624459..d6509c74c 100644
--- a/infra/base-images/base-builder/compile_afl
+++ b/infra/base-images/base-builder/compile_afl
@@ -22,6 +22,8 @@
# AFL++ settings.
export AFL_LLVM_MODE_WORKAROUND=0
export AFL_ENABLE_DICTIONARY=0
+export AFL_ENABLE_CMPLOG=1
+export AFL_LAF_CHANCE=3
# Start compiling afl++.
echo "Copying precompiled afl++"
@@ -45,19 +47,32 @@ export ASAN_OPTIONS="detect_leaks=0:symbolize=0:detect_odr_violation=0:abort_on_
# AFL compile option roulette. It is OK if they all happen together.
-# 40% chance to perform CMPLOG
+# 20% chance for CTX-2 coverage instrumentation (Caller conTeXt sensitive
+# edge coverage).
+test $(($RANDOM % 100)) -lt 20 && {
+ export AFL_LLVM_INSTRUMENT=CLASSIC,CTX-2
+ export AFL_ENABLE_CMPLOG=0
+ export AFL_LAF_CHANCE=30
+}
+
+# 40% chance to create a dictionary.
+test $(($RANDOM % 100)) -lt 40 && {
+ export AFL_ENABLE_DICTIONARY=1
+}
+
+# 60% chance to perform CMPLOG/REDQUEEN.
rm -f "$OUT/afl_cmplog.txt"
-test $(($RANDOM % 10)) -lt 4 && {
+test "$AFL_ENABLE_CMPLOG" = "1" -a $(($RANDOM % 100)) -lt 60 && {
export AFL_LLVM_CMPLOG=1
touch "$OUT/afl_cmplog.txt"
}
-# 10% chance to perform LAF_INTEL
-test $(($RANDOM % 10)) -lt 1 && {
+# 3% chance to perform COMPCOV/LAF_INTEL.
+test $(($RANDOM % 100)) -lt $AFL_LAF_CHANCE && {
export AFL_LLVM_LAF_ALL=1
}
-# If the targets wants a dictionary - then create one.
+# Create a dictionary if one is wanted.
test "$AFL_ENABLE_DICTIONARY" = "1" && {
export AFL_LLVM_DICT2FILE="$OUT/afl++.dict"
}
diff --git a/infra/base-images/base-builder/compile_go_fuzzer b/infra/base-images/base-builder/compile_go_fuzzer
index 2342800fb..dd8c9f6a1 100755
--- a/infra/base-images/base-builder/compile_go_fuzzer
+++ b/infra/base-images/base-builder/compile_go_fuzzer
@@ -29,7 +29,7 @@ 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"@*"}'`; }
+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 ;}
@@ -42,7 +42,9 @@ if [[ $SANITIZER = *coverage* ]]; then
sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go
sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go
- fuzzed_repo=`echo $path | cut -d/ -f-3`
+ # 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
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py b/infra/base-images/base-builder/install_go.sh
index 8071b7ecd..21138831c 100644..100755
--- a/infra/base-images/base-sanitizer-libs-builder/packages/boost1_58.py
+++ b/infra/base-images/base-builder/install_go.sh
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+#!/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.
@@ -15,15 +15,14 @@
#
################################################################################
-import package
+cd /tmp
+curl -O https://storage.googleapis.com/golang/getgo/installer_linux
+chmod +x ./installer_linux
+SHELL="bash" ./installer_linux
+rm -rf ./installer_linux
+echo 'Set "GOPATH=/root/go"'
+echo 'Set "PATH=$PATH:/root/.go/bin:$GOPATH/bin"'
-class Package(package.Package):
- """boost1.58 package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('boost1.58', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- # Otherwise py_nonblocking.cpp fails to build.
- env['DEB_CXXFLAGS_APPEND'] += ' -std=c++98'
+go get -u github.com/mdempsky/go114-fuzz-build
+ln -s $GOPATH/bin/go114-fuzz-build $GOPATH/bin/go-fuzz
diff --git a/infra/base-images/base-builder/install_java.sh b/infra/base-images/base-builder/install_java.sh
new file mode 100755
index 000000000..560c816a9
--- /dev/null
+++ b/infra/base-images/base-builder/install_java.sh
@@ -0,0 +1,37 @@
+#!/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 15 and trim its size by removing unused components.
+cd /tmp
+curl -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_HOME
+tar -xzv --strip-components=1 -f openjdk-15.0.2_linux-x64_bin.tar.gz --directory $JAVA_HOME && \
+rm -f openjdk-15.0.2_linux-x64_bin.tar.gz
+rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
+
+# Install the latest Jazzer in $OUT.
+# jazzer_api_deploy.jar is required only at build-time, the agent and the
+# drivers are copied to $OUT as they need to be present on the runners.
+cd $SRC/
+git clone --depth=1 https://github.com/CodeIntelligenceTesting/jazzer && \
+cd jazzer
+bazel build --java_runtime_version=localjdk_15 -c opt --cxxopt="-stdlib=libc++" --linkopt=-lc++ \
+ //agent:jazzer_agent_deploy.jar //driver:jazzer_driver //driver:jazzer_driver_asan //driver:jazzer_driver_ubsan //agent:jazzer_api_deploy.jar
+cp bazel-bin/agent/jazzer_agent_deploy.jar bazel-bin/driver/jazzer_driver bazel-bin/driver/jazzer_driver_asan bazel-bin/driver/jazzer_driver_ubsan /usr/local/bin/
+cp bazel-bin/agent/jazzer_api_deploy.jar $JAZZER_API_PATH
+rm -rf ~/.cache/bazel ~/.cache/bazelisk
+rm -rf $SRC/jazzer
diff --git a/infra/base-images/base-builder/install_python.sh b/infra/base-images/base-builder/install_python.sh
new file mode 100755
index 000000000..b9c9a38c3
--- /dev/null
+++ b/infra/base-images/base-builder/install_python.sh
@@ -0,0 +1,21 @@
+#!/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
+pip3 install -v --no-cache-dir atheris>=2.0.6 pyinstaller==4.1
+rm -rf /tmp/*
diff --git a/infra/base-images/base-builder/install_rust.sh b/infra/base-images/base-builder/install_rust.sh
new file mode 100755
index 000000000..cbb461fd6
--- /dev/null
+++ b/infra/base-images/base-builder/install_rust.sh
@@ -0,0 +1,21 @@
+#!/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=nightly --profile=minimal
+cargo install cargo-fuzz && rm -rf /rust/registry
+# Needed to recompile rust std library for MSAN
+rustup component add rust-src --toolchain nightly
diff --git a/infra/base-images/base-builder/install_swift.sh b/infra/base-images/base-builder/install_swift.sh
new file mode 100755
index 000000000..d88a7b5cd
--- /dev/null
+++ b/infra/base-images/base-builder/install_swift.sh
@@ -0,0 +1,66 @@
+#!/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 \
+ 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 https://swift.org/builds/swift-5.4.2-release/ubuntu2004/swift-5.4.2-RELEASE/swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+tar xzf swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+cp -r swift-5.4.2-RELEASE-ubuntu20.04/usr/* /usr/
+rm -rf swift-5.4.2-RELEASE-ubuntu20.04.tar.gz
+# TODO: Move to a seperate work dir
+git clone --depth 1 https://github.com/llvm/llvm-project.git
+cd llvm-project
+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 zlib1g-dev
+apt-get autoremove -y
diff --git a/infra/base-images/base-builder/llvmsymbol.diff b/infra/base-images/base-builder/llvmsymbol.diff
new file mode 100644
index 000000000..70181bf39
--- /dev/null
+++ b/infra/base-images/base-builder/llvmsymbol.diff
@@ -0,0 +1,50 @@
+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,11 @@ add_llvm_component_library(LLVMSymbolize
+ Object
+ Support
+ Demangle
+- )
++
++ LINK_LIBS
++ /usr/lib/swift_static/linux/libswiftCore.a
++ /usr/lib/swift_static/linux/libicui18nswift.a
++ /usr/lib/swift_static/linux/libicuucswift.a
++ /usr/lib/swift_static/linux/libicudataswift.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 <cassert>
+ #include <cstring>
+
++
++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));
diff --git a/infra/base-images/base-builder/write_labels.py b/infra/base-images/base-builder/write_labels.py
index 6766e37fe..92a820a43 100755
--- a/infra/base-images/base-builder/write_labels.py
+++ b/infra/base-images/base-builder/write_labels.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/infra/base-images/base-clang/Dockerfile b/infra/base-images/base-clang/Dockerfile
index 3c16a8f3c..45260941c 100644
--- a/infra/base-images/base-clang/Dockerfile
+++ b/infra/base-images/base-clang/Dockerfile
@@ -19,7 +19,7 @@
FROM gcr.io/oss-fuzz-base/base-image
# Install newer cmake.
-ENV CMAKE_VERSION 3.19.2
+ENV CMAKE_VERSION 3.21.1
RUN apt-get update && apt-get install -y wget sudo && \
wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.sh && \
chmod +x cmake-$CMAKE_VERSION-Linux-x86_64.sh && \
diff --git a/infra/base-images/base-clang/checkout_build_install_llvm.sh b/infra/base-images/base-clang/checkout_build_install_llvm.sh
index f6e8ca99c..a62b27cff 100755
--- a/infra/base-images/base-clang/checkout_build_install_llvm.sh
+++ b/infra/base-images/base-clang/checkout_build_install_llvm.sh
@@ -21,8 +21,8 @@
NPROC=$(expr $(nproc) / 2)
# zlib1g-dev is needed for llvm-profdata to handle coverage data from rust compiler
-LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python3 g++-multilib binutils-dev zlib1g-dev"
-apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends
+LLVM_DEP_PACKAGES="build-essential make cmake ninja-build git python3 python3-distutils g++-multilib binutils-dev zlib1g-dev"
+apt-get update && apt-get install -y $LLVM_DEP_PACKAGES --no-install-recommends
# Checkout
CHECKOUT_RETRIES=10
@@ -74,7 +74,7 @@ OUR_LLVM_REVISION=llvmorg-12-init-17251-g6de48655
# To allow for manual downgrades. Set to 0 to use Chrome's clang version (i.e.
# *not* force a manual downgrade). Set to 1 to force a manual downgrade.
-FORCE_OUR_REVISION=1
+FORCE_OUR_REVISION=0
LLVM_REVISION=$(grep -Po "CLANG_REVISION = '\K([^']+)" scripts/update.py)
clone_with_retries https://github.com/llvm/llvm-project.git $LLVM_SRC
@@ -124,10 +124,24 @@ rm -rf $WORK/llvm-stage1 $WORK/llvm-stage2
# Use the clang we just built from now on.
CMAKE_EXTRA_ARGS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
+function cmake_libcxx {
+ extra_args="$@"
+ 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="$TARGET_TO_BUILD" \
+ -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \
+ -DLLVM_BINUTILS_INCDIR="/usr/include/" \
+ $extra_args \
+ $LLVM_SRC/llvm
+}
+
# 32-bit libraries.
mkdir -p $WORK/i386
cd $WORK/i386
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
-DCMAKE_INSTALL_PREFIX=/usr/i386/ \
-DCMAKE_C_FLAGS="-m32" \
-DCMAKE_CXX_FLAGS="-m32"
@@ -145,7 +159,7 @@ cat <<EOF > $WORK/msan/blocklist.txt
fun:__gxx_personality_*
EOF
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
-DLLVM_USE_SANITIZER=Memory \
-DCMAKE_INSTALL_PREFIX=/usr/msan/ \
-DCMAKE_CXX_FLAGS="-fsanitize-blacklist=$WORK/msan/blocklist.txt"
@@ -158,7 +172,7 @@ rm -rf $WORK/msan
mkdir -p $WORK/dfsan
cd $WORK/dfsan
-cmake_llvm $CMAKE_EXTRA_ARGS \
+cmake_libcxx $CMAKE_EXTRA_ARGS \
-DLLVM_USE_SANITIZER=DataFlow \
-DCMAKE_INSTALL_PREFIX=/usr/dfsan/
@@ -197,7 +211,7 @@ rm -rf /usr/local/bin/llvm-*
mv $LLVM_TOOLS_TMPDIR/* /usr/local/bin/
rm -rf $LLVM_TOOLS_TMPDIR
-# Remove binaries from LLVM buld that we don't need.
+# Remove binaries from LLVM build that we don't need.
rm -f \
/usr/local/bin/bugpoint \
/usr/local/bin/llc \
diff --git a/infra/base-images/base-image/Dockerfile b/infra/base-images/base-image/Dockerfile
index 2099ffdd2..bc6035b72 100644
--- a/infra/base-images/base-image/Dockerfile
+++ b/infra/base-images/base-image/Dockerfile
@@ -16,11 +16,11 @@
# Base image for all other images.
-FROM ubuntu:16.04
+FROM ubuntu:20.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
apt-get upgrade -y && \
- apt-get install -y libc6-dev binutils libgcc-5-dev && \
+ apt-get install -y libc6-dev binutils libgcc-9-dev && \
apt-get autoremove -y
ENV OUT=/out
diff --git a/infra/base-images/base-runner/Dockerfile b/infra/base-images/base-runner/Dockerfile
index f847de026..fadd00acc 100755
--- a/infra/base-images/base-runner/Dockerfile
+++ b/infra/base-images/base-runner/Dockerfile
@@ -45,12 +45,18 @@ RUN apt-get update && apt-get install -y \
libcap2 \
python3 \
python3-pip \
+ python3-setuptools \
unzip \
wget \
zip --no-install-recommends
-RUN git clone https://chromium.googlesource.com/chromium/src/tools/code_coverage /opt/code_coverage && \
- pip3 install -r /opt/code_coverage/requirements.txt
+ENV CODE_COVERAGE_SRC=/opt/code_coverage
+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 && \
+ pip3 install -r requirements.txt && \
+ pip3 install MarkupSafe==0.23
# Default environment options for various sanitizers.
# Note that these match the settings used in ClusterFuzz and
@@ -91,6 +97,12 @@ RUN wget https://download.java.net/java/GA/jdk15.0.2/0d1cfde4252546c6931946de8db
rm -f openjdk-15.0.2_linux-x64_bin.tar.gz && \
rm -rf $JAVA_HOME/jmods $JAVA_HOME/lib/src.zip
+# 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
+
# Do this last to make developing these files easier/faster due to caching.
COPY bad_build_check \
collect_dft \
@@ -98,10 +110,12 @@ COPY bad_build_check \
coverage_helper \
dataflow_tracer.py \
download_corpus \
+ jacoco_report_converter.py \
rcfilt \
reproduce \
run_fuzzer \
parse_options.py \
+ profraw_update.py \
targets_list \
test_all.py \
test_one.py \
diff --git a/infra/base-images/base-runner/bad_build_check b/infra/base-images/base-runner/bad_build_check
index 01f8fbbab..bb328c793 100755
--- a/infra/base-images/base-runner/bad_build_check
+++ b/infra/base-images/base-runner/bad_build_check
@@ -39,7 +39,7 @@ 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=2
+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
@@ -90,10 +90,7 @@ function check_engine {
echo "BAD BUILD: $FUZZER seems to have only partial coverage instrumentation."
fi
elif [[ "$FUZZING_ENGINE" == afl ]]; then
- # TODO(https://github.com/google/oss-fuzz/issues/2470): Dont use
- # AFL_DRIVER_DONT_DEFER by default, support .options files in
- # bad_build_check instead.
- AFL_DRIVER_DONT_DEFER=1 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
+ 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."
@@ -136,10 +133,7 @@ function check_startup_crash {
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
- # TODO(https://github.com/google/oss-fuzz/issues/2470): Dont use
- # AFL_DRIVER_DONT_DEFER by default, support .options files in
- # bad_build_check instead.
- AFL_DRIVER_DONT_DEFER=1 AFL_NO_UI=1 SKIP_SEED_CORPUS=1 timeout --preserve-status -s INT 20s run_fuzzer $FUZZER_NAME &>$FUZZER_OUTPUT
+ 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
diff --git a/infra/base-images/base-runner/coverage b/infra/base-images/base-runner/coverage
index a86b00dec..3c7b274e4 100755
--- a/infra/base-images/base-runner/coverage
+++ b/infra/base-images/base-runner/coverage
@@ -19,14 +19,21 @@ cd $OUT
if (( $# > 0 )); then
FUZZ_TARGETS="$@"
else
- FUZZ_TARGETS="$(find . -maxdepth 1 -type f -executable -printf '%P\n')"
+ 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')"
fi
-DUMPS_DIR="$OUT/dumps"
-FUZZER_STATS_DIR="$OUT/fuzzer_stats"
-LOGS_DIR="$OUT/logs"
-REPORT_ROOT_DIR="$OUT/report"
-REPORT_PLATFORM_DIR="$OUT/report/linux"
+COVERAGE_OUTPUT_DIR=${COVERAGE_OUTPUT_DIR:-$OUT}
+
+DUMPS_DIR="$COVERAGE_OUTPUT_DIR/dumps"
+FUZZER_STATS_DIR="$COVERAGE_OUTPUT_DIR/fuzzer_stats"
+LOGS_DIR="$COVERAGE_OUTPUT_DIR/logs"
+REPORT_ROOT_DIR="$COVERAGE_OUTPUT_DIR/report"
+REPORT_PLATFORM_DIR="$COVERAGE_OUTPUT_DIR/report/linux"
for directory in $DUMPS_DIR $FUZZER_STATS_DIR $LOGS_DIR $REPORT_ROOT_DIR \
$REPORT_PLATFORM_DIR; do
@@ -54,6 +61,8 @@ objects=""
# Number of CPUs available, this is needed for running tests in parallel.
NPROC=$(nproc)
+CORPUS_DIR=${CORPUS_DIR:-"/corpus"}
+
function run_fuzz_target {
local target=$1
@@ -62,7 +71,7 @@ function run_fuzz_target {
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/${target}"
+ 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}"
@@ -74,7 +83,7 @@ function run_fuzz_target {
# 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 -close_fd_mask=3 $corpus_dummy $corpus_real"
+ 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
@@ -90,6 +99,9 @@ function run_fuzz_target {
return 0
fi
+ # If necessary translate to latest profraw version.
+ profraw_update.py $OUT/$target $profraw_file_mask tmp.profraw
+ mv tmp.profraw $profraw_file_mask
llvm-profdata merge -j=1 -sparse $profraw_file_mask -o $profdata_file
# Delete unnecessary and (potentially) large .profraw files.
@@ -115,7 +127,7 @@ function run_go_fuzz_target {
local target=$1
echo "Running go target $target"
- export FUZZ_CORPUS_DIR="/corpus/${target}/"
+ export FUZZ_CORPUS_DIR="$CORPUS_DIR/${target}/"
export FUZZ_PROFILE_NAME="$DUMPS_DIR/$target.perf"
$OUT/$target -test.coverprofile $DUMPS_DIR/$target.profdata &> $LOGS_DIR/$target.log
# translate from golangish paths to current absolute paths
@@ -125,6 +137,47 @@ function run_go_fuzz_target {
$SYSGOPATH/bin/gocovsum $DUMPS_DIR/$target.profdata > $FUZZER_STATS_DIR/$target.json
}
+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.*"
+ 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.
+ 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
+}
+
export SYSGOPATH=$GOPATH
export GOPATH=$OUT/$GOPATH
# Run each fuzz target, generate raw coverage dumps.
@@ -136,6 +189,14 @@ for fuzz_target in $FUZZ_TARGETS; do
grep "FUZZ_CORPUS_DIR" $fuzz_target > /dev/null 2>&1 || continue
fi
run_go_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"
+ run_java_fuzz_target $fuzz_target &
else
# Continue if not a fuzz target.
if [[ $FUZZING_ENGINE != "none" ]]; then
@@ -175,6 +236,43 @@ if [[ $FUZZING_LANGUAGE == "go" ]]; then
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 == "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
+
+ # Merge .class files from the individual targets.
+ classes_dir=$DUMPS_DIR/classes
+ mkdir $classes_dir
+ for fuzz_target in $FUZZ_TARGETS; do
+ cp -r $DUMPS_DIR/${fuzz_target}_classes/* $classes_dir/
+ 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[@]}"
+
+ # Write llvm-cov summary file.
+ jacoco_report_converter.py $xml_report $SUMMARY_FILE
+
+ set +e
else
# From this point on the script does not tolerate any errors.
@@ -206,6 +304,10 @@ else
fi
+# Make sure report is readable.
+chmod -R +r $REPORT_ROOT_DIR
+find $REPORT_ROOT_DIR -type d -exec chmod +x {} +
+
if [[ -n $HTTP_PORT ]]; then
# Serve the report locally.
echo "Serving the report on http://127.0.0.1:$HTTP_PORT/linux/index.html"
diff --git a/infra/base-images/base-runner/coverage_helper b/infra/base-images/base-runner/coverage_helper
index 22c9cb5d6..4d29ceac8 100755
--- a/infra/base-images/base-runner/coverage_helper
+++ b/infra/base-images/base-runner/coverage_helper
@@ -14,4 +14,4 @@
# limitations under the License.
#
################################################################################
-python3 /opt/code_coverage/coverage_utils.py $@
+python3 $CODE_COVERAGE_SRC/coverage_utils.py $@
diff --git a/infra/base-images/base-runner/jacoco_report_converter.py b/infra/base-images/base-runner/jacoco_report_converter.py
new file mode 100755
index 000000000..3c36065f1
--- /dev/null
+++ b/infra/base-images/base-runner/jacoco_report_converter.py
@@ -0,0 +1,158 @@
+#!/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"):
+ class_name = class_element.attrib["name"]
+ package_name = os.path.dirname(class_name)
+ if "sourcefilename" not in class_element.attrib:
+ continue
+ basename = class_element.attrib["sourcefilename"]
+ # This path is "foo/Bar.java" for the class element
+ # <class name="foo/Bar" sourcefilename="Bar.java">.
+ canonical_path = os.path.join(package_name, basename)
+
+ class_summary = make_element_summary(class_element)
+ summary["data"][0]["files"].append({
+ "filename": relative_to_src_path(src_files, canonical_path),
+ "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/...
+ src_path = full_path[len(out_path):]
+ filename_to_paths.setdefault(filename, []).append(src_path)
+ return filename_to_paths
+
+
+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 <counter> 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 <path_to_jacoco_xml> <out_path_json>\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())
diff --git a/infra/base-images/base-runner/profraw_update.py b/infra/base-images/base-runner/profraw_update.py
new file mode 100644
index 000000000..408b5fb93
--- /dev/null
+++ b/infra/base-images/base-runner/profraw_update.py
@@ -0,0 +1,123 @@
+#!/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')
+HeaderVersion7 = namedtuple(
+ 'HeaderVersion7',
+ 'BinaryIdsSize DataSize PaddingBytesBeforeCounters CountersSize \
+ PaddingBytesAfterCounters NamesSize CountersDelta 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]
+
+
+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.')
+ if generic_header.version == 5:
+ generic_header = generic_header._replace(version=7)
+ # Upgrade from version 5 to 7 by adding binaryids field.
+ data = struct.pack('QQ', generic_header) + struct.pack('Q', 0) + data[16:]
+ if generic_header.version < 7:
+ raise Exception('Unhandled version.')
+ v7_header = HeaderVersion7._make(struct.unpack('QQQQQQQQQ', data[16:88]))
+
+ if v7_header.BinaryIdsSize % 8 != 0:
+ # Adds padding for binary ids.
+ # cf commit b9f547e8e51182d32f1912f97a3e53f4899ea6be
+ # cf https://reviews.llvm.org/D110365
+ padlen = 8 - (v7_header.BinaryIdsSize % 8)
+ v7_header = v7_header._replace(BinaryIdsSize=v7_header.BinaryIdsSize +
+ padlen)
+ data = data[:16] + struct.pack('Q', v7_header.BinaryIdsSize) + data[24:]
+ data = data[:88 + v7_header.BinaryIdsSize] + bytes(
+ padlen) + data[88 + v7_header.BinaryIdsSize:]
+
+ if v7_header.CountersDelta != sect_prf_cnts - sect_prf_data:
+ # Rust linking seems to add an offset...
+ sect_prf_data = v7_header.CountersDelta - sect_prf_cnts + sect_prf_data
+ sect_prf_cnts = v7_header.CountersDelta
+
+ dataref = sect_prf_data
+ relativize_address(data, 64, dataref, sect_prf_cnts, sect_prf_data)
+
+ offset = 88 + v7_header.BinaryIdsSize
+ # This also works for C+Rust binaries compiled with
+ # clang-14/rust-nightly-clang-13.
+ for _ in range(v7_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 * (v7_header.ValueKindLast + 1)
+ # This is the size of one ProfrawData structure.
+ offset += 44 + 2 * (v7_header.ValueKindLast + 1)
+
+ return data
+
+
+def main():
+ """Helper script for upgrading a profraw file to latest version."""
+ if len(sys.argv) != 4:
+ sys.stderr.write('Usage: %s <binary> <profraw> <output>\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()[4], 16)
+ elif b'__llvm_prf_data' in line:
+ sect_prf_data = int(line.split()[4], 16)
+
+ # Then open and read the input profraw file.
+ with open(sys.argv[2], '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.
+ with open(sys.argv[3], 'wb') as output_file:
+ output_file.write(profraw_latest)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/infra/base-images/base-runner/run_fuzzer b/infra/base-images/base-runner/run_fuzzer
index b9bc8d9d6..426688ea3 100755
--- a/infra/base-images/base-runner/run_fuzzer
+++ b/infra/base-images/base-runner/run_fuzzer
@@ -26,7 +26,14 @@ DEBUGGER=${DEBUGGER:-}
FUZZER=$1
shift
-CORPUS_DIR=${CORPUS_DIR:-"/tmp/${FUZZER}_corpus"}
+# 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
@@ -63,14 +70,13 @@ function get_dictionary() {
fi
}
-rm -rf $CORPUS_DIR && mkdir -p $CORPUS_DIR
rm -rf $FUZZER_OUT && mkdir -p $FUZZER_OUT
SEED_CORPUS="${FUZZER}_seed_corpus.zip"
if [ -f $SEED_CORPUS ] && [ -z ${SKIP_SEED_CORPUS:-} ]; then
echo "Using seed corpus: $SEED_CORPUS"
- unzip -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null
+ unzip -o -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null
fi
OPTIONS_FILE="${FUZZER}.options"
@@ -103,19 +109,18 @@ if [[ "$FUZZING_ENGINE" = afl ]]; then
export UBSAN_OPTIONS="$UBSAN_OPTIONS:symbolize=0"
export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
export AFL_SKIP_CPUFREQ=1
- export AFL_NO_AFFINITY=1
+ export AFL_TRY_AFFINITY=1
export AFL_FAST_CAL=1
+ export AFL_CMPLOG_ONLY_NEW=1
+ export AFL_FORKSRV_INIT_TMOUT=30000
# 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. `-l 2` is
- # CMPLOG level 2, which will colorize larger files but not huge files and
- # not enable transform analysis unless there have been several cycles without
- # any finds.
- test -e "$OUT/afl_cmplog.txt" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -l 2 -c $OUT/$FUZZER"
+ # 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 large than 1sec as some of the OSS-Fuzz fuzzers
- # are slower than this.
- AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -t 5000+"
+ # Ensure timeout is a bit larger than 1sec as some of the OSS-Fuzz fuzzers
+ # are slower than this.
+ AFL_FUZZER_ARGS="$FUZZER_ARGS $AFL_FUZZER_ARGS -t 5000+"
# AFL expects at least 1 file in the input dir.
echo input > ${CORPUS_DIR}/input
echo afl++ setup:
@@ -135,7 +140,7 @@ elif [[ "$FUZZING_ENGINE" = honggfuzz ]]; then
# -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 -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $* -- \"$OUT/$FUZZER\""
+ CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $FUZZER_ARGS $* -- \"$OUT/$FUZZER\""
else
diff --git a/infra/base-images/base-runner/targets_list b/infra/base-images/base-runner/targets_list
index d35534258..95615c811 100755
--- a/infra/base-images/base-runner/targets_list
+++ b/infra/base-images/base-runner/targets_list
@@ -2,7 +2,8 @@
for binary in $(find $OUT/ -executable -type f); do
[[ "$binary" != *.so ]] || continue
- file "$binary" | grep ELF > /dev/null 2>&1 || 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"
diff --git a/infra/base-images/base-runner/test_all.py b/infra/base-images/base-runner/test_all.py
index 925ebde69..16dfcbfa9 100755
--- a/infra/base-images/base-runner/test_all.py
+++ b/infra/base-images/base-runner/test_all.py
@@ -20,12 +20,12 @@ import contextlib
import multiprocessing
import os
import re
-import shutil
import subprocess
import stat
import sys
+import tempfile
-TMP_FUZZER_DIR = '/tmp/not-out'
+BASE_TMP_FUZZER_DIR = '/tmp/not-out'
EXECUTABLE = stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH
@@ -37,14 +37,6 @@ IGNORED_TARGETS = [
IGNORED_TARGETS_RE = re.compile('^' + r'$|^'.join(IGNORED_TARGETS) + '$')
-def recreate_directory(directory):
- """Creates |directory|. If it already exists than deletes it first before
- creating."""
- if os.path.exists(directory):
- shutil.rmtree(directory)
- os.mkdir(directory)
-
-
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
@@ -67,7 +59,15 @@ def is_elf(filepath):
return b'ELF' in result.stdout
-def find_fuzz_targets(directory, fuzzing_language):
+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.
@@ -84,10 +84,10 @@ def find_fuzz_targets(directory, fuzzing_language):
continue
if not os.stat(path).st_mode & EXECUTABLE:
continue
- # Fuzz targets are expected to be ELF binaries for languages other than
- # Python and Java.
- if (fuzzing_language != 'python' and fuzzing_language != 'jvm' and
- not is_elf(path)):
+ # 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') != 'none':
with open(path, 'rb') as file_handle:
@@ -132,51 +132,66 @@ def has_ignored_targets(out_dir):
@contextlib.contextmanager
def use_different_out_dir():
- """Context manager that moves OUT to 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."""
+ """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.
- out = os.getenv('OUT')
- initial_out = out
- recreate_directory(TMP_FUZZER_DIR)
- out = TMP_FUZZER_DIR
- # 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)
- shutil.rmtree(out)
- os.environ['OUT'] = initial_out
-
-
-def test_all_outside_out(fuzzing_language, allowed_broken_targets_percentage):
+ 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, fuzzing_language, allowed_broken_targets_percentage)
+ return test_all(out, allowed_broken_targets_percentage)
-def test_all(out, fuzzing_language, allowed_broken_targets_percentage):
+def test_all(out, allowed_broken_targets_percentage):
"""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, fuzzing_language)
+ fuzz_targets = find_fuzz_targets(out)
if not fuzz_targets:
print('ERROR: No fuzz targets found.')
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
@@ -211,11 +226,8 @@ def get_allowed_broken_targets_percentage():
def main():
"""Does bad_build_check on all fuzz targets in parallel. Returns 0 on success.
Returns 1 on failure."""
- # Set these environment variables here so that stdout
- fuzzing_language = os.getenv('FUZZING_LANGUAGE')
allowed_broken_targets_percentage = get_allowed_broken_targets_percentage()
- if not test_all_outside_out(fuzzing_language,
- allowed_broken_targets_percentage):
+ if not test_all_outside_out(allowed_broken_targets_percentage):
return 1
return 0
diff --git a/infra/base-images/base-runner/test_all_test.py b/infra/base-images/base-runner/test_all_test.py
index 3771ec231..b3077ec1e 100644
--- a/infra/base-images/base-runner/test_all_test.py
+++ b/infra/base-images/base-runner/test_all_test.py
@@ -25,15 +25,13 @@ class TestTestAll(unittest.TestCase):
@mock.patch('test_all.find_fuzz_targets', return_value=[])
@mock.patch('builtins.print')
- def test_test_all_no_fuzz_targets(self, mocked_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'
- fuzzing_language = 'c++'
allowed_broken_targets_percentage = 0
self.assertFalse(
- test_all.test_all(outdir, fuzzing_language,
- allowed_broken_targets_percentage))
- mocked_print.assert_called_with('ERROR: No fuzz targets found.')
+ test_all.test_all(outdir, allowed_broken_targets_percentage))
+ mock_print.assert_called_with('ERROR: No fuzz targets found.')
if __name__ == '__main__':
diff --git a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py b/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py
deleted file mode 100755
index 04aa4207c..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper.py
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-import os
-import subprocess
-import sys
-
-import msan_build
-
-GCC_ONLY_ARGS = [
- '-aux-info',
-]
-
-
-def InvokedAsGcc():
- """Return whether or not we're pretending to be GCC."""
- return sys.argv[0].endswith('gcc') or sys.argv[0].endswith('g++')
-
-
-def Is32Bit(args):
- """Return whether or not we're 32-bit."""
- M32_BIT_ARGS = [
- '-m32',
- '-mx32',
- ]
-
- return any(arg in M32_BIT_ARGS for arg in args)
-
-
-def FilterWlArg(arg):
- """Remove -z,defs and equivalents from a single -Wl option."""
- parts = arg.split(',')[1:]
-
- filtered = []
- for part in parts:
- if part == 'defs':
- removed = filtered.pop()
- assert removed == '-z'
- continue
-
- if part == '--no-undefined':
- continue
-
- filtered.append(part)
-
- if filtered:
- return '-Wl,' + ','.join(filtered)
-
- # Filtered entire argument.
- return None
-
-
-def _RemoveLastMatching(l, find):
- for i in xrange(len(l) - 1, -1, -1):
- if l[i] == find:
- del l[i]
- return
-
- raise IndexError('Not found')
-
-
-def RemoveZDefs(args):
- """Remove unsupported -Wl,-z,defs linker option."""
- filtered = []
-
- for arg in args:
- if arg == '-Wl,defs':
- _RemoveLastMatching(filtered, '-Wl,-z')
- continue
-
- if arg == '-Wl,--no-undefined':
- continue
-
- if arg.startswith('-Wl,'):
- arg = FilterWlArg(arg)
- if not arg:
- continue
-
- filtered.append(arg)
-
- return filtered
-
-
-def GetCompilerArgs(args, is_cxx):
- """Generate compiler args."""
- compiler_args = args[1:]
-
- if Is32Bit(args):
- # 32 bit builds not supported.
- compiler_args.extend([
- '-fno-sanitize=memory',
- '-fno-sanitize-memory-track-origins',
- ])
-
- return compiler_args
-
- compiler_args = RemoveZDefs(compiler_args)
- compiler_args.extend([
- # FORTIFY_SOURCE is not supported by sanitizers.
- '-U_FORTIFY_SOURCE',
- '-Wp,-U_FORTIFY_SOURCE',
- # Reduce binary size.
- '-gline-tables-only',
- # Disable all warnings.
- '-w',
- # LTO isn't supported.
- '-fno-lto',
- ])
-
- if InvokedAsGcc():
- compiler_args.extend([
- # For better compatibility with flags passed via -Wa,...
- '-fno-integrated-as',
- ])
-
- if '-fsanitize=memory' not in args:
- # If MSan flags weren't added for some reason, add them here.
- compiler_args.extend(msan_build.GetInjectedFlags())
-
- if is_cxx:
- compiler_args.append('-stdlib=libc++')
-
- return compiler_args
-
-
-def FindRealClang():
- """Return path to real clang."""
- return os.environ['REAL_CLANG_PATH']
-
-
-def FallbackToGcc(args):
- """Check whether if we should fall back to GCC."""
- if not InvokedAsGcc():
- return False
-
- return any(arg in GCC_ONLY_ARGS for arg in args[1:])
-
-
-def main(args):
- if FallbackToGcc(args):
- sys.exit(subprocess.call(['/usr/bin/' + os.path.basename(args[0])] +
- args[1:]))
-
- is_cxx = args[0].endswith('++')
- real_clang = FindRealClang()
-
- if is_cxx:
- real_clang += '++'
-
- args = [real_clang] + GetCompilerArgs(args, is_cxx)
- debug_log_path = os.getenv('WRAPPER_DEBUG_LOG_PATH')
- if debug_log_path:
- with open(debug_log_path, 'a') as f:
- f.write(str(args) + '\n')
-
- sys.exit(subprocess.call(args))
-
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py b/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py
deleted file mode 100644
index a05592d38..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/compiler_wrapper_test.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""Tests for compiler_wrapper."""
-
-from __future__ import print_function
-
-import unittest
-
-import compiler_wrapper
-
-
-class CompilerWrapperTest(unittest.TestCase):
-
- def testFilterZDefs(self):
- self.assertListEqual(
- ['arg'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,defs']))
-
- self.assertListEqual(
- ['arg'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,--no-undefined']))
-
- self.assertListEqual(
- ['arg', '-Wl,-z,relro'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,relro']))
-
- self.assertListEqual(
- ['arg', '-Wl,-soname,lib.so.1,-z,relro'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-soname,lib.so.1,-z,defs,-z,relro']))
-
- self.assertListEqual(
- ['arg', '-Wl,-z,relro'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z,relro,-z,defs']))
-
- self.assertListEqual(
- ['arg'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z', '-Wl,defs']))
-
- self.assertListEqual(
- ['arg', 'arg2'],
- compiler_wrapper.RemoveZDefs(['arg', '-Wl,-z', 'arg2', '-Wl,--no-undefined']))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/msan_build.py b/infra/base-images/base-sanitizer-libs-builder/msan_build.py
deleted file mode 100755
index 5ea00ab10..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/msan_build.py
+++ /dev/null
@@ -1,460 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-import argparse
-import imp
-import os
-import multiprocessing
-import resource
-import shutil
-import subprocess
-import tempfile
-
-import apt
-from apt import debfile
-
-from packages import package
-import wrapper_utils
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-PACKAGES_DIR = os.path.join(SCRIPT_DIR, 'packages')
-
-TRACK_ORIGINS_ARG = '-fsanitize-memory-track-origins='
-
-INJECTED_ARGS = [
- '-fsanitize=memory',
- '-fsanitize-recover=memory',
- '-fPIC',
- '-fno-omit-frame-pointer',
-]
-
-
-class MSanBuildException(Exception):
- """Base exception."""
-
-
-def GetTrackOriginsFlag():
- """Get the track origins flag."""
- if os.getenv('MSAN_NO_TRACK_ORIGINS'):
- return TRACK_ORIGINS_ARG + '0'
-
- return TRACK_ORIGINS_ARG + '2'
-
-
-def GetInjectedFlags():
- return INJECTED_ARGS + [GetTrackOriginsFlag()]
-
-
-def SetUpEnvironment(work_dir):
- """Set up build environment."""
- env = {}
- env['REAL_CLANG_PATH'] = subprocess.check_output(['which', 'clang']).strip()
- print('Real clang at', env['REAL_CLANG_PATH'])
- compiler_wrapper_path = os.path.join(SCRIPT_DIR, 'compiler_wrapper.py')
-
- # Symlink binaries into TMP/bin
- bin_dir = os.path.join(work_dir, 'bin')
- os.mkdir(bin_dir)
-
- dpkg_host_architecture = wrapper_utils.DpkgHostArchitecture()
- wrapper_utils.CreateSymlinks(
- compiler_wrapper_path,
- bin_dir,
- [
- 'clang',
- 'clang++',
- # Not all build rules respect $CC/$CXX, so make additional symlinks.
- 'gcc',
- 'g++',
- 'cc',
- 'c++',
- dpkg_host_architecture + '-gcc',
- dpkg_host_architecture + '-g++',
- ])
-
- env['CC'] = os.path.join(bin_dir, 'clang')
- env['CXX'] = os.path.join(bin_dir, 'clang++')
-
- MSAN_OPTIONS = ' '.join(GetInjectedFlags())
-
- # We don't use nostrip because some build rules incorrectly break when it is
- # passed. Instead we install our own no-op strip binaries.
- env['DEB_BUILD_OPTIONS'] = ('nocheck parallel=%d' %
- multiprocessing.cpu_count())
- env['DEB_CFLAGS_APPEND'] = MSAN_OPTIONS
- env['DEB_CXXFLAGS_APPEND'] = MSAN_OPTIONS + ' -stdlib=libc++'
- env['DEB_CPPFLAGS_APPEND'] = MSAN_OPTIONS
- env['DEB_LDFLAGS_APPEND'] = MSAN_OPTIONS
- env['DPKG_GENSYMBOLS_CHECK_LEVEL'] = '0'
-
- # debian/rules can set DPKG_GENSYMBOLS_CHECK_LEVEL explicitly, so override it.
- gen_symbols_wrapper = ('#!/bin/sh\n'
- 'export DPKG_GENSYMBOLS_CHECK_LEVEL=0\n'
- '/usr/bin/dpkg-gensymbols "$@"\n')
-
- wrapper_utils.InstallWrapper(bin_dir, 'dpkg-gensymbols', gen_symbols_wrapper)
-
- # Install no-op strip binaries.
- no_op_strip = ('#!/bin/sh\n' 'exit 0\n')
- wrapper_utils.InstallWrapper(bin_dir, 'strip', no_op_strip,
- [dpkg_host_architecture + '-strip'])
-
- env['PATH'] = bin_dir + ':' + os.environ['PATH']
-
- # nocheck doesn't disable override_dh_auto_test. So we have this hack to try
- # to disable "make check" or "make test" invocations.
- make_wrapper = ('#!/bin/bash\n'
- 'if [ "$1" = "test" ] || [ "$1" = "check" ]; then\n'
- ' exit 0\n'
- 'fi\n'
- '/usr/bin/make "$@"\n')
- wrapper_utils.InstallWrapper(bin_dir, 'make', make_wrapper)
-
- # Prevent entire build from failing because of bugs/uninstrumented in tools
- # that are part of the build.
- msan_log_dir = os.path.join(work_dir, 'msan')
- os.mkdir(msan_log_dir)
- msan_log_path = os.path.join(msan_log_dir, 'log')
- env['MSAN_OPTIONS'] = ('halt_on_error=0:exitcode=0:report_umrs=0:log_path=' +
- msan_log_path)
-
- # Increase maximum stack size to prevent tests from failing.
- limit = 128 * 1024 * 1024
- resource.setrlimit(resource.RLIMIT_STACK, (limit, limit))
- return env
-
-
-def FindPackageDebs(package_name, work_directory):
- """Find package debs."""
- deb_paths = []
- cache = apt.Cache()
-
- for filename in os.listdir(work_directory):
- file_path = os.path.join(work_directory, filename)
- if not file_path.endswith('.deb'):
- continue
-
- # Matching package name.
- deb = debfile.DebPackage(file_path)
- if deb.pkgname == package_name:
- deb_paths.append(file_path)
- continue
-
- # Also include -dev packages that depend on the runtime package.
- pkg = cache[deb.pkgname]
- if pkg.section != 'libdevel' and pkg.section != 'universe/libdevel':
- continue
-
- # But ignore -dbg packages.
- if deb.pkgname.endswith('-dbg'):
- continue
-
- for dependency in deb.depends:
- if any(dep[0] == package_name for dep in dependency):
- deb_paths.append(file_path)
- break
-
- return deb_paths
-
-
-def ExtractLibraries(deb_paths, work_directory, output_directory):
- """Extract libraries from .deb packages."""
- extract_directory = os.path.join(work_directory, 'extracted')
- if os.path.exists(extract_directory):
- shutil.rmtree(extract_directory, ignore_errors=True)
-
- os.mkdir(extract_directory)
-
- for deb_path in deb_paths:
- subprocess.check_call(['dpkg-deb', '-x', deb_path, extract_directory])
-
- extracted = []
- for root, _, filenames in os.walk(extract_directory):
- if 'libx32' in root or 'lib32' in root:
- continue
-
- for filename in filenames:
- if (not filename.endswith('.so') and '.so.' not in filename and
- not filename.endswith('.a') and '.a' not in filename):
- continue
-
- file_path = os.path.join(root, filename)
- rel_file_path = os.path.relpath(file_path, extract_directory)
- rel_directory = os.path.dirname(rel_file_path)
-
- target_dir = os.path.join(output_directory, rel_directory)
- if not os.path.exists(target_dir):
- os.makedirs(target_dir)
-
- target_file_path = os.path.join(output_directory, rel_file_path)
- extracted.append(target_file_path)
-
- if os.path.lexists(target_file_path):
- os.remove(target_file_path)
-
- if os.path.islink(file_path):
- link_path = os.readlink(file_path)
- if os.path.isabs(link_path):
- # Make absolute links relative.
- link_path = os.path.relpath(link_path,
- os.path.join('/', rel_directory))
-
- os.symlink(link_path, target_file_path)
- else:
- shutil.copy2(file_path, target_file_path)
-
- return extracted
-
-
-def GetPackage(package_name):
- apt_cache = apt.Cache()
- version = apt_cache[package_name].candidate
- source_name = version.source_name
- local_source_name = source_name.replace('.', '_')
-
- custom_package_path = os.path.join(PACKAGES_DIR, local_source_name) + '.py'
- if not os.path.exists(custom_package_path):
- print('Using default package build steps.')
- return package.Package(source_name, version)
-
- print('Using custom package build steps.')
- module = imp.load_source('packages.' + local_source_name, custom_package_path)
- return module.Package(version)
-
-
-def PatchRpath(path, output_directory):
- """Patch rpath to be relative to $ORIGIN."""
- try:
- rpaths = subprocess.check_output(['patchelf', '--print-rpath',
- path]).strip()
- except subprocess.CalledProcessError:
- return
-
- if not rpaths:
- return
-
- processed_rpath = []
- rel_directory = os.path.join(
- '/', os.path.dirname(os.path.relpath(path, output_directory)))
-
- for rpath in rpaths.split(':'):
- if '$ORIGIN' in rpath:
- # Already relative.
- processed_rpath.append(rpath)
- continue
-
- processed_rpath.append(
- os.path.join('$ORIGIN', os.path.relpath(rpath, rel_directory)))
-
- processed_rpath = ':'.join(processed_rpath)
- print('Patching rpath for', path, 'to', processed_rpath)
- subprocess.check_call(
- ['patchelf', '--force-rpath', '--set-rpath', processed_rpath, path])
-
-
-def _CollectDependencies(apt_cache, pkg, cache, dependencies):
- """Collect dependencies that need to be built."""
- C_OR_CXX_DEPS = [
- 'libc++1',
- 'libc6',
- 'libc++abi1',
- 'libgcc1',
- 'libstdc++6',
- ]
-
- BLACKLISTED_PACKAGES = [
- 'libcapnp-0.5.3', # fails to compile on newer clang.
- 'libllvm5.0',
- 'libmircore1',
- 'libmircommon7',
- 'libmirclient9',
- 'libmirprotobuf3',
- 'multiarch-support',
- ]
-
- if pkg.name in BLACKLISTED_PACKAGES:
- return False
-
- if pkg.section != 'libs' and pkg.section != 'universe/libs':
- return False
-
- if pkg.name in C_OR_CXX_DEPS:
- return True
-
- is_c_or_cxx = False
- for dependency in pkg.candidate.dependencies:
- dependency = dependency[0]
-
- if dependency.name in cache:
- is_c_or_cxx |= cache[dependency.name]
- else:
- is_c_or_cxx |= _CollectDependencies(apt_cache, apt_cache[dependency.name],
- cache, dependencies)
- if is_c_or_cxx:
- dependencies.append(pkg.name)
-
- cache[pkg.name] = is_c_or_cxx
- return is_c_or_cxx
-
-
-def GetBuildList(package_name):
- """Get list of packages that need to be built including dependencies."""
- apt_cache = apt.Cache()
- pkg = apt_cache[package_name]
-
- dependencies = []
- _CollectDependencies(apt_cache, pkg, {}, dependencies)
- return dependencies
-
-
-class MSanBuilder(object):
- """MSan builder."""
-
- def __init__(self,
- debug=False,
- log_path=None,
- work_dir=None,
- no_track_origins=False):
- self.debug = debug
- self.log_path = log_path
- self.work_dir = work_dir
- self.no_track_origins = no_track_origins
- self.env = None
-
- def __enter__(self):
- if not self.work_dir:
- self.work_dir = tempfile.mkdtemp(dir=self.work_dir)
-
- if os.path.exists(self.work_dir):
- shutil.rmtree(self.work_dir, ignore_errors=True)
-
- os.makedirs(self.work_dir)
- self.env = SetUpEnvironment(self.work_dir)
-
- if self.debug and self.log_path:
- self.env['WRAPPER_DEBUG_LOG_PATH'] = self.log_path
-
- if self.no_track_origins:
- self.env['MSAN_NO_TRACK_ORIGINS'] = '1'
-
- return self
-
- def __exit__(self, exc_type, exc_value, traceback):
- if not self.debug:
- shutil.rmtree(self.work_dir, ignore_errors=True)
-
- def Build(self, package_name, output_directory, create_subdirs=False):
- """Build the package and write results into the output directory."""
- deb_paths = FindPackageDebs(package_name, self.work_dir)
- if deb_paths:
- print('Source package already built for', package_name)
- else:
- pkg = GetPackage(package_name)
-
- pkg.InstallBuildDeps()
- source_directory = pkg.DownloadSource(self.work_dir)
- print('Source downloaded to', source_directory)
-
- # custom bin directory for custom build scripts to write wrappers.
- custom_bin_dir = os.path.join(self.work_dir, package_name + '_bin')
- os.mkdir(custom_bin_dir)
- env = self.env.copy()
- env['PATH'] = custom_bin_dir + ':' + env['PATH']
-
- pkg.Build(source_directory, env, custom_bin_dir)
- shutil.rmtree(custom_bin_dir, ignore_errors=True)
-
- deb_paths = FindPackageDebs(package_name, self.work_dir)
-
- if not deb_paths:
- raise MSanBuildException('Failed to find .deb packages.')
-
- print('Extracting', ' '.join(deb_paths))
-
- if create_subdirs:
- extract_directory = os.path.join(output_directory, package_name)
- else:
- extract_directory = output_directory
-
- extracted_paths = ExtractLibraries(deb_paths, self.work_dir,
- extract_directory)
- for extracted_path in extracted_paths:
- if os.path.islink(extracted_path):
- continue
- if os.path.basename(extracted_path) == 'llvm-symbolizer':
- continue
- PatchRpath(extracted_path, extract_directory)
-
-
-def main():
- parser = argparse.ArgumentParser('msan_build.py', description='MSan builder.')
- parser.add_argument('package_names', nargs='+', help='Name of the packages.')
- parser.add_argument('output_dir', help='Output directory.')
- parser.add_argument('--create-subdirs',
- action='store_true',
- help=('Create subdirectories in the output '
- 'directory for each package.'))
- parser.add_argument('--work-dir', help='Work directory.')
- parser.add_argument('--no-build-deps',
- action='store_true',
- help='Don\'t build dependencies.')
- parser.add_argument('--debug', action='store_true', help='Enable debug mode.')
- parser.add_argument('--log-path', help='Log path for debugging.')
- parser.add_argument('--no-track-origins',
- action='store_true',
- help='Build with -fsanitize-memory-track-origins=0.')
- args = parser.parse_args()
-
- if args.no_track_origins:
- os.environ['MSAN_NO_TRACK_ORIGINS'] = '1'
-
- if not os.path.exists(args.output_dir):
- os.makedirs(args.output_dir)
-
- if args.no_build_deps:
- package_names = args.package_names
- else:
- all_packages = set()
- package_names = []
-
- # Get list of packages to build, including all dependencies.
- for package_name in args.package_names:
- for dep in GetBuildList(package_name):
- if dep in all_packages:
- continue
-
- if args.create_subdirs:
- os.mkdir(os.path.join(args.output_dir, dep))
-
- all_packages.add(dep)
- package_names.append(dep)
-
- print('Going to build:')
- for package_name in package_names:
- print('\t', package_name)
-
- with MSanBuilder(debug=args.debug,
- log_path=args.log_path,
- work_dir=args.work_dir,
- no_track_origins=args.no_track_origins) as builder:
- for package_name in package_names:
- builder.Build(package_name, args.output_dir, args.create_subdirs)
-
-
-if __name__ == '__main__':
- main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py b/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/__init__.py
+++ /dev/null
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py b/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py
deleted file mode 100644
index e1b0e2f81..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/nettle.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python
-# 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.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-def AddNoAsmArg(config_path):
- """Add --disable-assembler to config scripts."""
- shutil.move(config_path, config_path + '.real')
- with open(config_path, 'w') as f:
- f.write(
- '#!/bin/sh\n'
- '%s.real --disable-assembler "$@"\n' % config_path)
- os.chmod(config_path, 0755)
-
-
-class Package(package.Package):
- """nettle package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('nettle', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- AddNoAsmArg(os.path.join(source_directory, 'configure'))
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py b/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py
deleted file mode 100644
index e24ccc588..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/openssl.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# 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.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-def AddNoAsmArg(config_path):
- """Add --no-asm to config scripts."""
- shutil.move(config_path, config_path + '.real')
- with open(config_path, 'w') as f:
- f.write(
- '#!/bin/sh\n'
- '%s.real no-asm "$@"\n' % config_path)
- os.chmod(config_path, 0755)
-
-
-class Package(package.Package):
- """openssl package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('openssl', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- AddNoAsmArg(os.path.join(source_directory, 'Configure'))
- AddNoAsmArg(os.path.join(source_directory, 'config'))
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/package.py b/infra/base-images/base-sanitizer-libs-builder/packages/package.py
deleted file mode 100644
index 059c23587..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/package.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# 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.
-#
-################################################################################
-
-import os
-import subprocess
-
-import apt
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-
-
-def ApplyPatch(source_directory, patch_name):
- """Apply custom patch."""
- subprocess.check_call(['patch', '-p1', '-i',
- os.path.join(SCRIPT_DIR, patch_name)],
- cwd=source_directory)
-
-
-class PackageException(Exception):
- """Base package exception."""
-
-
-class Package(object):
- """Base package."""
-
- def __init__(self, name, apt_version):
- self.name = name
- self.apt_version = apt_version
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- return
-
- def PostBuild(self, source_directory, env, custom_bin_dir):
- return
-
- def PreDownload(self, download_directory):
- return
-
- def PostDownload(self, source_directory):
- return
-
- def InstallBuildDeps(self):
- """Install build dependencies for a package."""
- subprocess.check_call(['apt-get', 'update'])
- subprocess.check_call(['apt-get', 'build-dep', '-y', self.name])
-
- # Reload package after update.
- self.apt_version = (
- apt.Cache()[self.apt_version.package.name].candidate)
-
- def DownloadSource(self, download_directory):
- """Download the source for a package."""
- self.PreDownload(download_directory)
-
- source_directory = self.apt_version.fetch_source(download_directory)
-
- self.PostDownload(source_directory)
- return source_directory
-
- def Build(self, source_directory, env, custom_bin_dir):
- """Build .deb packages."""
- self.PreBuild(source_directory, env, custom_bin_dir)
- subprocess.check_call(
- ['dpkg-buildpackage', '-us', '-uc', '-B'],
- cwd=source_directory, env=env)
- self.PostBuild(source_directory, env, custom_bin_dir)
-
-
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py b/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py
deleted file mode 100644
index 52512461e..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pixman.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# 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.
-#
-################################################################################
-
-import os
-import shutil
-
-import package
-
-
-class Package(package.Package):
- """pixman package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('pixman', apt_version)
-
- def PostDownload(self, source_directory):
- # Incorrect checking of GCC vector extension availability.
- os.system('sed s/support_for_gcc_vector_extensions=yes/'
- 'support_for_gcc_vector_extensions=no/ -i %s/configure.ac' %
- source_directory)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- blocklist_flag = ' -fsanitize-blacklist=' + os.path.join(
- os.path.dirname(os.path.abspath(__file__)), 'pixman_blocklist.txt')
- env['DEB_CXXFLAGS_APPEND'] += blocklist_flag
- env['DEB_CFLAGS_APPEND'] += blocklist_flag
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt b/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt
deleted file mode 100644
index 69cf159dd..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pixman_blocklist.txt
+++ /dev/null
@@ -1 +0,0 @@
-src:*/pixman-sse2.c
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py b/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py
deleted file mode 100644
index d3ce7a113..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-import glob
-import os
-import subprocess
-
-import package
-
-
-class Package(package.Package):
- """PulseAudio package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('pulseaudio', apt_version)
-
- def PostDownload(self, source_directory):
- """Remove blocklisted patches."""
- # Fix *droid* patches.
- bad_patch_path = os.path.join(
- source_directory, 'debian', 'patches',
- '0600-droid-sync-with-upstream-for-Android-5-support-and-b.patch')
- if not os.path.exists(bad_patch_path):
- return
-
- print('Applying custom patches.')
- package.ApplyPatch(source_directory, 'pulseaudio_fix_android.patch')
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch b/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch
deleted file mode 100644
index e86f79823..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/pulseaudio_fix_android.patch
+++ /dev/null
@@ -1,39 +0,0 @@
---- pulseaudio-8.0/src/modules/droid/module-droid-card.c 2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-card.c 2017-11-27 22:28:23.847250467 +0000
-@@ -66,10 +66,11 @@
- #include "droid-extcon.h"
- #endif
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-card-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-card-22-symdef.h"
-+#else
- #endif
-
- PA_MODULE_AUTHOR("Juho Hämäläinen");
-diff -ru pulseaudio-8.0/src/modules/droid/module-droid-sink.c pulseaudio-8.0.fixed/src/modules/droid/module-droid-sink.c
---- pulseaudio-8.0/src/modules/droid/module-droid-sink.c 2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-sink.c 2017-11-27 22:29:53.776348900 +0000
-@@ -40,7 +40,7 @@
- #include "droid-util.h"
- #include "droid-sink.h"
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-sink-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-sink-22-symdef.h"
-diff -ru pulseaudio-8.0/src/modules/droid/module-droid-source.c pulseaudio-8.0.fixed/src/modules/droid/module-droid-source.c
---- pulseaudio-8.0/src/modules/droid/module-droid-source.c 2017-11-27 22:09:42.533589970 +0000
-+++ pulseaudio-8.0.fixed/src/modules/droid/module-droid-source.c 2017-11-27 22:30:03.920472828 +0000
-@@ -40,7 +40,7 @@
- #include "droid-util.h"
- #include "droid-source.h"
-
--#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 2
-+#if ANDROID_VERSION_MAJOR == 4 && ANDROID_VERSION_MINOR == 4
- #include "module-droid-source-19-symdef.h"
- #elif ANDROID_VERSION_MAJOR == 5 && ANDROID_VERSION_MINOR == 1
- #include "module-droid-source-22-symdef.h"
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py b/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py
deleted file mode 100644
index 5cb6d60be..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/packages/systemd.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-import glob
-import os
-import subprocess
-
-import package
-import wrapper_utils
-
-
-class Package(package.Package):
- """systemd package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('systemd', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- # Hide msan symbols from nm. the systemd build system uses this to find
- # undefined symbols and errors out if it does.
- nm_wrapper = (
- '#!/bin/bash\n'
- '/usr/bin/nm "$@" | grep -E -v "U (__msan|memset)"\n'
- 'exit ${PIPESTATUS[0]}\n')
-
- wrapper_utils.InstallWrapper(custom_bin_dir, 'nm', nm_wrapper,
- [wrapper_utils.DpkgHostArchitecture() + '-nm'])
diff --git a/infra/base-images/base-sanitizer-libs-builder/patch_build.py b/infra/base-images/base-sanitizer-libs-builder/patch_build.py
deleted file mode 100755
index cb1f4b1d7..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/patch_build.py
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-import argparse
-import os
-import re
-import shutil
-import subprocess
-import sys
-
-INSTRUMENTED_LIBRARIES_DIRNAME = 'instrumented_libraries'
-MSAN_LIBS_PATH = os.getenv('MSAN_LIBS_PATH', '/msan')
-
-
-def IsElf(file_path):
- """Whether if the file is an elf file."""
- with open(file_path) as f:
- return f.read(4) == '\x7fELF'
-
-
-def Ldd(binary_path):
- """Run ldd on a file."""
- try:
- output = subprocess.check_output(['ldd', binary_path], stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError:
- print('Failed to call ldd on', binary_path, file=sys.stderr)
- return []
-
- libs = []
-
- OUTPUT_PATTERN = re.compile(r'\s*([^\s]+)\s*=>\s*([^\s]+)')
- for line in output.splitlines():
- match = OUTPUT_PATTERN.match(line)
- if not match:
- continue
-
- libs.append((match.group(1), match.group(2)))
-
- return libs
-
-
-def FindLib(path):
- """Find instrumented version of lib."""
- candidate_path = os.path.join(MSAN_LIBS_PATH, path[1:])
- if os.path.exists(candidate_path):
- return candidate_path
-
- for lib_dir in os.listdir(MSAN_LIBS_PATH):
- candidate_path = os.path.join(MSAN_LIBS_PATH, lib_dir, path[1:])
- if os.path.exists(candidate_path):
- return candidate_path
-
- return None
-
-
-def PatchBinary(binary_path, instrumented_dir):
- """Patch binary to link to instrumented libs."""
- extra_rpaths = set()
-
- for name, path in Ldd(binary_path):
- if not os.path.isabs(path):
- continue
-
- instrumented_path = FindLib(path)
- if not instrumented_path:
- print('WARNING: Instrumented library not found for', path,
- file=sys.stderr)
- continue
-
- target_path = os.path.join(instrumented_dir, path[1:])
- if not os.path.exists(target_path):
- print('Copying instrumented lib to', target_path)
- target_dir = os.path.dirname(target_path)
- if not os.path.exists(target_dir):
- os.makedirs(target_dir)
- shutil.copy2(instrumented_path, target_path)
-
- extra_rpaths.add(
- os.path.join('$ORIGIN', INSTRUMENTED_LIBRARIES_DIRNAME,
- os.path.dirname(path[1:])))
-
- if not extra_rpaths:
- return
-
- existing_rpaths = subprocess.check_output(
- ['patchelf', '--print-rpath', binary_path]).strip()
- processed_rpaths = ':'.join(extra_rpaths)
- if existing_rpaths:
- processed_rpaths += ':' + existing_rpaths
- print('Patching rpath for', binary_path, 'from', existing_rpaths, 'to',
- processed_rpaths)
-
- subprocess.check_call(
- ['patchelf', '--force-rpath', '--set-rpath',
- processed_rpaths, binary_path])
-
-
-def PatchBuild(output_directory):
- """Patch build to use msan libs."""
- instrumented_dir = os.path.join(output_directory,
- INSTRUMENTED_LIBRARIES_DIRNAME)
- if not os.path.exists(instrumented_dir):
- os.mkdir(instrumented_dir)
-
- for root_dir, _, filenames in os.walk(output_directory):
- for filename in filenames:
- file_path = os.path.join(root_dir, filename)
-
- if os.path.islink(file_path):
- continue
-
- if not IsElf(file_path):
- continue
-
- PatchBinary(file_path, instrumented_dir)
-
-
-def main():
- parser = argparse.ArgumentParser('patch_build.py', description='MSan build patcher.')
- parser.add_argument('output_dir', help='Output directory.')
-
- args = parser.parse_args()
-
- PatchBuild(os.path.abspath(args.output_dir))
-
-
-if __name__ == '__main__':
- main()
diff --git a/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py b/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py
deleted file mode 100644
index 0cbf1677d..000000000
--- a/infra/base-images/base-sanitizer-libs-builder/wrapper_utils.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-# 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 __future__ import print_function
-
-import contextlib
-import os
-import subprocess
-
-
-def DpkgHostArchitecture():
- """Return the host architecture."""
- return subprocess.check_output(
- ['dpkg-architecture', '-qDEB_HOST_GNU_TYPE']).strip()
-
-
-def InstallWrapper(bin_dir, name, contents, extra_names=None):
- """Install a custom wrapper script into |bin_dir|."""
- path = os.path.join(bin_dir, name)
- with open(path, 'w') as f:
- f.write(contents)
-
- os.chmod(path, 0755)
-
- if extra_names:
- CreateSymlinks(path, bin_dir, extra_names)
-
-
-def CreateSymlinks(original_path, bin_dir, extra_names):
- """Create symlinks."""
- for extra_name in extra_names:
- extra_path = os.path.join(bin_dir, extra_name)
- os.symlink(original_path, extra_path)
diff --git a/infra/bisector.py b/infra/bisector.py
index 1438d0de9..51f93c132 100644
--- a/infra/bisector.py
+++ b/infra/bisector.py
@@ -115,7 +115,10 @@ def main():
'Bisection Error: Both the first and the last commits in'
'the given range have the same behavior, bisection is not possible. ')
return 1
- print('Error was introduced at commit %s' % result.commit)
+ 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
@@ -131,7 +134,7 @@ def _get_dedup_token(output):
return None
-def _check_for_crash(project_name, fuzz_target, test_case_path):
+def _check_for_crash(project_name, fuzz_target, testcase_path):
"""Check for crash."""
def docker_run(args):
@@ -142,12 +145,15 @@ def _check_for_crash(project_name, fuzz_target, test_case_path):
return utils.execute(command + args)
logging.info('Checking for crash')
- out, err, return_code = helper.reproduce_impl(project_name,
- fuzz_target,
- False, [], [],
- test_case_path,
- runner=docker_run,
- err_result=(None, None, None))
+ 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
@@ -167,7 +173,7 @@ def _check_for_crash(project_name, fuzz_target, test_case_path):
# pylint: disable=too-many-locals
# pylint: disable=too-many-arguments
# pylint: disable=too-many-statements
-def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
+def _bisect(bisect_type, old_commit, new_commit, testcase_path, fuzz_target,
build_data):
"""Perform the bisect."""
# pylint: disable=too-many-branches
@@ -212,7 +218,7 @@ def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
raise BisectError('Invalid bisect type ' + bisect_type, repo_url)
expected_error = _check_for_crash(build_data.project_name, fuzz_target,
- test_case_path)
+ testcase_path)
logging.info('new_commit result = %s', expected_error)
if not should_crash and expected_error:
@@ -231,7 +237,7 @@ def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
raise BisectError('Failed to build old_commit', repo_url)
if _check_for_crash(build_data.project_name, fuzz_target,
- test_case_path) == expected_error:
+ 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.
@@ -266,7 +272,7 @@ def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
continue
current_error = _check_for_crash(build_data.project_name, fuzz_target,
- test_case_path)
+ testcase_path)
logging.info('Current result = %s', current_error)
if expected_error == current_error:
new_idx = curr_idx
@@ -277,16 +283,16 @@ def _bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
# pylint: disable=too-many-locals
# pylint: disable=too-many-arguments
-def bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
+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 test_case_path.
+ 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.
- test_case_path: The file path of the test case that triggers the error
+ 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.
@@ -297,7 +303,7 @@ def bisect(bisect_type, old_commit, new_commit, test_case_path, fuzz_target,
ValueError: when a repo url can't be determine from the project.
"""
try:
- return _bisect(bisect_type, old_commit, new_commit, test_case_path,
+ return _bisect(bisect_type, old_commit, new_commit, testcase_path,
fuzz_target, build_data)
finally:
# Clean up projects/ as _bisect may have modified it.
diff --git a/infra/bisector_test.py b/infra/bisector_test.py
index 5e3dc5232..d93ac3239 100644
--- a/infra/bisector_test.py
+++ b/infra/bisector_test.py
@@ -45,7 +45,7 @@ class BisectIntegrationTests(unittest.TestCase):
architecture='x86_64')
with self.assertRaises(ValueError):
bisector.bisect(self.BISECT_TYPE, test_repo.old_commit,
- test_repo.new_commit, test_repo.test_case_path,
+ test_repo.new_commit, test_repo.testcase_path,
test_repo.fuzz_target, build_data)
def test_bisect(self):
@@ -58,7 +58,7 @@ class BisectIntegrationTests(unittest.TestCase):
sanitizer='address',
architecture='x86_64')
result = bisector.bisect(self.BISECT_TYPE, test_repo.old_commit,
- test_repo.new_commit, test_repo.test_case_path,
+ test_repo.new_commit, test_repo.testcase_path,
test_repo.fuzz_target, build_data)
self.assertEqual(result.commit, test_repo.intro_commit)
diff --git a/infra/build/functions/base_images.py b/infra/build/functions/base_images.py
index 8c9b2d85f..593323fc3 100644
--- a/infra/build/functions/base_images.py
+++ b/infra/build/functions/base_images.py
@@ -15,7 +15,6 @@
################################################################################
"""Cloud function to build base images on Google Cloud Builder."""
-import datetime
import logging
import google.auth
@@ -25,14 +24,17 @@ BASE_IMAGES = [
'base-image',
'base-clang',
'base-builder',
+ 'base-builder-go',
+ 'base-builder-jvm',
+ 'base-builder-python',
+ 'base-builder-rust',
+ 'base-builder-swift',
'base-runner',
'base-runner-debug',
]
BASE_PROJECT = 'oss-fuzz-base'
TAG_PREFIX = f'gcr.io/{BASE_PROJECT}/'
-
-BASE_SANITIZER_LIBS_IMAGE = TAG_PREFIX + 'base-sanitizer-libs-builder'
-MSAN_LIBS_IMAGE = TAG_PREFIX + 'msan-libs-builder'
+MAJOR_VERSION = 'v1'
def _get_base_image_steps(images, tag_prefix=TAG_PREFIX):
@@ -46,11 +48,14 @@ def _get_base_image_steps(images, tag_prefix=TAG_PREFIX):
}]
for base_image in images:
+ image = tag_prefix + base_image
steps.append({
'args': [
'build',
'-t',
- tag_prefix + base_image,
+ image,
+ '-t',
+ f'{image}:{MAJOR_VERSION}',
'.',
],
'dir': 'oss-fuzz/infra/base-images/' + base_image,
@@ -62,9 +67,8 @@ def _get_base_image_steps(images, tag_prefix=TAG_PREFIX):
def get_logs_url(build_id, project_id='oss-fuzz-base'):
"""Returns url that displays the build logs."""
- url_format = ('https://console.developers.google.com/logs/viewer?'
- 'resource=build%2Fbuild_id%2F{0}&project={1}')
- return url_format.format(build_id, project_id)
+ return ('https://console.developers.google.com/logs/viewer?'
+ f'resource=build%2Fbuild_id%2F{build_id}&project={project_id}')
# pylint: disable=no-member
@@ -77,7 +81,7 @@ def run_build(steps, images):
'options': {
'machineType': 'N1_HIGHCPU_32'
},
- 'images': images
+ 'images': images + [f'{image}:{MAJOR_VERSION}' for image in images]
}
cloudbuild = build('cloudbuild',
'v1',
@@ -99,43 +103,3 @@ def base_builder(event, context):
images = [tag_prefix + base_image for base_image in BASE_IMAGES]
run_build(steps, images)
-
-
-def _get_msan_steps(image):
- """Get build steps for msan-libs-builder."""
- timestamp = datetime.datetime.utcnow().strftime('%Y%m%d%H%M')
- upload_name = 'msan-libs-' + timestamp + '.zip'
-
- steps = _get_base_image_steps([
- 'base-sanitizer-libs-builder',
- 'msan-libs-builder',
- ])
- steps.extend([{
- 'name': image,
- 'args': [
- 'bash',
- '-c',
- 'cd /msan && zip -r /workspace/libs.zip .',
- ],
- }, {
- 'name':
- 'gcr.io/cloud-builders/gsutil',
- 'args': [
- 'cp',
- '/workspace/libs.zip',
- 'gs://oss-fuzz-msan-libs/' + upload_name,
- ],
- }])
- return steps
-
-
-def base_msan_builder(event, context):
- """Cloud function to build base images."""
- del event, context
- steps = _get_msan_steps(MSAN_LIBS_IMAGE)
- images = [
- BASE_SANITIZER_LIBS_IMAGE,
- MSAN_LIBS_IMAGE,
- ]
-
- run_build(steps, images)
diff --git a/infra/build/functions/build_and_run_coverage.py b/infra/build/functions/build_and_run_coverage.py
index cc2de5a32..1195776d9 100644..100755
--- a/infra/build/functions/build_and_run_coverage.py
+++ b/infra/build/functions/build_and_run_coverage.py
@@ -13,11 +13,11 @@
# limitations under the License.
#
################################################################################
-#!/usr/bin/python2
+#!/usr/bin/env python3
"""Starts and runs coverage build on Google Cloud Builder.
-Usage: build_and_run_coverage.py <project_dir>
+
+Usage: build_and_run_coverage.py <project>.
"""
-import datetime
import json
import logging
import os
@@ -27,119 +27,105 @@ import build_lib
import build_project
SANITIZER = 'coverage'
-CONFIGURATION = ['FUZZING_ENGINE=libfuzzer', 'SANITIZER=%s' % SANITIZER]
+FUZZING_ENGINE = 'libfuzzer'
+ARCHITECTURE = 'x86_64'
+
PLATFORM = 'linux'
-COVERAGE_BUILD_TAG = 'coverage'
+COVERAGE_BUILD_TYPE = 'coverage'
# Where code coverage reports need to be uploaded to.
COVERAGE_BUCKET_NAME = 'oss-fuzz-coverage'
-# Link to the code coverage report in HTML format.
-HTML_REPORT_URL_FORMAT = (build_lib.GCS_URL_BASENAME + COVERAGE_BUCKET_NAME +
- '/{project}/reports/{date}/{platform}/index.html')
-
# This is needed for ClusterFuzz to pick up the most recent reports data.
-LATEST_REPORT_INFO_URL = ('/' + COVERAGE_BUCKET_NAME +
- '/latest_report_info/{project}.json')
-LATEST_REPORT_INFO_CONTENT_TYPE = 'application/json'
-# Link where to upload code coverage report files to.
-UPLOAD_URL_FORMAT = 'gs://' + COVERAGE_BUCKET_NAME + '/{project}/{type}/{date}'
+LATEST_REPORT_INFO_CONTENT_TYPE = 'application/json'
# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
+LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'jvm', 'rust', 'swift']
+
+
+class Bucket: # pylint: disable=too-few-public-methods
+ """Class representing the coverage GCS bucket."""
+ def __init__(self, project, date, platform, testing):
+ self.coverage_bucket_name = 'oss-fuzz-coverage'
+ if testing:
+ self.coverage_bucket_name += '-testing'
-def usage():
- """Exit with code 1 and display syntax to use this file."""
- sys.stderr.write("Usage: " + sys.argv[0] + " <project_dir>\n")
- sys.exit(1)
+ self.date = date
+ self.project = project
+ self.html_report_url = (
+ f'{build_lib.GCS_URL_BASENAME}{self.coverage_bucket_name}/{project}'
+ f'/reports/{date}/{platform}/index.html')
+ self.latest_report_info_url = (f'/{COVERAGE_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.coverage_bucket_name}/{self.project}'
+ f'/{upload_type}/{self.date}')
-# pylint: disable=too-many-locals
-def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
- image_project, base_images_project):
+
+def get_build_steps( # pylint: disable=too-many-locals, too-many-arguments
+ project_name, project_yaml_contents, dockerfile_lines, image_project,
+ base_images_project, config):
"""Returns build steps for project."""
- project_yaml = build_project.load_project_yaml(project_name,
- project_yaml_file,
- image_project)
- if project_yaml['disabled']:
- logging.info('Project "%s" is disabled.', project_name)
+ project = build_project.Project(project_name, project_yaml_contents,
+ dockerfile_lines, image_project)
+ if project.disabled:
+ logging.info('Project "%s" is disabled.', project.name)
return []
- if project_yaml['language'] not in LANGUAGES_WITH_COVERAGE_SUPPORT:
+ if project.fuzzing_language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
logging.info(
'Project "%s" is written in "%s", coverage is not supported yet.',
- project_name, project_yaml['language'])
+ project.name, project.fuzzing_language)
return []
- name = project_yaml['name']
- image = project_yaml['image']
- language = project_yaml['language']
- report_date = datetime.datetime.now().strftime('%Y%m%d')
-
- build_steps = build_lib.project_image_steps(name, image, language)
+ report_date = build_project.get_datetime_now().strftime('%Y%m%d')
+ bucket = Bucket(project.name, report_date, PLATFORM, config.testing)
- env = CONFIGURATION[:]
- out = '/workspace/out/' + SANITIZER
- env.append('OUT=' + out)
- env.append('FUZZING_LANGUAGE=' + language)
+ build_steps = build_lib.project_image_steps(
+ project.name,
+ project.image,
+ project.fuzzing_language,
+ branch=config.branch,
+ test_image_suffix=config.test_image_suffix)
- workdir = build_project.workdir_from_dockerfile(dockerfile_lines)
- if not workdir:
- workdir = '/src'
-
- failure_msg = ('*' * 80 + '\nCoverage build failed.\nTo reproduce, run:\n'
- 'python infra/helper.py build_image {name}\n'
- 'python infra/helper.py build_fuzzers --sanitizer coverage '
- '{name}\n' + '*' * 80).format(name=name)
-
- # Compilation step.
- build_steps.append({
- 'name':
- 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.
- ('rm -r /out && cd /src && cd {workdir} && mkdir -p {out} && '
- 'compile || (echo "{failure_msg}" && false)'
- ).format(workdir=workdir, out=out, failure_msg=failure_msg),
- ],
- })
-
- download_corpora_steps = build_lib.download_corpora_steps(project_name)
+ build = build_project.Build('libfuzzer', 'coverage', 'x86_64')
+ 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, testing=config.testing)
if not download_corpora_steps:
- logging.info('Skipping code coverage build for %s.', project_name)
+ logging.info('Skipping code coverage build for %s.', project.name)
return []
build_steps.extend(download_corpora_steps)
failure_msg = ('*' * 80 + '\nCode coverage report generation failed.\n'
'To reproduce, run:\n'
- 'python infra/helper.py build_image {name}\n'
+ f'python infra/helper.py build_image {project.name}\n'
'python infra/helper.py build_fuzzers --sanitizer coverage '
- '{name}\n'
- 'python infra/helper.py coverage {name}\n' +
- '*' * 80).format(name=name)
+ 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=',
- 'COVERAGE_EXTRA_ARGS=%s' % project_yaml['coverage_extra_args'].strip(),
+ f'COVERAGE_EXTRA_ARGS={project.coverage_extra_args.strip()}',
]
- if 'dataflow' in project_yaml['fuzzing_engines']:
+ if 'dataflow' in project.fuzzing_engines:
coverage_env.append('FULL_SUMMARY_PER_TARGET=1')
build_steps.append({
- 'name': 'gcr.io/{0}/base-runner'.format(base_images_project),
- 'env': coverage_env,
+ 'name':
+ build_project.get_runner_image_name(base_images_project,
+ config.test_image_suffix),
+ 'env':
+ coverage_env,
'args': [
'bash', '-c',
('for f in /corpus/*.zip; do unzip -q $f -d ${f%%.*} || ('
@@ -158,9 +144,7 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
})
# Upload the report.
- upload_report_url = UPLOAD_URL_FORMAT.format(project=project_name,
- type='reports',
- date=report_date)
+ upload_report_url = bucket.get_upload_url('reports')
# 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).
@@ -172,15 +156,14 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
'-m',
'cp',
'-r',
- os.path.join(out, 'report'),
+ os.path.join(build.out, 'report'),
upload_report_url,
],
})
# Upload the fuzzer stats. Delete the old ones just in case.
- upload_fuzzer_stats_url = UPLOAD_URL_FORMAT.format(project=project_name,
- type='fuzzer_stats',
- date=report_date)
+ 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':
@@ -189,15 +172,13 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
'-m',
'cp',
'-r',
- os.path.join(out, 'fuzzer_stats'),
+ os.path.join(build.out, 'fuzzer_stats'),
upload_fuzzer_stats_url,
],
})
# Upload the fuzzer logs. Delete the old ones just in case
- upload_fuzzer_logs_url = UPLOAD_URL_FORMAT.format(project=project_name,
- type='logs',
- date=report_date)
+ 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':
@@ -206,15 +187,13 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
'-m',
'cp',
'-r',
- os.path.join(out, 'logs'),
+ os.path.join(build.out, 'logs'),
upload_fuzzer_logs_url,
],
})
# Upload srcmap.
- srcmap_upload_url = UPLOAD_URL_FORMAT.format(project=project_name,
- type='srcmap',
- date=report_date)
+ 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',
@@ -227,15 +206,13 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
# Update the latest report information file for ClusterFuzz.
latest_report_info_url = build_lib.get_signed_url(
- LATEST_REPORT_INFO_URL.format(project=project_name),
+ 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':
- HTML_REPORT_URL_FORMAT.format(project=project_name,
- date=report_date,
- platform=PLATFORM),
+ bucket.html_report_url,
'report_date':
report_date,
'report_summary_path':
@@ -251,25 +228,10 @@ def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
def main():
"""Build and run coverage for projects."""
- if len(sys.argv) != 2:
- usage()
-
- image_project = 'oss-fuzz'
- base_images_project = 'oss-fuzz-base'
- project_dir = sys.argv[1].rstrip(os.path.sep)
- project_name = os.path.basename(project_dir)
- dockerfile_path = os.path.join(project_dir, 'Dockerfile')
- project_yaml_path = os.path.join(project_dir, 'project.yaml')
-
- with open(dockerfile_path) as docker_file:
- dockerfile_lines = docker_file.readlines()
-
- with open(project_yaml_path) as project_yaml_file:
- steps = get_build_steps(project_name, project_yaml_file, dockerfile_lines,
- image_project, base_images_project)
-
- build_project.run_build(steps, project_name, COVERAGE_BUILD_TAG)
+ return build_project.build_script_main(
+ 'Generates coverage report for project.', get_build_steps,
+ COVERAGE_BUILD_TYPE)
-if __name__ == "__main__":
- main()
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/infra/build/functions/build_and_run_coverage_test.py b/infra/build/functions/build_and_run_coverage_test.py
new file mode 100644
index 000000000..83ea39ecd
--- /dev/null
+++ b/infra/build/functions/build_and_run_coverage_test.py
@@ -0,0 +1,78 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
+ def test_get_coverage_build_steps(self, mock_url, mock_corpora_steps,
+ mock_get_datetime_now):
+ """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')
+ 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(False, False, None, 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, test_utils.IMAGE_PROJECT,
+ test_utils.BASE_IMAGES_PROJECT, config)
+ self.assertEqual(build_steps, expected_coverage_build_steps)
+
+
+if __name__ == '__main__':
+ unittest.main(exit=False)
diff --git a/infra/build/functions/build_lib.py b/infra/build/functions/build_lib.py
index 007579ef9..292ef682f 100644
--- a/infra/build/functions/build_lib.py
+++ b/infra/build/functions/build_lib.py
@@ -83,11 +83,23 @@ def get_targets_list_url(bucket, project, sanitizer):
return url
-def _get_targets_list(project_name):
+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, testing):
"""Returns target list."""
- # libFuzzer ASan is the default configuration, get list of targets from it.
- url = get_targets_list_url(ENGINE_INFO['libfuzzer'].upload_bucket,
- project_name, 'address')
+ # libFuzzer ASan 'x86_84' is the default configuration, get list of targets
+ # from it.
+ bucket = get_upload_bucket('libfuzzer', 'x86_64', testing)
+ url = get_targets_list_url(bucket, project_name, 'address')
url = urlparse.urljoin(GCS_URL_BASENAME, url)
response = requests.get(url)
@@ -104,7 +116,7 @@ def _get_targets_list(project_name):
def get_signed_url(path, method='PUT', content_type=''):
"""Returns signed url."""
timestamp = int(time.time() + BUILD_TIMEOUT)
- blob = '{0}\n\n{1}\n{2}\n{3}'.format(method, content_type, timestamp, path)
+ blob = f'{method}\n\n{content_type}\n{timestamp}\n{path}'
service_account_path = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')
if service_account_path:
@@ -119,7 +131,7 @@ def get_signed_url(path, method='PUT', content_type=''):
credentials=credentials,
cache_discovery=False)
client_id = project + '@appspot.gserviceaccount.com'
- service_account = 'projects/-/serviceAccounts/{0}'.format(client_id)
+ service_account = f'projects/-/serviceAccounts/{client_id}'
response = iam.projects().serviceAccounts().signBlob(
name=service_account,
body={
@@ -133,14 +145,13 @@ def get_signed_url(path, method='PUT', content_type=''):
'Expires': timestamp,
'Signature': signature,
}
- return ('https://storage.googleapis.com{0}?'.format(path) +
- urlparse.urlencode(values))
+ return f'https://storage.googleapis.com{path}?{urlparse.urlencode(values)}'
-def download_corpora_steps(project_name):
+def download_corpora_steps(project_name, testing):
"""Returns GCB steps for downloading corpora backups for the given project.
"""
- fuzz_targets = _get_targets_list(project_name)
+ fuzz_targets = _get_targets_list(project_name, testing)
if not fuzz_targets:
sys.stderr.write('No fuzz targets found for project "%s".\n' % project_name)
return None
@@ -206,15 +217,72 @@ def gsutil_rm_rf_step(url):
return step
-def project_image_steps(name, image, language):
+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-jvm',
+ 'gcr.io/oss-fuzz-base/base-builder-go',
+ 'gcr.io/oss-fuzz-base/base-builder-python',
+ 'gcr.io/oss-fuzz-base/base-builder-rust',
+ ]
+ steps = []
+ for image in images:
+ test_image = image + '-' + test_image_suffix
+ steps.append({
+ 'name': 'gcr.io/cloud-builders/docker',
+ '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': 'gcr.io/cloud-builders/docker',
+ 'args': ['tag', test_image, image],
+ })
+ return steps
+
+
+def get_srcmap_step_id():
+ """Returns the id for the srcmap step."""
+ return 'srcmap'
+
+
+def project_image_steps(name,
+ image,
+ language,
+ branch=None,
+ test_image_suffix=None):
"""Returns GCB steps to build OSS-Fuzz project image."""
- steps = [{
+ clone_step = {
'args': [
- 'clone',
- 'https://github.com/google/oss-fuzz.git',
+ 'clone', 'https://github.com/google/oss-fuzz.git', '--depth', '1'
],
'name': 'gcr.io/cloud-builders/git',
- }, {
+ }
+ if branch:
+ # Do this to support testing other branches.
+ clone_step['args'].extend(['--branch', branch])
+
+ steps = [clone_step]
+ if test_image_suffix:
+ steps.extend(get_pull_test_images_steps(test_image_suffix))
+
+ srcmap_step_id = get_srcmap_step_id()
+ steps += [{
'name': 'gcr.io/cloud-builders/docker',
'args': [
'build',
@@ -224,8 +292,7 @@ def project_image_steps(name, image, language):
],
'dir': 'oss-fuzz/projects/' + name,
}, {
- 'name':
- image,
+ 'name': image,
'args': [
'bash', '-c',
'srcmap > /workspace/srcmap.json && cat /workspace/srcmap.json'
@@ -234,6 +301,7 @@ def project_image_steps(name, image, language):
'OSSFUZZ_REVISION=$REVISION_ID',
'FUZZING_LANGUAGE=%s' % language,
],
+ 'id': srcmap_step_id
}]
return steps
diff --git a/infra/build/functions/build_project.py b/infra/build/functions/build_project.py
index 9115c85fd..bdc7985e1 100644..100755
--- a/infra/build/functions/build_project.py
+++ b/infra/build/functions/build_project.py
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-#!/usr/bin/python2
+#!/usr/bin/env python3
"""Starts project build on Google Cloud Builder.
Usage: build_project.py <project_dir>
@@ -21,37 +21,27 @@ Usage: build_project.py <project_dir>
from __future__ import print_function
+import argparse
+import collections
import datetime
import json
import logging
import os
+import posixpath
import re
import sys
+from googleapiclient.discovery import build as cloud_build
+import oauth2client.client
import six
import yaml
-from oauth2client.client import GoogleCredentials
-from googleapiclient.discovery import build
-
import build_lib
-FUZZING_BUILD_TAG = 'fuzzing'
+FUZZING_BUILD_TYPE = 'fuzzing'
GCB_LOGS_BUCKET = 'oss-fuzz-gcb-logs'
-CONFIGURATIONS = {
- 'sanitizer-address': ['SANITIZER=address'],
- 'sanitizer-dataflow': ['SANITIZER=dataflow'],
- 'sanitizer-memory': ['SANITIZER=memory'],
- 'sanitizer-undefined': ['SANITIZER=undefined'],
- 'engine-libfuzzer': ['FUZZING_ENGINE=libfuzzer'],
- 'engine-afl': ['FUZZING_ENGINE=afl'],
- 'engine-honggfuzz': ['FUZZING_ENGINE=honggfuzz'],
- 'engine-dataflow': ['FUZZING_ENGINE=dataflow'],
- 'engine-none': ['FUZZING_ENGINE=none'],
-}
-
DEFAULT_ARCHITECTURES = ['x86_64']
DEFAULT_ENGINES = ['libfuzzer', 'afl', 'honggfuzz']
DEFAULT_SANITIZERS = ['address', 'undefined']
@@ -61,19 +51,100 @@ 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_GCB_OPTIONS = {'machineType': 'N1_HIGHCPU_32'}
+
+Config = collections.namedtuple(
+ 'Config', ['testing', 'test_image_suffix', 'branch', 'parallel'])
+
+WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
+
-def usage():
- """Exit with code 1 and display syntax to use this file."""
- sys.stderr.write('Usage: ' + sys.argv[0] + ' <project_dir>\n')
- sys.exit(1)
+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)
-def set_yaml_defaults(project_name, project_yaml, image_project):
- """Set project.yaml's default parameters."""
+ @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):
+ """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:
+ logging.error('Project "%s" does not have a dockerfile.', project_name)
+ 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()
+ return project_yaml_contents, dockerfile
+
+
+class Project: # pylint: disable=too-many-instance-attributes
+ """Class representing an OSS-Fuzz project."""
+
+ def __init__(self, name, project_yaml_contents, dockerfile, image_project):
+ project_yaml = yaml.safe_load(project_yaml_contents)
+ self.name = name
+ self.image_project = image_project
+ self.workdir = workdir_from_dockerfile(dockerfile)
+ set_yaml_defaults(project_yaml)
+ 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']
+
+ @property
+ def sanitizers(self):
+ """Returns processed sanitizers."""
+ assert isinstance(self._sanitizers, list)
+ processed_sanitizers = []
+ for sanitizer in self._sanitizers:
+ if isinstance(sanitizer, six.string_types):
+ processed_sanitizers.append(sanitizer)
+ elif isinstance(sanitizer, dict):
+ for key in sanitizer.keys():
+ processed_sanitizers.append(key)
+
+ return processed_sanitizers
+
+ @property
+ def image(self):
+ """Returns the docker image for the project."""
+ return f'gcr.io/{self.image_project}/{self.name}'
+
+
+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('name', project_name)
- project_yaml.setdefault('image',
- 'gcr.io/{0}/{1}'.format(image_project, project_name))
project_yaml.setdefault('architectures', DEFAULT_ARCHITECTURES)
project_yaml.setdefault('sanitizers', DEFAULT_SANITIZERS)
project_yaml.setdefault('fuzzing_engines', DEFAULT_ENGINES)
@@ -82,291 +153,310 @@ def set_yaml_defaults(project_name, project_yaml, image_project):
project_yaml.setdefault('labels', {})
-def is_supported_configuration(fuzzing_engine, sanitizer, architecture):
+def is_supported_configuration(build):
"""Check if the given configuration is supported."""
- fuzzing_engine_info = build_lib.ENGINE_INFO[fuzzing_engine]
- if architecture == 'i386' and sanitizer != 'address':
+ fuzzing_engine_info = build_lib.ENGINE_INFO[build.fuzzing_engine]
+ if build.architecture == 'i386' and build.sanitizer != 'address':
return False
- return (sanitizer in fuzzing_engine_info.supported_sanitizers and
- architecture in fuzzing_engine_info.supported_architectures)
-
+ return (build.sanitizer in fuzzing_engine_info.supported_sanitizers and
+ build.architecture in fuzzing_engine_info.supported_architectures)
-def get_sanitizers(project_yaml):
- """Retrieve sanitizers from project.yaml."""
- sanitizers = project_yaml['sanitizers']
- assert isinstance(sanitizers, list)
- processed_sanitizers = []
- for sanitizer in sanitizers:
- if isinstance(sanitizer, six.string_types):
- processed_sanitizers.append(sanitizer)
- elif isinstance(sanitizer, dict):
- for key in sanitizer.keys():
- processed_sanitizers.append(key)
-
- return processed_sanitizers
-
-
-def workdir_from_dockerfile(dockerfile_lines):
- """Parse WORKDIR from the Dockerfile."""
- workdir_regex = re.compile(r'\s*WORKDIR\s*([^\s]+)')
+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)
+ 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 None
+ return '/src'
-def load_project_yaml(project_name, project_yaml_file, image_project):
- """Loads project yaml and sets default values."""
- project_yaml = yaml.safe_load(project_yaml_file)
- set_yaml_defaults(project_name, project_yaml, image_project)
- return project_yaml
+def get_datetime_now():
+ """Returns datetime.datetime.now(). Used for mocking."""
+ return datetime.datetime.now()
-# pylint: disable=too-many-locals, too-many-statements, too-many-branches
-def get_build_steps(project_name, project_yaml_file, dockerfile_lines,
- image_project, base_images_project):
- """Returns build steps for project."""
- project_yaml = load_project_yaml(project_name, project_yaml_file,
- image_project)
-
- if project_yaml['disabled']:
- logging.info('Project "%s" is disabled.', project_name)
- return []
-
- name = project_yaml['name']
- image = project_yaml['image']
- language = project_yaml['language']
- run_tests = project_yaml['run_tests']
- time_stamp = datetime.datetime.now().strftime('%Y%m%d%H%M')
-
- build_steps = build_lib.project_image_steps(name, image, language)
- # Copy over MSan instrumented libraries.
- build_steps.append({
- 'name': 'gcr.io/{0}/msan-libs-builder'.format(base_images_project),
+def get_env(fuzzing_language, build):
+ """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,
+ }
+ return list(sorted([f'{key}={value}' for key, value in env_dict.items()]))
+
+
+def get_compile_step(project, build, env, parallel):
+ """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_step = {
+ 'name': project.image,
+ 'env': env,
'args': [
'bash',
'-c',
- 'cp -r /msan /workspace',
+ # 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 || '
+ f'(echo "{failure_msg}" && false)'),
],
- })
+ 'id': get_id('compile', build),
+ }
+ if parallel:
+ maybe_add_parallel(compile_step, build_lib.get_srcmap_step_id(), parallel)
+ return compile_step
- for fuzzing_engine in project_yaml['fuzzing_engines']:
- for sanitizer in get_sanitizers(project_yaml):
- for architecture in project_yaml['architectures']:
- if not is_supported_configuration(fuzzing_engine, sanitizer,
- architecture):
- continue
- env = CONFIGURATIONS['engine-' + fuzzing_engine][:]
- env.extend(CONFIGURATIONS['sanitizer-' + sanitizer])
- out = '/workspace/out/' + sanitizer
- stamped_name = '-'.join([name, sanitizer, time_stamp])
- latest_version_file = '-'.join(
- [name, sanitizer, LATEST_VERSION_FILENAME])
- zip_file = stamped_name + '.zip'
- stamped_srcmap_file = stamped_name + '.srcmap.json'
- bucket = build_lib.ENGINE_INFO[fuzzing_engine].upload_bucket
- if architecture != 'x86_64':
- bucket += '-' + architecture
-
- upload_url = build_lib.get_signed_url(
- build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, name, zip_file))
- srcmap_url = build_lib.get_signed_url(
- build_lib.GCS_UPLOAD_URL_FORMAT.format(bucket, name,
- stamped_srcmap_file))
- latest_version_url = build_lib.GCS_UPLOAD_URL_FORMAT.format(
- bucket, name, latest_version_file)
- latest_version_url = build_lib.get_signed_url(
- latest_version_url, content_type=LATEST_VERSION_CONTENT_TYPE)
-
- targets_list_filename = build_lib.get_targets_list_filename(sanitizer)
- targets_list_url = build_lib.get_signed_url(
- build_lib.get_targets_list_url(bucket, name, sanitizer))
-
- env.append('OUT=' + out)
- env.append('MSAN_LIBS_PATH=/workspace/msan')
- env.append('ARCHITECTURE=' + architecture)
- env.append('FUZZING_LANGUAGE=' + language)
-
- workdir = workdir_from_dockerfile(dockerfile_lines)
- if not workdir:
- workdir = '/src'
-
- failure_msg = ('*' * 80 + '\nFailed to build.\nTo reproduce, run:\n'
- 'python infra/helper.py build_image {name}\n'
- 'python infra/helper.py build_fuzzers --sanitizer '
- '{sanitizer} --engine {engine} --architecture '
- '{architecture} {name}\n' + '*' * 80).format(
- name=name,
- sanitizer=sanitizer,
- engine=fuzzing_engine,
- architecture=architecture)
-
- build_steps.append(
- # compile
- {
- 'name':
- image,
- 'env':
- env,
- 'args': [
- 'bash',
- '-c',
- # Remove /out to break loudly when a build script
- # incorrectly uses /out instead of $OUT.
- # `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.
- ('rm -r /out && cd /src && cd {workdir} && mkdir -p {out} '
- '&& compile || (echo "{failure_msg}" && false)'
- ).format(workdir=workdir, out=out, failure_msg=failure_msg),
- ],
- })
+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
- if sanitizer == 'memory':
- # Patch dynamic libraries to use instrumented ones.
- build_steps.append({
+
+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_contents, dockerfile, image_project,
+ base_images_project, config):
+ """Returns build steps for project."""
+
+ project = Project(project_name, project_yaml_contents, dockerfile,
+ image_project)
+
+ if project.disabled:
+ logging.info('Project "%s" is disabled.', project.name)
+ return []
+
+ timestamp = get_datetime_now().strftime('%Y%m%d%H%M')
+
+ build_steps = build_lib.project_image_steps(
+ project.name,
+ project.image,
+ project.fuzzing_language,
+ branch=config.branch,
+ test_image_suffix=config.test_image_suffix)
+
+ # 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):
+ for sanitizer in project.sanitizers:
+ for architecture in project.architectures:
+ build = Build(fuzzing_engine, sanitizer, architecture)
+ if not is_supported_configuration(build):
+ continue
+
+ env = get_env(project.fuzzing_language, build)
+ compile_step = get_compile_step(project, build, env, config.parallel)
+ build_steps.append(compile_step)
+
+ 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.
+ test_step = {
'name':
- 'gcr.io/{0}/msan-libs-builder'.format(base_images_project),
+ get_runner_image_name(base_images_project,
+ config.test_image_suffix),
+ 'env':
+ env,
'args': [
- 'bash',
- '-c',
- # TODO(ochang): Replace with just patch_build.py once
- # permission in image is fixed.
- 'python /usr/local/bin/patch_build.py {0}'.format(out),
+ 'bash', '-c',
+ f'test_all.py || (echo "{failure_msg}" && false)'
],
- })
-
- if run_tests:
- failure_msg = ('*' * 80 + '\nBuild checks failed.\n'
- 'To reproduce, run:\n'
- 'python infra/helper.py build_image {name}\n'
- 'python infra/helper.py build_fuzzers --sanitizer '
- '{sanitizer} --engine {engine} --architecture '
- '{architecture} {name}\n'
- 'python infra/helper.py check_build --sanitizer '
- '{sanitizer} --engine {engine} --architecture '
- '{architecture} {name}\n' + '*' * 80).format(
- name=name,
- sanitizer=sanitizer,
- engine=fuzzing_engine,
- architecture=architecture)
-
- build_steps.append(
- # test binaries
- {
- 'name':
- 'gcr.io/{0}/base-runner'.format(base_images_project),
- 'env':
- env,
- 'args': [
- 'bash', '-c',
- 'test_all.py || (echo "{0}" && false)'.format(failure_msg)
- ],
- })
-
- if project_yaml['labels']:
- # write target labels
+ 'id':
+ get_id('build-check', 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':
- image,
+ project.image,
'env':
env,
'args': [
'/usr/local/bin/write_labels.py',
- json.dumps(project_yaml['labels']),
- out,
+ json.dumps(project.labels),
+ build.out,
],
})
- if sanitizer == 'dataflow' and fuzzing_engine == 'dataflow':
- dataflow_steps = dataflow_post_build_steps(name, env,
- base_images_project)
+ if build.sanitizer == 'dataflow' and build.fuzzing_engine == 'dataflow':
+ dataflow_steps = dataflow_post_build_steps(project.name, env,
+ base_images_project,
+ config.testing,
+ config.test_image_suffix)
if dataflow_steps:
build_steps.extend(dataflow_steps)
else:
sys.stderr.write('Skipping dataflow post build steps.\n')
build_steps.extend([
- # generate targets list
+ # Generate targets list.
{
'name':
- 'gcr.io/{0}/base-runner'.format(base_images_project),
+ get_runner_image_name(base_images_project,
+ config.test_image_suffix),
'env':
env,
'args': [
- 'bash',
- '-c',
- 'targets_list > /workspace/{0}'.format(
- targets_list_filename),
- ],
- },
- # zip binaries
- {
- 'name':
- image,
- 'args': [
'bash', '-c',
- 'cd {out} && zip -r {zip_file} *'.format(out=out,
- zip_file=zip_file)
- ],
- },
- # upload srcmap
- {
- 'name': 'gcr.io/{0}/uploader'.format(base_images_project),
- 'args': [
- '/workspace/srcmap.json',
- srcmap_url,
- ],
- },
- # upload binaries
- {
- 'name': 'gcr.io/{0}/uploader'.format(base_images_project),
- 'args': [
- os.path.join(out, zip_file),
- upload_url,
- ],
- },
- # upload targets list
- {
- 'name':
- 'gcr.io/{0}/uploader'.format(base_images_project),
- 'args': [
- '/workspace/{0}'.format(targets_list_filename),
- targets_list_url,
- ],
- },
- # upload the latest.version file
- build_lib.http_upload_step(zip_file, latest_version_url,
- LATEST_VERSION_CONTENT_TYPE),
- # cleanup
- {
- 'name': image,
- 'args': [
- 'bash',
- '-c',
- 'rm -r ' + out,
+ f'targets_list > /workspace/{build.targets_list_filename}'
],
- },
+ }
])
+ upload_steps = get_upload_steps(project, build, timestamp,
+ base_images_project, config.testing)
+ build_steps.extend(upload_steps)
return build_steps
-def dataflow_post_build_steps(project_name, env, base_images_project):
+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(base_images_project):
+ """Returns the uploader base image in |base_images_project|."""
+ return f'gcr.io/{base_images_project}/uploader'
+
+
+def get_upload_steps(project, build, timestamp, base_images_project, testing):
+ """Returns the steps for uploading the fuzzer build specified by |project| and
+ |build|. Uses |timestamp| for naming the uploads. Uses |base_images_project|
+ and |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(base_images_project)
+
+ 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,
+ ],
+ }
+
+
+def get_runner_image_name(base_images_project, test_image_suffix):
+ """Returns the runner image that should be used, based on
+ |base_images_project|. Returns the testing image if |test_image_suffix|."""
+ image = f'gcr.io/{base_images_project}/base-runner'
+ if test_image_suffix:
+ image += '-' + test_image_suffix
+ return image
+
+
+def dataflow_post_build_steps(project_name, env, base_images_project, testing,
+ test_image_suffix):
"""Appends dataflow post build steps."""
- steps = build_lib.download_corpora_steps(project_name)
+ steps = build_lib.download_corpora_steps(project_name, testing)
if not steps:
return None
steps.append({
'name':
- 'gcr.io/{0}/base-runner'.format(base_images_project),
+ get_runner_image_name(base_images_project, test_image_suffix),
'env':
env + [
'COLLECT_DFT_TIMEOUT=2h',
@@ -387,63 +477,126 @@ def dataflow_post_build_steps(project_name, env, base_images_project):
return steps
-def get_logs_url(build_id, image_project='oss-fuzz'):
+def get_logs_url(build_id, cloud_project='oss-fuzz'):
"""Returns url where logs are displayed for the build."""
- url_format = ('https://console.developers.google.com/logs/viewer?'
- 'resource=build%2Fbuild_id%2F{0}&project={1}')
- return url_format.format(build_id, image_project)
+ return ('https://console.cloud.google.com/logs/viewer?'
+ f'resource=build%2Fbuild_id%2F{build_id}&project={cloud_project}')
+
+
+def get_gcb_url(build_id, cloud_project='oss-fuzz'):
+ """Returns url where logs are displayed for the build."""
+ return (f'https://console.cloud.google.com/cloud-build/builds/{build_id}'
+ f'?project={cloud_project}')
# pylint: disable=no-member
-def run_build(build_steps, project_name, tag):
- """Run the build for given steps on cloud build."""
+def run_build(oss_fuzz_project,
+ build_steps,
+ credentials,
+ build_type,
+ cloud_project='oss-fuzz'):
+ """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."""
options = {}
if 'GCB_OPTIONS' in os.environ:
options = yaml.safe_load(os.environ['GCB_OPTIONS'])
+ else:
+ options = DEFAULT_GCB_OPTIONS
+ tags = [oss_fuzz_project + '-' + build_type, build_type, oss_fuzz_project]
build_body = {
'steps': build_steps,
'timeout': str(build_lib.BUILD_TIMEOUT) + 's',
'options': options,
'logsBucket': GCB_LOGS_BUCKET,
- 'tags': [project_name + '-' + tag,],
+ 'tags': tags,
'queueTtl': str(QUEUE_TTL_SECONDS) + 's',
}
- credentials = GoogleCredentials.get_application_default()
- cloudbuild = build('cloudbuild',
- 'v1',
- credentials=credentials,
- cache_discovery=False)
- build_info = cloudbuild.projects().builds().create(projectId='oss-fuzz',
+ cloudbuild = cloud_build('cloudbuild',
+ 'v1',
+ credentials=credentials,
+ cache_discovery=False)
+ build_info = cloudbuild.projects().builds().create(projectId=cloud_project,
body=build_body).execute()
build_id = build_info['metadata']['build']['id']
- print('Logs:', get_logs_url(build_id), file=sys.stderr)
- print(build_id)
-
-
-def main():
- """Build and run projects."""
- if len(sys.argv) != 2:
- usage()
+ logging.info('Build ID: %s', build_id)
+ logging.info('Logs: %s', get_logs_url(build_id, cloud_project))
+ logging.info('Cloud build page: %s', get_gcb_url(build_id, cloud_project))
+ return build_id
+
+
+def get_args(description):
+ """Parses command line arguments 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('--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.')
+ return parser.parse_args()
+
+
+def build_script_main(script_description, get_build_steps_func, build_type):
+ """Gets arguments from command line using |script_description| as helpstring
+ description. 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 = get_args(script_description)
+ logging.basicConfig(level=logging.INFO)
image_project = 'oss-fuzz'
base_images_project = 'oss-fuzz-base'
- project_dir = sys.argv[1].rstrip(os.path.sep)
- dockerfile_path = os.path.join(project_dir, 'Dockerfile')
- project_yaml_path = os.path.join(project_dir, 'project.yaml')
- project_name = os.path.basename(project_dir)
- with open(dockerfile_path) as dockerfile:
- dockerfile_lines = dockerfile.readlines()
+ credentials = oauth2client.client.GoogleCredentials.get_application_default()
+ error = False
+ config = Config(args.testing, args.test_image_suffix, args.branch,
+ args.parallel)
+ for project_name in args.projects:
+ logging.info('Getting steps for: "%s".', project_name)
+ try:
+ project_yaml_contents, dockerfile_contents = get_project_data(
+ project_name)
+ except FileNotFoundError:
+ logging.error('Couldn\'t get project data. Skipping %s.', project_name)
+ error = True
+ continue
+
+ steps = get_build_steps_func(project_name, project_yaml_contents,
+ dockerfile_contents, image_project,
+ base_images_project, config)
+ if not steps:
+ logging.error('No steps. Skipping %s.', project_name)
+ error = True
+ continue
+
+ run_build(project_name, steps, credentials, build_type)
+ return 0 if not error else 1
- with open(project_yaml_path) as project_yaml_file:
- steps = get_build_steps(project_name, project_yaml_file, dockerfile_lines,
- image_project, base_images_project)
- run_build(steps, project_name, FUZZING_BUILD_TAG)
+def main():
+ """Build and run projects."""
+ return build_script_main('Builds a project on GCB.', get_build_steps,
+ FUZZING_BUILD_TYPE)
if __name__ == '__main__':
- main()
+ sys.exit(main())
diff --git a/infra/build/functions/build_project_test.py b/infra/build/functions/build_project_test.py
new file mode 100644
index 000000000..43f6c1cfa
--- /dev/null
+++ b/infra/build/functions/build_project_test.py
@@ -0,0 +1,77 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
+ def test_get_build_steps(self, mock_url, mock_get_datetime_now):
+ """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')
+ 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(False, False, None, False)
+ project_yaml, dockerfile = build_project.get_project_data(
+ test_utils.PROJECT)
+ build_steps = build_project.get_build_steps(test_utils.PROJECT,
+ project_yaml, dockerfile,
+ test_utils.IMAGE_PROJECT,
+ test_utils.BASE_IMAGES_PROJECT,
+ config)
+ self.assertEqual(build_steps, expected_build_steps)
+
+
+if __name__ == '__main__':
+ unittest.main(exit=False)
diff --git a/infra/build/functions/deploy.sh b/infra/build/functions/deploy.sh
index ea094e3b2..3edf6ee17 100755
--- a/infra/build/functions/deploy.sh
+++ b/infra/build/functions/deploy.sh
@@ -80,9 +80,10 @@ function deploy_cloud_function {
--runtime python38 \
--project $project \
--timeout 540 \
- --region us-central1 \
- --set-env-vars GCP_PROJECT=$project,FUNCTION_REGION=us-central1 \
- --max-instances 1
+ --region us-central1 \
+ --set-env-vars GCP_PROJECT=$project,FUNCTION_REGION=us-central1 \
+ --max-instances 1 \
+ --memory 2048MB
}
if [ $# == 1 ]; then
@@ -135,11 +136,6 @@ deploy_cloud_function base-image-build \
$BASE_IMAGE_JOB_TOPIC \
$PROJECT_ID
-deploy_cloud_function base-msan-build \
- build_msan \
- $BASE_IMAGE_JOB_TOPIC \
- $PROJECT_ID
-
deploy_cloud_function request-build \
build_project \
$BUILD_JOB_TOPIC \
diff --git a/infra/build/functions/expected_build_steps.json b/infra/build/functions/expected_build_steps.json
deleted file mode 100644
index da9c63654..000000000
--- a/infra/build/functions/expected_build_steps.json
+++ /dev/null
@@ -1,330 +0,0 @@
-[
- {
- "args": [
- "clone",
- "https://github.com/google/oss-fuzz.git"
- ],
- "name": "gcr.io/cloud-builders/git"
- },
- {
- "name": "gcr.io/cloud-builders/docker",
- "args": [
- "build",
- "-t",
- "gcr.io/oss-fuzz/test-project",
- "."
- ],
- "dir": "oss-fuzz/projects/test-project"
- },
- {
- "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++"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/msan-libs-builder",
- "args": [
- "bash",
- "-c",
- "cp -r /msan /workspace"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "env": [
- "FUZZING_ENGINE=libfuzzer",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && 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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=libfuzzer",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=libfuzzer",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "targets_list > /workspace/targets.list.address"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "args": [
- "bash",
- "-c",
- "cd /workspace/out/address && 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/address/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/address"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "env": [
- "FUZZING_ENGINE=afl",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && 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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=afl",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=afl",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "targets_list > /workspace/targets.list.address"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "args": [
- "bash",
- "-c",
- "cd /workspace/out/address && 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/address/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/address"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "env": [
- "FUZZING_ENGINE=honggfuzz",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/address && 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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=honggfuzz",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "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)"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz-base/base-runner",
- "env": [
- "FUZZING_ENGINE=honggfuzz",
- "SANITIZER=address",
- "OUT=/workspace/out/address",
- "MSAN_LIBS_PATH=/workspace/msan",
- "ARCHITECTURE=x86_64",
- "FUZZING_LANGUAGE=c++"
- ],
- "args": [
- "bash",
- "-c",
- "targets_list > /workspace/targets.list.address"
- ]
- },
- {
- "name": "gcr.io/oss-fuzz/test-project",
- "args": [
- "bash",
- "-c",
- "cd /workspace/out/address && 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/address/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/address"
- ]
- }
-]
diff --git a/infra/build/functions/main.py b/infra/build/functions/main.py
index 1bfd35818..c34dc1329 100644
--- a/infra/build/functions/main.py
+++ b/infra/build/functions/main.py
@@ -45,8 +45,3 @@ def coverage_build(event, context):
def builds_status(event, context):
"""Entry point for builds status cloud function."""
update_build_status.update_status(event, context)
-
-
-def build_msan(event, context):
- """Entry point for base msan builder."""
- base_images.base_msan_builder(event, context)
diff --git a/infra/build/functions/project_sync.py b/infra/build/functions/project_sync.py
index debdbbd9a..7b30cae2d 100644
--- a/infra/build/functions/project_sync.py
+++ b/infra/build/functions/project_sync.py
@@ -94,8 +94,8 @@ def update_scheduler(cloud_scheduler_client, project, schedule, tag):
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_TAG,
- build_and_run_coverage.COVERAGE_BUILD_TAG):
+ for tag in (build_project.FUZZING_BUILD_TYPE,
+ build_and_run_coverage.COVERAGE_BUILD_TYPE):
try:
delete_scheduler(cloud_scheduler_client, project.name, tag)
except exceptions.NotFound:
@@ -124,9 +124,9 @@ def sync_projects(cloud_scheduler_client, projects):
try:
create_scheduler(cloud_scheduler_client, project_name,
projects[project_name].schedule,
- build_project.FUZZING_BUILD_TAG, FUZZING_BUILD_TOPIC)
+ build_project.FUZZING_BUILD_TYPE, FUZZING_BUILD_TOPIC)
create_scheduler(cloud_scheduler_client, project_name, COVERAGE_SCHEDULE,
- build_and_run_coverage.COVERAGE_BUILD_TAG,
+ build_and_run_coverage.COVERAGE_BUILD_TYPE,
COVERAGE_BUILD_TOPIC)
project_metadata = projects[project_name]
Project(name=project_name,
@@ -149,7 +149,7 @@ def sync_projects(cloud_scheduler_client, projects):
logging.info('Schedule changed.')
update_scheduler(cloud_scheduler_client, project,
projects[project.name].schedule,
- build_project.FUZZING_BUILD_TAG)
+ build_project.FUZZING_BUILD_TYPE)
project.schedule = project_metadata.schedule
project_changed = True
except exceptions.GoogleAPICallError as error:
@@ -232,7 +232,7 @@ def get_github_creds():
def sync(event, context):
"""Sync projects with cloud datastore."""
- del event, context #unused
+ del event, context # Unused.
with ndb.Client().context():
git_creds = get_github_creds()
diff --git a/infra/build/functions/project_sync_test.py b/infra/build/functions/project_sync_test.py
index f90733810..ad1330eaf 100644
--- a/infra/build/functions/project_sync_test.py
+++ b/infra/build/functions/project_sync_test.py
@@ -71,7 +71,7 @@ class CloudSchedulerClient:
# pylint: disable=no-self-use
def location_path(self, project_id, location_id):
"""Return project path."""
- return 'projects/{}/location/{}'.format(project_id, location_id)
+ return f'projects/{project_id}/location/{location_id}'
def create_job(self, parent, job):
"""Simulate create job."""
@@ -81,8 +81,7 @@ class CloudSchedulerClient:
# pylint: disable=no-self-use
def job_path(self, project_id, location_id, name):
"""Return job path."""
- return 'projects/{}/location/{}/jobs/{}'.format(project_id, location_id,
- name)
+ return f'projects/{project_id}/location/{location_id}/jobs/{name}'
def delete_job(self, name):
"""Simulate delete jobs."""
diff --git a/infra/build/functions/request_build.py b/infra/build/functions/request_build.py
index 6f0ab62a3..543bafb33 100644
--- a/infra/build/functions/request_build.py
+++ b/infra/build/functions/request_build.py
@@ -15,13 +15,10 @@
################################################################################
"""Cloud function to request builds."""
import base64
-import logging
import google.auth
-from googleapiclient.discovery import build
from google.cloud import ndb
-import build_lib
import build_project
from datastore_entities import BuildsHistory
from datastore_entities import Project
@@ -55,46 +52,33 @@ def get_project_data(project_name):
project = query.get()
if not project:
raise RuntimeError(
- 'Project {0} not available in cloud datastore'.format(project_name))
- project_yaml_contents = project.project_yaml_contents
- dockerfile_lines = project.dockerfile_contents.split('\n')
+ f'Project {project_name} not available in cloud datastore')
- return (project_yaml_contents, dockerfile_lines)
+ return project.project_yaml_contents, project.dockerfile_contents
+
+
+def get_empty_config():
+ """Returns an empty build config."""
+ return build_project.Config(False, None, None, False)
def get_build_steps(project_name, image_project, base_images_project):
"""Retrieve build steps."""
+ # TODO(metzman): Figure out if we need this.
project_yaml_contents, dockerfile_lines = get_project_data(project_name)
+ build_config = get_empty_config()
return build_project.get_build_steps(project_name, project_yaml_contents,
dockerfile_lines, image_project,
- base_images_project)
+ base_images_project, build_config)
-# pylint: disable=no-member
-def run_build(project_name, image_project, build_steps, credentials, tag):
- """Execute build on cloud build."""
- build_body = {
- 'steps': build_steps,
- 'timeout': str(build_lib.BUILD_TIMEOUT) + 's',
- 'options': {
- 'machineType': 'N1_HIGHCPU_32'
- },
- 'logsBucket': build_project.GCB_LOGS_BUCKET,
- 'tags': [project_name + '-' + tag,],
- 'queueTtl': str(QUEUE_TTL_SECONDS) + 's',
- }
-
- cloudbuild = build('cloudbuild',
- 'v1',
- credentials=credentials,
- cache_discovery=False)
- build_info = cloudbuild.projects().builds().create(projectId=image_project,
- body=build_body).execute()
- build_id = build_info['metadata']['build']['id']
-
- update_build_history(project_name, build_id, tag)
- logging.info('Build ID: %s', build_id)
- logging.info('Logs: %s', build_project.get_logs_url(build_id, image_project))
+def run_build(oss_fuzz_project, build_steps, credentials, build_type,
+ cloud_project):
+ """Execute build on cloud build. Wrapper around build_project.py that also
+ updates the db."""
+ build_id = build_project.run_build(oss_fuzz_project, build_steps, credentials,
+ build_type, cloud_project)
+ update_build_history(oss_fuzz_project, build_id, build_type)
# pylint: disable=no-member
@@ -107,9 +91,14 @@ def request_build(event, context):
raise RuntimeError('Project name missing from payload')
with ndb.Client().context():
- credentials, image_project = google.auth.default()
- build_steps = get_build_steps(project_name, image_project, BASE_PROJECT)
+ credentials, cloud_project = google.auth.default()
+ build_steps = get_build_steps(project_name, cloud_project, BASE_PROJECT)
if not build_steps:
return
- run_build(project_name, image_project, build_steps, credentials,
- build_project.FUZZING_BUILD_TAG)
+ run_build(
+ project_name,
+ build_steps,
+ credentials,
+ build_project.FUZZING_BUILD_TYPE,
+ cloud_project=cloud_project,
+ )
diff --git a/infra/build/functions/request_build_test.py b/infra/build/functions/request_build_test.py
index 22a4a1056..1eb1d8efc 100644
--- a/infra/build/functions/request_build_test.py
+++ b/infra/build/functions/request_build_test.py
@@ -14,23 +14,17 @@
#
################################################################################
"""Unit tests for Cloud Function request builds which builds projects."""
-import json
-import datetime
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
-from datastore_entities import BuildsHistory
-from datastore_entities import Project
-from request_build import get_build_steps
-from request_build import get_project_data
-from request_build import update_build_history
+import datastore_entities
+import request_build
import test_utils
# pylint: disable=no-member
@@ -48,65 +42,42 @@ class TestRequestBuilds(unittest.TestCase):
def setUp(self):
test_utils.reset_ds_emulator()
-
- @mock.patch('build_lib.get_signed_url', return_value='test_url')
- @mock.patch('datetime.datetime')
- def test_get_build_steps(self, mocked_url, mocked_time):
- """Test for get_build_steps."""
- del mocked_url, mocked_time
- datetime.datetime = test_utils.SpoofedDatetime
- project_yaml_contents = ('language: c++\n'
- 'sanitizers:\n'
- ' - address\n'
- 'architectures:\n'
- ' - x86_64\n')
- image_project = 'oss-fuzz'
- base_images_project = 'oss-fuzz-base'
- testcase_path = os.path.join(os.path.dirname(__file__),
- 'expected_build_steps.json')
- with open(testcase_path) as testcase_file:
- expected_build_steps = json.load(testcase_file)
-
- with ndb.Client().context():
- Project(name='test-project',
- project_yaml_contents=project_yaml_contents,
- dockerfile_contents='test line').put()
- build_steps = get_build_steps('test-project', image_project,
- base_images_project)
- self.assertEqual(build_steps, expected_build_steps)
+ self.maxDiff = None # pylint: disable=invalid-name
def test_get_build_steps_no_project(self):
"""Test for when project isn't available in datastore."""
with ndb.Client().context():
- self.assertRaises(RuntimeError, get_build_steps, 'test-project',
- 'oss-fuzz', 'oss-fuzz-base')
+ self.assertRaises(RuntimeError, request_build.get_build_steps,
+ 'test-project', 'oss-fuzz', 'oss-fuzz-base')
def test_build_history(self):
"""Testing build history."""
with ndb.Client().context():
- BuildsHistory(id='test-project-fuzzing',
- build_tag='fuzzing',
- project='test-project',
- build_ids=[str(i) for i in range(1, 65)]).put()
- update_build_history('test-project', '65', 'fuzzing')
+ 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(BuildsHistory.query().get().build_ids,
+ 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():
- update_build_history('test-project', '1', 'fuzzing')
+ request_build.update_build_history('test-project', '1', 'fuzzing')
expected_build_ids = ['1']
- self.assertEqual(BuildsHistory.query().get().build_ids,
+ 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, get_project_data, 'test-project')
+ self.assertRaises(RuntimeError, request_build.get_project_data,
+ 'test-project')
@classmethod
def tearDownClass(cls):
diff --git a/infra/build/functions/request_coverage_build.py b/infra/build/functions/request_coverage_build.py
index 1b4ac0e47..a3890cb32 100644
--- a/infra/build/functions/request_coverage_build.py
+++ b/infra/build/functions/request_coverage_build.py
@@ -27,27 +27,31 @@ BASE_PROJECT = 'oss-fuzz-base'
def get_build_steps(project_name, image_project, base_images_project):
"""Retrieve build steps."""
+ build_config = request_build.get_empty_config()
project_yaml_contents, dockerfile_lines = request_build.get_project_data(
project_name)
return build_and_run_coverage.get_build_steps(project_name,
project_yaml_contents,
dockerfile_lines, image_project,
- base_images_project)
+ base_images_project,
+ build_config)
def request_coverage_build(event, context):
"""Entry point for coverage build cloud function."""
- del context #unused
+ 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, image_project = google.auth.default()
- build_steps = get_build_steps(project_name, image_project, BASE_PROJECT)
+ 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, image_project, build_steps,
+ request_build.run_build(project_name,
+ build_steps,
credentials,
- build_and_run_coverage.COVERAGE_BUILD_TAG)
+ build_and_run_coverage.COVERAGE_BUILD_TYPE,
+ cloud_project=cloud_project)
diff --git a/infra/build/functions/request_coverage_build_test.py b/infra/build/functions/request_coverage_build_test.py
deleted file mode 100644
index 1327e36a0..000000000
--- a/infra/build/functions/request_coverage_build_test.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# 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 that builds coverage reports."""
-import json
-import datetime
-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
-
-from datastore_entities import Project
-from build_and_run_coverage import get_build_steps
-import test_utils
-
-# pylint: disable=no-member
-
-
-class TestRequestCoverageBuilds(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()
-
- @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('datetime.datetime')
- def test_get_coverage_build_steps(self, mocked_url, mocked_corpora_steps,
- mocked_time):
- """Test for get_build_steps."""
- del mocked_url, mocked_corpora_steps, mocked_time
- datetime.datetime = test_utils.SpoofedDatetime
- project_yaml_contents = ('language: c++\n'
- 'sanitizers:\n'
- ' - address\n'
- 'architectures:\n'
- ' - x86_64\n')
- dockerfile_contents = 'test line'
- image_project = 'oss-fuzz'
- base_images_project = 'oss-fuzz-base'
- testcase_path = os.path.join(os.path.dirname(__file__),
- 'expected_coverage_build_steps.json')
- with open(testcase_path) as testcase_file:
- expected_coverage_build_steps = json.load(testcase_file)
-
- with ndb.Client().context():
- Project(name='test-project',
- project_yaml_contents=project_yaml_contents,
- dockerfile_contents=dockerfile_contents).put()
-
- dockerfile_lines = dockerfile_contents.split('\n')
- build_steps = get_build_steps('test-project', project_yaml_contents,
- dockerfile_lines, image_project,
- base_images_project)
- self.assertEqual(build_steps, expected_coverage_build_steps)
-
- @classmethod
- def tearDownClass(cls):
- test_utils.cleanup_emulator(cls.ds_emulator)
-
-
-if __name__ == '__main__':
- unittest.main(exit=False)
diff --git a/infra/build/functions/test_data/expected_build_steps.json b/infra/build/functions/test_data/expected_build_steps.json
new file mode 100644
index 000000000..f0e39832b
--- /dev/null
+++ b/infra/build/functions/test_data/expected_build_steps.json
@@ -0,0 +1,628 @@
+[
+ {
+ "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",
+ "-t",
+ "gcr.io/oss-fuzz/test-project",
+ "."
+ ],
+ "dir": "oss-fuzz/projects/test-project"
+ },
+ {
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=x86_64",
+ "FUZZING_ENGINE=afl",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/afl-address-x86_64",
+ "SANITIZER=address"
+ ],
+ "args": [
+ "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/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",
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=x86_64",
+ "FUZZING_ENGINE=honggfuzz",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/honggfuzz-address-x86_64",
+ "SANITIZER=address"
+ ],
+ "args": [
+ "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/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",
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=x86_64",
+ "FUZZING_ENGINE=libfuzzer",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-address-x86_64",
+ "SANITIZER=address"
+ ],
+ "args": [
+ "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/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",
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=i386",
+ "FUZZING_ENGINE=libfuzzer",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-address-i386",
+ "SANITIZER=address"
+ ],
+ "args": [
+ "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/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",
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=x86_64",
+ "FUZZING_ENGINE=libfuzzer",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-memory-x86_64",
+ "SANITIZER=memory"
+ ],
+ "args": [
+ "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/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",
+ "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/oss-fuzz/test-project",
+ "env": [
+ "ARCHITECTURE=x86_64",
+ "FUZZING_ENGINE=libfuzzer",
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-undefined-x86_64",
+ "SANITIZER=undefined"
+ ],
+ "args": [
+ "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/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",
+ "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"
+ ]
+ }
+]
diff --git a/infra/build/functions/expected_coverage_build_steps.json b/infra/build/functions/test_data/expected_coverage_build_steps.json
index 19b1d5b81..2af48f58d 100644
--- a/infra/build/functions/expected_coverage_build_steps.json
+++ b/infra/build/functions/test_data/expected_coverage_build_steps.json
@@ -2,7 +2,9 @@
{
"args": [
"clone",
- "https://github.com/google/oss-fuzz.git"
+ "https://github.com/google/oss-fuzz.git",
+ "--depth",
+ "1"
],
"name": "gcr.io/cloud-builders/git"
},
@@ -26,21 +28,25 @@
"env": [
"OSSFUZZ_REVISION=$REVISION_ID",
"FUZZING_LANGUAGE=c++"
- ]
+ ],
+ "id": "srcmap"
},
{
"name": "gcr.io/oss-fuzz/test-project",
"env": [
+ "ARCHITECTURE=x86_64",
"FUZZING_ENGINE=libfuzzer",
- "SANITIZER=coverage",
- "OUT=/workspace/out/coverage",
- "FUZZING_LANGUAGE=c++"
+ "FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-coverage-x86_64",
+ "SANITIZER=coverage"
],
"args": [
"bash",
"-c",
- "rm -r /out && cd /src && cd /src && mkdir -p /workspace/out/coverage && compile || (echo \"********************************************************************************\nCoverage build failed.\nTo reproduce, run:\npython infra/helper.py build_image test-project\npython infra/helper.py build_fuzzers --sanitizer coverage test-project\n********************************************************************************\" && false)"
- ]
+ "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"
@@ -48,10 +54,12 @@
{
"name": "gcr.io/oss-fuzz-base/base-runner",
"env": [
+ "ARCHITECTURE=x86_64",
"FUZZING_ENGINE=libfuzzer",
- "SANITIZER=coverage",
- "OUT=/workspace/out/coverage",
"FUZZING_LANGUAGE=c++",
+ "HOME=/root",
+ "OUT=/workspace/out/libfuzzer-coverage-x86_64",
+ "SANITIZER=coverage",
"HTTP_PORT=",
"COVERAGE_EXTRA_ARGS="
],
@@ -81,7 +89,7 @@
"-m",
"cp",
"-r",
- "/workspace/out/coverage/report",
+ "/workspace/out/libfuzzer-coverage-x86_64/report",
"gs://oss-fuzz-coverage/test-project/reports/20200101"
]
},
@@ -99,7 +107,7 @@
"-m",
"cp",
"-r",
- "/workspace/out/coverage/fuzzer_stats",
+ "/workspace/out/libfuzzer-coverage-x86_64/fuzzer_stats",
"gs://oss-fuzz-coverage/test-project/fuzzer_stats/20200101"
]
},
@@ -117,7 +125,7 @@
"-m",
"cp",
"-r",
- "/workspace/out/coverage/logs",
+ "/workspace/out/libfuzzer-coverage-x86_64/logs",
"gs://oss-fuzz-coverage/test-project/logs/20200101"
]
},
@@ -141,4 +149,4 @@
"test_url"
]
}
-] \ No newline at end of file
+]
diff --git a/infra/build/functions/test_utils.py b/infra/build/functions/test_utils.py
index 9aac8eac8..a093bcfa0 100644
--- a/infra/build/functions/test_utils.py
+++ b/infra/build/functions/test_utils.py
@@ -24,16 +24,31 @@ import requests
DATASTORE_READY_INDICATOR = b'is now running'
DATASTORE_EMULATOR_PORT = 8432
EMULATOR_TIMEOUT = 20
-TEST_PROJECT_ID = 'test-project'
+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')
-# pylint: disable=arguments-differ
-class SpoofedDatetime(datetime.datetime):
- """Mocking Datetime class for now() function."""
+FAKE_DATETIME = datetime.datetime(2020, 1, 1, 0, 0, 0)
+IMAGE_PROJECT = 'oss-fuzz'
+BASE_IMAGES_PROJECT = 'oss-fuzz-base'
+PROJECT = 'test-project'
+PROJECT_DIR = os.path.join(PROJECTS_DIR, PROJECT)
- @classmethod
- def now(cls):
- return datetime.datetime(2020, 1, 1, 0, 0, 0)
+
+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():
@@ -46,7 +61,7 @@ def start_datastore_emulator():
'start',
'--consistency=1.0',
'--host-port=localhost:' + str(DATASTORE_EMULATOR_PORT),
- '--project=' + TEST_PROJECT_ID,
+ '--project=' + PROJECT,
'--no-store-on-disk',
],
stdout=subprocess.PIPE,
@@ -76,15 +91,13 @@ def wait_for_emulator_ready(proc,
thread.daemon = True
thread.start()
if not ready_event.wait(timeout):
- raise RuntimeError(
- '{} emulator did not get ready in time.'.format(emulator))
+ raise RuntimeError(f'{emulator} emulator did not get ready in time.')
return thread
def reset_ds_emulator():
"""Reset ds emulator/clean all entities."""
- req = requests.post(
- 'http://localhost:{}/reset'.format(DATASTORE_EMULATOR_PORT))
+ req = requests.post(f'http://localhost:{DATASTORE_EMULATOR_PORT}/reset')
req.raise_for_status()
@@ -98,7 +111,12 @@ 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'] = TEST_PROJECT_ID
- os.environ['DATASTORE_DATASET'] = TEST_PROJECT_ID
- os.environ['GCP_PROJECT'] = TEST_PROJECT_ID
+ 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)
diff --git a/infra/build/functions/update_build_status.py b/infra/build/functions/update_build_status.py
index af65a41ab..927216628 100644
--- a/infra/build/functions/update_build_status.py
+++ b/infra/build/functions/update_build_status.py
@@ -145,8 +145,8 @@ def get_build_history(build_ids):
}
if not upload_log(build_id):
- log_name = 'log-{0}'.format(build_id)
- raise MissingBuildLogError('Missing build log file {0}'.format(log_name))
+ log_name = f'log-{build_id}'
+ raise MissingBuildLogError(f'Missing build log file {log_name}')
history.append({
'build_id': build_id,
@@ -203,19 +203,15 @@ def update_build_badges(project, last_build_successful,
if not last_build_successful:
badge = 'failing'
- print("[badge] {}: {}".format(project, badge))
+ print(f'[badge] {project}: {badge}')
for extension in BADGE_IMAGE_TYPES:
- badge_name = '{badge}.{extension}'.format(badge=badge, extension=extension)
+ badge_name = f'{badge}.{extension}'
# Copy blob from badge_images/badge_name to badges/project/
- blob_name = '{badge_dir}/{badge_name}'.format(badge_dir=BADGE_DIR,
- badge_name=badge_name)
+ blob_name = f'{BADGE_DIR}/{badge_name}'
- destination_blob_name = '{badge_dir}/{project_name}.{extension}'.format(
- badge_dir=DESTINATION_BADGE_DIR,
- project_name=project,
- extension=extension)
+ 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)
@@ -228,12 +224,12 @@ 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 = 'log-{0}.txt'.format(build_id)
+ 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 {0}'.format(log_name), file=sys.stderr)
+ print('Failed to find build log', log_name, file=sys.stderr)
return False
if dest_log.exists():
@@ -258,10 +254,10 @@ def update_status(event, context):
return
if status_type == 'fuzzing':
- tag = build_project.FUZZING_BUILD_TAG
+ tag = build_project.FUZZING_BUILD_TYPE
status_filename = FUZZING_STATUS_FILENAME
elif status_type == 'coverage':
- tag = build_and_run_coverage.COVERAGE_BUILD_TAG
+ tag = build_and_run_coverage.COVERAGE_BUILD_TYPE
status_filename = COVERAGE_STATUS_FILENAME
else:
raise RuntimeError('Invalid build status type ' + status_type)
diff --git a/infra/build/functions/update_build_status_test.py b/infra/build/functions/update_build_status_test.py
index 6784fac2d..24a32f676 100644
--- a/infra/build/functions/update_build_status_test.py
+++ b/infra/build/functions/update_build_status_test.py
@@ -56,14 +56,14 @@ class MockGetBuild:
class TestGetBuildHistory(unittest.TestCase):
"""Unit tests for get_build_history."""
- def test_get_build_history(self, mocked_upload_log, mocked_cloud_build,
- mocked_google_auth):
+ def test_get_build_history(self, mock_upload_log, mock_cloud_build,
+ mock_google_auth):
"""Test for get_build_steps."""
- del mocked_cloud_build, mocked_google_auth
- mocked_upload_log.return_value = True
+ del mock_cloud_build, mock_google_auth
+ mock_upload_log.return_value = True
builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS'}]
- mocked_get_build = MockGetBuild(builds)
- update_build_status.get_build = mocked_get_build.get_build
+ mock_get_build = MockGetBuild(builds)
+ update_build_status.get_build = mock_get_build.get_build
expected_projects = {
'history': [{
@@ -79,27 +79,26 @@ class TestGetBuildHistory(unittest.TestCase):
self.assertDictEqual(update_build_status.get_build_history(['1']),
expected_projects)
- def test_get_build_history_missing_log(self, mocked_upload_log,
- mocked_cloud_build,
- mocked_google_auth):
+ def test_get_build_history_missing_log(self, mock_upload_log,
+ mock_cloud_build, mock_google_auth):
"""Test for missing build log file."""
- del mocked_cloud_build, mocked_google_auth
+ del mock_cloud_build, mock_google_auth
builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'SUCCESS'}]
- mocked_get_build = MockGetBuild(builds)
- update_build_status.get_build = mocked_get_build.get_build
- mocked_upload_log.return_value = False
+ mock_get_build = MockGetBuild(builds)
+ update_build_status.get_build = mock_get_build.get_build
+ mock_upload_log.return_value = False
self.assertRaises(update_build_status.MissingBuildLogError,
update_build_status.get_build_history, ['1'])
- def test_get_build_history_no_last_success(self, mocked_upload_log,
- mocked_cloud_build,
- mocked_google_auth):
+ 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 mocked_cloud_build, mocked_google_auth
+ del mock_cloud_build, mock_google_auth
builds = [{'build_id': '1', 'finishTime': 'test_time', 'status': 'FAILURE'}]
- mocked_get_build = MockGetBuild(builds)
- update_build_status.get_build = mocked_get_build.get_build
- mocked_upload_log.return_value = True
+ mock_get_build = MockGetBuild(builds)
+ update_build_status.get_build = mock_get_build.get_build
+ mock_upload_log.return_value = True
expected_projects = {
'history': [{
@@ -229,12 +228,12 @@ class TestUpdateBuildStatus(unittest.TestCase):
@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, mocked_upload_log, mocked_cloud_build,
- mocked_google_auth):
+ def test_update_build_status(self, mock_upload_log, mock_cloud_build,
+ mock_google_auth):
"""Testing update build status as a whole."""
- del self, mocked_cloud_build, mocked_google_auth
+ del self, mock_cloud_build, mock_google_auth
update_build_status.upload_status = MagicMock()
- mocked_upload_log.return_value = True
+ mock_upload_log.return_value = True
status_filename = 'status.json'
with ndb.Client().context():
BuildsHistory(id='test-project-1-fuzzing',
@@ -264,8 +263,8 @@ class TestUpdateBuildStatus(unittest.TestCase):
'build_id': '3',
'status': 'WORKING'
}]
- mocked_get_build = MockGetBuild(builds)
- update_build_status.get_build = mocked_get_build.get_build
+ mock_get_build = MockGetBuild(builds)
+ update_build_status.get_build = mock_get_build.get_build
expected_data = {
'projects': [{
diff --git a/infra/build_and_push_test_images.py b/infra/build_and_push_test_images.py
new file mode 100755
index 000000000..44c65ae2c
--- /dev/null
+++ b/infra/build_and_push_test_images.py
@@ -0,0 +1,92 @@
+#! /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 reusing the build infra to test image
+changes."""
+import logging
+import multiprocessing
+import os
+import subprocess
+import sys
+
+TAG_PREFIX = 'gcr.io/oss-fuzz-base/'
+INFRA_DIR = os.path.dirname(__file__)
+IMAGES_DIR = os.path.join(INFRA_DIR, 'base-images')
+
+
+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_suffix):
+ """Builds and pushes |image| to docker registry with "-testing" suffix."""
+ main_tag = TAG_PREFIX + image
+ testing_tag = main_tag + '-' + test_image_suffix
+ tags = [main_tag, testing_tag]
+ build_image(image, tags)
+ push_image(testing_tag)
+
+
+def build_image(image, tags):
+ """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)
+ command.append(path)
+ subprocess.run(command, check=True)
+ logging.info('Built: %s', image)
+
+
+def build_and_push_images(test_image_suffix):
+ """Builds and pushes base-images."""
+ images = [
+ ['base-image'],
+ ['base-clang'],
+ # base-runner is also dependent on base-clang.
+ ['base-builder', 'base-runner'],
+ [
+ 'base-runner-debug', 'base-builder-go', 'base-builder-jvm',
+ 'base-builder-python', 'base-builder-rust', 'base-builder-swift'
+ ],
+ ]
+ 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)
+ pool = multiprocessing.Pool(proc_count)
+ for image_list in images:
+ args_list = [(image, test_image_suffix) for image in image_list]
+ 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_suffix = 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_suffix)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/infra/build_fuzzers.Dockerfile b/infra/build_fuzzers.Dockerfile
index df06ff754..77a34ae40 100644
--- a/infra/build_fuzzers.Dockerfile
+++ b/infra/build_fuzzers.Dockerfile
@@ -13,7 +13,8 @@
# limitations under the License.
#
################################################################################
-# Docker image to run the CIFuzz action build_fuzzers in.
+# Docker image to run fuzzers for CIFuzz (the run_fuzzers action on GitHub
+# actions).
FROM gcr.io/oss-fuzz-base/cifuzz-base
@@ -22,5 +23,9 @@ FROM gcr.io/oss-fuzz-base/cifuzz-base
# 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 \ No newline at end of file
diff --git a/infra/build_specified_commit.py b/infra/build_specified_commit.py
index b2130ea85..d7b667004 100644
--- a/infra/build_specified_commit.py
+++ b/infra/build_specified_commit.py
@@ -11,7 +11,7 @@
# WITHOUT 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
+"""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
@@ -147,7 +147,7 @@ def copy_src_from_docker(project_name, host_dir):
@retry.wrap(_IMAGE_BUILD_TRIES, 2)
def _build_image_with_retries(project_name):
"""Build image with retries."""
- return helper.build_image_impl(project_name)
+ return helper.build_image_impl(helper.Project(project_name))
def get_required_post_checkout_steps(dockerfile_path):
@@ -223,15 +223,16 @@ def build_fuzzers_from_commit(commit,
post_checkout_step,
])
- result = helper.build_fuzzers_impl(project_name=build_data.project_name,
+ 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_location='/src')
- if result == 0 or i == num_retry:
+ mount_path='/src')
+ if result or i == num_retry:
break
# Retry with an OSS-Fuzz builder container that's closer to the project
@@ -285,7 +286,7 @@ def build_fuzzers_from_commit(commit,
cleanup()
cleanup()
- return result == 0
+ return result
def detect_main_repo(project_name, repo_name=None, commit=None):
@@ -297,10 +298,9 @@ def detect_main_repo(project_name, repo_name=None, commit=None):
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.
- src_dir: The location of the projects source on the docker image.
Returns:
- The repo's origin, the repo's path.
+ A tuple containing (the repo's origin, the repo's path).
"""
if not repo_name and not commit:
diff --git a/infra/build_specified_commit_test.py b/infra/build_specified_commit_test.py
index a86504580..00f50947f 100644
--- a/infra/build_specified_commit_test.py
+++ b/infra/build_specified_commit_test.py
@@ -16,7 +16,6 @@ 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.
-IMPORTANT: This test needs to be run with root privileges.
"""
import os
import tempfile
@@ -27,7 +26,7 @@ import helper
import repo_manager
import test_repos
-# Necessary because __file__ changes with os.chdir
+# necessary because __file__ changes with os.chdir
TEST_DIR_PATH = os.path.dirname(os.path.realpath(__file__))
@@ -45,32 +44,39 @@ class BuildImageIntegrationTest(unittest.TestCase):
should not.
"""
with tempfile.TemporaryDirectory() as tmp_dir:
- test_case = test_repos.TEST_REPOS[1]
- self.assertTrue(helper.build_image_impl(test_case.project_name))
+ 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_case.project_name, tmp_dir)
+ test_repo.project_name, tmp_dir)
test_repo_manager = repo_manager.clone_repo_and_get_manager(
- test_case.git_url, host_src_dir, test_case.oss_repo_name)
+ 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_case.project_name)
+ project_name=test_repo.project_name)
- build_specified_commit.build_fuzzers_from_commit(test_case.old_commit,
+ build_specified_commit.build_fuzzers_from_commit(test_repo.old_commit,
test_repo_manager,
host_src_dir, build_data)
- old_error_code = helper.reproduce_impl(test_case.project_name,
- test_case.fuzz_target, False, [],
- [], test_case.test_case_path)
- build_specified_commit.build_fuzzers_from_commit(test_case.new_commit,
+ 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_error_code = helper.reproduce_impl(test_case.project_name,
- test_case.fuzz_target, False, [],
- [], test_case.test_case_path)
- self.assertNotEqual(new_error_code, old_error_code)
+ 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."""
diff --git a/infra/ci/build.py b/infra/ci/build.py
index addeb7879..7a02d6001 100755
--- a/infra/ci/build.py
+++ b/infra/ci/build.py
@@ -25,20 +25,22 @@ 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']
DEFAULT_SANITIZERS = ['address', 'undefined']
-# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
-
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', 'FETCH_HEAD', 'origin/HEAD']).strip().decode()
+ ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode()
return subprocess.check_output(
['git', 'diff', '--name-only', branch_commit_hash + '..']).decode()
@@ -112,7 +114,7 @@ def should_build_coverage(project_yaml):
return False
language = project_yaml.get('language')
- if language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
+ 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
@@ -213,11 +215,16 @@ def build_base_images():
images = [
'base-image',
'base-builder',
+ 'base-builder-go',
+ 'base-builder-jvm',
+ 'base-builder-python',
+ 'base-builder-rust',
+ 'base-builder-swift',
'base-runner',
]
for image in images:
try:
- execute_helper_command(['build_image', image, '--no-pull'])
+ execute_helper_command(['build_image', image, '--no-pull', '--cache'])
except subprocess.CalledProcessError:
return 1
@@ -239,6 +246,7 @@ def build_canary_project():
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.')
diff --git a/infra/ci/requirements.txt b/infra/ci/requirements.txt
index f0a8be0b5..310ba53e8 100644
--- a/infra/ci/requirements.txt
+++ b/infra/ci/requirements.txt
@@ -6,3 +6,5 @@ pytest==6.2.1
pytest-xdist==2.2.0
PyYAML==5.4
yapf==0.30.0
+# Needed for cifuzz tests.
+Jinja2==2.11.3
diff --git a/infra/cifuzz/actions/build_fuzzers/action.yml b/infra/cifuzz/actions/build_fuzzers/action.yml
index 835b7b430..5cc35a15f 100644
--- a/infra/cifuzz/actions/build_fuzzers/action.yml
+++ b/infra/cifuzz/actions/build_fuzzers/action.yml
@@ -21,9 +21,6 @@ inputs:
project-src-path:
description: "The path to the project's source code checkout."
required: false
- build-integration-path:
- description: "The path to the the project's build integration."
- required: false
bad-build-check:
description: "Whether or not OSS-Fuzz's check for bad builds should be done."
required: false
@@ -38,6 +35,5 @@ runs:
ALLOWED_BROKEN_TARGETS_PERCENTAGE: ${{ inputs.allowed-broken-targets-percentage}}
SANITIZER: ${{ inputs.sanitizer }}
PROJECT_SRC_PATH: ${{ inputs.project-src-path }}
- BUILD_INTEGRATION_PATH: ${{ inputs.build-integration-path }}
LOW_DISK_SPACE: 'True'
BAD_BUILD_CHECK: ${{ inputs.bad-build-check }}
diff --git a/infra/cifuzz/actions/run_fuzzers/action.yml b/infra/cifuzz/actions/run_fuzzers/action.yml
index d1c03c833..b56dbce3d 100644
--- a/infra/cifuzz/actions/run_fuzzers/action.yml
+++ b/infra/cifuzz/actions/run_fuzzers/action.yml
@@ -19,9 +19,6 @@ inputs:
sanitizer:
description: 'The sanitizer to run the fuzzers with.'
default: 'address'
- build-integration-path:
- description: "The path to the the project's build integration."
- required: false
run-fuzzers-mode:
description: |
The mode to run the fuzzers with ("ci" or "batch").
@@ -30,6 +27,18 @@ inputs:
"batch" is in alpha and should not be used in production.
required: false
default: 'ci'
+ 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 by CIFuzz.'
+ required: false
+ default: false
runs:
using: 'docker'
image: '../../../run_fuzzers.Dockerfile'
@@ -40,8 +49,6 @@ runs:
DRY_RUN: ${{ inputs.dry-run}}
SANITIZER: ${{ inputs.sanitizer }}
RUN_FUZZERS_MODE: ${{ inputs.run-fuzzers-mode }}
- # TODO(metzman): Even though this param is used for building, it's needed
- # for running because we use it to distinguish OSS-Fuzz from non-OSS-Fuzz.
- # We should do something explicit instead.
- BUILD_INTEGRATION_PATH: ${{ inputs.build-integration-path }}
+ GITHUB_TOKEN: ${{ inputs.github-token }}
LOW_DISK_SPACE: 'True'
+ REPORT_UNREPRODUCIBLE_CRASHES: ${{ inputs.report-unreproducible-crashes }}
diff --git a/infra/cifuzz/affected_fuzz_targets.py b/infra/cifuzz/affected_fuzz_targets.py
index f9f2242a3..be35c5cc5 100644
--- a/infra/cifuzz/affected_fuzz_targets.py
+++ b/infra/cifuzz/affected_fuzz_targets.py
@@ -17,19 +17,17 @@ import logging
import os
import sys
-import coverage
-
# 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(project_name, out_dir, files_changed,
- repo_path):
+def remove_unaffected_fuzz_targets(clusterfuzz_deployment, out_dir,
+ files_changed, repo_path):
"""Removes all non affected fuzz targets in the out directory.
Args:
- project_name: The name of the relevant OSS-Fuzz project.
+ 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.
@@ -38,7 +36,6 @@ def remove_unaffected_fuzz_targets(project_name, out_dir, files_changed,
targets are unaffected. For example, this means that fuzz targets which don't
have coverage data on will not be deleted.
"""
- # TODO(metzman): Make this use clusterfuzz deployment.
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.')
@@ -52,14 +49,13 @@ def remove_unaffected_fuzz_targets(project_name, out_dir, files_changed,
logging.error('No fuzz targets found in out dir.')
return
- coverage_getter = coverage.OssFuzzCoverageGetter(project_name, repo_path)
- if not coverage_getter.fuzzer_stats_url:
+ 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_getter,
- fuzz_target_paths,
+ affected_fuzz_targets = get_affected_fuzz_targets(coverage, fuzz_target_paths,
files_changed)
if not affected_fuzz_targets:
@@ -79,11 +75,11 @@ def remove_unaffected_fuzz_targets(project_name, out_dir, files_changed,
fuzz_target_path)
-def is_fuzz_target_affected(coverage_getter, fuzz_target_path, files_changed):
+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_getter.get_files_covered_by_target(fuzz_target)
+ 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.
@@ -104,13 +100,11 @@ def is_fuzz_target_affected(coverage_getter, fuzz_target_path, files_changed):
return False
-def get_affected_fuzz_targets(coverage_getter, fuzz_target_paths,
- files_changed):
+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_getter, fuzz_target_path,
- files_changed):
+ if is_fuzz_target_affected(coverage, fuzz_target_path, files_changed):
affected_fuzz_targets.add(fuzz_target_path)
return affected_fuzz_targets
diff --git a/infra/cifuzz/affected_fuzz_targets_test.py b/infra/cifuzz/affected_fuzz_targets_test.py
index 05f27c072..823654d11 100644
--- a/infra/cifuzz/affected_fuzz_targets_test.py
+++ b/infra/cifuzz/affected_fuzz_targets_test.py
@@ -21,6 +21,9 @@ from unittest import mock
import parameterized
import affected_fuzz_targets
+import clusterfuzz_deployment
+import test_helpers
+import workspace_utils
# pylint: disable=protected-access
@@ -30,15 +33,15 @@ EXAMPLE_PROJECT = 'example'
EXAMPLE_FILE_CHANGED = 'test.txt'
-TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
- 'test_data')
+TEST_DATA_OUT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
+ 'test_data', 'build-out')
class RemoveUnaffectedFuzzTargets(unittest.TestCase):
"""Tests remove_unaffected_fuzzers."""
- TEST_FUZZER_1 = os.path.join(TEST_DATA_PATH, 'out', 'example_crash_fuzzer')
- TEST_FUZZER_2 = os.path.join(TEST_DATA_PATH, 'out', 'example_nocrash_fuzzer')
+ 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([
@@ -57,18 +60,27 @@ class RemoveUnaffectedFuzzTargets(unittest.TestCase):
# 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(
+ is_github=True,
+ 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(
- 'coverage.OssFuzzCoverageGetter.get_files_covered_by_target'
- ) as mocked_get_files:
- with mock.patch('coverage._get_fuzzer_stats_dir_url', return_value=1):
- mocked_get_files.side_effect = side_effect
+ '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(
- EXAMPLE_PROJECT, tmp_dir, [EXAMPLE_FILE_CHANGED], '')
+ deployment, tmp_dir, [EXAMPLE_FILE_CHANGED], '')
self.assertEqual(expected_dir_len, len(os.listdir(tmp_dir)))
diff --git a/infra/cifuzz/base_runner_utils.py b/infra/cifuzz/base_runner_utils.py
new file mode 100644
index 000000000..246375481
--- /dev/null
+++ b/infra/cifuzz/base_runner_utils.py
@@ -0,0 +1,33 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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_utils.DEFAULT_ARCHITECTURE
+ # Do this so we don't fail in tests.
+ env['FUZZER_ARGS'] = '-rss_limit_mb=2560 -timeout=25'
+ return env
diff --git a/infra/cifuzz/build_fuzzers.py b/infra/cifuzz/build_fuzzers.py
index 78180b52b..6722be5e9 100644
--- a/infra/cifuzz/build_fuzzers.py
+++ b/infra/cifuzz/build_fuzzers.py
@@ -19,18 +19,17 @@ import os
import sys
import affected_fuzz_targets
+import base_runner_utils
+import clusterfuzz_deployment
import continuous_integration
import docker
+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
-# Default fuzz configuration.
-DEFAULT_ENGINE = 'libfuzzer'
-DEFAULT_ARCHITECTURE = 'x86_64'
-
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
@@ -55,89 +54,82 @@ class Builder: # pylint: disable=too-many-instance-attributes
def __init__(self, config, ci_system):
self.config = config
self.ci_system = ci_system
- self.out_dir = os.path.join(config.workspace, 'out')
- os.makedirs(self.out_dir, exist_ok=True)
- self.work_dir = os.path.join(config.workspace, 'work')
- os.makedirs(self.work_dir, exist_ok=True)
+ 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.
- Must be implemented by child classes."""
+ 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
+ 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 = get_common_docker_args(self.config.sanitizer,
- self.config.language)
- container = utils.get_container_name()
-
- if container:
- docker_args.extend(
- _get_docker_build_fuzzers_args_container(self.out_dir, container))
- else:
+ docker_args, docker_container = docker.get_base_docker_run_args(
+ self.workspace, self.config.sanitizer, self.config.language,
+ self.config.docker_in_docker)
+ if not docker_container:
docker_args.extend(
- _get_docker_build_fuzzers_args_not_container(self.out_dir,
- self.host_repo_path))
-
- if self.config.sanitizer == 'memory':
- docker_args.extend(_get_docker_build_fuzzers_args_msan(self.work_dir))
- self.handle_msan_prebuild(container)
+ _get_docker_build_fuzzers_args_not_container(self.host_repo_path))
docker_args.extend([
- docker.get_project_image_name(self.config.project_name),
+ docker.get_project_image_name(self.config.oss_fuzz_project_name),
'/bin/bash',
'-c',
])
- rm_path = os.path.join(self.image_repo_path, '*')
- image_src_path = os.path.dirname(self.image_repo_path)
- bash_command = 'rm -rf {0} && cp -r {1} {2} && compile'.format(
- rm_path, self.host_repo_path, image_src_path)
- docker_args.append(bash_command)
+ build_command = self.ci_system.get_build_command(self.host_repo_path,
+ self.image_repo_path)
+ docker_args.append(build_command)
logging.info('Building with %s sanitizer.', self.config.sanitizer)
- if helper.docker_run(docker_args):
- # docker_run returns nonzero on failure.
+
+ # 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
- if self.config.sanitizer == 'memory':
- self.handle_msan_postbuild(container)
return True
- def handle_msan_postbuild(self, container):
- """Post-build step for MSAN builds. Patches the build to use MSAN
- libraries."""
- helper.docker_run([
- '--volumes-from', container, '-e',
- 'WORK={work_dir}'.format(work_dir=self.work_dir),
- docker.MSAN_LIBS_BUILDER_TAG, 'patch_build.py', '/out'
- ])
+ def upload_build(self):
+ """Upload build."""
+ if self.config.upload_build:
+ self.clusterfuzz_deployment.upload_build(
+ self.repo_manager.get_current_commit())
- def handle_msan_prebuild(self, container):
- """Pre-build step for MSAN builds. Copies MSAN libs to |msan_libs_dir| and
- returns docker arguments to use that directory for MSAN libs."""
- logging.info('Copying MSAN libs.')
- helper.docker_run([
- '--volumes-from', container, docker.MSAN_LIBS_BUILDER_TAG, 'bash', '-c',
- 'cp -r /msan {work_dir}'.format(work_dir=self.work_dir)
- ])
+ 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.build_image_and_checkout_src,
+ self.build_fuzzers,
+ self.remove_unaffected_fuzz_targets,
+ self.check_fuzzer_build,
+ self.upload_build,
]
for method in methods:
if not method():
@@ -154,7 +146,7 @@ class Builder: # pylint: disable=too-many-instance-attributes
changed_files = self.ci_system.get_changed_code_under_test(
self.repo_manager)
affected_fuzz_targets.remove_unaffected_fuzz_targets(
- self.config.project_name, self.out_dir, changed_files,
+ self.clusterfuzz_deployment, self.workspace.out, changed_files,
self.image_repo_path)
return True
@@ -186,94 +178,39 @@ def build_fuzzers(config):
return builder.build()
-def get_common_docker_args(sanitizer, language):
- """Returns a list of common docker arguments."""
- return [
- '--cap-add',
- 'SYS_PTRACE',
- '-e',
- 'FUZZING_ENGINE=' + DEFAULT_ENGINE,
- '-e',
- 'SANITIZER=' + sanitizer,
- '-e',
- 'ARCHITECTURE=' + DEFAULT_ARCHITECTURE,
- '-e',
- 'CIFUZZ=True',
- '-e',
- 'FUZZING_LANGUAGE=' + language,
- ]
-
-
-def check_fuzzer_build(out_dir,
- sanitizer,
- language,
- allowed_broken_targets_percentage=None):
+def check_fuzzer_build(config):
"""Checks the integrity of the built fuzzers.
Args:
- out_dir: The directory containing the fuzzer binaries.
- sanitizer: The sanitizer the fuzzers are built with.
+ config: The config object.
Returns:
- True if fuzzers are correct.
+ True if fuzzers pass OSS-Fuzz's build check.
"""
- if not os.path.exists(out_dir):
- logging.error('Invalid out directory: %s.', out_dir)
+ 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(out_dir):
- logging.error('No fuzzers found in out directory: %s.', out_dir)
+ if not os.listdir(workspace.out):
+ logging.error('No fuzzers found in out directory: %s.', workspace.out)
return False
- command = get_common_docker_args(sanitizer, language)
-
- if allowed_broken_targets_percentage is not None:
- command += [
- '-e',
- ('ALLOWED_BROKEN_TARGETS_PERCENTAGE=' +
- allowed_broken_targets_percentage)
- ]
+ 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)
- container = utils.get_container_name()
- if container:
- command += ['-e', 'OUT=' + out_dir, '--volumes-from', container]
- else:
- command += ['-v', '%s:/out' % out_dir]
- command.extend(['-t', docker.BASE_RUNNER_TAG, 'test_all.py'])
- exit_code = helper.docker_run(command)
- logging.info('check fuzzer build exit code: %d', exit_code)
- if exit_code:
- logging.error('Check fuzzer build failed.')
- return False
- return True
-
-
-def _get_docker_build_fuzzers_args_container(host_out_dir, container):
- """Returns arguments to the docker build arguments that are needed to use
- |host_out_dir| when the host of the OSS-Fuzz builder container is another
- container."""
- return ['-e', 'OUT=' + host_out_dir, '--volumes-from', container]
+ 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_out_dir, host_repo_path):
+def _get_docker_build_fuzzers_args_not_container(host_repo_path):
"""Returns arguments to the docker build arguments that are needed to use
- |host_out_dir| when the host of the OSS-Fuzz builder container is not
+ |host_repo_path| when the host of the OSS-Fuzz builder container is not
another container."""
- image_out_dir = '/out'
- return [
- '-e',
- 'OUT=' + image_out_dir,
- '-v',
- '%s:%s' % (host_out_dir, image_out_dir),
- '-v',
- '%s:%s' % (host_repo_path, host_repo_path),
- ]
-
-
-def _get_docker_build_fuzzers_args_msan(work_dir):
- """Returns arguments to the docker build command that are needed to use
- MSAN."""
- # TODO(metzman): MSAN is broken, fix.
- return [
- '-e', 'MSAN_LIBS_PATH={msan_libs_path}'.format(
- msan_libs_path=os.path.join(work_dir, 'msan'))
- ]
+ return ['-v', f'{host_repo_path}:{host_repo_path}']
diff --git a/infra/cifuzz/build_fuzzers_entrypoint.py b/infra/cifuzz/build_fuzzers_entrypoint.py
index 04f562068..e8e368f1b 100644
--- a/infra/cifuzz/build_fuzzers_entrypoint.py
+++ b/infra/cifuzz/build_fuzzers_entrypoint.py
@@ -13,7 +13,6 @@
# limitations under the License.
"""Builds a specific OSS-Fuzz project's fuzzers for CI tools."""
import logging
-import os
import sys
import build_fuzzers
@@ -22,19 +21,34 @@ import config_utils
# pylint: disable=c-extension-no-member
# pylint gets confused because of the relative import of cifuzz.
-# TODO: Turn default logging to INFO when CIFuzz is stable
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
+def build_fuzzers_entrypoint():
+ """Builds OSS-Fuzz project's fuzzers for CI tools."""
+ config = config_utils.BuildFuzzersConfig()
+
+ 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.commit_sha, config.pr_ref)
+ return returncode
+
+ return 0
+
+
def main():
- """Build OSS-Fuzz project's fuzzers for CI tools.
- This script is used to kick off the Github Actions CI tool. It is the
- entrypoint of the Dockerfile in this directory. This action can be added to
- any OSS-Fuzz project's workflow that uses Github.
+ """Builds OSS-Fuzz project's fuzzers for CI tools.
- Note: The resulting clusterfuzz binaries of this build are placed in
+ Note: The resulting fuzz target binaries of this build are placed in
the directory: ${GITHUB_WORKSPACE}/out
Required environment variables:
@@ -50,44 +64,9 @@ def main():
SANITIZER: The sanitizer to use when running fuzzers.
Returns:
- 0 on success or 1 on failure.
+ 0 on success or nonzero on failure.
"""
- config = config_utils.BuildFuzzersConfig()
-
- 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 config.workspace:
- logging.error('This script needs to be run within Github actions.')
- return returncode
-
- if not build_fuzzers.build_fuzzers(config):
- logging.error(
- 'Error building fuzzers for project %s (commit: %s, pr_ref: %s).',
- config.project_name, config.commit_sha, config.pr_ref)
- return returncode
-
- out_dir = os.path.join(config.workspace, 'out')
-
- if not config.bad_build_check:
- # If we've gotten to this point and we don't need to do bad_build_check,
- # then the build has succeeded.
- returncode = 0
- # yapf: disable
- elif build_fuzzers.check_fuzzer_build(
- out_dir,
- config.sanitizer,
- config.language,
- allowed_broken_targets_percentage=config.allowed_broken_targets_percentage
- ):
- # yapf: enable
- returncode = 0
-
- return returncode
+ return build_fuzzers_entrypoint()
if __name__ == '__main__':
diff --git a/infra/cifuzz/build_fuzzers_test.py b/infra/cifuzz/build_fuzzers_test.py
index 298778867..5c068ac4d 100644
--- a/infra/cifuzz/build_fuzzers_test.py
+++ b/infra/cifuzz/build_fuzzers_test.py
@@ -28,8 +28,8 @@ sys.path.append(INFRA_DIR)
OSS_FUZZ_DIR = os.path.dirname(INFRA_DIR)
import build_fuzzers
-import config_utils
import continuous_integration
+import repo_manager
import test_helpers
# NOTE: This integration test relies on
@@ -53,23 +53,7 @@ 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
-
-
-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."""
- with mock.patch('os.path.basename', return_value=None), mock.patch(
- 'config_utils.get_project_src_path',
- return_value=None), mock.patch('config_utils._is_dry_run',
- return_value=True):
- config = config_utils.BuildFuzzersConfig()
-
- for key, value in kwargs.items():
- assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
- setattr(config, key, value)
- return config
+# pylint: disable=no-self-use,protected-access,too-few-public-methods,unused-argument
class BuildFuzzersTest(unittest.TestCase):
@@ -79,17 +63,19 @@ class BuildFuzzersTest(unittest.TestCase):
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')
- def test_cifuzz_env_var(self, mocked_docker_run, _, __, ___):
+ @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(
- create_config(project_name=EXAMPLE_PROJECT,
- project_repo_name=EXAMPLE_PROJECT,
- workspace=tmp_dir,
- pr_ref='refs/pull/1757/merge'))
- docker_run_command = mocked_docker_run.call_args_list[0][0][0]
+ 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]
def command_has_env_var_arg(command, env_var_arg):
for idx, element in enumerate(command):
@@ -105,23 +91,25 @@ class BuildFuzzersTest(unittest.TestCase):
class InternalGithubBuildTest(unittest.TestCase):
"""Tests for building OSS-Fuzz projects on GitHub actions."""
- PROJECT_NAME = 'myproject'
PROJECT_REPO_NAME = 'myproject'
SANITIZER = 'address'
COMMIT_SHA = 'fake'
PR_REF = 'fake'
- def _create_builder(self, tmp_dir):
+ def _create_builder(self, tmp_dir, oss_fuzz_project_name='myproject'):
"""Creates an InternalGithubBuilder and returns it."""
- config = create_config(project_name=self.PROJECT_NAME,
- project_repo_name=self.PROJECT_REPO_NAME,
- workspace=tmp_dir,
- sanitizer=self.SANITIZER,
- commit_sha=self.COMMIT_SHA,
- pr_ref=self.PR_REF,
- is_github=True)
+ 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,
+ commit_sha=self.COMMIT_SHA,
+ pr_ref=self.PR_REF,
+ is_github=True)
ci_system = continuous_integration.get_ci(config)
- return build_fuzzers.Builder(config, ci_system)
+ builder = build_fuzzers.Builder(config, ci_system)
+ builder.repo_manager = repo_manager.RepoManager('/fake')
+ return builder
@mock.patch('repo_manager._clone', side_effect=None)
@mock.patch('continuous_integration.checkout_specified_commit',
@@ -141,6 +129,29 @@ class InternalGithubBuildTest(unittest.TestCase):
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')
@@ -148,36 +159,59 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
"""Integration tests for build_fuzzers."""
def setUp(self):
- self.tmp_dir_obj = tempfile.TemporaryDirectory()
- self.workspace = self.tmp_dir_obj.name
- self.out_dir = os.path.join(self.workspace, 'out')
+ self.temp_dir_obj = tempfile.TemporaryDirectory()
+ self.workspace = self.temp_dir_obj.name
+ 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.tmp_dir_obj.cleanup()
+ self.temp_dir_obj.cleanup()
def test_external_github_project(self):
"""Tests building fuzzers from an external project on Github."""
- project_name = 'external-project'
- build_integration_path = 'fuzzer-build-integration'
+ 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 = create_config(project_name=project_name,
- project_repo_name=project_name,
- workspace=self.workspace,
- build_integration_path=build_integration_path,
- git_url=git_url,
- commit_sha='HEAD',
- base_commit='HEAD^1')
+ config = test_helpers.create_build_config(
+ project_repo_name=project_repo_name,
+ workspace=self.workspace,
+ git_url=git_url,
+ commit_sha='HEAD',
+ is_github=True,
+ 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.temp_dir_obj.name)
+ 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,
+ commit_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 = create_config(
- project_name=EXAMPLE_PROJECT,
+ config = test_helpers.create_build_config(
+ oss_fuzz_project_name=EXAMPLE_PROJECT,
project_repo_name='oss-fuzz',
workspace=self.workspace,
commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523',
@@ -189,31 +223,32 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
def test_valid_pull_request(self):
"""Tests building fuzzers with valid pull request."""
- # TODO(metzman): What happens when this branch closes?
- config = create_config(project_name=EXAMPLE_PROJECT,
- project_repo_name='oss-fuzz',
- workspace=self.workspace,
- pr_ref='refs/pull/1757/merge',
- base_ref='master',
- is_github=True)
+ 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',
+ is_github=True)
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 = create_config(project_name=EXAMPLE_PROJECT,
- project_repo_name='oss-fuzz',
- workspace=self.workspace,
- pr_ref='ref-1/merge',
- base_ref='master',
- is_github=True)
+ 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',
+ is_github=True)
self.assertTrue(build_fuzzers.build_fuzzers(config))
- def test_invalid_project_name(self):
+ def test_invalid_oss_fuzz_project_name(self):
"""Tests building fuzzers with invalid project name."""
- config = create_config(
- project_name='not_a_valid_project',
+ config = test_helpers.create_build_config(
+ oss_fuzz_project_name='not_a_valid_project',
project_repo_name='oss-fuzz',
workspace=self.workspace,
commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -221,8 +256,8 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
def test_invalid_repo_name(self):
"""Tests building fuzzers with invalid repo name."""
- config = create_config(
- project_name=EXAMPLE_PROJECT,
+ config = test_helpers.create_build_config(
+ oss_fuzz_project_name=EXAMPLE_PROJECT,
project_repo_name='not-real-repo',
workspace=self.workspace,
commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -230,18 +265,19 @@ class BuildFuzzersIntegrationTest(unittest.TestCase):
def test_invalid_commit_sha(self):
"""Tests building fuzzers with invalid commit SHA."""
- config = create_config(project_name=EXAMPLE_PROJECT,
- project_repo_name='oss-fuzz',
- workspace=self.workspace,
- commit_sha='',
- is_github=True)
+ config = test_helpers.create_build_config(
+ oss_fuzz_project_name=EXAMPLE_PROJECT,
+ project_repo_name='oss-fuzz',
+ workspace=self.workspace,
+ commit_sha='',
+ is_github=True)
with self.assertRaises(AssertionError):
build_fuzzers.build_fuzzers(config)
def test_invalid_workspace(self):
"""Tests building fuzzers with invalid workspace."""
- config = create_config(
- project_name=EXAMPLE_PROJECT,
+ 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'),
commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523')
@@ -255,44 +291,47 @@ class CheckFuzzerBuildTest(unittest.TestCase):
LANGUAGE = 'c++'
def setUp(self):
- self.tmp_dir_obj = tempfile.TemporaryDirectory()
- self.test_files_path = os.path.join(self.tmp_dir_obj.name, 'test_files')
- shutil.copytree(TEST_DATA_PATH, self.test_files_path)
+ 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.tmp_dir_obj.cleanup()
+ self.temp_dir_obj.cleanup()
def test_correct_fuzzer_build(self):
"""Checks check_fuzzer_build function returns True for valid fuzzers."""
- test_fuzzer_dir = os.path.join(self.test_files_path, 'out')
- self.assertTrue(
- build_fuzzers.check_fuzzer_build(test_fuzzer_dir, self.SANITIZER,
- self.LANGUAGE))
-
- def test_not_a_valid_fuzz_path(self):
- """Tests that False is returned when a bad path is given."""
- self.assertFalse(
- build_fuzzers.check_fuzzer_build('not/a/valid/path', self.SANITIZER,
- self.LANGUAGE))
-
- def test_not_a_valid_fuzzer(self):
- """Checks a directory that exists but does not have fuzzers is False."""
- self.assertFalse(
- build_fuzzers.check_fuzzer_build(self.test_files_path, self.SANITIZER,
- self.LANGUAGE))
-
- @mock.patch('helper.docker_run')
- def test_allow_broken_fuzz_targets_percentage(self, mocked_docker_run):
+ 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."""
- mocked_docker_run.return_value = 0
- test_fuzzer_dir = os.path.join(TEST_DATA_PATH, 'out')
- build_fuzzers.check_fuzzer_build(test_fuzzer_dir,
- self.SANITIZER,
- self.LANGUAGE,
- allowed_broken_targets_percentage='0')
- self.assertIn('-e ALLOWED_BROKEN_TARGETS_PERCENTAGE=0',
- ' '.join(mocked_docker_run.call_args[0][0]))
+ 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.')
@@ -304,11 +343,12 @@ class BuildSantizerIntegrationTest(unittest.TestCase):
@classmethod
def _create_config(cls, tmp_dir, sanitizer):
- return create_config(project_name=cls.PROJECT_NAME,
- project_repo_name=cls.PROJECT_NAME,
- workspace=tmp_dir,
- pr_ref=cls.PR_REF,
- sanitizer=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):
@@ -318,18 +358,6 @@ class BuildSantizerIntegrationTest(unittest.TestCase):
build_fuzzers.build_fuzzers(self._create_config(tmp_dir, sanitizer)))
-class GetDockerBuildFuzzersArgsContainerTest(unittest.TestCase):
- """Tests that _get_docker_build_fuzzers_args_container works as intended."""
-
- def test_get_docker_build_fuzzers_args_container(self):
- """Tests that _get_docker_build_fuzzers_args_container works as intended."""
- out_dir = '/my/out'
- container = 'my-container'
- result = build_fuzzers._get_docker_build_fuzzers_args_container(
- out_dir, container)
- self.assertEqual(result, ['-e', 'OUT=/my/out', '--volumes-from', container])
-
-
class GetDockerBuildFuzzersArgsNotContainerTest(unittest.TestCase):
"""Tests that _get_docker_build_fuzzers_args_not_container works as
intended."""
@@ -337,25 +365,10 @@ class GetDockerBuildFuzzersArgsNotContainerTest(unittest.TestCase):
def test_get_docker_build_fuzzers_args_no_container(self):
"""Tests that _get_docker_build_fuzzers_args_not_container works
as intended."""
- host_out_dir = '/cifuzz/out'
host_repo_path = '/host/repo'
result = build_fuzzers._get_docker_build_fuzzers_args_not_container(
- host_out_dir, host_repo_path)
- expected_result = [
- '-e', 'OUT=/out', '-v', '/cifuzz/out:/out', '-v',
- '/host/repo:/host/repo'
- ]
- self.assertEqual(result, expected_result)
-
-
-class GetDockerBuildFuzzersArgsMsanTest(unittest.TestCase):
- """Tests that _get_docker_build_fuzzers_args_msan works as intended."""
-
- def test_get_docker_build_fuzzers_args_msan(self):
- """Tests that _get_docker_build_fuzzers_args_msan works as intended."""
- work_dir = '/work_dir'
- result = build_fuzzers._get_docker_build_fuzzers_args_msan(work_dir)
- expected_result = ['-e', 'MSAN_LIBS_PATH=/work_dir/msan']
+ host_repo_path)
+ expected_result = ['-v', '/host/repo:/host/repo']
self.assertEqual(result, expected_result)
diff --git a/infra/cifuzz/cifuzz-base/Dockerfile b/infra/cifuzz/cifuzz-base/Dockerfile
index e0599dbbe..bb1431dd8 100644
--- a/infra/cifuzz/cifuzz-base/Dockerfile
+++ b/infra/cifuzz/cifuzz-base/Dockerfile
@@ -14,19 +14,20 @@
#
################################################################################
-# Don't bother with a slimmer base image.
-# When we pull base-builder to build project builder image we need to pull
-# ubuntu:16.04 anyway. So in the long run we probably would waste time if
-# we pulled something like alpine here instead.
-FROM ubuntu:16.04
+FROM gcr.io/oss-fuzz-base/base-runner
RUN apt-get update && \
- apt-get install ca-certificates wget python3 git-core --no-install-recommends -y && \
- wget https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce-cli_20.10.5~3-0~ubuntu-xenial_amd64.deb -O /tmp/docker-ce.deb && \
- dpkg -i /tmp/docker-ce.deb && rm /tmp/docker-ce.deb && \
- apt-get remove wget -y --purge
-
+ apt-get install -y systemd && \
+ apt-get install -y --no-install-recommends nodejs npm && \
+ wget https://download.docker.com/linux/ubuntu/dists/focal/pool/stable/amd64/docker-ce-cli_20.10.8~3-0~ubuntu-focal_amd64.deb -O /tmp/docker-ce.deb && \
+ dpkg -i /tmp/docker-ce.deb && rm /tmp/docker-ce.deb
ENV OSS_FUZZ_ROOT=/opt/oss-fuzz
ADD . ${OSS_FUZZ_ROOT}
-RUN rm -rf ${OSS_FUZZ_ROOT}/infra \ No newline at end of file
+RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt
+RUN npm install ${OSS_FUZZ_ROOT}/infra/cifuzz
+
+# 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"]
diff --git a/infra/cifuzz/cifuzz_combined_entrypoint.py b/infra/cifuzz/cifuzz_combined_entrypoint.py
new file mode 100644
index 000000000..008ce1088
--- /dev/null
+++ b/infra/cifuzz/cifuzz_combined_entrypoint.py
@@ -0,0 +1,53 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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:
+ ${GITHUB_WORKSPACE}/out/testcase
+ This can be used with GitHub's upload-artifact action to surface the logs.
+
+ Required environment variables:
+ OSS_FUZZ_PROJECT_NAME: The name of OSS-Fuzz project.
+ GITHUB_REPOSITORY: The name of the Github repo that called this script.
+ GITHUB_SHA: The commit SHA that triggered this script.
+ GITHUB_EVENT_NAME: The name of the hook event that triggered this script.
+ GITHUB_EVENT_PATH:
+ The path to the file containing the POST payload of the webhook:
+ https://help.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners#filesystems-on-github-hosted-runners
+ GITHUB_WORKSPACE: The shared volume directory where input artifacts are.
+ DRY_RUN: If true, no failures will surface.
+ SANITIZER: The sanitizer to use when running fuzzers.
+ FUZZ_SECONDS: The length of time in seconds that fuzzers are to be run.
+
+ 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())
diff --git a/infra/cifuzz/cifuzz_end_to_end_test.py b/infra/cifuzz/cifuzz_end_to_end_test.py
new file mode 100644
index 000000000..2a4234faf
--- /dev/null
+++ b/infra/cifuzz/cifuzz_end_to_end_test.py
@@ -0,0 +1,46 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+ 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)
diff --git a/infra/cifuzz/cloudbuild.yaml b/infra/cifuzz/cloudbuild.yaml
new file mode 100644
index 000000000..6f38ccecd
--- /dev/null
+++ b/infra/cifuzz/cloudbuild.yaml
@@ -0,0 +1,39 @@
+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
+ - '-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
+ - '-f'
+ - infra/run_fuzzers.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
+timeout: 1800s
diff --git a/infra/cifuzz/clusterfuzz_deployment.py b/infra/cifuzz/clusterfuzz_deployment.py
index 8c46e9d4e..fdc3738df 100644
--- a/infra/cifuzz/clusterfuzz_deployment.py
+++ b/infra/cifuzz/clusterfuzz_deployment.py
@@ -11,15 +11,20 @@
# WITHOUT 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."""
+"""Module for interacting with the ClusterFuzz deployment."""
import logging
import os
import sys
-import tempfile
-import time
import urllib.error
import urllib.request
-import zipfile
+
+import config_utils
+import continuous_integration
+import filestore
+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__))))
@@ -29,13 +34,12 @@ import utils
class BaseClusterFuzzDeployment:
"""Base class for ClusterFuzz deployments."""
- CORPUS_DIR_NAME = 'cifuzz-corpus'
- BUILD_DIR_NAME = 'cifuzz-latest-build'
-
- def __init__(self, config):
+ def __init__(self, config, workspace):
self.config = config
+ self.workspace = workspace
+ self.ci_system = continuous_integration.get_ci(config)
- def download_latest_build(self, out_dir):
+ def download_latest_build(self):
"""Downloads the latest build from ClusterFuzz.
Returns:
@@ -43,23 +47,167 @@ class BaseClusterFuzzDeployment:
"""
raise NotImplementedError('Child class must implement method.')
- def download_corpus(self, target_name, out_dir):
- """Downloads the corpus for |target_name| from ClusterFuzz to |out_dir|.
+ 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."""
- def download_latest_build(self, out_dir):
- logging.info('download_latest_build not implemented for 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)
+
+ # Builds are stored by commit, so try the latest |LATEST_BUILD_WINDOW|
+ # commits before the current.
+ # TODO(ochang): If API usage becomes an issue, this can be optimized by the
+ # filestore accepting a list of filenames to try.
+ for old_commit in repo.get_commit_list('HEAD^',
+ limit=self.LATEST_BUILD_WINDOW):
+ 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 previus 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)
- def download_corpus(self, target_name, out_dir):
- logging.info('download_corpus not implemented for ClusterFuzzLite.')
+ 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 _get_crashes_artifact_name(self): # pylint: disable=no-self-use
+ """Returns the name of the crashes artifact."""
+ return 'current'
+
+ 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 error: # pylint: disable=broad-except
+ logging.error('Failed to upload corpus for target: %s. Error: %s.',
+ target_name, error)
+
+ 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 error: # pylint: disable=broad-except
+ logging.error('Failed to upload latest build: %s. Error: %s',
+ self.workspace.out, error)
+
+ def upload_crashes(self):
+ """Uploads crashes."""
+ if not os.listdir(self.workspace.artifacts):
+ logging.info('No crashes in %s. Not uploading.', self.workspace.artifacts)
+ return
+
+ crashes_artifact_name = self._get_crashes_artifact_name()
+
+ logging.info('Uploading crashes in %s.', self.workspace.artifacts)
+ try:
+ self.filestore.upload_crashes(crashes_artifact_name,
+ self.workspace.artifacts)
+ logging.info('Done uploading crashes.')
+ except Exception as error: # pylint: disable=broad-except
+ logging.error('Failed to upload crashes. Error: %s', error)
+
+ 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."""
+ 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 (get_coverage.CoverageError, filestore.FilestoreError):
+ logging.error('Could not get coverage.')
+ return None
class OSSFuzz(BaseClusterFuzzDeployment):
@@ -68,9 +216,6 @@ class OSSFuzz(BaseClusterFuzzDeployment):
# Location of clusterfuzz builds on GCS.
CLUSTERFUZZ_BUILDS = 'clusterfuzz-builds'
- # Format string for the latest version of a project's build.
- VERSION_STRING = '{project_name}-{sanitizer}-latest.version'
-
# Zip file name containing the corpus.
CORPUS_ZIP_NAME = 'public.zip'
@@ -80,139 +225,148 @@ class OSSFuzz(BaseClusterFuzzDeployment):
Returns:
A string with the latest build version or None.
"""
- version_file = self.VERSION_STRING.format(
- project_name=self.config.project_name, sanitizer=self.config.sanitizer)
+ 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.project_name, version_file)
+ 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.project_name, version_url)
+ self.config.oss_fuzz_project_name, version_url)
return None
return response.read().decode()
- def download_latest_build(self, out_dir):
+ 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.
"""
- build_dir = os.path.join(out_dir, self.BUILD_DIR_NAME)
- if os.path.exists(build_dir):
- return build_dir
+ 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
- os.makedirs(build_dir, exist_ok=True)
+ _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.project_name,
+ self.config.oss_fuzz_project_name,
latest_build_name)
- if download_and_unpack_zip(oss_fuzz_build_url, build_dir):
- return build_dir
+ 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 download_corpus(self, target_name, out_dir):
+ 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.
"""
- corpus_dir = os.path.join(out_dir, self.CORPUS_DIR_NAME, target_name)
- os.makedirs(corpus_dir, exist_ok=True)
- # TODO(metzman): Clean up this code.
+ _make_empty_dir_if_nonexistent(corpus_dir)
project_qualified_fuzz_target_name = target_name
- qualified_name_prefix = self.config.project_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 = utils.url_join(
- utils.GCS_BASE_URL,
- '{0}-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/'.format(
- self.config.project_name), project_qualified_fuzz_target_name,
- self.CORPUS_ZIP_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}')
- if download_and_unpack_zip(corpus_url, corpus_dir):
- return corpus_dir
-
- return None
+ 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 download_url(url, filename, num_attempts=3):
- """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.
- num_retries: The number of times to retry the download on
- ConnectionResetError.
+ 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
- Returns:
- True on success.
- """
- sleep_time = 1
- # Don't use retry wrapper since we don't want this to raise any exceptions.
- for _ in range(num_attempts):
- try:
- urllib.request.urlretrieve(url, filename)
- return True
- except urllib.error.HTTPError:
- # In these cases, retrying probably wont work since the error probably
- # means there is nothing at the URL to download.
- logging.error('Unable to download from: %s.', url)
- return False
- except ConnectionResetError:
- # These errors are more likely to be transient. Retry.
- pass
- time.sleep(sleep_time)
+class NoClusterFuzzDeployment(BaseClusterFuzzDeployment):
+ """ClusterFuzzDeployment implementation used when there is no deployment of
+ ClusterFuzz to use."""
- logging.error('Failed to download %s, %d times.', url, num_attempts)
+ 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.')
- return False
+ 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_and_unpack_zip(url, extract_directory):
- """Downloads and unpacks a zip file from an HTTP URL.
+ 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)
- Args:
- url: A url to the zip file to be downloaded and unpacked.
- out_dir: The path where the zip file should be extracted to.
+ 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.')
- Returns:
- True on success.
- """
- if not os.path.exists(extract_directory):
- logging.error('Extract directory: %s does not exist.', extract_directory)
- return False
+ def upload_coverage(self):
+ """Noop Implementation of upload_coverage."""
+ logging.info(
+ 'Not uploading coverage report because no ClusterFuzz deployment.')
- # 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):
- return False
+ def get_coverage(self, repo_path):
+ """Noop Implementation of get_coverage."""
+ logging.info(
+ 'Not getting project coverage because no ClusterFuzz deployment.')
- 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
+_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:
+ NoClusterFuzzDeployment,
+ config_utils.BaseConfig.Platform.EXTERNAL_GITHUB:
+ ClusterFuzzLite,
+}
-def get_clusterfuzz_deployment(config):
+def get_clusterfuzz_deployment(config, workspace):
"""Returns object reprsenting deployment of ClusterFuzz used by |config|."""
- if (config.platform == config.Platform.INTERNAL_GENERIC_CI or
- config.platform == config.Platform.INTERNAL_GITHUB):
- logging.info('Using OSS-Fuzz as ClusterFuzz deployment.')
- return OSSFuzz(config)
- logging.info('Using ClusterFuzzLite as ClusterFuzz deployment.')
- return ClusterFuzzLite(config)
+ deployment_cls = _PLATFORM_CLUSTERFUZZ_DEPLOYMENT_MAPPING[config.platform]
+ result = deployment_cls(config, workspace)
+ logging.info('ClusterFuzzDeployment: %s.', result)
+ return result
diff --git a/infra/cifuzz/clusterfuzz_deployment_test.py b/infra/cifuzz/clusterfuzz_deployment_test.py
index 06ff78476..247678548 100644
--- a/infra/cifuzz/clusterfuzz_deployment_test.py
+++ b/infra/cifuzz/clusterfuzz_deployment_test.py
@@ -16,12 +16,14 @@
import os
import unittest
from unittest import mock
-import urllib.error
+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.
@@ -30,62 +32,60 @@ 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 = {'is_github': True, 'project_name': EXAMPLE_PROJECT}
+ defaults = {
+ 'is_github': True,
+ '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
- with mock.patch('os.path.basename', return_value=None), mock.patch(
- 'config_utils.get_project_src_path',
- return_value=None), mock.patch('config_utils._is_dry_run',
- return_value=True):
- config = config_utils.RunFuzzersConfig()
-
- for key, value in kwargs.items():
- assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
- setattr(config, key, value)
- return config
+ return test_helpers.create_run_config(**kwargs)
def _create_deployment(**kwargs):
config = _create_config(**kwargs)
- return clusterfuzz_deployment.get_clusterfuzz_deployment(config)
+ workspace = workspace_utils.Workspace(config)
+ return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace)
class OSSFuzzTest(fake_filesystem_unittest.TestCase):
"""Tests OSSFuzz."""
- OUT_DIR = '/out'
-
def setUp(self):
self.setUpPyfakefs()
self.deployment = _create_deployment()
+ self.corpus_dir = os.path.join(self.deployment.workspace.corpora,
+ EXAMPLE_FUZZER)
- @mock.patch('clusterfuzz_deployment.download_and_unpack_zip',
- return_value=True)
- def test_download_corpus(self, mocked_download_and_unpack_zip):
+ @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."""
- result = self.deployment.download_corpus(EXAMPLE_FUZZER, self.OUT_DIR)
- self.assertIsNotNone(result)
- expected_corpus_dir = os.path.join(self.OUT_DIR, 'cifuzz-corpus',
- EXAMPLE_FUZZER)
+ 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, _ = mocked_download_and_unpack_zip.call_args
- self.assertEqual(call_args, (expected_url, expected_corpus_dir))
+ 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('clusterfuzz_deployment.download_and_unpack_zip',
- return_value=False)
- def test_download_fail(self, _):
- """Tests that when downloading fails, None is returned."""
- corpus_path = self.deployment.download_corpus(EXAMPLE_FUZZER, self.OUT_DIR)
- self.assertIsNone(corpus_path)
+ @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."""
@@ -93,58 +93,170 @@ class OSSFuzzTest(fake_filesystem_unittest.TestCase):
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')
+ 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(run_fuzzers_mode='batch',
+ oss_fuzz_project_name='',
+ is_github=True)
+ 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.BaseCi.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.BaseCi.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())
-class DownloadUrlTest(unittest.TestCase):
- """Tests that download_url works."""
- URL = 'example.com/file'
- FILE_PATH = '/tmp/file'
-
- @mock.patch('time.sleep')
- @mock.patch('urllib.request.urlretrieve', return_value=True)
- def test_download_url_no_error(self, mocked_urlretrieve, _):
- """Tests that download_url works when there is no error."""
- self.assertTrue(
- clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
- self.assertEqual(1, mocked_urlretrieve.call_count)
-
- @mock.patch('time.sleep')
- @mock.patch('logging.error')
- @mock.patch('urllib.request.urlretrieve',
- side_effect=urllib.error.HTTPError(None, None, None, None, None))
- def test_download_url_http_error(self, mocked_urlretrieve, mocked_error, _):
- """Tests that download_url doesn't retry when there is an HTTP error."""
- self.assertFalse(
- clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
- mocked_error.assert_called_with('Unable to download from: %s.', self.URL)
- self.assertEqual(1, mocked_urlretrieve.call_count)
-
- @mock.patch('time.sleep')
- @mock.patch('logging.error')
- @mock.patch('urllib.request.urlretrieve', side_effect=ConnectionResetError)
- def test_download_url_connection_error(self, mocked_urlretrieve, mocked_error,
- mocked_sleep):
- """Tests that download_url doesn't retry when there is an HTTP error."""
- self.assertFalse(
- clusterfuzz_deployment.download_url(self.URL, self.FILE_PATH))
- self.assertEqual(3, mocked_urlretrieve.call_count)
- self.assertEqual(3, mocked_sleep.call_count)
- mocked_error.assert_called_with('Failed to download %s, %d times.',
- self.URL, 3)
-
-
-class DownloadAndUnpackZipTest(fake_filesystem_unittest.TestCase):
- """Tests download_and_unpack_zip."""
+ @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,
+ is_github=False)
+ 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.NoClusterFuzzDeployment),
+ (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):
+ config = _create_config()
+ workspace = workspace_utils.Workspace(config)
- @mock.patch('urllib.request.urlretrieve', return_value=True)
- 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(
- clusterfuzz_deployment.download_and_unpack_zip('/not/a/real/url',
- '/extract-directory'))
+ self.assertIsInstance(
+ clusterfuzz_deployment.get_clusterfuzz_deployment(
+ config, workspace), expected_deployment_cls)
if __name__ == '__main__':
diff --git a/infra/cifuzz/config_utils.py b/infra/cifuzz/config_utils.py
index ad2cd36c6..bc73536bd 100644
--- a/infra/cifuzz/config_utils.py
+++ b/infra/cifuzz/config_utils.py
@@ -16,55 +16,44 @@
import logging
import enum
import os
+import sys
import json
import environment
+# pylint: disable=wrong-import-position,import-error
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-def _get_project_repo_name():
- return os.path.basename(environment.get('GITHUB_REPOSITORY', ''))
+import constants
+
+RUN_FUZZERS_MODES = ['batch', 'ci', 'coverage', 'prune']
+SANITIZERS = ['address', 'memory', 'undefined', 'coverage']
+
+# TODO(metzman): Set these on config objects so there's one source of truth.
+DEFAULT_ENGINE = 'libfuzzer'
+DEFAULT_ARCHITECTURE = 'x86_64'
+
+# 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_pr_ref(event):
if event == 'pull_request':
- return environment.get('GITHUB_REF')
+ return os.getenv('GITHUB_REF')
return None
def _get_sanitizer():
- return os.getenv('SANITIZER', 'address').lower()
-
-
-def _get_project_name():
- # TODO(metzman): Remove OSS-Fuzz reference.
- return os.getenv('OSS_FUZZ_PROJECT_NAME')
+ return os.getenv('SANITIZER', constants.DEFAULT_SANITIZER).lower()
def _is_dry_run():
"""Returns True if configured to do a dry run."""
- return environment.get_bool('DRY_RUN', 'false')
-
-
-def get_project_src_path(workspace):
- """Returns the manually checked out path of the project's source if specified
- or None."""
- # TODO(metzman): Get rid of MANUAL_SRC_PATH when Skia switches to
- # PROJECT_SRC_PATH.
- path = os.getenv('PROJECT_SRC_PATH', os.getenv('MANUAL_SRC_PATH'))
- if not path:
- logging.debug('No PROJECT_SRC_PATH.')
- return path
-
- logging.debug('PROJECT_SRC_PATH set.')
- if os.path.isabs(path):
- return path
-
- # If |src| is not absolute, assume we are running in GitHub actions.
- # TODO(metzman): Don't make this assumption.
- return os.path.join(workspace, path)
-
-
-DEFAULT_LANGUAGE = 'c++'
+ return environment.get_bool('DRY_RUN', False)
def _get_language():
@@ -74,12 +63,114 @@ def _get_language():
# 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', DEFAULT_LANGUAGE)
+ return os.getenv('LANGUAGE', constants.DEFAULT_LANGUAGE)
# pylint: disable=too-few-public-methods,too-many-instance-attributes
+class BaseCiEnvironment:
+ """Base class for CiEnvironment subclasses."""
+
+ @property
+ def workspace(self):
+ """Returns the workspace."""
+ raise NotImplementedError('Child class must implment method.')
+
+ @property
+ def git_sha(self):
+ """Returns the Git SHA to diff against."""
+ raise NotImplementedError('Child class must implment method.')
+
+ @property
+ def token(self):
+ """Returns the CI API token."""
+ raise NotImplementedError('Child class must implment method.')
+
+ @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 set: %s.', path)
+ return path
+
+
+class GenericCiEnvironment(BaseCiEnvironment):
+ """CI Environment for generic CI systems."""
+
+ @property
+ def workspace(self):
+ """Returns the workspace."""
+ return os.getenv('WORKSPACE')
+
+ @property
+ def git_sha(self):
+ """Returns the Git SHA to diff against."""
+ return os.getenv('GIT_SHA')
+
+ @property
+ def token(self):
+ """Returns the CI API token."""
+ return os.getenv('TOKEN')
+
+ @property
+ def project_repo_owner_and_name(self):
+ """Returns a tuple containing the project repo owner and None."""
+ repository = os.getenv('REPOSITORY')
+ # Repo owner is a githubism.
+ return None, repository
+
+
+class GithubEnvironment(BaseCiEnvironment):
+ """CI environment for GitHub."""
+
+ @property
+ def workspace(self):
+ """Returns the workspace."""
+ return os.getenv('GITHUB_WORKSPACE')
+
+ @property
+ def git_sha(self):
+ """Returns the Git SHA to diff against."""
+ return os.getenv('GITHUB_SHA')
+
+ @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."""
+ # On GitHub, they don't know the absolute path, it is relative to
+ # |workspace|.
+ project_src_path = super().project_src_path
+ if project_src_path is None:
+ return project_src_path
+ 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)
+
+
+class ConfigError(Exception):
+ """Error for invalid configuration."""
+
+
class BaseConfig:
"""Object containing constant configuration for CIFuzz."""
@@ -88,66 +179,144 @@ class BaseConfig:
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.
def __init__(self):
- self.workspace = os.getenv('GITHUB_WORKSPACE')
- self.project_name = _get_project_name()
+ # Need to set these before calling self.platform.
+ self._github_event_path = os.getenv('GITHUB_EVENT_PATH')
+ self.is_github = bool(self._github_event_path)
+ logging.debug('Is github: %s.', self.is_github)
+ self.oss_fuzz_project_name = os.getenv('OSS_FUZZ_PROJECT_NAME')
+
+ self._ci_env = _get_ci_environment(self.platform)
+ self.workspace = self._ci_env.workspace
+
+ self.project_repo_owner, self.project_repo_name = (
+ self._ci_env.project_repo_owner_and_name)
+
# Check if failures should not be reported.
self.dry_run = _is_dry_run()
+
self.sanitizer = _get_sanitizer()
- self.build_integration_path = os.getenv('BUILD_INTEGRATION_PATH')
+
+ self.build_integration_path = (
+ constants.DEFAULT_EXTERNAL_BUILD_INTEGRATION_PATH)
self.language = _get_language()
- event_path = os.getenv('GITHUB_EVENT_PATH')
- self.is_github = bool(event_path)
- logging.debug('Is github: %s.', self.is_github)
- # TODO(metzman): Parse env like we do in ClusterFuzz.
- self.low_disk_space = environment.get('LOW_DISK_SPACE', False)
+ self.low_disk_space = environment.get_bool('LOW_DISK_SPACE', False)
+
+ self.token = self._ci_env.token
+ 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.docker_in_docker = os.environ.get('DOCKER_IN_DOCKER')
+
+ # 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.
+ 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.language not in constants.LANGUAGES:
+ logging.error('Invalid LANGUAGE: %s. Must be one of: %s.', self.language,
+ constants.LANGUAGES)
+ return False
+
+ return True
@property
def is_internal(self):
"""Returns True if this is an OSS-Fuzz project."""
- return not self.build_integration_path
+ 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'
+
+
+_CI_ENVIRONMENT_MAPPING = {
+ BaseConfig.Platform.EXTERNAL_GITHUB: GithubEnvironment,
+ BaseConfig.Platform.INTERNAL_GITHUB: GithubEnvironment,
+ BaseConfig.Platform.INTERNAL_GENERIC_CI: GenericCiEnvironment,
+ BaseConfig.Platform.EXTERNAL_GENERIC_CI: GenericCiEnvironment,
+}
+
+
+def _get_ci_environment(platform):
+ """Returns the CI environment object for |platform|."""
+ return _CI_ENVIRONMENT_MAPPING[platform]()
+
class RunFuzzersConfig(BaseConfig):
"""Class containing constant configuration for running fuzzers in CIFuzz."""
- RUN_FUZZERS_MODES = {'batch', 'ci'}
-
def __init__(self):
super().__init__()
+ # TODO(metzman): Pick a better default for pruning.
self.fuzz_seconds = int(os.environ.get('FUZZ_SECONDS', 600))
self.run_fuzzers_mode = os.environ.get('RUN_FUZZERS_MODE', 'ci').lower()
- if self.run_fuzzers_mode not in self.RUN_FUZZERS_MODES:
- raise Exception(
- ('Invalid RUN_FUZZERS_MODE %s not one of allowed choices: %s.' %
- self.run_fuzzers_mode, self.RUN_FUZZERS_MODES))
+ if self.is_coverage:
+ self.run_fuzzers_mode = 'coverage'
+
+ self.report_unreproducible_crashes = environment.get_bool(
+ 'REPORT_UNREPRODUCIBLE_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.run_fuzzers_mode not in RUN_FUZZERS_MODES:
+ logging.error('Invalid RUN_FUZZERS_MODE: %s. Must be one of %s.',
+ self.run_fuzzers_mode, RUN_FUZZERS_MODES)
+ return False
+
+ return True
class BuildFuzzersConfig(BaseConfig):
"""Class containing constant configuration for building fuzzers in CIFuzz."""
def _get_config_from_event_path(self, event):
- event_path = os.getenv('GITHUB_EVENT_PATH')
- if not event_path:
+ if not self._github_event_path:
return
- with open(event_path, encoding='utf-8') as file_handle:
+ with open(self._github_event_path, encoding='utf-8') as file_handle:
event_data = json.load(file_handle)
if event == 'push':
self.base_commit = event_data['before']
logging.debug('base_commit: %s', self.base_commit)
- else:
- self.pr_ref = 'refs/pull/{0}/merge'.format(
- event_data['pull_request']['number'])
+ elif event == 'pull_request':
+ self.pr_ref = f'refs/pull/{event_data["pull_request"]["number"]}/merge'
logging.debug('pr_ref: %s', self.pr_ref)
self.git_url = event_data['repository']['html_url']
@@ -155,11 +324,8 @@ class BuildFuzzersConfig(BaseConfig):
def __init__(self):
"""Get the configuration from CIFuzz from the environment. These variables
are set by GitHub or the user."""
- # TODO(metzman): Some of this config is very CI-specific. Move it into the
- # CI class.
super().__init__()
- self.project_repo_name = _get_project_repo_name()
- self.commit_sha = os.getenv('GITHUB_SHA')
+ self.commit_sha = self._ci_env.git_sha
event = os.getenv('GITHUB_EVENT_NAME')
self.pr_ref = None
@@ -168,13 +334,21 @@ class BuildFuzzersConfig(BaseConfig):
self._get_config_from_event_path(event)
self.base_ref = os.getenv('GITHUB_BASE_REF')
- self.project_src_path = get_project_src_path(self.workspace)
+ self.project_src_path = self._ci_env.project_src_path
self.allowed_broken_targets_percentage = os.getenv(
'ALLOWED_BROKEN_TARGETS_PERCENTAGE')
- self.bad_build_check = environment.get_bool('BAD_BUILD_CHECK', 'true')
-
- # TODO(metzman): Use better system for interpreting env vars. What if env
- # var is set to '0'?
- self.keep_unaffected_fuzz_targets = bool(
- os.getenv('KEEP_UNAFFECTED_FUZZERS'))
+ self.bad_build_check = environment.get_bool('BAD_BUILD_CHECK', True)
+ # pylint: disable=consider-using-ternary
+ self.keep_unaffected_fuzz_targets = (
+ # Not from a commit or PR.
+ (not self.base_ref and not self.base_commit) or
+ environment.get_bool('KEEP_UNAFFECTED_FUZZERS'))
+ self.upload_build = environment.get_bool('UPLOAD_BUILD', False)
+ if self.upload_build:
+ logging.info('Keeping all fuzzers because we are uploading build.')
+ self.keep_unaffected_fuzz_targets = True
+
+ if self.sanitizer == 'coverage':
+ self.keep_unaffected_fuzz_targets = True
+ self.bad_build_check = False
diff --git a/infra/cifuzz/config_utils_test.py b/infra/cifuzz/config_utils_test.py
index 6f87bd4c5..32499bfd0 100644
--- a/infra/cifuzz/config_utils_test.py
+++ b/infra/cifuzz/config_utils_test.py
@@ -14,11 +14,13 @@
"""Module for getting the configuration CIFuzz needs to run."""
import os
import unittest
+from unittest import mock
import config_utils
+import constants
import test_helpers
-# pylint: disable=no-self-use
+# pylint: disable=no-self-use,protected-access
class BaseConfigTest(unittest.TestCase):
@@ -32,18 +34,66 @@ class BaseConfigTest(unittest.TestCase):
def test_language_default(self):
"""Tests that the correct default language is set."""
- os.environ['BUILD_INTEGRATION_PATH'] = '/path'
config = self._create_config()
self.assertEqual(config.language, 'c++')
def test_language(self):
"""Tests that the correct language is set."""
- os.environ['BUILD_INTEGRATION_PATH'] = '/path'
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'
+ config = self._create_config()
+ self.assertTrue(config.validate())
+
class BuildFuzzersConfigTest(unittest.TestCase):
"""Tests for BuildFuzzersConfig."""
@@ -61,11 +111,151 @@ class BuildFuzzersConfigTest(unittest.TestCase):
config = self._create_config()
self.assertEqual(config.base_ref, expected_base_ref)
- def test_keep_unaffected_defaults_to_false(self):
- """Tests that keep_unaffected_fuzz_targets defaults to false."""
+ 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['GITHUB_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)
+
+ def _create_config(self):
+ return config_utils.RunFuzzersConfig()
+
+ def test_coverage(self):
+ """Tests that run_fuzzers_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['RUN_FUZZERS_MODE'] = 'ci'
+ config = self._create_config()
+ self.assertEqual(config.run_fuzzers_mode, 'coverage')
+
+ # Test that it isn't overriden when it isn't supposed to be.
+ os.environ['SANITIZER'] = 'address'
+ run_fuzzers_mode = 'ci'
+ os.environ['RUN_FUZZERS_MODE'] = run_fuzzers_mode
+ config = self._create_config()
+ self.assertEqual(config.run_fuzzers_mode, run_fuzzers_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 run_fuzzers_mode is
+ invalid."""
+ fake_mode = 'fake-mode'
+ os.environ['RUN_FUZZERS_MODE'] = fake_mode
+ self.assertFalse(self._create_config()._run_config_validate())
+ mock_error.assert_called_with(
+ 'Invalid RUN_FUZZERS_MODE: %s. Must be one of %s.', fake_mode,
+ config_utils.RUN_FUZZERS_MODES)
+
+
+class GetProjectRepoOwnerAndNameTest(unittest.TestCase):
+ """Tests for BaseCiEnv.get_project_repo_owner_and_name."""
+
+ def setUp(self):
+ test_helpers.patch_environ(self)
+ self.repo_owner = 'repo-owner'
+ self.repo_name = 'repo-name'
+ self.github_env = config_utils.GithubEnvironment()
+ self.generic_ci_env = config_utils.GenericCiEnvironment()
+
+ def test_unset_repository(self):
+ """Tests that the correct result is returned when repository is not set."""
+ self.assertEqual(self.generic_ci_env.project_repo_owner_and_name,
+ (None, None))
+
+ def test_empty_repository(self):
+ """Tests that the correct result is returned when repository is an empty
+ string."""
+ os.environ['REPOSITORY'] = ''
+ self.assertEqual(self.generic_ci_env.project_repo_owner_and_name,
+ (None, ''))
+
+ def test_github_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'] = f'{self.repo_owner}/{self.repo_name}'
+ self.assertEqual(self.github_env.project_repo_owner_and_name,
+ (self.repo_owner, self.repo_name))
+
+ def test_nongithub_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.generic_ci_env.project_repo_owner_and_name,
+ (None, self.repo_name))
+
+
+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)
+
+
+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'
+
+ def test_unset(self):
+ """Tests that project_src_path returns None when no PROJECT_SRC_PATH is
+ set."""
+ github_env = config_utils.GithubEnvironment()
+ self.assertIsNone(github_env.project_src_path)
+
+ 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 = config_utils.GithubEnvironment()
+ self.assertEqual(github_env.project_src_path, expected_project_src_path)
+
+ def test_not_github(self):
+ """Tests that project_src_path returns the correct result not on
+ GitHub."""
+ project_src_path = os.path.join('/', self.project_src_dir_name)
+ os.environ['PROJECT_SRC_PATH'] = project_src_path
+ generic_ci_env = config_utils.GenericCiEnvironment()
+ self.assertEqual(generic_ci_env.project_src_path, project_src_path)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/infra/cifuzz/continuous_integration.py b/infra/cifuzz/continuous_integration.py
index b2e8af28e..47c4a7cbf 100644
--- a/infra/cifuzz/continuous_integration.py
+++ b/infra/cifuzz/continuous_integration.py
@@ -21,16 +21,21 @@ 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
@@ -47,16 +52,34 @@ class BaseCi:
def __init__(self, config):
self.config = config
+ self.workspace = workspace_utils.Workspace(config)
+
+ 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.workspace.repo_storage):
+ return None
+
+ # Note: this assumes there is only one repo checked out here.
+ listing = os.listdir(self.workspace.repo_storage)
+ if len(listing) != 1:
+ raise RuntimeError('Invalid repo storage.')
+
+ repo_path = os.path.join(self.workspace.repo_storage, listing[0])
+ if not os.path.isdir(repo_path):
+ raise RuntimeError('Repo is not a directory.')
+
+ return repo_path
def prepare_for_fuzzer_build(self):
"""Builds the fuzzer builder image and gets the source code we need to
fuzz."""
- raise NotImplementedError('Children must implement this method.')
+ 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."""
- raise NotImplementedError('Children must implement this method.')
+ raise NotImplementedError('Child class must implement method.')
def get_changed_code_under_test(self, repo_manager_obj):
"""Returns the changed files that need to be tested."""
@@ -65,10 +88,38 @@ class BaseCi:
logging.info('Diffing against %s.', base)
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 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).
@@ -127,27 +178,35 @@ class InternalGithub(GithubCiMixin, BaseCi):
assert self.config.pr_ref or self.config.commit_sha
# detect_main_repo builds the image as a side effect.
inferred_url, image_repo_path = (build_specified_commit.detect_main_repo(
- self.config.project_name, repo_name=self.config.project_repo_name))
+ 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 from project %s.',
- self.config.project_name)
- return BuildPreparationResult(False, None, None)
+ logging.error('Could not detect repo.')
+ return BuildPreparationResult(success=False,
+ image_repo_path=None,
+ repo_manager=None)
- git_workspace = os.path.join(self.config.workspace, 'storage')
- os.makedirs(git_workspace, exist_ok=True)
+ os.makedirs(self.workspace.repo_storage, exist_ok=True)
# Use the same name used in the docker image so we can overwrite it.
image_repo_name = os.path.basename(image_repo_path)
# Checkout project's repo in the shared volume.
- manager = repo_manager.clone_repo_and_get_manager(inferred_url,
- git_workspace,
- repo_name=image_repo_name)
+ manager = repo_manager.clone_repo_and_get_manager(
+ inferred_url, self.workspace.repo_storage, repo_name=image_repo_name)
checkout_specified_commit(manager, self.config.pr_ref,
self.config.commit_sha)
- return BuildPreparationResult(True, image_repo_path, 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)
class InternalGeneric(BaseCi):
@@ -162,35 +221,71 @@ class InternalGeneric(BaseCi):
logging.info('Building OSS-Fuzz project.')
# detect_main_repo builds the image as a side effect.
_, image_repo_path = (build_specified_commit.detect_main_repo(
- self.config.project_name, repo_name=self.config.project_repo_name))
+ self.config.oss_fuzz_project_name,
+ repo_name=self.config.project_repo_name))
if not image_repo_path:
- logging.error('Could not detect repo from project %s.',
- self.config.project_name)
- return BuildPreparationResult(False, None, None)
+ logging.error('Could not detect repo.')
+ return BuildPreparationResult(success=False,
+ image_repo_path=None,
+ repo_manager=None)
manager = repo_manager.RepoManager(self.config.project_src_path)
- return BuildPreparationResult(True, image_repo_path, manager)
+ return BuildPreparationResult(success=True,
+ image_repo_path=image_repo_path,
+ repo_manager=manager)
def get_diff_base(self):
return 'origin...'
-
-_IMAGE_BUILD_TRIES = 3
-_IMAGE_BUILD_BACKOFF = 2
+ 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_name, project_src,
- build_integration_path):
+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')
- tag = 'gcr.io/oss-fuzz/{project_name}'.format(project_name=project_name)
- command = ['-t', tag, '-f', dockerfile_path, project_src]
+ 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 get_diff_base(self):
+ return 'origin...'
+
+ def prepare_for_fuzzer_build(self):
+ logging.info('ExternalGeneric: preparing for fuzzer build.')
+ manager = repo_manager.RepoManager(self.config.project_src_path)
+ 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: %s.',
+ self.config.oss_fuzz_project_name)
+ return BuildPreparationResult(success=False,
+ image_repo_path=None,
+ repo_manager=None)
+
+ 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 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."""
@@ -200,24 +295,32 @@ class ExternalGithub(GithubCiMixin, BaseCi):
projects are expected to bring their own source code to CIFuzz. Returns True
on success."""
logging.info('Building external project.')
- git_workspace = os.path.join(self.config.workspace, 'storage')
- os.makedirs(git_workspace, exist_ok=True)
+ os.makedirs(self.workspace.repo_storage, exist_ok=True)
# Checkout before building, so we don't need to rely on copying the source
# into the image.
# TODO(metzman): Figure out if we want second copy at all.
manager = repo_manager.clone_repo_and_get_manager(
self.config.git_url,
- git_workspace,
+ self.workspace.repo_storage,
repo_name=self.config.project_repo_name)
checkout_specified_commit(manager, self.config.pr_ref,
self.config.commit_sha)
- build_integration_path = os.path.join(manager.repo_dir,
- self.config.build_integration_path)
- if not build_external_project_docker_image(
- self.config.project_name, manager.repo_dir, build_integration_path):
+ 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 BuildPreparationResult(False, None, None)
+ return BuildPreparationResult(success=False,
+ image_repo_path=None,
+ repo_manager=None)
image_repo_path = os.path.join('/src', self.config.project_repo_name)
- return BuildPreparationResult(True, image_repo_path, 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."""
+ return get_build_command()
diff --git a/infra/cifuzz/continuous_integration_test.py b/infra/cifuzz/continuous_integration_test.py
new file mode 100644
index 000000000..7c7e3eefd
--- /dev/null
+++ b/infra/cifuzz/continuous_integration_test.py
@@ -0,0 +1,87 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+# 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', 'external-project', '-f',
+ os.path.join('.clusterfuzzlite', 'Dockerfile'), project_src
+ ])
+
+
+# TODO(metzman): Write tests for the rest of continuous_integration.py.
diff --git a/infra/cifuzz/coverage_test.py b/infra/cifuzz/coverage_test.py
deleted file mode 100644
index 1b24d798c..000000000
--- a/infra/cifuzz/coverage_test.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2021 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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 coverage.py"""
-import os
-import json
-import unittest
-from unittest import mock
-
-import 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 GetFuzzerStatsDirUrlTest(unittest.TestCase):
- """Tests _get_fuzzer_stats_dir_url."""
-
- @mock.patch('coverage.get_json_from_url',
- return_value={
- 'fuzzer_stats_dir':
- 'gs://oss-fuzz-coverage/systemd/fuzzer_stats/20210303'
- })
- def test_get_valid_project(self, mocked_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 = coverage._get_fuzzer_stats_dir_url(PROJECT_NAME)
- (url,), _ = mocked_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(coverage._get_fuzzer_stats_dir_url('not-a-proj'))
-
-
-class GetTargetCoverageReportTest(unittest.TestCase):
- """Tests get_target_coverage_report."""
-
- def setUp(self):
- with mock.patch('coverage._get_latest_cov_report_info',
- return_value=PROJECT_COV_INFO):
- self.coverage_getter = coverage.OssFuzzCoverageGetter(
- PROJECT_NAME, REPO_PATH)
-
- @mock.patch('coverage.get_json_from_url', return_value={})
- def test_valid_target(self, mocked_get_json_from_url):
- """Tests that a target's coverage report can be downloaded and parsed."""
- self.coverage_getter.get_target_coverage_report(FUZZ_TARGET)
- (url,), _ = mocked_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.coverage_getter.get_target_coverage_report(INVALID_TARGET))
-
- @mock.patch('coverage._get_latest_cov_report_info', return_value=None)
- def test_invalid_project_json(self, _):
- """Tests an invalid project JSON results in None being returned."""
- coverage_getter = coverage.OssFuzzCoverageGetter(PROJECT_NAME, REPO_PATH)
- self.assertIsNone(coverage_getter.get_target_coverage_report(FUZZ_TARGET))
-
-
-class GetFilesCoveredByTargetTest(unittest.TestCase):
- """Tests get_files_covered_by_target."""
-
- def setUp(self):
- with mock.patch('coverage._get_latest_cov_report_info',
- return_value=PROJECT_COV_INFO):
- self.coverage_getter = coverage.OssFuzzCoverageGetter(
- PROJECT_NAME, REPO_PATH)
-
- def test_valid_target(self):
- """Tests that covered files can be retrieved from a coverage report."""
- with open(os.path.join(TEST_DATA_PATH,
- FUZZ_TARGET_COV_JSON_FILENAME),) as file_handle:
- fuzzer_cov_info = json.loads(file_handle.read())
-
- with mock.patch('coverage.OssFuzzCoverageGetter.get_target_coverage_report',
- return_value=fuzzer_cov_info):
- file_list = self.coverage_getter.get_files_covered_by_target(FUZZ_TARGET)
-
- curl_files_list_path = os.path.join(TEST_DATA_PATH,
- 'example_curl_file_list.json')
- with open(curl_files_list_path) as file_handle:
- expected_file_list = json.loads(file_handle.read())
- self.assertCountEqual(file_list, expected_file_list)
-
- def test_invalid_target(self):
- """Tests passing invalid fuzz target returns None."""
- self.assertIsNone(
- self.coverage_getter.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(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(coverage.is_file_covered(file_coverage))
-
-
-class GetLatestCovReportInfo(unittest.TestCase):
- """Tests that _get_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('coverage.get_json_from_url', return_value={'coverage': 1})
- def test_get_latest_cov_report_info(self, mocked_get_json_from_url,
- mocked_error):
- """Tests that _get_latest_cov_report_info works as intended."""
- result = coverage._get_latest_cov_report_info(self.PROJECT)
- self.assertEqual(result, {'coverage': 1})
- mocked_error.assert_not_called()
- mocked_get_json_from_url.assert_called_with(self.LATEST_REPORT_INFO_URL)
-
- @mock.patch('logging.error')
- @mock.patch('coverage.get_json_from_url', return_value=None)
- def test_get_latest_cov_report_info_fail(self, _, mocked_error):
- """Tests that _get_latest_cov_report_info works as intended when we can't
- get latest report info."""
- result = coverage._get_latest_cov_report_info('project')
- self.assertIsNone(result)
- mocked_error.assert_called_with(
- 'Could not get the coverage report json from url: %s.',
- self.LATEST_REPORT_INFO_URL)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/infra/cifuzz/docker.py b/infra/cifuzz/docker.py
index eb993e28d..935773d92 100644
--- a/infra/cifuzz/docker.py
+++ b/infra/cifuzz/docker.py
@@ -12,23 +12,52 @@
# 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
# pylint: disable=wrong-import-position,import-error
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import constants
import utils
BASE_BUILDER_TAG = 'gcr.io/oss-fuzz-base/base-builder'
-BASE_RUNNER_TAG = 'gcr.io/oss-fuzz-base/base-runner'
-MSAN_LIBS_BUILDER_TAG = 'gcr.io/oss-fuzz-base/msan-libs-builder'
PROJECT_TAG_PREFIX = 'gcr.io/oss-fuzz/'
+# Default fuzz configuration.
+_DEFAULT_DOCKER_RUN_ARGS = [
+ '--cap-add', 'SYS_PTRACE', '-e',
+ 'FUZZING_ENGINE=' + constants.DEFAULT_ENGINE, '-e',
+ 'ARCHITECTURE=' + constants.DEFAULT_ARCHITECTURE, '-e', 'CIFUZZ=True'
+]
+
+EXTERNAL_PROJECT_IMAGE = 'external-project'
+
+_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|."""
- return PROJECT_TAG_PREFIX + project
+ # TODO(ochang): We may need unique names to support parallel fuzzing.
+ if project:
+ return PROJECT_TAG_PREFIX + project
+
+ return EXTERNAL_PROJECT_IMAGE
def delete_images(images):
@@ -36,3 +65,49 @@ def delete_images(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,
+ 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,
+ 'FUZZING_LANGUAGE': language,
+ 'OUT': workspace.out
+ }
+ docker_args += get_docker_env_vars(env_mapping)
+ docker_container = 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,
+ 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, 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}']
diff --git a/infra/cifuzz/docker_test.py b/infra/cifuzz/docker_test.py
new file mode 100644
index 000000000..b356138cb
--- /dev/null
+++ b/infra/cifuzz/docker_test.py
@@ -0,0 +1,122 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 = [
+ '--cap-add',
+ 'SYS_PTRACE',
+ '-e',
+ 'FUZZING_ENGINE=libfuzzer',
+ '-e',
+ 'ARCHITECTURE=x86_64',
+ '-e',
+ 'CIFUZZ=True',
+ '-e',
+ f'SANITIZER={SANITIZER}',
+ '-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 = [
+ '--cap-add', 'SYS_PTRACE', '-e', 'FUZZING_ENGINE=libfuzzer', '-e',
+ 'ARCHITECTURE=x86_64', '-e', 'CIFUZZ=True', '-e',
+ f'SANITIZER={SANITIZER}', '-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', '--cap-add', 'SYS_PTRACE',
+ '-e', 'FUZZING_ENGINE=libfuzzer', '-e', 'ARCHITECTURE=x86_64', '-e',
+ 'CIFUZZ=True', '-e', f'SANITIZER={SANITIZER}', '-e',
+ f'FUZZING_LANGUAGE={LANGUAGE}', '-e', f'OUT={WORKSPACE.out}', '-v',
+ f'{WORKSPACE.workspace}:{WORKSPACE.workspace}'
+ ]
+ self.assertEqual(docker_args, expected_docker_command)
diff --git a/infra/cifuzz/environment.py b/infra/cifuzz/environment.py
index 4cc0f846b..e99a67910 100644
--- a/infra/cifuzz/environment.py
+++ b/infra/cifuzz/environment.py
@@ -46,9 +46,6 @@ def get_bool(env_var, default_value=None):
lower_value = value.lower()
allowed_values = {'true', 'false'}
if lower_value not in allowed_values:
- raise Exception(('Bool env var {env_var} value {value} is invalid. '
- 'Must be one of {allowed_values}').format(
- env_var=env_var,
- value=value,
- allowed_values=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'
diff --git a/infra/cifuzz/external-actions/build_fuzzers/action.yml b/infra/cifuzz/external-actions/build_fuzzers/action.yml
new file mode 100644
index 000000000..f45d02e20
--- /dev/null
+++ b/infra/cifuzz/external-actions/build_fuzzers/action.yml
@@ -0,0 +1,63 @@
+# 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
+ 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
+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 }}
diff --git a/infra/cifuzz/external-actions/run_fuzzers/action.yml b/infra/cifuzz/external-actions/run_fuzzers/action.yml
new file mode 100644
index 000000000..cdefb5675
--- /dev/null
+++ b/infra/cifuzz/external-actions/run_fuzzers/action.yml
@@ -0,0 +1,69 @@
+# 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'
+ run-fuzzers-mode:
+ description: |
+ The mode to run the fuzzers with ("ci" or "batch").
+ "ci" is for fuzzing a pull request or commit.
+ "batch" is for non-interactive fuzzing of an entire project.
+ "batch" is in alpha and should not be used in production.
+ required: false
+ default: 'ci'
+ 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 by CIFuzz.'
+ required: false
+ default: false
+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 }}
+ RUN_FUZZERS_MODE: ${{ inputs.run-fuzzers-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 }}
diff --git a/infra/cifuzz/filestore/__init__.py b/infra/cifuzz/filestore/__init__.py
new file mode 100644
index 000000000..d112f7b8c
--- /dev/null
+++ b/infra/cifuzz/filestore/__init__.py
@@ -0,0 +1,54 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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, dst_directory):
+ """Downloads the latest project coverage report."""
+ raise NotImplementedError('Child class must implement method.')
diff --git a/infra/cifuzz/filestore/git/__init__.py b/infra/cifuzz/filestore/git/__init__.py
new file mode 100644
index 000000000..5414003da
--- /dev/null
+++ b/infra/cifuzz/filestore/git/__init__.py
@@ -0,0 +1,159 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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."""
+
+from distutils import dir_util
+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
+_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)
+
+ 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)
+
+ dir_util.copy_tree(local_path, full_repo_path)
+ 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
+
+ dir_util.copy_tree(path, dst_directory)
+ 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
+
+ dir_util.copy_tree(path, dst_directory)
+ return True
diff --git a/infra/cifuzz/filestore/git/git_test.py b/infra/cifuzz/filestore/git/git_test.py
new file mode 100644
index 000000000..56be23bac
--- /dev/null
+++ b/infra/cifuzz/filestore/git/git_test.py
@@ -0,0 +1,122 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
diff --git a/infra/cifuzz/filestore/github_actions/__init__.py b/infra/cifuzz/filestore/github_actions/__init__.py
new file mode 100644
index 000000000..3b03f9c0b
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/__init__.py
@@ -0,0 +1,177 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+sys.path.append(
+ os.path.join(os.path.pardir, os.path.pardir, os.path.pardir,
+ os.path.dirname(os.path.abspath(__file__))))
+
+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)
+ 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)
diff --git a/infra/cifuzz/filestore/github_actions/github_actions_test.py b/infra/cifuzz/filestore/github_actions/github_actions_test.py
new file mode 100644
index 000000000..7745065a9
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_actions_test.py
@@ -0,0 +1,281 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+from pyfakefs import fake_filesystem_unittest
+
+# 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 github_actions
+import test_helpers
+
+# pylint: disable=protected-access,no-self-use
+
+
+class GithubActionsFilestoreTest(fake_filesystem_unittest.TestCase):
+ """Tests for GithubActionsFilestore."""
+
+ def setUp(self):
+ 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'
+ self.config = test_helpers.create_run_config(token=self.token)
+ self.local_dir = '/local-dir'
+ self.testcase = os.path.join(self.local_dir, 'testcase')
+
+ 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 = '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):
+ self.fs.create_file(archive_path)
+
+ 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', ['/local-dir/testcase'], '/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):
+ self.fs.create_file(archive_path)
+
+ 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):
+ self.fs.create_file(archive_path)
+
+ 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):
+ """Sets up pyfakefs and creates a corpus directory containing
+ self.testcase."""
+ self.setUpPyfakefs()
+ self.fs.create_file(self.testcase, contents='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))
diff --git a/infra/cifuzz/filestore/github_actions/github_api.py b/infra/cifuzz/filestore/github_actions/github_api.py
new file mode 100644
index 000000000..191b75058
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_api.py
@@ -0,0 +1,108 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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|."""
+ return (f'https://api.github.com/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)
diff --git a/infra/cifuzz/filestore/github_actions/github_api_test.py b/infra/cifuzz/filestore/github_actions/github_api_test.py
new file mode 100644
index 000000000..c7cad6db0
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/github_api_test.py
@@ -0,0 +1,33 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 unittest
+
+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))
diff --git a/infra/cifuzz/filestore/github_actions/upload.js b/infra/cifuzz/filestore/github_actions/upload.js
new file mode 100755
index 000000000..cd025e560
--- /dev/null
+++ b/infra/cifuzz/filestore/github_actions/upload.js
@@ -0,0 +1,33 @@
+#!/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 <aritfactName> <rootDirectory> <file 1>...<file N>
+
+const fs = require('fs');
+const artifact = require('@actions/artifact');
+const artifactClient = artifact.create()
+const artifactName = process.argv[2];
+const rootDirectory = process.argv[3]
+const files = process.argv.slice(4);
+const options = {
+ continueOnError: true
+}
+
+const uploadResult = artifactClient.uploadArtifact(artifactName, files, rootDirectory, options)
+console.log(uploadResult);
+if (uploadResult['failedItems']) {
+ return 1;
+}
+return 0;
diff --git a/infra/cifuzz/filestore_utils.py b/infra/cifuzz/filestore_utils.py
new file mode 100644
index 000000000..d3aaecd82
--- /dev/null
+++ b/infra/cifuzz/filestore_utils.py
@@ -0,0 +1,31 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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.git
+import filestore.github_actions
+
+
+def get_filestore(config):
+ """Returns the correct filestore based on the platform in |config|.
+ Raises an exception if there is no correct filestore for the platform."""
+ # TODO(metzman): Force specifying of filestore.
+ 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)
+
+ raise filestore.FilestoreError('Filestore doesn\'t support platform.')
diff --git a/infra/cifuzz/filestore_utils_test.py b/infra/cifuzz/filestore_utils_test.py
new file mode 100644
index 000000000..db5fc5bc1
--- /dev/null
+++ b/infra/cifuzz/filestore_utils_test.py
@@ -0,0 +1,50 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 config_utils
+import filestore
+from filestore import github_actions
+import filestore_utils
+import test_helpers
+
+
+class GetFilestoreTest(unittest.TestCase):
+ """Tests for get_filestore."""
+
+ @parameterized.parameterized.expand([
+ ({
+ 'is_github': True,
+ }, 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_ci_environment',
+ return_value=config_utils.GenericCiEnvironment())
+ 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)
diff --git a/infra/cifuzz/fuzz_target.py b/infra/cifuzz/fuzz_target.py
index c623bf60d..ae92b14c9 100644
--- a/infra/cifuzz/fuzz_target.py
+++ b/infra/cifuzz/fuzz_target.py
@@ -15,17 +15,13 @@
import collections
import logging
import os
-import re
import shutil
import stat
-import subprocess
-import sys
-import docker
+import clusterfuzz.environment
+import clusterfuzz.fuzz
-# pylint: disable=wrong-import-position,import-error
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-import utils
+import config_utils
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
@@ -33,46 +29,59 @@ logging.basicConfig(
# Use a fixed seed for determinism. Use len_control=0 since we don't have enough
# time fuzzing for len_control to make sense (probably).
-LIBFUZZER_OPTIONS = '-seed=1337 -len_control=0'
+LIBFUZZER_OPTIONS = ['-seed=1337', '-len_control=0']
# The number of reproduce attempts for a crash.
REPRODUCE_ATTEMPTS = 10
+REPRODUCE_TIME_SECONDS = 30
+
# 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_RECENT_MESSAGE = (
- 'Crash is reproducible. Could not run recent build of '
- 'target to determine if this code change (pr/commit) introduced crash. '
- 'Assuming this code change introduced crash.')
+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'])
+FuzzResult = collections.namedtuple('FuzzResult',
+ ['testcase', 'stacktrace', 'corpus_path'])
class ReproduceError(Exception):
"""Error for when we can't attempt to reproduce a crash."""
-class FuzzTarget:
+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.
- out_dir: The location of where output artifacts are stored.
+ workspace: The workspace for storing things related to fuzzing.
"""
# pylint: disable=too-many-arguments
- def __init__(self, target_path, duration, out_dir, clusterfuzz_deployment,
+ 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.
- out_dir: The location of where the output from crashes should be stored.
+ workspace: The path used for storing things needed for fuzzing.
clusterfuzz_deployment: The object representing the ClusterFuzz
deployment.
config: The config of this project.
@@ -80,10 +89,39 @@ class FuzzTarget:
self.target_path = target_path
self.target_name = os.path.basename(self.target_path)
self.duration = int(duration)
- self.out_dir = out_dir
+ self.workspace = workspace
self.clusterfuzz_deployment = clusterfuzz_deployment
self.config = config
- self.latest_corpus_path = None
+ 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 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,
+ interactive=True):
+ 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.workspace.artifacts,
+ self.duration)
+
+ return FuzzResult(None, result.logs, self.pruned_corpus_path)
def fuzz(self):
"""Starts the fuzz target run for the length of time specified by duration.
@@ -91,85 +129,65 @@ class FuzzTarget:
Returns:
FuzzResult namedtuple with stacktrace and testcase if applicable.
"""
- logging.info('Fuzzer %s, started.', self.target_name)
- docker_container = utils.get_container_name()
- command = ['docker', 'run', '--rm', '--privileged']
- if docker_container:
- command += [
- '--volumes-from', docker_container, '-e', 'OUT=' + self.out_dir
- ]
- else:
- command += ['-v', '%s:%s' % (self.out_dir, '/out')]
-
- command += [
- '-e', 'FUZZING_ENGINE=libfuzzer', '-e',
- 'SANITIZER=' + self.config.sanitizer, '-e', 'CIFUZZ=True', '-e',
- 'RUN_FUZZER_MODE=interactive', docker.BASE_RUNNER_TAG, 'bash', '-c'
- ]
-
- run_fuzzer_command = 'run_fuzzer {fuzz_target} {options}'.format(
- fuzz_target=self.target_name,
- options=LIBFUZZER_OPTIONS + ' -max_total_time=' + str(self.duration))
-
- # If corpus can be downloaded use it for fuzzing.
- self.latest_corpus_path = self.clusterfuzz_deployment.download_corpus(
- self.target_name, self.out_dir)
- if self.latest_corpus_path:
- run_fuzzer_command = run_fuzzer_command + ' ' + self.latest_corpus_path
- command.append(run_fuzzer_command)
-
- logging.info('Running command: %s', ' '.join(command))
- process = subprocess.Popen(command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ logging.info('Running fuzzer: %s.', self.target_name)
- try:
- _, stderr = process.communicate(timeout=self.duration + BUFFER_TIME)
- except subprocess.TimeoutExpired:
- logging.error('Fuzzer %s timed out, ending fuzzing.', self.target_name)
- return FuzzResult(None, None)
+ self._download_corpus()
+ corpus_path = self.latest_corpus_path
+
+ logging.info('Starting fuzzing')
+ with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+ self.config.sanitizer,
+ self.target_path,
+ interactive=True) 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
+ options.arguments.extend(LIBFUZZER_OPTIONS)
+
+ result = engine_impl.fuzz(self.target_path, options,
+ self.workspace.artifacts, self.duration)
# Libfuzzer timeout was reached.
- if not process.returncode:
+ if not result.crashes:
logging.info('Fuzzer %s finished with no crashes discovered.',
self.target_name)
- return FuzzResult(None, None)
-
- # Crash was discovered.
- logging.info('Fuzzer %s, ended before timeout.', self.target_name)
- testcase = self.get_testcase(stderr)
- if not testcase:
- logging.error(b'No testcase found in stacktrace: %s.', stderr)
- return FuzzResult(None, None)
-
- utils.binary_print(b'Fuzzer: %s. Detected bug:\n%s' %
- (self.target_name.encode(), stderr))
- if self.is_crash_reportable(testcase):
+ return FuzzResult(None, None, self.latest_corpus_path)
+
+ # Only report first crash.
+ crash = result.crashes[0]
+ logging.info('Fuzzer: %s. Detected bug:\n%s', self.target_name,
+ crash.stacktrace)
+
+ if self.is_crash_reportable(crash.input_path):
# We found a bug in the fuzz target and we will report it.
- return FuzzResult(testcase, stderr)
+ return FuzzResult(crash.input_path, result.logs, self.latest_corpus_path)
# We found a bug but we won't report it.
- return FuzzResult(None, None)
+ return FuzzResult(None, None, self.latest_corpus_path)
- def free_disk_if_needed(self):
+ 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, seed corpus and fuzz target of %s to save disk.',
- self.target_name)
+ logging.info('Deleting corpus and seed corpus of %s to save disk.',
+ self.target_name)
# Delete the seed corpus, corpus, and fuzz target.
- if self.latest_corpus_path and os.path.exists(self.latest_corpus_path):
+ 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(self.latest_corpus_path, ignore_errors=True)
+ shutil.rmtree(corpus_path, ignore_errors=True)
- os.remove(self.target_path)
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):
@@ -186,41 +204,31 @@ class FuzzTarget:
Raises:
ReproduceError if we can't attempt to reproduce the crash.
"""
-
if not os.path.exists(target_path):
- raise ReproduceError('Target %s not found.' % 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)
- target_dirname = os.path.dirname(target_path)
- command = ['docker', 'run', '--rm', '--privileged']
- container = utils.get_container_name()
- if container:
- command += [
- '--volumes-from', container, '-e', 'OUT=' + target_dirname, '-e',
- 'TESTCASE=' + testcase
- ]
- else:
- command += [
- '-v',
- '%s:/out' % target_dirname, '-v',
- '%s:/testcase' % testcase
- ]
-
- command += [
- '-t', docker.BASE_RUNNER_TAG, 'reproduce', self.target_name, '-runs=100'
- ]
-
- logging.info('Running reproduce command: %s.', ' '.join(command))
- for _ in range(REPRODUCE_ATTEMPTS):
- _, _, returncode = utils.execute(command)
- if returncode != 0:
- logging.info('Reproduce command returned: %s. Reproducible on %s.',
- returncode, target_path)
-
- return True
-
- logging.info('Reproduce command returned 0. Not reproducible on %s.',
+ logging.info('Trying to reproduce crash using: %s.', testcase)
+ with clusterfuzz.environment.Environment(config_utils.DEFAULT_ENGINE,
+ self.config.sanitizer,
+ target_path,
+ interactive=True):
+ for _ in range(REPRODUCE_ATTEMPTS):
+ engine_impl = clusterfuzz.fuzz.get_engine(config_utils.DEFAULT_ENGINE)
+ result = engine_impl.reproduce(target_path,
+ testcase,
+ arguments=[],
+ max_time=REPRODUCE_TIME_SECONDS)
+
+ 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
@@ -239,60 +247,52 @@ class FuzzTarget:
ReproduceError if we can't attempt to reproduce the crash on the PR build.
"""
if not os.path.exists(testcase):
- raise ReproduceError('Testcase %s not found.' % testcase)
+ raise ReproduceError(f'Testcase {testcase} not found.')
try:
reproducible_on_code_change = self.is_reproducible(
testcase, self.target_path)
except ReproduceError as error:
- logging.error('Could not run target when checking for reproducibility.'
+ 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('Failed to reproduce the crash using the obtained testcase.')
- return False
+ logging.info('Crash is not reproducible.')
+ return self.config.report_unreproducible_crashes
- clusterfuzz_build_dir = self.clusterfuzz_deployment.download_latest_build(
- self.out_dir)
+ logging.info('Crash is reproducible.')
+ return self.is_crash_novel(testcase)
+
+ def is_crash_novel(self, testcase):
+ """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_RECENT_MESSAGE)
+ 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)
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_RECENT_MESSAGE)
+ logging.info(COULD_NOT_TEST_ON_CLUSTERFUZZ_MESSAGE)
return True
- if not reproducible_on_clusterfuzz_build:
- logging.info('The crash is reproducible. The crash doesn\'t reproduce '
- 'on old builds. This code change probably introduced the '
- 'crash.')
- return True
-
- logging.info('The crash is reproducible on old builds '
- '(without the current code change).')
- return False
-
- def get_testcase(self, error_bytes):
- """Gets the file from a fuzzer run stacktrace.
-
- Args:
- error_bytes: The bytes containing the output from the fuzzer.
-
- Returns:
- The path to the testcase or None if not found.
- """
- match = re.search(rb'\bTest unit written to \.\/([^\s]+)', error_bytes)
- if match:
- return os.path.join(self.out_dir, match.group(1).decode('utf-8'))
- return None
+ 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
diff --git a/infra/cifuzz/fuzz_target_test.py b/infra/cifuzz/fuzz_target_test.py
index 8bec234dc..ecea6fbbf 100644
--- a/infra/cifuzz/fuzz_target_test.py
+++ b/infra/cifuzz/fuzz_target_test.py
@@ -18,12 +18,18 @@ 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 config_utils
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.
@@ -32,153 +38,118 @@ EXAMPLE_PROJECT = 'example'
# An example fuzzer that triggers an error.
EXAMPLE_FUZZER = 'example_crash_fuzzer'
-# The return value of a successful call to utils.execute.
-EXECUTE_SUCCESS_RETVAL = ('', '', 0)
-
-# The return value of a failed call to utils.execute.
-EXECUTE_FAILURE_RETVAL = ('', '', 1)
+# Mock return values for engine_impl.reproduce.
+EXECUTE_SUCCESS_RESULT = engine.ReproduceResult([], 0, 0, '')
+EXECUTE_FAILURE_RESULT = engine.ReproduceResult([], 1, 0, '')
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 = {'is_github': True, 'project_name': EXAMPLE_PROJECT}
+ defaults = {
+ 'is_github': True,
+ '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
- with mock.patch('os.path.basename', return_value=None), mock.patch(
- 'config_utils.get_project_src_path',
- return_value=None), mock.patch('config_utils._is_dry_run',
- return_value=True):
- config = config_utils.RunFuzzersConfig()
-
- for key, value in kwargs.items():
- assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
- setattr(config, key, value)
- return config
+ return test_helpers.create_run_config(**kwargs)
def _create_deployment(**kwargs):
config = _create_config(**kwargs)
- return clusterfuzz_deployment.get_clusterfuzz_deployment(config)
+ workspace = workspace_utils.Workspace(config)
+ return clusterfuzz_deployment.get_clusterfuzz_deployment(config, workspace)
-# TODO(metzman): Use patch from test_libs/helpers.py in clusterfuzz so that we
-# don't need to accept this as an argument in every test method.
@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_path = '/example/path'
- self.testcase_path = '/testcase'
+ self.fuzz_target_name = 'fuzz-target'
deployment = _create_deployment()
- self.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path,
- fuzz_target.REPRODUCE_ATTEMPTS,
- '/example/outdir', deployment,
- deployment.config)
+ 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
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."""
- self._set_up_fakefs()
- all_repro = [EXECUTE_FAILURE_RETVAL] * fuzz_target.REPRODUCE_ATTEMPTS
- with mock.patch('utils.execute', side_effect=all_repro) as mocked_execute:
- result = self.test_target.is_reproducible(self.testcase_path,
- self.fuzz_target_path)
- mocked_execute.assert_called_once_with([
- 'docker', 'run', '--rm', '--privileged', '--volumes-from',
- 'container', '-e', 'OUT=/example', '-e',
- 'TESTCASE=' + self.testcase_path, '-t',
- 'gcr.io/oss-fuzz-base/base-runner', 'reproduce', 'path', '-runs=100'
- ])
+ 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, mocked_execute.call_count)
-
- def _set_up_fakefs(self):
- """Helper to setup pyfakefs and add important files to the fake
- filesystem."""
- self.setUpPyfakefs()
- self.fs.create_file(self.fuzz_target_path)
- self.fs.create_file(self.testcase_path)
+ 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."""
- self._set_up_fakefs()
- last_time_repro = [EXECUTE_SUCCESS_RETVAL] * 9 + [EXECUTE_FAILURE_RETVAL]
- with mock.patch('utils.execute',
- side_effect=last_time_repro) as mocked_execute:
+ 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.test_target.is_reproducible(self.testcase_path,
- self.fuzz_target_path))
+ self.target.is_reproducible(self.testcase_path,
+ self.fuzz_target_path))
self.assertEqual(fuzz_target.REPRODUCE_ATTEMPTS,
- mocked_execute.call_count)
+ 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.test_target.is_reproducible(self.testcase_path, '/non-existent-path')
+ 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_RETVAL] * fuzz_target.REPRODUCE_ATTEMPTS
- self._set_up_fakefs()
- with mock.patch('utils.execute', side_effect=all_unrepro):
- result = self.test_target.is_reproducible(self.testcase_path,
- self.fuzz_target_path)
+ 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 GetTestCaseTest(unittest.TestCase):
- """Tests get_testcase."""
-
- def setUp(self):
- """Sets up example fuzz target to test get_testcase method."""
- deployment = _create_deployment()
- self.test_target = fuzz_target.FuzzTarget('/example/path', 10,
- '/example/outdir', deployment,
- deployment.config)
-
- def test_valid_error_string(self):
- """Tests that get_testcase returns the correct testcase give an error."""
- testcase_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
- 'test_data', 'example_crash_fuzzer_output.txt')
- with open(testcase_path, 'rb') as test_fuzz_output:
- parsed_testcase = self.test_target.get_testcase(test_fuzz_output.read())
- self.assertEqual(
- parsed_testcase,
- '/example/outdir/crash-ad6700613693ef977ff3a8c8f4dae239c3dde6f5')
-
- def test_invalid_error_string(self):
- """Tests that get_testcase returns None with a bad error string."""
- self.assertIsNone(self.test_target.get_testcase(b''))
- self.assertIsNone(self.test_target.get_testcase(b' Example crash string.'))
-
- def test_encoding(self):
- """Tests that get_testcase accepts bytes and returns a string."""
- fuzzer_output = b'\x8fTest unit written to ./crash-1'
- result = self.test_target.get_testcase(fuzzer_output)
- self.assertTrue(isinstance(result, str))
-
-
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.test_target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100,
- '/example/outdir', deployment,
- deployment.config)
+ self.target = fuzz_target.FuzzTarget(self.fuzz_target_path, 100,
+ deployment.workspace, deployment,
+ deployment.config)
self.oss_fuzz_build_path = '/oss-fuzz-build'
- self.setUpPyfakefs()
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))
@@ -186,18 +157,20 @@ class IsCrashReportableTest(fake_filesystem_unittest.TestCase):
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, mocked_info, _):
+ def test_new_reproducible_crash(self, mock_info, _):
"""Tests that a new reproducible crash returns True."""
with tempfile.TemporaryDirectory() as tmp_dir:
- self.test_target.out_dir = tmp_dir
- self.assertTrue(self.test_target.is_crash_reportable(self.testcase_path))
- mocked_info.assert_called_with(
- 'The crash is reproducible. The crash doesn\'t reproduce '
- 'on old builds. This code change probably introduced the '
- 'crash.')
+ 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([
@@ -218,12 +191,11 @@ class IsCrashReportableTest(fake_filesystem_unittest.TestCase):
side_effect=is_reproducible_retvals):
with mock.patch('clusterfuzz_deployment.OSSFuzz.download_latest_build',
return_value=self.oss_fuzz_build_path):
- self.assertFalse(
- self.test_target.is_crash_reportable(self.testcase_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, _, mocked_info):
+ 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)."""
@@ -236,17 +208,16 @@ class IsCrashReportableTest(fake_filesystem_unittest.TestCase):
with mock.patch(
'fuzz_target.FuzzTarget.is_reproducible',
- side_effect=is_reproducible_side_effect) as mocked_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.test_target.is_crash_reportable(
- self.testcase_path))
- mocked_is_reproducible.assert_any_call(self.testcase_path,
- self.oss_fuzz_target_path)
- mocked_info.assert_called_with(
- 'Crash is reproducible. Could not run recent build of '
- 'target to determine if this code change (pr/commit) introduced crash. '
- 'Assuming this code change introduced crash.')
+ 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.')
if __name__ == '__main__':
diff --git a/infra/cifuzz/generate_coverage_report.py b/infra/cifuzz/generate_coverage_report.py
new file mode 100644
index 000000000..9901c452a
--- /dev/null
+++ b/infra/cifuzz/generate_coverage_report.py
@@ -0,0 +1,48 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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()
diff --git a/infra/cifuzz/generate_coverage_report_test.py b/infra/cifuzz/generate_coverage_report_test.py
new file mode 100644
index 000000000..df2c9b206
--- /dev/null
+++ b/infra/cifuzz/generate_coverage_report_test.py
@@ -0,0 +1,71 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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)
diff --git a/infra/cifuzz/coverage.py b/infra/cifuzz/get_coverage.py
index 9a179c59d..b4b2d25d6 100644
--- a/infra/cifuzz/coverage.py
+++ b/infra/cifuzz/get_coverage.py
@@ -12,57 +12,44 @@
# 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 json
-import urllib.error
-import urllib.request
+
+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 project's latest report json file.
-LATEST_REPORT_INFO_PATH = 'oss-fuzz-coverage/latest_report_info/'
+# The path to get OSS-Fuzz project's latest report json file.`
+OSS_FUZZ_LATEST_COVERAGE_INFO_PATH = 'oss-fuzz-coverage/latest_report_info/'
-class OssFuzzCoverageGetter:
- """Gets coverage data for a project from OSS-Fuzz."""
+# pylint: disable=too-few-public-methods
+class CoverageError(Exception):
+ """Exceptions for project coverage."""
- def __init__(self, project_name, repo_path):
- """Constructor for OssFuzzCoverageGetter. Callers should check that
- fuzzer_stats_url is initialized."""
- self.project_name = project_name
- self.repo_path = _normalize_repo_path(repo_path)
- self.fuzzer_stats_url = _get_fuzzer_stats_dir_url(self.project_name)
- def get_target_coverage_report(self, target):
- """Get the coverage report for a specific fuzz target.
+class BaseCoverage:
+ """Gets coverage data for a project."""
- 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 get_json_from_url(target_url)
+ def __init__(self, repo_path):
+ self.repo_path = _normalize_repo_path(repo_path)
def get_files_covered_by_target(self, target):
- """Gets a list of source files covered by the specific fuzz 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 targets covers or None.
+ A list of files that the fuzz target covers or None.
"""
- target_cov = self.get_target_coverage_report(target)
+ 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)
@@ -88,33 +75,53 @@ class OssFuzzCoverageGetter:
return affected_file_list
+ def get_target_coverage(self, target):
+ """Get the coverage report for a specific fuzz target.
-def is_file_covered(file_cov):
- """Returns whether the file is covered."""
- return file_cov['summary']['regions']['covered']
+ 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.')
-def get_coverage_per_file(target_cov):
- """Returns the coverage per file within |target_cov|."""
- return target_cov['data'][0]['files']
+class OSSFuzzCoverage(BaseCoverage):
+ """Gets coverage data for a project from OSS-Fuzz."""
-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
+ 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.
-def _get_latest_cov_report_info(project_name):
+ 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,
- LATEST_REPORT_INFO_PATH,
- project_name + '.json')
- latest_cov_info = get_json_from_url(latest_report_info_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)
@@ -122,16 +129,17 @@ def _get_latest_cov_report_info(project_name):
return latest_cov_info
-def _get_fuzzer_stats_dir_url(project_name):
- """Gets latest coverage report info for a specific OSS-Fuzz project from GCS.
+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:
- project_name: The name of the relevant OSS-Fuzz project.
+ 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_latest_cov_report_info(project_name)
+ latest_cov_info = _get_oss_fuzz_latest_cov_report_info(oss_fuzz_project_name)
if not latest_cov_info:
return None
@@ -145,25 +153,52 @@ def _get_fuzzer_stats_dir_url(project_name):
return fuzzer_stats_dir_url
-def get_json_from_url(url):
- """Gets a json object from a specified HTTP URL.
+class FilesystemCoverage(BaseCoverage):
+ """Class that gets a project's coverage from the filesystem."""
- Args:
- url: The url of the json to be downloaded.
+ def __init__(self, repo_path, project_coverage_dir):
+ super().__init__(repo_path)
+ self.project_coverage_dir = project_coverage_dir
- Returns:
- A dictionary deserialized from JSON or None on failure.
- """
- try:
- response = urllib.request.urlopen(url)
- except urllib.error.HTTPError:
- logging.error('HTTP error with url %s.', url)
- return None
+ def get_target_coverage(self, target):
+ """Get the coverage report for a specific fuzz target.
- try:
- # read().decode() fixes compatibility issue with urllib response object.
- result_json = json.loads(response.read().decode())
- except (ValueError, TypeError, json.JSONDecodeError) as err:
- logging.error('Loading json from url %s failed with: %s.', url, str(err))
- return None
- return result_json
+ 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|."""
+ return target_cov['data'][0]['files']
+
+
+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
diff --git a/infra/cifuzz/get_coverage_test.py b/infra/cifuzz/get_coverage_test.py
new file mode 100644
index 000000000..fcfc9bd25
--- /dev/null
+++ b/infra/cifuzz/get_coverage_test.py
@@ -0,0 +1,239 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+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)
+
+ 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()
diff --git a/infra/cifuzz/http_utils.py b/infra/cifuzz/http_utils.py
new file mode 100644
index 000000000..931183593
--- /dev/null
+++ b/infra/cifuzz/http_utils.py
@@ -0,0 +1,117 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+
+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.
+ """
+ response = requests.get(url)
+ try:
+ return response.json()
+ except (ValueError, TypeError, json.JSONDecodeError) 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
diff --git a/infra/cifuzz/http_utils_test.py b/infra/cifuzz/http_utils_test.py
new file mode 100644
index 000000000..64d0598ac
--- /dev/null
+++ b/infra/cifuzz/http_utils_test.py
@@ -0,0 +1,71 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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'))
diff --git a/infra/cifuzz/package-lock.json b/infra/cifuzz/package-lock.json
new file mode 100644
index 000000000..9ee58404c
--- /dev/null
+++ b/infra/cifuzz/package-lock.json
@@ -0,0 +1,316 @@
+{
+ "name": "cifuzz",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "version": "1.0.0",
+ "license": "Apache2",
+ "dependencies": {
+ "@actions/artifact": "^0.5.2"
+ }
+ },
+ "node_modules/@actions/artifact": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-0.5.2.tgz",
+ "integrity": "sha512-q/r8WSqyxBJ0ffLCRrtjCBTGnAYqP+ID4yG7f7YSlhrQ4thNg/d+Tq9f1YkLPKX46ZR97OWtGDY+oU/nxcqvLw==",
+ "dependencies": {
+ "@actions/core": "^1.2.6",
+ "@actions/http-client": "^1.0.11",
+ "@types/tmp": "^0.1.0",
+ "tmp": "^0.1.0",
+ "tmp-promise": "^2.0.2"
+ }
+ },
+ "node_modules/@actions/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
+ "dependencies": {
+ "@actions/http-client": "^1.0.11"
+ }
+ },
+ "node_modules/@actions/http-client": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
+ "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
+ "dependencies": {
+ "tunnel": "0.0.6"
+ }
+ },
+ "node_modules/@types/tmp": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz",
+ "integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA=="
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
+ "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
+ "dependencies": {
+ "rimraf": "^2.6.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tmp-promise": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.1.1.tgz",
+ "integrity": "sha512-Z048AOz/w9b6lCbJUpevIJpRpUztENl8zdv1bmAKVHimfqRFl92ROkmT9rp7TVBnrEw2gtMTol/2Cp2S2kJa4Q==",
+ "dependencies": {
+ "tmp": "0.1.0"
+ }
+ },
+ "node_modules/tunnel": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+ "engines": {
+ "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ },
+ "dependencies": {
+ "@actions/artifact": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-0.5.2.tgz",
+ "integrity": "sha512-q/r8WSqyxBJ0ffLCRrtjCBTGnAYqP+ID4yG7f7YSlhrQ4thNg/d+Tq9f1YkLPKX46ZR97OWtGDY+oU/nxcqvLw==",
+ "requires": {
+ "@actions/core": "^1.2.6",
+ "@actions/http-client": "^1.0.11",
+ "@types/tmp": "^0.1.0",
+ "tmp": "^0.1.0",
+ "tmp-promise": "^2.0.2"
+ }
+ },
+ "@actions/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
+ "requires": {
+ "@actions/http-client": "^1.0.11"
+ }
+ },
+ "@actions/http-client": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
+ "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
+ "requires": {
+ "tunnel": "0.0.6"
+ }
+ },
+ "@types/tmp": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.1.0.tgz",
+ "integrity": "sha512-6IwZ9HzWbCq6XoQWhxLpDjuADodH/MKXRUIDFudvgjcVdjFknvmR+DNsoUeer4XPrEnrZs04Jj+kfV9pFsrhmA=="
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "tmp": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
+ "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
+ "requires": {
+ "rimraf": "^2.6.3"
+ }
+ },
+ "tmp-promise": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.1.1.tgz",
+ "integrity": "sha512-Z048AOz/w9b6lCbJUpevIJpRpUztENl8zdv1bmAKVHimfqRFl92ROkmT9rp7TVBnrEw2gtMTol/2Cp2S2kJa4Q==",
+ "requires": {
+ "tmp": "0.1.0"
+ }
+ },
+ "tunnel": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ }
+ }
+}
diff --git a/infra/cifuzz/package.json b/infra/cifuzz/package.json
new file mode 100644
index 000000000..5823747dd
--- /dev/null
+++ b/infra/cifuzz/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "cifuzz",
+ "version": "1.0.0",
+ "description": "",
+ "author": "Google",
+ "license": "Apache2",
+ "dependencies": {
+ "@actions/artifact": "^0.5.2"
+ }
+}
diff --git a/infra/cifuzz/requirements.txt b/infra/cifuzz/requirements.txt
new file mode 100644
index 000000000..270c15547
--- /dev/null
+++ b/infra/cifuzz/requirements.txt
@@ -0,0 +1,2 @@
+clusterfuzz==2.5.6
+requests==2.25.1
diff --git a/infra/cifuzz/run_cifuzz.py b/infra/cifuzz/run_cifuzz.py
new file mode 100644
index 000000000..0382d78a8
--- /dev/null
+++ b/infra/cifuzz/run_cifuzz.py
@@ -0,0 +1,88 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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'
+ ]
+ 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())
diff --git a/infra/cifuzz/run_fuzzers.py b/infra/cifuzz/run_fuzzers.py
index 513cfb6fa..67c4c66fd 100644
--- a/infra/cifuzz/run_fuzzers.py
+++ b/infra/cifuzz/run_fuzzers.py
@@ -21,7 +21,9 @@ import time
import clusterfuzz_deployment
import fuzz_target
+import generate_coverage_report
import stack_parser
+import workspace_utils
# pylint: disable=wrong-import-position,import-error
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
@@ -41,12 +43,17 @@ class BaseFuzzTargetRunner:
def __init__(self, config):
self.config = config
+ self.workspace = workspace_utils.Workspace(config)
self.clusterfuzz_deployment = (
- clusterfuzz_deployment.get_clusterfuzz_deployment(self.config))
+ clusterfuzz_deployment.get_clusterfuzz_deployment(
+ self.config, self.workspace))
+
# Set by the initialize method.
- self.out_dir = None
self.fuzz_target_paths = None
- self.artifacts_dir = 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.
@@ -64,55 +71,51 @@ class BaseFuzzTargetRunner:
self.config.fuzz_seconds)
return False
- self.out_dir = os.path.join(self.config.workspace, 'out')
- if not os.path.exists(self.out_dir):
- logging.error('Out directory: %s does not exist.', self.out_dir)
+ if not os.path.exists(self.workspace.out):
+ logging.error('Out directory: %s does not exist.', self.workspace.out)
return False
- self.artifacts_dir = os.path.join(self.out_dir, 'artifacts')
- if not os.path.exists(self.artifacts_dir):
- os.mkdir(self.artifacts_dir)
- elif (not os.path.isdir(self.artifacts_dir) or
- os.listdir(self.artifacts_dir)):
+ 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.artifacts_dir)
+ self.workspace.artifacts)
return False
- self.fuzz_target_paths = utils.get_fuzz_targets(self.out_dir)
+ 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.out_dir)
+ 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."""
- # TODO(metzman): Make children implement this so that the batch runner can
- # do things differently.
- result = fuzz_target_obj.fuzz()
- fuzz_target_obj.free_disk_if_needed()
- return 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')
+ raise NotImplementedError('Child class must implement method.')
def get_fuzz_target_artifact(self, target, artifact_name):
"""Returns the path of a fuzzing artifact named |artifact_name| for
|fuzz_target|."""
- artifact_name = '{target_name}-{sanitizer}-{artifact_name}'.format(
- target_name=target.target_name,
- sanitizer=self.config.sanitizer,
- artifact_name=artifact_name)
- return os.path.join(self.artifacts_dir, artifact_name)
+ artifact_name = (f'{target.target_name}-{self.config.sanitizer}-'
+ f'{artifact_name}')
+ return os.path.join(self.workspace.artifacts, artifact_name)
def create_fuzz_target_obj(self, target_path, run_seconds):
"""Returns a fuzz target object."""
- return fuzz_target.FuzzTarget(target_path, run_seconds, self.out_dir,
+ return fuzz_target.FuzzTarget(target_path, run_seconds, self.workspace,
self.clusterfuzz_deployment, self.config)
def run_fuzz_targets(self):
@@ -134,6 +137,7 @@ class BaseFuzzTargetRunner:
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.
@@ -162,6 +166,60 @@ class BaseFuzzTargetRunner:
return bug_found
+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()
+
+
+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."""
+ # 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.
+ # TOOD(metzman): Figure out if top_level_only should be the only behavior
+ # for this function.
+ return utils.get_fuzz_targets(self.workspace.out, top_level_only=True)
+
+ 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."""
@@ -169,6 +227,13 @@ class CiFuzzTargetRunner(BaseFuzzTargetRunner):
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."""
@@ -177,14 +242,42 @@ class BatchFuzzTargetRunner(BaseFuzzTargetRunner):
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()
+ 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)
+
+ def run_fuzz_targets(self):
+ result = super().run_fuzz_targets()
+ self.clusterfuzz_deployment.upload_crashes()
+ return result
+
+
+_RUN_FUZZERS_MODE_RUNNER_MAPPING = {
+ 'batch': BatchFuzzTargetRunner,
+ 'coverage': CoverageTargetRunner,
+ 'prune': PruneTargetRunner,
+ 'ci': CiFuzzTargetRunner,
+}
+
def get_fuzz_target_runner(config):
"""Returns a fuzz target runner object based on the run_fuzzers_mode of
|config|."""
- logging.info('RUN_FUZZERS_MODE is: %s', config.run_fuzzers_mode)
- if config.run_fuzzers_mode == 'batch':
- return BatchFuzzTargetRunner(config)
- return CiFuzzTargetRunner(config)
+ runner = _RUN_FUZZERS_MODE_RUNNER_MAPPING[config.run_fuzzers_mode](config)
+ logging.info('RUN_FUZZERS_MODE is: %s. Runner: %s.', config.run_fuzzers_mode,
+ runner)
+ return runner
def run_fuzzers(config): # pylint: disable=too-many-locals
diff --git a/infra/cifuzz/run_fuzzers_entrypoint.py b/infra/cifuzz/run_fuzzers_entrypoint.py
index 46e208dc0..adfd1a960 100644
--- a/infra/cifuzz/run_fuzzers_entrypoint.py
+++ b/infra/cifuzz/run_fuzzers_entrypoint.py
@@ -33,19 +33,49 @@ def delete_unneeded_docker_images(config):
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.project_name)
+ project_image = docker.get_project_image_name(config.oss_fuzz_project_name)
images = [
project_image,
- docker.BASE_RUNNER_TAG,
- docker.MSAN_LIBS_BUILDER_TAG,
+ docker.BASE_BUILDER_TAG,
+ docker.BASE_BUILDER_TAG + ':xenial',
+ docker.BASE_BUILDER_TAG + '-go',
+ docker.BASE_BUILDER_TAG + '-jvm',
+ docker.BASE_BUILDER_TAG + '-python',
+ docker.BASE_BUILDER_TAG + '-rust',
+ 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()
+ # 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 OSS-Fuzz project's fuzzers for CI tools.
+ """Runs project's fuzzers for CI tools.
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.
NOTE: libFuzzer binaries must be located in the ${GITHUB_WORKSPACE}/out
directory in order for this action to be used. This action will only fuzz the
@@ -65,32 +95,9 @@ def main():
SANITIZER: The sanitizer to use when running fuzzers.
Returns:
- 0 on success or 1 on failure.
+ 0 on success or nonzero on failure.
"""
- config = config_utils.RunFuzzersConfig()
- # 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
-
- if not config.workspace:
- logging.error('This script needs to be run within Github actions.')
- return returncode
-
- 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
+ return run_fuzzers_entrypoint()
if __name__ == '__main__':
diff --git a/infra/cifuzz/run_fuzzers_test.py b/infra/cifuzz/run_fuzzers_test.py
index b2659903c..db442b188 100644
--- a/infra/cifuzz/run_fuzzers_test.py
+++ b/infra/cifuzz/run_fuzzers_test.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for running fuzzers."""
+import json
import os
import sys
import shutil
@@ -22,7 +23,7 @@ from unittest import mock
import parameterized
from pyfakefs import fake_filesystem_unittest
-import config_utils
+import build_fuzzers
import fuzz_target
import run_fuzzers
@@ -30,6 +31,7 @@ import run_fuzzers
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
@@ -49,22 +51,6 @@ UNDEFINED_FUZZER = 'curl_fuzzer_undefined'
FUZZ_SECONDS = 10
-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."""
- with mock.patch('os.path.basename', return_value=None), mock.patch(
- 'config_utils.get_project_src_path',
- return_value=None), mock.patch('config_utils._is_dry_run',
- return_value=True):
- config = config_utils.RunFuzzersConfig()
-
- for key, value in kwargs.items():
- assert hasattr(config, key), 'Config doesn\'t have attribute: ' + key
- setattr(config, key, value)
- return config
-
-
class RunFuzzerIntegrationTestMixin: # pylint: disable=too-few-public-methods,invalid-name
"""Mixin for integration test classes that runbuild_fuzzers on builds of a
specific sanitizer."""
@@ -72,39 +58,43 @@ class RunFuzzerIntegrationTestMixin: # pylint: disable=too-few-public-methods,i
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 = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=fuzzer_dir_copy,
- project_name='curl',
- sanitizer=sanitizer)
+ 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
- @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
- 'INTEGRATION_TESTS=1 not set')
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
- @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
- 'INTEGRATION_TESTS=1 not set')
def test_run_with_undefined_sanitizer(self):
"""Tests run_fuzzers with a valid UBSAN build."""
self._test_run_with_sanitizer(self.FUZZER_DIR, 'undefined')
@@ -114,19 +104,22 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
"""Tests BaseFuzzTargetRunner."""
def _create_runner(self, **kwargs): # pylint: disable=no-self-use
- defaults = {'fuzz_seconds': FUZZ_SECONDS, 'project_name': EXAMPLE_PROJECT}
+ 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 = _create_config(**kwargs)
+ 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 mocked_error:
+ with mock.patch('logging.error') as mock_error:
runner = self._create_runner(**create_runner_kwargs)
self.assertFalse(runner.initialize())
- mocked_error.assert_called_with(*expected_error_args)
+ mock_error.assert_called_with(*expected_error_args)
@parameterized.parameterized.expand([(0,), (None,), (-1,)])
def test_initialize_invalid_fuzz_seconds(self, fuzz_seconds):
@@ -134,10 +127,10 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
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, 'out')
+ out_path = os.path.join(tmp_dir, 'build-out')
os.mkdir(out_path)
- with mock.patch('utils.get_fuzz_targets') as mocked_get_fuzz_targets:
- mocked_get_fuzz_targets.return_value = [
+ 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,
@@ -147,16 +140,17 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
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, 'out')
+ 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, 'out')
+ out_path = os.path.join(tmp_dir, 'build-out')
os.mkdir(out_path)
- artifacts_path = os.path.join(out_path, 'artifacts')
+ 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 = (
@@ -167,8 +161,9 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
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, 'out')
- artifacts_path = os.path.join(out_path, 'artifacts')
+ 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:
@@ -180,37 +175,37 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
@mock.patch('utils.get_fuzz_targets')
@mock.patch('logging.error')
- def test_initialize_empty_artifacts(self, mocked_log_error,
- mocked_get_fuzz_targets):
+ def test_initialize_empty_artifacts(self, mock_log_error,
+ mock_get_fuzz_targets):
"""Tests initialize with an empty artifacts dir."""
- mocked_get_fuzz_targets.return_value = ['fuzz-target']
+ mock_get_fuzz_targets.return_value = ['fuzz-target']
with tempfile.TemporaryDirectory() as tmp_dir:
- out_path = os.path.join(tmp_dir, 'out')
- artifacts_path = os.path.join(out_path, 'artifacts')
+ 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())
- mocked_log_error.assert_not_called()
+ 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, mocked_log_error,
- mocked_get_fuzz_targets):
+ def test_initialize_no_artifacts(self, mock_log_error, mock_get_fuzz_targets):
"""Tests initialize with no artifacts dir (the expected setting)."""
- mocked_get_fuzz_targets.return_value = ['fuzz-target']
+ mock_get_fuzz_targets.return_value = ['fuzz-target']
with tempfile.TemporaryDirectory() as tmp_dir:
- out_path = os.path.join(tmp_dir, 'out')
- os.makedirs(out_path)
+ out_path = os.path.join(tmp_dir, 'build-out')
+ os.mkdir(out_path)
runner = self._create_runner(workspace=tmp_dir)
self.assertTrue(runner.initialize())
- mocked_log_error.assert_not_called()
- self.assertTrue(os.path.isdir(os.path.join(out_path, 'artifacts')))
+ 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, 'out')
+ 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)
@@ -218,18 +213,21 @@ class BaseFuzzTargetRunnerTest(unittest.TestCase):
def test_get_fuzz_target_artifact(self):
"""Tests that get_fuzz_target_artifact works as intended."""
- runner = self._create_runner()
- artifacts_dir = 'artifacts-dir'
- runner.artifacts_dir = artifacts_dir
- artifact_name = 'artifact-name'
- target = mock.MagicMock()
- target_name = 'target_name'
- target.target_name = target_name
- fuzz_target_artifact = runner.get_fuzz_target_artifact(
- target, artifact_name)
- expected_fuzz_target_artifact = (
- 'artifacts-dir/target_name-address-artifact-name')
- self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact)
+ with tempfile.TemporaryDirectory() as tmp_dir:
+ runner = self._create_runner(workspace=tmp_dir)
+ crashes_dir = 'crashes-dir'
+ runner.crashes_dir = crashes_dir
+ artifact_name = 'artifact-name'
+ target = mock.MagicMock()
+ target_name = 'target_name'
+ target.target_name = target_name
+
+ fuzz_target_artifact = runner.get_fuzz_target_artifact(
+ target, artifact_name)
+ expected_fuzz_target_artifact = os.path.join(
+ tmp_dir, 'out', 'artifacts', 'target_name-address-artifact-name')
+
+ self.assertEqual(fuzz_target_artifact, expected_fuzz_target_artifact)
class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
@@ -241,91 +239,176 @@ class CiFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
@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, mocked_create_fuzz_target_obj,
- mocked_run_fuzz_target,
- mocked_get_fuzz_targets):
+ def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj,
+ mock_run_fuzz_target, mock_get_fuzz_targets):
"""Tests that run_fuzz_targets quits on the first crash it finds."""
workspace = 'workspace'
- out_path = os.path.join(workspace, 'out')
+ out_path = os.path.join(workspace, 'build-out')
self.fs.create_dir(out_path)
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=workspace,
- project_name=EXAMPLE_PROJECT)
+ config = test_helpers.create_run_config(
+ fuzz_seconds=FUZZ_SECONDS,
+ workspace=workspace,
+ oss_fuzz_project_name=EXAMPLE_PROJECT)
runner = run_fuzzers.CiFuzzTargetRunner(config)
- mocked_get_fuzz_targets.return_value = ['target1', 'target2']
+ mock_get_fuzz_targets.return_value = ['target1', 'target2']
runner.initialize()
testcase = os.path.join(workspace, 'testcase')
self.fs.create_file(testcase)
- stacktrace = b'stacktrace'
- mocked_run_fuzz_target.return_value = fuzz_target.FuzzResult(
- testcase, stacktrace)
+ 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'
- mocked_create_fuzz_target_obj.return_value = magic_mock
+ mock_create_fuzz_target_obj.return_value = magic_mock
self.assertTrue(runner.run_fuzz_targets())
- self.assertIn('target1-address-testcase', os.listdir(runner.artifacts_dir))
- self.assertEqual(mocked_run_fuzz_target.call_count, 1)
+ self.assertIn('target1-address-testcase',
+ os.listdir(runner.workspace.artifacts))
+ self.assertEqual(mock_run_fuzz_target.call_count, 1)
class BatchFuzzTargetRunnerTest(fake_filesystem_unittest.TestCase):
- """Tests that CiFuzzTargetRunner works as intended."""
+ """Tests that BatchFuzzTargetRunnerTest works as intended."""
+ WORKSPACE = 'workspace'
+ STACKTRACE = 'stacktrace'
+ CORPUS_DIR = 'corpus'
def setUp(self):
self.setUpPyfakefs()
-
- @mock.patch('utils.get_fuzz_targets')
+ 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,
+ is_github=True)
+
+ @mock.patch('utils.get_fuzz_targets', return_value=['target1', 'target2'])
+ @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_build',
+ return_value=True)
@mock.patch('run_fuzzers.BatchFuzzTargetRunner.run_fuzz_target')
@mock.patch('run_fuzzers.BatchFuzzTargetRunner.create_fuzz_target_obj')
- def test_run_fuzz_targets_quits(self, mocked_create_fuzz_target_obj,
- mocked_run_fuzz_target,
- mocked_get_fuzz_targets):
+ def test_run_fuzz_targets_quits(self, mock_create_fuzz_target_obj,
+ mock_run_fuzz_target, _, __):
"""Tests that run_fuzz_targets doesn't quit on the first crash it finds."""
- workspace = 'workspace'
- out_path = os.path.join(workspace, 'out')
- self.fs.create_dir(out_path)
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=workspace,
- project_name=EXAMPLE_PROJECT)
- runner = run_fuzzers.BatchFuzzTargetRunner(config)
-
- mocked_get_fuzz_targets.return_value = ['target1', 'target2']
+ runner = run_fuzzers.BatchFuzzTargetRunner(self.config)
runner.initialize()
- testcase1 = os.path.join(workspace, 'testcase-aaa')
- testcase2 = os.path.join(workspace, 'testcase-bbb')
- self.fs.create_file(testcase1)
- self.fs.create_file(testcase2)
- stacktrace = b'stacktrace'
+
call_count = 0
- def mock_run_fuzz_target(_):
+ def mock_run_fuzz_target_impl(_):
nonlocal call_count
if call_count == 0:
- testcase = testcase1
+ testcase = self.testcase1
elif call_count == 1:
- testcase = testcase2
+ testcase = self.testcase2
assert call_count != 2
call_count += 1
- return fuzz_target.FuzzResult(testcase, stacktrace)
+ 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)
- mocked_run_fuzz_target.side_effect = mock_run_fuzz_target
+ mock_run_fuzz_target.side_effect = mock_run_fuzz_target_impl
magic_mock = mock.MagicMock()
magic_mock.target_name = 'target1'
- mocked_create_fuzz_target_obj.return_value = magic_mock
+ mock_create_fuzz_target_obj.return_value = magic_mock
self.assertTrue(runner.run_fuzz_targets())
- self.assertIn('target1-address-testcase-aaa',
- os.listdir(runner.artifacts_dir))
- self.assertEqual(mocked_run_fuzz_target.call_count, 2)
+ self.assertEqual(mock_run_fuzz_target.call_count, 2)
+
+ @mock.patch('run_fuzzers.BaseFuzzTargetRunner.run_fuzz_targets',
+ return_value=False)
+ @mock.patch('clusterfuzz_deployment.ClusterFuzzLite.upload_crashes')
+ def test_run_fuzz_targets_upload_crashes_and_builds(self, mock_upload_crashes,
+ _):
+ """Tests that run_fuzz_targets uploads crashes and builds correctly."""
+ runner = run_fuzzers.BatchFuzzTargetRunner(self.config)
+ # TODO(metzman): Don't rely on this failing gracefully.
+ runner.initialize()
+
+ self.assertFalse(runner.run_fuzz_targets())
+ self.assertEqual(mock_upload_crashes.call_count, 1)
+@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,
+ commit_sha='0b95fe1039ed7c38fea1f97078316bfc1030c523',
+ base_commit='da0746452433dc18bae699e355a9821285d863c8',
+ sanitizer=self.SANITIZER,
+ is_github=True,
+ # 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,
+ run_fuzzers_mode='coverage',
+ is_github=True)
+ 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'
- @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
- 'INTEGRATION_TESTS=1 not set')
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
@@ -336,46 +419,61 @@ class RunAddressFuzzersIntegrationTest(RunFuzzerIntegrationTestMixin,
with tempfile.TemporaryDirectory() as tmp_dir:
workspace = os.path.join(tmp_dir, 'workspace')
shutil.copytree(TEST_DATA_PATH, workspace)
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=workspace,
- project_name=EXAMPLE_PROJECT)
+ 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)
- build_dir = os.path.join(workspace, 'out', self.BUILD_DIR_NAME)
- self.assertNotEqual(0, len(os.listdir(build_dir)))
- @unittest.skipIf(not os.getenv('INTEGRATION_TESTS'),
- 'INTEGRATION_TESTS=1 not set')
@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."""
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=TEST_DATA_PATH,
- project_name=EXAMPLE_PROJECT)
with tempfile.TemporaryDirectory() as tmp_dir:
workspace = os.path.join(tmp_dir, 'workspace')
shutil.copytree(TEST_DATA_PATH, workspace)
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=TEST_DATA_PATH,
- project_name=EXAMPLE_PROJECT)
+ 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)
- build_dir = os.path.join(TEST_DATA_PATH, 'out', self.BUILD_DIR_NAME)
- self.assertTrue(os.path.exists(build_dir))
- self.assertNotEqual(0, len(os.listdir(build_dir)))
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, 'out')
+ out_path = os.path.join(tmp_dir, 'build-out')
os.mkdir(out_path)
- config = _create_config(fuzz_seconds=FUZZ_SECONDS,
- workspace=tmp_dir,
- project_name=EXAMPLE_PROJECT)
+ 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),
+ ('ci', run_fuzzers.CiFuzzTargetRunner),
+ ('coverage', run_fuzzers.CoverageTargetRunner)
+ ])
+ def test_get_fuzz_target_runner(self, run_fuzzers_mode,
+ fuzz_target_runner_cls):
+ """Tests that get_fuzz_target_runner returns the correct runner based on the
+ specified run_fuzzers_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',
+ run_fuzzers_mode=run_fuzzers_mode)
+ runner = run_fuzzers.get_fuzz_target_runner(run_config)
+ self.assertTrue(isinstance(runner, fuzz_target_runner_cls))
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/infra/cifuzz/stack_parser.py b/infra/cifuzz/stack_parser.py
index 69c44bc2e..b53f875fe 100644
--- a/infra/cifuzz/stack_parser.py
+++ b/infra/cifuzz/stack_parser.py
@@ -18,30 +18,30 @@ import logging
# From clusterfuzz: src/python/crash_analysis/crash_analyzer.py
# Used to get the beginning of the stacktrace.
STACKTRACE_TOOL_MARKERS = [
- b'AddressSanitizer',
- b'ASAN:',
- b'CFI: Most likely a control flow integrity violation;',
- b'ERROR: libFuzzer',
- b'KASAN:',
- b'LeakSanitizer',
- b'MemorySanitizer',
- b'ThreadSanitizer',
- b'UndefinedBehaviorSanitizer',
- b'UndefinedSanitizer',
+ 'AddressSanitizer',
+ 'ASAN:',
+ 'CFI: Most likely a control flow integrity violation;',
+ 'ERROR: libFuzzer',
+ 'KASAN:',
+ 'LeakSanitizer',
+ 'MemorySanitizer',
+ 'ThreadSanitizer',
+ 'UndefinedBehaviorSanitizer',
+ 'UndefinedSanitizer',
]
# From clusterfuzz: src/python/crash_analysis/crash_analyzer.py
# Used to get the end of the stacktrace.
STACKTRACE_END_MARKERS = [
- b'ABORTING',
- b'END MEMORY TOOL REPORT',
- b'End of process memory map.',
- b'END_KASAN_OUTPUT',
- b'SUMMARY:',
- b'Shadow byte and word',
- b'[end of stack trace]',
- b'\nExiting',
- b'minidump has been written',
+ 'ABORTING',
+ 'END MEMORY TOOL REPORT',
+ 'End of process memory map.',
+ 'END_KASAN_OUTPUT',
+ 'SUMMARY:',
+ 'Shadow byte and word',
+ '[end of stack trace]',
+ '\nExiting',
+ 'minidump has been written',
]
@@ -82,5 +82,5 @@ def parse_fuzzer_output(fuzzer_output, parsed_output_file_path):
summary_str = fuzzer_output[begin_stack:end_stack]
# Write sections of fuzzer output to specific files.
- with open(parsed_output_file_path, 'ab') as summary_handle:
+ with open(parsed_output_file_path, 'a') as summary_handle:
summary_handle.write(summary_str)
diff --git a/infra/cifuzz/stack_parser_test.py b/infra/cifuzz/stack_parser_test.py
index faf601fd5..5a631b427 100644
--- a/infra/cifuzz/stack_parser_test.py
+++ b/infra/cifuzz/stack_parser_test.py
@@ -46,12 +46,12 @@ class ParseOutputTest(fake_filesystem_unittest.TestCase):
# Read the fuzzer output from disk.
fuzzer_output_path = os.path.join(TEST_DATA_PATH, fuzzer_output_file)
self.fs.add_real_file(fuzzer_output_path)
- with open(fuzzer_output_path, 'rb') as fuzzer_output_handle:
+ with open(fuzzer_output_path, 'r') as fuzzer_output_handle:
fuzzer_output = fuzzer_output_handle.read()
bug_summary_path = '/bug-summary.txt'
- with mock.patch('logging.info') as mocked_info:
+ with mock.patch('logging.info') as mock_info:
stack_parser.parse_fuzzer_output(fuzzer_output, bug_summary_path)
- mocked_info.assert_not_called()
+ mock_info.assert_not_called()
with open(bug_summary_path) as bug_summary_handle:
bug_summary = bug_summary_handle.read()
@@ -67,10 +67,10 @@ class ParseOutputTest(fake_filesystem_unittest.TestCase):
def test_parse_invalid_output(self):
"""Checks that no files are created when an invalid input was given."""
artifact_path = '/bug-summary.txt'
- with mock.patch('logging.error') as mocked_error:
- stack_parser.parse_fuzzer_output(b'not a valid output_string',
+ with mock.patch('logging.error') as mock_error:
+ stack_parser.parse_fuzzer_output('not a valid output_string',
artifact_path)
- assert mocked_error.call_count
+ assert mock_error.call_count
self.assertFalse(os.path.exists(artifact_path))
diff --git a/infra/cifuzz/test_data/out/example_crash_fuzzer b/infra/cifuzz/test_data/build-out/example_crash_fuzzer
index 704800dda..704800dda 100755
--- a/infra/cifuzz/test_data/out/example_crash_fuzzer
+++ b/infra/cifuzz/test_data/build-out/example_crash_fuzzer
Binary files differ
diff --git a/infra/cifuzz/test_data/out/example_nocrash_fuzzer b/infra/cifuzz/test_data/build-out/example_nocrash_fuzzer
index e4ff86042..e4ff86042 100755
--- a/infra/cifuzz/test_data/out/example_nocrash_fuzzer
+++ b/infra/cifuzz/test_data/build-out/example_nocrash_fuzzer
Binary files differ
diff --git a/infra/cifuzz/test_data/example_coverage_report_summary.json b/infra/cifuzz/test_data/example_coverage_report_summary.json
new file mode 100644
index 000000000..0004a1b57
--- /dev/null
+++ b/infra/cifuzz/test_data/example_coverage_report_summary.json
@@ -0,0 +1 @@
+{"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"} \ No newline at end of file
diff --git a/infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile
index e9dc33031..e24553825 100644
--- a/infra/cifuzz/test_data/external-project/oss-fuzz/Dockerfile
+++ b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/Dockerfile
@@ -18,5 +18,5 @@ FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make
COPY . $SRC/external-project
-WORKDIR external-project
-COPY oss-fuzz/build.sh $SRC/
+WORKDIR $SRC/external-project
+COPY .clusterfuzzlite/build.sh $SRC/
diff --git a/infra/cifuzz/test_data/external-project/oss-fuzz/build.sh b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh
index 2c52ef90f..2c52ef90f 100644
--- a/infra/cifuzz/test_data/external-project/oss-fuzz/build.sh
+++ b/infra/cifuzz/test_data/external-project/.clusterfuzzlite/build.sh
diff --git a/infra/cifuzz/test_data/memory/out/curl_fuzzer_memory b/infra/cifuzz/test_data/memory/build-out/curl_fuzzer_memory
index c602ce970..c602ce970 100755
--- a/infra/cifuzz/test_data/memory/out/curl_fuzzer_memory
+++ b/infra/cifuzz/test_data/memory/build-out/curl_fuzzer_memory
Binary files differ
diff --git a/infra/cifuzz/test_data/undefined/out/curl_fuzzer_undefined b/infra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined
index 504cab108..504cab108 100755
--- a/infra/cifuzz/test_data/undefined/out/curl_fuzzer_undefined
+++ b/infra/cifuzz/test_data/undefined/build-out/curl_fuzzer_undefined
Binary files differ
diff --git a/infra/cifuzz/test_helpers.py b/infra/cifuzz/test_helpers.py
new file mode 100644
index 000000000..85b5a8a67
--- /dev/null
+++ b/infra/cifuzz/test_helpers.py
@@ -0,0 +1,116 @@
+# 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
+
+
+@mock.patch('config_utils._is_dry_run', return_value=True)
+@mock.patch('config_utils.GenericCiEnvironment.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/*'
+ ])
diff --git a/infra/cifuzz/workspace_utils.py b/infra/cifuzz/workspace_utils.py
new file mode 100644
index 000000000..ed296bc2b
--- /dev/null
+++ b/infra/cifuzz/workspace_utils.py
@@ -0,0 +1,75 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+
+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')
diff --git a/infra/constants.py b/infra/constants.py
new file mode 100644
index 000000000..a323a4368
--- /dev/null
+++ b/infra/constants.py
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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',
+ 'jvm',
+ 'python',
+ 'rust',
+ 'swift',
+]
+LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'jvm', 'rust', 'swift']
+SANITIZERS = [
+ 'address', 'none', 'memory', 'undefined', 'dataflow', 'thread', 'coverage'
+]
+ARCHITECTURES = ['i386', 'x86_64']
+ENGINES = ['libfuzzer', 'afl', 'honggfuzz', 'dataflow', 'none']
diff --git a/infra/helper.py b/infra/helper.py
index e24df4ded..805f39a99 100755
--- a/infra/helper.py
+++ b/infra/helper.py
@@ -22,6 +22,7 @@ from multiprocessing.dummy import Pool as ThreadPool
import argparse
import datetime
import errno
+import logging
import os
import pipes
import re
@@ -29,25 +30,31 @@ import subprocess
import sys
import templates
+import constants
+
OSS_FUZZ_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
BUILD_DIR = os.path.join(OSS_FUZZ_DIR, 'build')
-BASE_IMAGES = [
- 'gcr.io/oss-fuzz-base/base-image',
- 'gcr.io/oss-fuzz-base/base-clang',
- 'gcr.io/oss-fuzz-base/base-builder',
- 'gcr.io/oss-fuzz-base/base-runner',
- 'gcr.io/oss-fuzz-base/base-runner-debug',
- 'gcr.io/oss-fuzz-base/base-sanitizer-libs-builder',
- 'gcr.io/oss-fuzz-base/msan-libs-builder',
-]
+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'],
+ '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'],
+ 'swift': ['gcr.io/oss-fuzz-base/base-builder-swift'],
+}
VALID_PROJECT_NAME_REGEX = re.compile(r'^[a-zA-Z0-9_-]+$')
MAX_PROJECT_NAME_LENGTH = 26
-if sys.version_info[0] >= 3:
- raw_input = input # pylint: disable=invalid-name
-
CORPUS_URL_FORMAT = (
'gs://{project_name}-corpus.clusterfuzz-external.appspot.com/libFuzzer/'
'{fuzz_target}/')
@@ -55,60 +62,158 @@ CORPUS_BACKUP_URL_FORMAT = (
'gs://{project_name}-backup.clusterfuzz-external.appspot.com/corpus/'
'libFuzzer/{fuzz_target}/')
+LANGUAGE_REGEX = re.compile(r'[^\s]+')
PROJECT_LANGUAGE_REGEX = re.compile(r'\s*language\s*:\s*([^\s]+)')
-# Languages from project.yaml that have code coverage support.
-LANGUAGES_WITH_COVERAGE_SUPPORT = ['c', 'c++', 'go', 'rust']
+WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
+
+LANGUAGES_WITH_BUILDER_IMAGES = {'go', 'jvm', 'python', 'rust', 'swift'}
+
+if sys.version_info[0] >= 3:
+ raw_input = input # pylint: disable=invalid-name
# pylint: disable=too-many-lines
+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."""
+ if self.is_external:
+ # TODO(metzman): Handle this properly.
+ return constants.DEFAULT_LANGUAGE
+
+ project_yaml_path = os.path.join(self.path, 'project.yaml')
+ 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)
+
+ logging.warning('Language not specified in project.yaml.')
+ return None
+
+ @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 main(): # pylint: disable=too-many-branches,too-many-return-statements
- """Get subcommand from program arguments and do it."""
+ """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)
+
+ # Note: this has to happen after parse_args above as parse_args needs to know
+ # the original CWD for external projects.
os.chdir(OSS_FUZZ_DIR)
if not os.path.exists(BUILD_DIR):
os.mkdir(BUILD_DIR)
- args = parse_args()
-
# 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.engine == 'dataflow':
args.sanitizer = 'dataflow'
else:
- args.sanitizer = 'address'
+ args.sanitizer = constants.DEFAULT_SANITIZER
if args.command == 'generate':
- return generate(args)
- if args.command == 'build_image':
- return build_image(args)
- if args.command == 'build_fuzzers':
- return build_fuzzers(args)
- if args.command == 'check_build':
- return check_build(args)
- if args.command == 'download_corpora':
- return download_corpora(args)
- if args.command == 'run_fuzzer':
- return run_fuzzer(args)
- if args.command == 'coverage':
- return coverage(args)
- if args.command == 'reproduce':
- return reproduce(args)
- if args.command == 'shell':
- return shell(args)
- if args.command == 'pull_images':
- return pull_images(args)
-
- return 0
-
-
-def parse_args(args=None):
- """Parses args using argparser and returns parsed args."""
+ result = generate(args)
+ elif args.command == 'build_image':
+ result = build_image(args)
+ elif args.command == 'build_fuzzers':
+ result = build_fuzzers(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 == 'reproduce':
+ result = reproduce(args)
+ elif args.command == 'shell':
+ result = shell(args)
+ elif args.command == 'pull_images':
+ result = pull_images()
+ 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.
- parser = get_parser()
- return parser.parse_args(args)
+ 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 = 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
@@ -118,17 +223,28 @@ def get_parser(): # pylint: disable=too-many-statements
generate_parser = subparsers.add_parser(
'generate', help='Generate files for new project.')
- generate_parser.add_argument('project_name')
+ generate_parser.add_argument('project')
+ generate_parser.add_argument(
+ '--language',
+ default=constants.DEFAULT_LANGUAGE,
+ choices=['c', 'c++', 'rust', 'go', 'jvm', 'swift', 'python'],
+ 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_name')
+ build_image_parser.add_argument('project')
build_image_parser.add_argument('--pull',
action='store_true',
help='Pull latest base image.')
+ 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.')
@@ -136,10 +252,15 @@ def get_parser(): # pylint: disable=too-many-statements
_add_engine_args(build_fuzzers_parser)
_add_sanitizer_args(build_fuzzers_parser)
_add_environment_args(build_fuzzers_parser)
- build_fuzzers_parser.add_argument('project_name')
+ _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',
@@ -154,26 +275,26 @@ def get_parser(): # pylint: disable=too-many-statements
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=['libfuzzer', 'afl', 'honggfuzz', 'dataflow', 'none'])
- _add_sanitizer_args(
- check_build_parser,
- choices=['address', 'memory', 'undefined', 'dataflow', 'thread'])
+ _add_engine_args(check_build_parser, choices=constants.ENGINES)
+ _add_sanitizer_args(check_build_parser, choices=constants.SANITIZERS)
_add_environment_args(check_build_parser)
- check_build_parser.add_argument('project_name', help='name of the project')
+ 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)
run_fuzzer_parser = subparsers.add_parser(
'run_fuzzer', help='Run a fuzzer in the emulated fuzzing environment.')
_add_engine_args(run_fuzzer_parser)
_add_sanitizer_args(run_fuzzer_parser)
_add_environment_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_name', help='name of the project')
+ 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',
@@ -197,35 +318,40 @@ def get_parser(): # pylint: disable=too-many-statements
coverage_parser.add_argument('--corpus-dir',
help='specify location of corpus'
' to be used (requires --fuzz-target argument)')
- coverage_parser.add_argument('project_name', help='name of the project')
+ 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)
download_corpora_parser = subparsers.add_parser(
'download_corpora', help='Download all corpora for a project.')
download_corpora_parser.add_argument('--fuzz-target',
help='specify name of a fuzz target')
- download_corpora_parser.add_argument('project_name',
- help='name of the project')
+ 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_name', help='name of the project')
+ 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=argparse.REMAINDER)
_add_environment_args(reproduce_parser)
+ _add_external_project_args(reproduce_parser)
shell_parser = subparsers.add_parser(
'shell', help='Run /bin/bash within the builder container.')
- shell_parser.add_argument('project_name', help='name of the project')
+ 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='?')
@@ -233,6 +359,7 @@ def get_parser(): # pylint: disable=too-many-statements
_add_engine_args(shell_parser)
_add_sanitizer_args(shell_parser)
_add_environment_args(shell_parser)
+ _add_external_project_args(shell_parser)
subparsers.add_parser('pull_images', help='Pull base images.')
return parser
@@ -243,29 +370,33 @@ def is_base_image(image_name):
return os.path.exists(os.path.join('infra', 'base-images', image_name))
-def check_project_exists(project_name):
+def check_project_exists(project):
"""Checks if a project exists."""
- if not os.path.exists(_get_project_dir(project_name)):
- print(project_name, 'does not exist', file=sys.stderr)
- return False
+ if os.path.exists(project.path):
+ return True
- return True
+ if project.is_external:
+ descriptive_project_name = project.path
+ else:
+ descriptive_project_name = project.name
+ logging.error('"%s" does not exist.', descriptive_project_name)
+ return False
-def _check_fuzzer_exists(project_name, fuzzer_name):
+
+def _check_fuzzer_exists(project, fuzzer_name):
"""Checks if a fuzzer exists."""
command = ['docker', 'run', '--rm']
- command.extend(['-v', '%s:/out' % _get_output_dir(project_name)])
- command.append('ubuntu:16.04')
+ command.extend(['-v', '%s:/out' % project.out])
+ command.append(BASE_RUNNER_IMAGE)
command.extend(['/bin/bash', '-c', 'test -f /out/%s' % fuzzer_name])
try:
subprocess.check_call(command)
except subprocess.CalledProcessError:
- print(fuzzer_name,
- 'does not seem to exist. Please run build_fuzzers first.',
- file=sys.stderr)
+ logging.error('%s does not seem to exist. Please run build_fuzzers first.',
+ fuzzer_name)
return False
return True
@@ -281,76 +412,44 @@ def _get_command_string(command):
return ' '.join(pipes.quote(part) for part in command)
-def _get_project_dir(project_name):
- """Returns path to the project."""
- return os.path.join(OSS_FUZZ_DIR, 'projects', project_name)
-
-
-def get_dockerfile_path(project_name):
- """Returns path to the project Dockerfile."""
- return os.path.join(_get_project_dir(project_name), 'Dockerfile')
-
-
-def _get_corpus_dir(project_name=''):
- """Creates and returns path to /corpus directory for the given project (if
- specified)."""
- directory = os.path.join(BUILD_DIR, 'corpus', project_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)
if not os.path.exists(directory):
os.makedirs(directory)
return directory
-def _get_output_dir(project_name=''):
+def _get_out_dir(project=''):
"""Creates and returns path to /out directory for the given project (if
specified)."""
- directory = os.path.join(BUILD_DIR, 'out', project_name)
- if not os.path.exists(directory):
- os.makedirs(directory)
+ return _get_project_build_subdir(project, 'out')
- return directory
+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 _get_work_dir(project_name=''):
- """Creates and returns path to /work directory for the given project (if
- specified)."""
- directory = os.path.join(BUILD_DIR, 'work', project_name)
- if not os.path.exists(directory):
- os.makedirs(directory)
- return directory
+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 _get_project_language(project_name):
- """Returns project language."""
- project_yaml_path = os.path.join(OSS_FUZZ_DIR, 'projects', project_name,
- 'project.yaml')
- 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)
-
- return None
-
-
-def _add_architecture_args(parser, choices=('x86_64', 'i386')):
- """Add common architecture args."""
- parser.add_argument('--architecture', default='x86_64', choices=choices)
-
-
-def _add_engine_args(parser,
- choices=('libfuzzer', 'afl', 'honggfuzz', 'dataflow',
- 'none')):
- """Add common engine args."""
- parser.add_argument('--engine', default='libfuzzer', choices=choices)
-
-
-def _add_sanitizer_args(parser,
- choices=('address', 'memory', 'undefined', 'coverage',
- 'dataflow', 'thread')):
- """Add common sanitizer args."""
+def _add_sanitizer_args(parser, choices=None):
+ """Adds common sanitizer args."""
+ if choices is None:
+ choices = constants.SANITIZERS
parser.add_argument(
'--sanitizer',
default=None,
@@ -359,47 +458,50 @@ def _add_sanitizer_args(parser,
def _add_environment_args(parser):
- """Add common environment args."""
+ """Adds common environment args."""
parser.add_argument('-e',
action='append',
help="set environment variable e.g. VAR=value")
-def build_image_impl(image_name, no_cache=False, pull=False):
- """Build image."""
+def build_image_impl(project, cache=True, pull=False):
+ """Builds image."""
+ image_name = project.name
- proj_is_base_image = is_base_image(image_name)
- if proj_is_base_image:
+ if is_base_image(image_name):
image_project = 'oss-fuzz-base'
- dockerfile_dir = os.path.join('infra', 'base-images', image_name)
+ docker_build_dir = os.path.join(OSS_FUZZ_DIR, 'infra', 'base-images',
+ image_name)
+ dockerfile_path = os.path.join(docker_build_dir, 'Dockerfile')
else:
- image_project = 'oss-fuzz'
- if not check_project_exists(image_name):
+ if not check_project_exists(project):
return False
+ dockerfile_path = project.dockerfile_path
+ docker_build_dir = project.path
+ image_project = 'oss-fuzz'
- dockerfile_dir = os.path.join('projects', image_name)
+ if pull and not pull_images(project.language):
+ return False
build_args = []
- if no_cache:
+ if not cache:
build_args.append('--no-cache')
build_args += [
- '-t', 'gcr.io/%s/%s' % (image_project, image_name), dockerfile_dir
+ '-t',
+ 'gcr.io/%s/%s' % (image_project, image_name), '--file', dockerfile_path
]
-
- return docker_build(build_args, pull=pull)
+ build_args.append(docker_build_dir)
+ return docker_build(build_args)
def _env_to_docker_args(env_list):
- """Turn envirnoment variable list into docker arguments."""
+ """Turns envirnoment variable list into docker arguments."""
return sum([['-e', v] for v in env_list], [])
-WORKDIR_REGEX = re.compile(r'\s*WORKDIR\s*([^\s]+)')
-
-
def workdir_from_lines(lines, default='/src'):
- """Get the WORKDIR from the given lines."""
+ """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:
@@ -414,18 +516,16 @@ def workdir_from_lines(lines, default='/src'):
return default
-def _workdir_from_dockerfile(project_name):
- """Parse WORKDIR from the Dockerfile for the given project."""
- dockerfile_path = get_dockerfile_path(project_name)
-
- with open(dockerfile_path) as file_handle:
+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))
+ return workdir_from_lines(lines, default=os.path.join('/src', project.name))
def docker_run(run_args, print_output=True):
- """Call `docker run`."""
+ """Calls `docker run`."""
command = ['docker', 'run', '--rm', '--privileged']
# Support environments with a TTY.
@@ -434,32 +534,29 @@ def docker_run(run_args, print_output=True):
command.extend(run_args)
- print('Running:', _get_command_string(command))
+ logging.info('Running: %s.', _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 as error:
- return error.returncode
+ except subprocess.CalledProcessError:
+ return False
- return 0
+ return True
-def docker_build(build_args, pull=False):
- """Call `docker build`."""
+def docker_build(build_args):
+ """Calls `docker build`."""
command = ['docker', 'build']
- if pull:
- command.append('--pull')
-
command.extend(build_args)
- print('Running:', _get_command_string(command))
+ logging.info('Running: %s.', _get_command_string(command))
try:
subprocess.check_call(command)
except subprocess.CalledProcessError:
- print('docker build failed.', file=sys.stderr)
+ logging.error('Docker build failed.')
return False
return True
@@ -468,22 +565,22 @@ def docker_build(build_args, pull=False):
def docker_pull(image):
"""Call `docker pull`."""
command = ['docker', 'pull', image]
- print('Running:', _get_command_string(command))
+ logging.info('Running: %s', _get_command_string(command))
try:
subprocess.check_call(command)
except subprocess.CalledProcessError:
- print('docker pull failed.', file=sys.stderr)
+ logging.error('Docker pull failed.')
return False
return True
def build_image(args):
- """Build docker image."""
+ """Builds docker image."""
if args.pull and args.no_pull:
- print('Incompatible arguments --pull and --no-pull.')
- return 1
+ logging.error('Incompatible arguments --pull and --no-pull.')
+ return False
if args.pull:
pull = True
@@ -494,89 +591,74 @@ def build_image(args):
pull = y_or_n.lower() == 'y'
if pull:
- print('Pulling latest base images...')
+ logging.info('Pulling latest base images...')
else:
- print('Using cached base images...')
+ logging.info('Using cached base images...')
# If build_image is called explicitly, don't use cache.
- if build_image_impl(args.project_name, no_cache=True, pull=pull):
- return 0
+ if build_image_impl(args.project, cache=args.cache, pull=pull):
+ return True
- return 1
+ return False
def build_fuzzers_impl( # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
- project_name,
+ project,
clean,
engine,
sanitizer,
architecture,
env_to_add,
source_path,
- no_cache=False,
- mount_location=None):
- """Build fuzzers."""
- if not build_image_impl(project_name, no_cache=no_cache):
- return 1
-
- project_out_dir = _get_output_dir(project_name)
- project_work_dir = _get_work_dir(project_name)
- project_language = _get_project_language(project_name)
- if not project_language:
- print('WARNING: language not specified in project.yaml. Build may fail.')
+ mount_path=None):
+ """Builds fuzzers."""
+ if not build_image_impl(project):
+ return False
if clean:
- print('Cleaning existing build artifacts.')
+ logging.info('Cleaning existing build artifacts.')
# Clean old and possibly conflicting artifacts in project's out directory.
docker_run([
'-v',
- '%s:/out' % project_out_dir, '-t',
- 'gcr.io/oss-fuzz/%s' % project_name, '/bin/bash', '-c', 'rm -rf /out/*'
+ '%s:/out' % project.out, '-t',
+ 'gcr.io/oss-fuzz/%s' % project.name, '/bin/bash', '-c', 'rm -rf /out/*'
])
docker_run([
'-v',
- '%s:/work' % project_work_dir, '-t',
- 'gcr.io/oss-fuzz/%s' % project_name, '/bin/bash', '-c', 'rm -rf /work/*'
+ '%s:/work' % project.work, '-t',
+ 'gcr.io/oss-fuzz/%s' % project.name, '/bin/bash', '-c', 'rm -rf /work/*'
])
else:
- print('Keeping existing build artifacts as-is (if any).')
+ logging.info('Keeping existing build artifacts as-is (if any).')
env = [
'FUZZING_ENGINE=' + engine,
'SANITIZER=' + sanitizer,
'ARCHITECTURE=' + architecture,
]
- if project_language:
- env.append('FUZZING_LANGUAGE=' + project_language)
+ _add_oss_fuzz_ci_if_needed(env)
+
+ if project.language:
+ env.append('FUZZING_LANGUAGE=' + project.language)
if env_to_add:
env += env_to_add
- # Copy instrumented libraries.
- if sanitizer == 'memory':
- docker_run([
- '-v',
- '%s:/work' % project_work_dir, 'gcr.io/oss-fuzz-base/msan-libs-builder',
- 'bash', '-c', 'cp -r /msan /work'
- ])
- env.append('MSAN_LIBS_PATH=' + '/work/msan')
-
command = ['--cap-add', 'SYS_PTRACE'] + _env_to_docker_args(env)
if source_path:
- workdir = _workdir_from_dockerfile(project_name)
- if mount_location:
+ workdir = _workdir_from_dockerfile(project)
+ if mount_path:
command += [
'-v',
- '%s:%s' % (_get_absolute_path(source_path), mount_location),
+ '%s:%s' % (_get_absolute_path(source_path), mount_path),
]
else:
if workdir == '/src':
- print('Cannot use local checkout with "WORKDIR: /src".',
- file=sys.stderr)
- return 1
+ logging.error('Cannot use local checkout with "WORKDIR: /src".')
+ return False
command += [
'-v',
@@ -585,50 +667,52 @@ def build_fuzzers_impl( # pylint: disable=too-many-arguments,too-many-locals,to
command += [
'-v',
- '%s:/out' % project_out_dir, '-v',
- '%s:/work' % project_work_dir, '-t',
- 'gcr.io/oss-fuzz/%s' % project_name
+ '%s:/out' % project.out, '-v',
+ '%s:/work' % project.work, '-t',
+ 'gcr.io/oss-fuzz/%s' % project.name
]
- result_code = docker_run(command)
- if result_code:
- print('Building fuzzers failed.', file=sys.stderr)
- return result_code
-
- # Patch MSan builds to use instrumented shared libraries.
- if sanitizer == 'memory':
- docker_run([
- '-v',
- '%s:/out' % project_out_dir, '-v',
- '%s:/work' % project_work_dir
- ] + _env_to_docker_args(env) + [
- 'gcr.io/oss-fuzz-base/base-sanitizer-libs-builder', 'patch_build.py',
- '/out'
- ])
+ result = docker_run(command)
+ if not result:
+ logging.error('Building fuzzers failed.')
+ return False
- return 0
+ return True
def build_fuzzers(args):
- """Build fuzzers."""
- return build_fuzzers_impl(args.project_name, args.clean, args.engine,
- args.sanitizer, args.architecture, args.e,
- args.source_path)
+ """Builds fuzzers."""
+ return build_fuzzers_impl(args.project,
+ args.clean,
+ args.engine,
+ args.sanitizer,
+ args.architecture,
+ args.e,
+ args.source_path,
+ mount_path=args.mount_path)
+
+
+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."""
- if not check_project_exists(args.project_name):
- return 1
+ if not check_project_exists(args.project):
+ return False
if (args.fuzzer_name and
- not _check_fuzzer_exists(args.project_name, args.fuzzer_name)):
- return 1
+ not _check_fuzzer_exists(args.project, args.fuzzer_name)):
+ return False
- fuzzing_language = _get_project_language(args.project_name)
- if fuzzing_language is None:
- print('WARNING: language not specified in project.yaml. Defaulting to C++.')
- fuzzing_language = 'c++'
+ fuzzing_language = args.project.language
+ if not fuzzing_language:
+ fuzzing_language = constants.DEFAULT_LANGUAGE
+ logging.warning('Language not specified in project.yaml. Defaulting to %s.',
+ fuzzing_language)
env = [
'FUZZING_ENGINE=' + args.engine,
@@ -636,13 +720,12 @@ def check_build(args):
'ARCHITECTURE=' + args.architecture,
'FUZZING_LANGUAGE=' + fuzzing_language,
]
+ _add_oss_fuzz_ci_if_needed(env)
if args.e:
env += args.e
run_args = _env_to_docker_args(env) + [
- '-v',
- '%s:/out' % _get_output_dir(args.project_name), '-t',
- 'gcr.io/oss-fuzz-base/base-runner'
+ '-v', '%s:/out' % args.project.out, '-t', BASE_RUNNER_IMAGE
]
if args.fuzzer_name:
@@ -650,39 +733,45 @@ def check_build(args):
else:
run_args.append('test_all.py')
- exit_code = docker_run(run_args)
- if exit_code == 0:
- print('Check build passed.')
+ result = docker_run(run_args)
+ if result:
+ logging.info('Check build passed.')
else:
- print('Check build failed.')
+ logging.error('Check build failed.')
- return exit_code
+ return result
-def _get_fuzz_targets(project_name):
- """Return names of fuzz targest build in the project's /out directory."""
+def _get_fuzz_targets(project):
+ """Returns names of fuzz targest build in the project's /out directory."""
fuzz_targets = []
- for name in os.listdir(_get_output_dir(project_name)):
+ for name in os.listdir(project.out):
if name.startswith('afl-'):
continue
+ if name.startswith('jazzer_'):
+ continue
+ if name == 'llvm-symbolizer':
+ continue
- path = os.path.join(_get_output_dir(project_name), name)
- if os.path.isfile(path) and os.access(path, os.X_OK):
+ 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_name, fuzz_target, base_corpus_dir):
- """Download the latest corpus for the given fuzz target."""
+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)
if not os.path.exists(corpus_dir):
os.makedirs(corpus_dir)
- if not fuzz_target.startswith(project_name + '_'):
- fuzz_target = '%s_%s' % (project_name, fuzz_target)
+ if not fuzz_target.startswith(project.name + '_'):
+ fuzz_target = '%s_%s' % (project.name, fuzz_target)
- corpus_backup_url = CORPUS_BACKUP_URL_FORMAT.format(project_name=project_name,
+ corpus_backup_url = CORPUS_BACKUP_URL_FORMAT.format(project_name=project.name,
fuzz_target=fuzz_target)
command = ['gsutil', 'ls', corpus_backup_url]
@@ -693,8 +782,7 @@ def _get_latest_corpus(project_name, fuzz_target, base_corpus_dir):
# Some fuzz targets (e.g. new ones) may not have corpus yet, just skip those.
if corpus_listing.returncode:
- print('WARNING: corpus for {0} not found:\n'.format(fuzz_target),
- file=sys.stderr)
+ logging.warning('Corpus for %s not found:\n', fuzz_target)
return
if output:
@@ -708,80 +796,73 @@ def _get_latest_corpus(project_name, fuzz_target, base_corpus_dir):
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,
+ 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 download_corpora(args):
- """Download most recent corpora from GCS for the given project."""
- if not check_project_exists(args.project_name):
- return 1
+ """Downloads most recent corpora from GCS for the given project."""
+ if not check_project_exists(args.project):
+ return False
try:
with open(os.devnull, 'w') as stdout:
subprocess.check_call(['gsutil', '--version'], stdout=stdout)
except OSError:
- print(
- 'ERROR: gsutil not found. Please install it from '
- 'https://cloud.google.com/storage/docs/gsutil_install',
- file=sys.stderr)
+ logging.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_name)
+ fuzz_targets = _get_fuzz_targets(args.project)
- corpus_dir = _get_corpus_dir(args.project_name)
- if not os.path.exists(corpus_dir):
- os.makedirs(corpus_dir)
+ corpus_dir = args.project.corpus
def _download_for_single_target(fuzz_target):
try:
- _get_latest_corpus(args.project_name, fuzz_target, corpus_dir)
+ _get_latest_corpus(args.project, fuzz_target, corpus_dir)
return True
except Exception as error: # pylint:disable=broad-except
- print('ERROR: corpus download for %s failed: %s' %
- (fuzz_target, str(error)),
- file=sys.stderr)
+ logging.error('Corpus download for %s failed: %s.', fuzz_target,
+ str(error))
return False
- print('Downloading corpora for %s project to %s' %
- (args.project_name, corpus_dir))
+ logging.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):
- """Generate code coverage using clang source based code coverage."""
+ """Generates code coverage using clang source based code coverage."""
if args.corpus_dir and not args.fuzz_target:
- print(
- 'ERROR: --corpus-dir requires specifying a particular fuzz target '
- 'using --fuzz-target',
- file=sys.stderr)
- return 1
-
- if not check_project_exists(args.project_name):
- return 1
-
- project_language = _get_project_language(args.project_name)
- if project_language not in LANGUAGES_WITH_COVERAGE_SUPPORT:
- print(
- 'ERROR: Project is written in %s, coverage for it is not supported yet.'
- % project_language,
- file=sys.stderr)
- return 1
-
- if not args.no_corpus_download and not args.corpus_dir:
+ logging.error(
+ '--corpus-dir requires specifying a particular fuzz target using '
+ '--fuzz-target')
+ return False
+
+ if not check_project_exists(args.project):
+ return False
+
+ if args.project.language not in constants.LANGUAGES_WITH_COVERAGE_SUPPORT:
+ logging.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 1
+ return False
env = [
'FUZZING_ENGINE=libfuzzer',
- 'FUZZING_LANGUAGE=%s' % project_language,
- 'PROJECT=%s' % args.project_name,
+ 'FUZZING_LANGUAGE=%s' % args.project.language,
+ 'PROJECT=%s' % args.project.name,
'SANITIZER=coverage',
'HTTP_PORT=%s' % args.port,
'COVERAGE_EXTRA_ARGS=%s' % ' '.join(args.extra_args),
@@ -797,41 +878,41 @@ def coverage(args):
if args.corpus_dir:
if not os.path.exists(args.corpus_dir):
- print('ERROR: the path provided in --corpus-dir argument does not exist',
- file=sys.stderr)
- return 1
+ logging.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' % _get_corpus_dir(args.project_name)])
+ run_args.extend(['-v', '%s:/corpus' % args.project.corpus])
run_args.extend([
'-v',
- '%s:/out' % _get_output_dir(args.project_name),
+ '%s:/out' % args.project.out,
'-t',
- 'gcr.io/oss-fuzz-base/base-runner',
+ BASE_RUNNER_IMAGE,
])
run_args.append('coverage')
if args.fuzz_target:
run_args.append(args.fuzz_target)
- exit_code = docker_run(run_args)
- if exit_code == 0:
- print('Successfully generated clang code coverage report.')
+ result = docker_run(run_args)
+ if result:
+ logging.info('Successfully generated clang code coverage report.')
else:
- print('Failed to generate clang code coverage report.')
+ logging.error('Failed to generate clang code coverage report.')
- return exit_code
+ return result
def run_fuzzer(args):
"""Runs a fuzzer in the container."""
- if not check_project_exists(args.project_name):
- return 1
+ if not check_project_exists(args.project):
+ return False
- if not _check_fuzzer_exists(args.project_name, args.fuzzer_name):
- return 1
+ if not _check_fuzzer_exists(args.project, args.fuzzer_name):
+ return False
env = [
'FUZZING_ENGINE=' + args.engine,
@@ -846,9 +927,8 @@ def run_fuzzer(args):
if args.corpus_dir:
if not os.path.exists(args.corpus_dir):
- print('ERROR: the path provided in --corpus-dir argument does not exist',
- file=sys.stderr)
- return 1
+ logging.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',
@@ -858,9 +938,9 @@ def run_fuzzer(args):
run_args.extend([
'-v',
- '%s:/out' % _get_output_dir(args.project_name),
+ '%s:/out' % args.project.out,
'-t',
- 'gcr.io/oss-fuzz-base/base-runner',
+ BASE_RUNNER_IMAGE,
'run_fuzzer',
args.fuzzer_name,
] + args.fuzzer_args)
@@ -869,25 +949,25 @@ def run_fuzzer(args):
def reproduce(args):
- """Reproduce a specific test case from a specific project."""
- return reproduce_impl(args.project_name, args.fuzzer_name, args.valgrind,
- args.e, args.fuzzer_args, args.testcase_path)
+ """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)
def reproduce_impl( # pylint: disable=too-many-arguments
- project_name,
+ project,
fuzzer_name,
valgrind,
env_to_add,
fuzzer_args,
testcase_path,
- runner=docker_run,
- err_result=1):
+ run_function=docker_run,
+ err_result=False):
"""Reproduces a testcase in the container."""
- if not check_project_exists(project_name):
+ if not check_project_exists(project):
return err_result
- if not _check_fuzzer_exists(project_name, fuzzer_name):
+ if not _check_fuzzer_exists(project, fuzzer_name):
return err_result
debugger = ''
@@ -906,7 +986,7 @@ def reproduce_impl( # pylint: disable=too-many-arguments
run_args = _env_to_docker_args(env) + [
'-v',
- '%s:/out' % _get_output_dir(project_name),
+ '%s:/out' % project.out,
'-v',
'%s:/testcase' % _get_absolute_path(testcase_path),
'-t',
@@ -916,55 +996,109 @@ def reproduce_impl( # pylint: disable=too-many-arguments
'-runs=100',
] + fuzzer_args
- return runner(run_args)
+ return run_function(run_args)
-def generate(args):
- """Generate empty project files."""
- if len(args.project_name) > MAX_PROJECT_NAME_LENGTH:
- print('Project name needs to be less than or equal to %d characters.' %
- MAX_PROJECT_NAME_LENGTH,
- file=sys.stderr)
- return 1
+def _validate_project_name(project_name):
+ """Validates |project_name| is a valid OSS-Fuzz project name."""
+ if len(project_name) > MAX_PROJECT_NAME_LENGTH:
+ logging.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(args.project_name):
- print('Invalid project name.', file=sys.stderr)
- return 1
+ if not VALID_PROJECT_NAME_REGEX.match(project_name):
+ logging.info('Invalid project name: %s.', project_name)
+ return False
+
+ return True
- directory = os.path.join('projects', args.project_name)
+def _validate_language(language):
+ if not LANGUAGE_REGEX.match(language):
+ logging.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.mkdir(directory)
+ os.makedirs(directory)
except OSError as error:
if error.errno != errno.EEXIST:
raise
- print(directory, 'already exists.', file=sys.stderr)
- return 1
+ logging.error('%s already exists.', directory)
+ return False
+ return True
- print('Writing new files to', directory)
- template_args = {
- 'project_name': args.project_name,
- 'year': datetime.datetime.now().year
- }
- with open(os.path.join(directory, 'project.yaml'), 'w') as file_handle:
- file_handle.write(templates.PROJECT_YAML_TEMPLATE % template_args)
+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)
+
- with open(os.path.join(directory, 'Dockerfile'), 'w') as file_handle:
- file_handle.write(templates.DOCKER_TEMPLATE % template_args)
+def _get_current_datetime():
+ """Returns this year. Needed for mocking."""
+ return datetime.datetime.now()
- build_sh_path = os.path.join(directory, 'build.sh')
- with open(build_sh_path, 'w') as file_handle:
- file_handle.write(templates.BUILD_TEMPLATE % template_args)
- os.chmod(build_sh_path, 0o755)
- return 0
+def _base_builder_from_language(language):
+ """Returns the base builder for the specified language."""
+ if language not in LANGUAGES_WITH_BUILDER_IMAGES:
+ return 'base-builder'
+ return 'base-builder-{language}'.format(language=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
+
+ logging.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 shell(args):
"""Runs a shell within a docker image."""
- if not build_image_impl(args.project_name):
- return 1
+ if not build_image_impl(args.project):
+ return False
env = [
'FUZZING_ENGINE=' + args.engine,
@@ -972,18 +1106,18 @@ def shell(args):
'ARCHITECTURE=' + args.architecture,
]
- if args.project_name != 'base-runner-debug':
- env.append('FUZZING_LANGUAGE=' + _get_project_language(args.project_name))
+ if args.project.name != 'base-runner-debug':
+ env.append('FUZZING_LANGUAGE=' + args.project.language)
if args.e:
env += args.e
- if is_base_image(args.project_name):
+ if is_base_image(args.project.name):
image_project = 'oss-fuzz-base'
- out_dir = _get_output_dir()
+ out_dir = _get_out_dir()
else:
image_project = 'oss-fuzz'
- out_dir = _get_output_dir(args.project_name)
+ out_dir = args.project.out
run_args = _env_to_docker_args(env)
if args.source_path:
@@ -995,21 +1129,25 @@ def shell(args):
run_args.extend([
'-v',
'%s:/out' % out_dir, '-v',
- '%s:/work' % _get_work_dir(args.project_name), '-t',
- 'gcr.io/%s/%s' % (image_project, args.project_name), '/bin/bash'
+ '%s:/work' % args.project.work, '-t',
+ 'gcr.io/%s/%s' % (image_project, args.project.name), '/bin/bash'
])
docker_run(run_args)
- return 0
+ return True
-def pull_images(_):
- """Pull base images."""
- for base_image in BASE_IMAGES:
- if not docker_pull(base_image):
- return 1
+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 0
+ return True
if __name__ == '__main__':
diff --git a/infra/helper_test.py b/infra/helper_test.py
index d899a835b..951eba47a 100644
--- a/infra/helper_test.py
+++ b/infra/helper_test.py
@@ -13,23 +13,224 @@
# 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 templates
+
+# pylint: disable=no-self-use,protected-access
-class TestShell(unittest.TestCase):
+class ShellTest(unittest.TestCase):
"""Tests 'shell' command."""
@mock.patch('helper.docker_run')
@mock.patch('helper.build_image_impl')
- def test_base_runner_debug(self, mocked_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]
- args = helper.parse_args(unparsed_args)
+ parser = helper.get_parser()
+ args = helper.parse_args(parser, unparsed_args)
args.sanitizer = 'address'
result = helper.shell(args)
- mocked_build_image_impl.assert_called_with(image_name)
- self.assertEqual(result, 0)
+ self.assertTrue(result)
+
+
+class BuildImageImplTest(unittest.TestCase):
+ """Tests for build_image_impl."""
+
+ @mock.patch('helper.docker_build')
+ def test_no_cache(self, mock_docker_build):
+ """Tests that cache=False is handled properly."""
+ image_name = 'base-image'
+ helper.build_image_impl(helper.Project(image_name), cache=False)
+ self.assertIn('--no-cache', mock_docker_build.call_args_list[0][0][0])
+
+ @mock.patch('helper.docker_build')
+ @mock.patch('helper.pull_images')
+ def test_pull(self, mock_pull_images, _):
+ """Tests that pull=True is handled properly."""
+ image_name = 'base-image'
+ project = helper.Project(image_name, is_external=True)
+ self.assertTrue(helper.build_image_impl(project, pull=True))
+ mock_pull_images.assert_called_with('c++')
+
+ @mock.patch('helper.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(helper.build_image_impl(helper.Project(image_name)))
+ build_dir = os.path.join(helper.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('helper.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(helper.build_image_impl(helper.Project(project_name)))
+ build_dir = os.path.join(helper.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('helper.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 = helper.Project(project_src_path,
+ is_external=True,
+ build_integration_path=build_integration_path)
+ self.assertTrue(helper.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.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)
+
+ 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++')
diff --git a/infra/presubmit.py b/infra/presubmit.py
index 90b4f90ac..6db1862be 100755
--- a/infra/presubmit.py
+++ b/infra/presubmit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright 2020 Google LLC.
+# 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.
@@ -14,7 +14,7 @@
# limitations under the License.
#
################################################################################
-"""Check code for common issues before submitting."""
+"""Checks code for common issues before submitting."""
import argparse
import os
@@ -23,6 +23,8 @@ import sys
import unittest
import yaml
+import constants
+
_SRC_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -62,8 +64,8 @@ def _check_one_lib_fuzzing_engine(build_sh_file):
def check_lib_fuzzing_engine(paths):
- """Call _check_one_lib_fuzzing_engine on each path in |paths|. Return True if
- the result of every call is True."""
+ """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])
@@ -73,9 +75,9 @@ class ProjectYamlChecker:
# Sections in a project.yaml and the constant values that they are allowed
# to have.
SECTIONS_AND_CONSTANTS = {
- 'sanitizers': {'address', 'none', 'memory', 'undefined', 'dataflow'},
- 'architectures': {'i386', 'x86_64'},
- 'fuzzing_engines': {'afl', 'libfuzzer', 'honggfuzz', 'dataflow', 'none'},
+ 'sanitizers': constants.SANITIZERS,
+ 'architectures': constants.ARCHITECTURES,
+ 'fuzzing_engines': constants.ENGINES,
}
# Note: this list must be updated when we allow new sections.
@@ -100,15 +102,6 @@ class ProjectYamlChecker:
'view_restrictions',
]
- LANGUAGES_SUPPORTED = [
- 'c',
- 'c++',
- 'go',
- 'jvm',
- 'python',
- 'rust',
- ]
-
# Note that some projects like boost only have auto-ccs. However, forgetting
# primary contact is probably a mistake.
REQUIRED_SECTIONS = ['primary_contact', 'main_repo']
@@ -121,7 +114,7 @@ class ProjectYamlChecker:
self.success = True
def do_checks(self):
- """Do all project.yaml checks. Return True if they pass."""
+ """Does all project.yaml checks. Returns True if they pass."""
if self.is_disabled():
return True
@@ -131,23 +124,43 @@ class ProjectYamlChecker:
self.check_valid_section_names,
self.check_valid_emails,
self.check_valid_language,
+ self.check_dataflow,
]
for check_function in checks:
check_function()
return self.success
def is_disabled(self):
- """Is this project disabled."""
+ """Returns True if this project is disabled."""
return self.data.get('disabled', False)
def error(self, message):
- """Print an error message and set self.success to False."""
+ """Prints an error message and sets self.success to False."""
self.success = False
print('Error in {filename}: {message}'.format(filename=self.filename,
message=message))
+ def check_dataflow(self):
+ """Checks that if "dataflow" is specified in "fuzzing_engines", it is also
+ specified in "sanitizers", and that if specified in "sanitizers", it is also
+ specified in "fuzzing_engines". Returns True if this condition is met."""
+ engines = self.data.get('fuzzing_engines', [])
+ dfsan_engines = 'dataflow' in engines
+ sanitizers = self.data.get('sanitizers', [])
+ dfsan_sanitizers = 'dataflow' in sanitizers
+
+ if dfsan_engines and not dfsan_sanitizers:
+ self.error('"dataflow" only specified in "fuzzing_engines" must also be '
+ 'specified in "sanitizers" or in neither.')
+ return
+
+ if dfsan_sanitizers and not dfsan_engines:
+ self.error('"dataflow" only specified in "sanitizers" must also be '
+ 'specified in "fuzzing_engines" or in neither.')
+ return
+
def check_project_yaml_constants(self):
- """Check that certain sections only have certain constant values."""
+ """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
@@ -172,20 +185,20 @@ class ProjectYamlChecker:
self.error('Not allowed value in the project.yaml: ' + str(constant))
def check_valid_section_names(self):
- """Check that only valid sections are included."""
+ """Returns True if all section names are valid."""
for name in self.data:
if name not in self.VALID_SECTION_NAMES:
self.error('{name} is not a valid section name ({valid_names})'.format(
name=name, valid_names=self.VALID_SECTION_NAMES))
def check_required_sections(self):
- """Check that all required sections are present."""
+ """Returns True if all required sections are in |self.data|."""
for section in self.REQUIRED_SECTIONS:
if section not in self.data:
self.error(section + ' section is missing.')
def check_valid_emails(self):
- """Check that emails are valid looking."""
+ """Returns True if emails are valid looking.."""
# Get email addresses.
email_addresses = []
primary_contact = self.data.get('primary_contact')
@@ -201,18 +214,18 @@ class ProjectYamlChecker:
self.error(email_address + ' is an invalid email address.')
def check_valid_language(self):
- """Check that the language is specified and valid."""
+ """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 self.LANGUAGES_SUPPORTED:
+ elif language not in constants.LANGUAGES:
self.error(
'"language: {language}" is not supported ({supported}).'.format(
- language=language, supported=self.LANGUAGES_SUPPORTED))
+ language=language, supported=constants.LANGUAGES))
def _check_one_project_yaml(project_yaml_filename):
- """Do checks on the project.yaml file."""
+ """Does checks on the project.yaml file. Returns True on success."""
if not _is_project_file(project_yaml_filename, 'project.yaml'):
return True
@@ -221,13 +234,13 @@ def _check_one_project_yaml(project_yaml_filename):
def check_project_yaml(paths):
- """Call _check_one_project_yaml on each path in |paths|. Return True if
- the result of every call is True."""
+ """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 do_checks(changed_files):
- """Run all presubmit checks return False if any fails."""
+ """Runs all presubmit checks. Returns False if any fails."""
checks = [
check_license, yapf, lint, check_project_yaml, check_lib_fuzzing_engine
]
@@ -245,6 +258,7 @@ _CHECK_LICENSE_EXTENSIONS = [
'.cc',
'.cpp',
'.css',
+ '.Dockerfile',
'.h',
'.htm',
'.html',
@@ -253,17 +267,21 @@ _CHECK_LICENSE_EXTENSIONS = [
'.py',
'.sh',
]
+THIRD_PARTY_DIR_NAME = 'third_party'
_LICENSE_STRING = 'http://www.apache.org/licenses/LICENSE-2.0'
def check_license(paths):
- """Validate license header."""
+ """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
@@ -279,7 +297,7 @@ def check_license(paths):
def bool_to_returncode(success):
- """Return 0 if |success|. Otherwise return 1."""
+ """Returns 0 if |success|. Otherwise returns 1."""
if success:
print('Success.')
return 0
@@ -294,7 +312,7 @@ def is_nonfuzzer_python(path):
def lint(_=None):
- """Run python's linter on infra. Return False if it fails linting."""
+ """Runs python's linter on infra. Returns False if it fails linting."""
command = ['python3', '-m', 'pylint', '-j', '0', 'infra']
returncode = subprocess.run(command, check=False).returncode
@@ -302,9 +320,9 @@ def lint(_=None):
def yapf(paths, validate=True):
- """Do yapf on |path| if it is Python file. Only validates format if
- |validate| otherwise, formats the file. Returns False if validation
- or formatting fails."""
+ """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
@@ -318,9 +336,9 @@ def yapf(paths, validate=True):
def get_changed_files():
- """Return a list of absolute paths of files changed in this git branch."""
+ """Returns a list of absolute paths of files changed in this git branch."""
branch_commit_hash = subprocess.check_output(
- ['git', 'merge-base', 'FETCH_HEAD', 'origin/HEAD']).strip().decode()
+ ['git', 'merge-base', 'HEAD', 'origin/HEAD']).strip().decode()
diff_commands = [
# Return list of modified files in the commits on this branch.
@@ -354,9 +372,9 @@ def run_build_tests():
def run_nonbuild_tests(parallel):
- """Run all tests but build tests. Do it 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."""
+ """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()
@@ -369,21 +387,34 @@ def run_nonbuild_tests(parallel):
# pass directories to pytest.
command = [
'pytest',
- # Test errors with error: "ModuleNotFoundError: No module named 'apt'.
- '--ignore-glob=infra/base-images/base-sanitizer-libs-builder/*',
'--ignore-glob=infra/build/*',
]
if parallel:
command.extend(['-n', 'auto'])
command += list(relevant_dirs)
print('Running non-build tests.')
- return subprocess.run(command, check=False).returncode == 0
+ # 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):
+
+def run_tests(_=None, parallel=False, build_tests=True, nonbuild_tests=True):
"""Runs all unit tests."""
- nonbuild_success = run_nonbuild_tests(parallel)
- build_success = run_build_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
@@ -411,6 +442,17 @@ def main():
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:
@@ -434,7 +476,10 @@ def main():
return bool_to_returncode(success)
if args.command == 'infra-tests':
- success = run_tests(relevant_files, parallel=args.parallel)
+ 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)
# Do all the checks (but no tests).
diff --git a/infra/pytest.ini b/infra/pytest.ini
index d9bb3737e..2a10272e2 100644
--- a/infra/pytest.ini
+++ b/infra/pytest.ini
@@ -1,2 +1,3 @@
[pytest]
-python_files = *_test.py \ No newline at end of file
+python_files = *_test.py
+log_cli = true \ No newline at end of file
diff --git a/infra/repo_manager.py b/infra/repo_manager.py
index a0b97b3ef..07880d81a 100644
--- a/infra/repo_manager.py
+++ b/infra/repo_manager.py
@@ -135,7 +135,7 @@ class RepoManager:
check_result=True)
self.git(['remote', 'update'], check_result=True)
- def get_commit_list(self, newest_commit, oldest_commit=None):
+ 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:
@@ -162,7 +162,11 @@ class RepoManager:
else:
commit_range = newest_commit
- out, _, err_code = self.git(['rev-list', commit_range])
+ 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:
diff --git a/infra/retry.py b/infra/retry.py
index 1a94180c6..1f6d54b8d 100644
--- a/infra/retry.py
+++ b/infra/retry.py
@@ -56,9 +56,9 @@ def wrap(retries,
"""Handle retry."""
if (exception is None or
isinstance(exception, exception_type)) and num_try < tries:
- logging.log('Retrying on %s failed with %s. Retrying again.',
- function_with_type,
- sys.exc_info()[1])
+ 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
diff --git a/infra/run_fuzzers.Dockerfile b/infra/run_fuzzers.Dockerfile
index b00bb12b9..8c8d7bb1b 100644
--- a/infra/run_fuzzers.Dockerfile
+++ b/infra/run_fuzzers.Dockerfile
@@ -13,7 +13,8 @@
# limitations under the License.
#
################################################################################
-# Docker image to run the CIFuzz action run_fuzzers in.
+# Docker image for running fuzzers on CIFuzz (the run_fuzzers action on GitHub
+# actions).
FROM gcr.io/oss-fuzz-base/cifuzz-base
@@ -22,5 +23,9 @@ FROM gcr.io/oss-fuzz-base/cifuzz-base
# 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 \ No newline at end of file
+ADD . ${OSS_FUZZ_ROOT}/infra
+
+RUN python3 -m pip install -r ${OSS_FUZZ_ROOT}/infra/cifuzz/requirements.txt
diff --git a/infra/templates.py b/infra/templates.py
index f16da924f..3db291453 100755
--- a/infra/templates.py
+++ b/infra/templates.py
@@ -17,7 +17,7 @@
PROJECT_YAML_TEMPLATE = """\
homepage: "<your_project_homepage>"
-language: <programming_language> # Example values: c, c++, go, rust.
+language: %(language)s"
primary_contact: "<primary_contact_email>"
main_repo: "https://path/to/main/repo.git"
"""
@@ -39,13 +39,21 @@ DOCKER_TEMPLATE = """\
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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 <git_url> %(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
+RUN COPY . $SRC/%(project_name)s
+WORKDIR %(project_name)s
+COPY .clusterfuzzlite/build.sh $SRC/
+"""
+
BUILD_TEMPLATE = """\
#!/bin/bash -eu
# Copyright %(year)d Google LLC
@@ -76,3 +84,30 @@ BUILD_TEMPLATE = """\
# /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
+"""
+
+TEMPLATES = {
+ 'build.sh': BUILD_TEMPLATE,
+ 'Dockerfile': DOCKER_TEMPLATE,
+ 'project.yaml': PROJECT_YAML_TEMPLATE
+}
+
+EXTERNAL_TEMPLATES = {
+ 'build.sh': EXTERNAL_BUILD_TEMPLATE,
+ 'Dockerfile': EXTERNAL_DOCKER_TEMPLATE
+}
diff --git a/infra/test_helpers.py b/infra/test_helpers.py
deleted file mode 100644
index be0b1b811..000000000
--- a/infra/test_helpers.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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 shutil
-import tempfile
-from unittest import mock
-
-
-def patch_environ(testcase_obj, env=None):
- """Patch environment."""
- if env is None:
- env = {}
-
- patcher = mock.patch.dict(os.environ, env)
- testcase_obj.addCleanup(patcher.stop)
- patcher.start()
-
-
-@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
diff --git a/infra/test_repos.py b/infra/test_repos.py
index fb12fbec5..389876864 100644
--- a/infra/test_repos.py
+++ b/infra/test_repos.py
@@ -27,7 +27,7 @@ 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',
- 'test_case_path'
+ 'testcase_path'
])
TEST_DIR_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)),
@@ -36,6 +36,8 @@ TEST_DIR_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)),
# 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',
@@ -46,7 +48,7 @@ TEST_REPOS = [
new_commit='dda418266c99ceab368d723facb52069cbb9c8d5',
intro_commit='df26f5f9c36e19cd503c0e462e9f72ad37b84c82',
fuzz_target='curl_fuzzer_ftp',
- test_case_path=os.path.join(TEST_DIR_PATH, 'curl_test_data')),
+ testcase_path=os.path.join(TEST_DIR_PATH, 'curl_test_data')),
ExampleRepo(project_name='libarchive',
oss_repo_name='libarchive',
git_repo_name='libarchive',
@@ -56,8 +58,8 @@ TEST_REPOS = [
new_commit='458e49358f17ec58d65ab1c45cf299baaf3c98d1',
intro_commit='840266712006de5e737f8052db920dfea2be4260',
fuzz_target='libarchive_fuzzer',
- test_case_path=os.path.join(TEST_DIR_PATH,
- 'libarchive_test_data')),
+ testcase_path=os.path.join(TEST_DIR_PATH,
+ 'libarchive_test_data')),
ExampleRepo(project_name='gonids',
oss_repo_name='gonids',
git_repo_name='gonids',
@@ -67,7 +69,7 @@ TEST_REPOS = [
new_commit='',
intro_commit='',
fuzz_target='',
- test_case_path='')
+ testcase_path='')
]
INVALID_REPO = ExampleRepo(project_name='notaproj',
@@ -79,4 +81,4 @@ INVALID_REPO = ExampleRepo(project_name='notaproj',
new_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
intro_commit='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
fuzz_target='NONEFUZZER',
- test_case_path='not/a/path')
+ testcase_path='not/a/path')
diff --git a/infra/triage-party/README.md b/infra/triage-party/README.md
new file mode 100644
index 000000000..2ab424148
--- /dev/null
+++ b/infra/triage-party/README.md
@@ -0,0 +1,13 @@
+# triage-party
+
+This folder contains the triage party config and deploy script for the oss-fuzz instance of [triage-party](https://github.com/google/triage-party).
+
+To make changes to triage party, you'll need to:
+1. Make changes to the [config](oss-fuzz.yaml)
+1. Deploy a new revision to Cloud Run via [deploy.sh](deploy.sh):
+
+```
+GITHUB_TOKEN_PATH=[path to file containing github token] DB_PASS=[CloudSQL database password] ./deploy.sh
+```
+
+Visit https://triage-party-pahypmb2lq-uc.a.run.app to join the party!
diff --git a/infra/triage-party/deploy.sh b/infra/triage-party/deploy.sh
new file mode 100755
index 000000000..cabdf43ab
--- /dev/null
+++ b/infra/triage-party/deploy.sh
@@ -0,0 +1,42 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+
+export PROJECT=oss-fuzz
+export IMAGE=gcr.io/oss-fuzz-base/triage-party
+export SERVICE_NAME=triage-party
+export CONFIG_FILE=config/examples/oss-fuzz.yaml
+
+
+# Copy triage-party into tmp dir, and copy config into correct spot
+readonly clean_repo=$(mktemp -d)
+git clone --depth 1 https://github.com/google/triage-party.git "${clean_repo}"
+cp ./oss-fuzz.yaml "${clean_repo}"/${CONFIG_FILE}
+cd "${clean_repo}"
+
+
+docker build -t "${IMAGE}" --build-arg "CFG=./${CONFIG_FILE}" .
+docker push "${IMAGE}" || exit 2
+
+readonly token="$(cat "${GITHUB_TOKEN_PATH}")"
+gcloud beta run deploy "${SERVICE_NAME}" \
+ --project "${PROJECT}" \
+ --image "${IMAGE}" \
+ --set-env-vars="GITHUB_TOKEN=${token},PERSIST_BACKEND=cloudsql,PERSIST_PATH=tp:${DB_PASS}@tcp(oss-fuzz/us-central1/triage-party)/tp" \
+ --allow-unauthenticated \
+ --region us-central1 \
+ --memory 384Mi \
+ --platform managed
diff --git a/infra/triage-party/oss-fuzz.yaml b/infra/triage-party/oss-fuzz.yaml
new file mode 100644
index 000000000..107e53e40
--- /dev/null
+++ b/infra/triage-party/oss-fuzz.yaml
@@ -0,0 +1,172 @@
+settings:
+ name: oss-fuzz
+ repos:
+ - https://github.com/google/oss-fuzz
+
+collections:
+ - id: Fuzzing Issues
+ name: Fuzzing Issues
+ dedup: true
+ description: >
+ Status of issues across oss-fuzz repos
+ rules:
+ # People who need a response
+ - fuzz-issue-updated-support
+ # fuzzing issues
+ - fuzz-bugs
+ - fuzz-priority
+ # Issues needing reprioritization
+ - fuzz-many-reactions
+ - fuzz-many-commenters
+ - fuzz-issue-zombies
+ # People with questions
+ - fuzz-issue-has-question
+ - id: PRs - fuzzing
+ name: OSS Fuzz PRs
+ description: >
+ Status of PRs in OSS-Fuzz
+ rules:
+ - prs-fuzz
+ - fuzz-pr-approved-stale
+ - fuzz-pr-unapproved-stale
+
+
+rules:
+ ### Pull requests
+
+ prs-fuzz:
+ name: "OSS Fuzz PRs"
+ type: pull_request
+ resolution: "Review requests or mark them as do-not-merge/work-in-progress"
+ filters:
+ - title: "!.*(WIP|wip).*"
+ - tag: "!(changes-requested|draft|approved)"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ # PR's needing closure
+ fuzz-pr-approved-stale:
+ name: "Pull requests: Approved and getting old"
+ resolution: "Merge PR"
+ type: pull_request
+ filters:
+ - label: "approved"
+ - updated: +2d
+ - responded: +1d
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ fuzz-pr-unapproved-stale:
+ name: "Pull Requests: Stale"
+ resolution: "Add comment and/or close PR"
+ type: pull_request
+ filters:
+ - created: +3d
+ - updated: +2d
+ - responded: +1d
+ - tag: "!draft"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ pr-approved-stale:
+ name: "Pull requests: Approved and getting old"
+ resolution: "Merge PR"
+ type: pull_request
+ filters:
+ - label: "approved"
+ - updated: +5d
+ - responded: +2d
+
+ pr-unapproved-stale:
+ name: "Pull Requests: Stale"
+ type: pull_request
+ resolution: "Add comment and/or close PR"
+ filters:
+ - created: +20d
+ - updated: +5d
+ - responded: +2d
+
+
+ ### Fuzzing Issues
+
+ fuzz-bugs:
+ name: "Fuzzing bugs that have not been commented on for 6 months"
+ resolution: "comment a status update"
+ type: issue
+ filters:
+ - label: "bug"
+ - responded: +180d
+ - tag: "!member-last"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+
+ fuzz-priority:
+ name: "Fuzzing priority issues that have not been commented on for 6 months"
+ resolution: "comment a status update"
+ type: issue
+ filters:
+ - label: "priority"
+ - responded: +180d
+ - tag: "!member-last"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+
+ fuzz-many-reactions:
+ name: "many reactions, low priority"
+ resolution: "Upgrade to priority"
+ filters:
+ - reactions: ">3"
+ - reactions-per-month: ">0.75"
+ - label: "!priority"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ fuzz-many-commenters:
+ name: "many commenters, low priority"
+ resolution: "Upgrade to priority"
+ filters:
+ - commenters: ">2"
+ - commenters-per-month: ">1.9"
+ - created: "+30d"
+ - label: "!priority"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ fuzz-issue-zombies:
+ name: "Screaming into the void"
+ resolution: "Reopen, or ask folks to open a new issue"
+ type: issue
+ filters:
+ - state: closed
+ - updated: -7d
+ - tag: recv
+ - comments-while-closed: ">1"
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ # People with questions
+ fuzz-issue-has-question:
+ name: "Overdue answers for a question"
+ resolution: "Add a comment"
+ type: issue
+ filters:
+ - tag: recv-q
+ - tag: "!member-last"
+ - tag: "!contributor-last"
+ - responded: +6d
+ repos:
+ - https://github.com/google/oss-fuzz
+
+ fuzz-issue-updated-support:
+ name: "Open support requests"
+ resolution: "Add a comment"
+ type: issue
+ filters:
+ - tag: recv
+ - tag: "!member-last"
+ - tag: "!contributor-last"
+ - responded: +6d
+ repos:
+ - https://github.com/google/oss-fuzz
diff --git a/infra/utils.py b/infra/utils.py
index fe5dd8730..f0b58a4da 100644
--- a/infra/utils.py
+++ b/infra/utils.py
@@ -17,6 +17,7 @@ import logging
import os
import posixpath
import re
+import shlex
import stat
import subprocess
import sys
@@ -25,7 +26,8 @@ import helper
ALLOWED_FUZZ_TARGET_EXTENSIONS = ['', '.exe']
FUZZ_TARGET_SEARCH_STRING = 'LLVMFuzzerTestOneInput'
-VALID_TARGET_NAME = re.compile(r'^[a-zA-Z0-9_-]+$')
+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/'
@@ -38,16 +40,25 @@ def chdir_to_root():
os.chdir(helper.OSS_FUZZ_DIR)
-def execute(command, location=None, check_result=False):
- """ Runs a shell command in the specified directory location.
+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):
+ """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.
+ 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, error code.
+ stdout, stderr, returncode.
Raises:
RuntimeError: running a command resulted in an error.
@@ -58,24 +69,27 @@ def execute(command, location=None, check_result=False):
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
- cwd=location)
+ cwd=location,
+ env=env)
out, err = process.communicate()
out = out.decode('utf-8', errors='ignore')
err = err.decode('utf-8', errors='ignore')
+
+ command_str = command_to_string(command)
if err:
- logging.debug('Stderr of command \'%s\' is %s.', ' '.join(command), err)
+ logging.debug('Stderr of command "%s" is: %s.', command_str, err)
if check_result and process.returncode:
- raise RuntimeError(
- 'Executing command \'{0}\' failed with error: {1}.'.format(
- ' '.join(command), err))
+ raise RuntimeError('Executing command "{0}" failed with error: {1}.'.format(
+ command_str, err))
return out, err, process.returncode
-def get_fuzz_targets(path):
- """Get list of fuzz targets in a directory.
+def get_fuzz_targets(path, top_level_only=False):
+ """Gets fuzz targets in a directory.
Args:
path: A path to search for fuzz targets in.
+ top_level_only: If True, only search |path|, do not recurse into subdirs.
Returns:
A list of paths to fuzzers or an empty list if None.
@@ -84,6 +98,9 @@ def get_fuzz_targets(path):
return []
fuzz_target_paths = []
for root, _, fuzzers in os.walk(path):
+ if top_level_only and path != root:
+ continue
+
for fuzzer in fuzzers:
file_path = os.path.join(root, fuzzer)
if is_fuzz_target_local(file_path):
@@ -112,11 +129,17 @@ def is_fuzz_target_local(file_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.match(filename):
+ 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
@@ -135,7 +158,7 @@ def is_fuzz_target_local(file_path):
def binary_print(string):
- """Print that can print a binary string."""
+ """Prints string. Can print a binary string."""
if isinstance(string, bytes):
string += b'\n'
else:
diff --git a/infra/utils_test.py b/infra/utils_test.py
index aa6ec7ba7..9b7fbc903 100644
--- a/infra/utils_test.py
+++ b/infra/utils_test.py
@@ -24,7 +24,7 @@ import helper
EXAMPLE_PROJECT = 'example'
TEST_OUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)),
- 'cifuzz', 'test_data', 'out')
+ 'cifuzz', 'test_data', 'build-out')
class IsFuzzTargetLocalTest(unittest.TestCase):
@@ -118,17 +118,33 @@ class BinaryPrintTest(unittest.TestCase):
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 mocked_write:
+ with mock.patch('sys.stdout.buffer.write') as mock_write:
utils.binary_print('hello')
- mocked_write.assert_called_with('hello\n')
+ 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 mocked_write:
+ with mock.patch('sys.stdout.buffer.write') as mock_write:
utils.binary_print(b'hello')
- mocked_write.assert_called_with(b'hello\n')
+ 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__':
diff --git a/projects/apache-commons/CompressSevenZFuzzer.java b/projects/apache-commons/CompressSevenZFuzzer.java
new file mode 100644
index 000000000..8bc19321f
--- /dev/null
+++ b/projects/apache-commons/CompressSevenZFuzzer.java
@@ -0,0 +1,39 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.SevenZFile;
+import org.apache.commons.compress.archivers.sevenz.SevenZFileOptions;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressSevenZFuzzer {
+ private static final SevenZFileOptions options = new SevenZFileOptions.Builder()
+ .withMaxMemoryLimitInKb(1_000_000)
+ .build();
+
+ public static void fuzzerInitialize() {
+ LogManager.getLogManager().reset();
+ }
+
+ public static void fuzzerTestOneInput(byte[] data) {
+ try {
+ new SevenZFile(new SeekableInMemoryByteChannel(data), options).close();
+ } catch (IOException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/CompressTarFuzzer.java b/projects/apache-commons/CompressTarFuzzer.java
new file mode 100644
index 000000000..2df863dfa
--- /dev/null
+++ b/projects/apache-commons/CompressTarFuzzer.java
@@ -0,0 +1,33 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.TarFile;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressTarFuzzer {
+ public static void fuzzerInitialize() {
+ LogManager.getLogManager().reset();
+ }
+
+ public static void fuzzerTestOneInput(byte[] data) {
+ try {
+ new TarFile(data).close();
+ } catch (IOException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/CompressZipFuzzer.java b/projects/apache-commons/CompressZipFuzzer.java
new file mode 100644
index 000000000..bc9a8a0e6
--- /dev/null
+++ b/projects/apache-commons/CompressZipFuzzer.java
@@ -0,0 +1,34 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.ZipFile;
+import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
+
+import java.io.IOException;
+import java.util.logging.LogManager;
+
+public class CompressZipFuzzer {
+ public static void fuzzerInitialize() {
+ LogManager.getLogManager().reset();
+ }
+
+ public static void fuzzerTestOneInput(byte[] data) {
+ try {
+ new ZipFile(new SeekableInMemoryByteChannel(data)).close();
+ } catch (IOException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/Dockerfile b/projects/apache-commons/Dockerfile
new file mode 100644
index 000000000..55b460cc0
--- /dev/null
+++ b/projects/apache-commons/Dockerfile
@@ -0,0 +1,61 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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://downloads.apache.org/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
+
+# Dictionaries
+RUN git clone --depth 1 https://github.com/google/fuzzing && \
+ mv fuzzing/dictionaries/zip.dict $SRC/CompressZipFuzzer.dict && \
+ 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/CompressTarFuzzer_seed_corpus.zip go-fuzz-corpus/tar/corpus/* && \
+ zip -j $SRC/CompressZipFuzzer_seed_corpus.zip go-fuzz-corpus/zip/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
+
+# Compress
+RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-compress.git
+
+RUN zip -uj $SRC/CompressTarFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.tar && \
+ zip -uj $SRC/CompressZipFuzzer_seed_corpus.zip commons-compress/src/test/resources/*.zip && \
+ zip -j $SRC/CompressSevenZFuzzer_seed_corpus.zip commons-compress/src/test/resources/bla.7z
+
+# Imaging
+RUN git clone --depth 1 https://gitbox.apache.org/repos/asf/commons-imaging.git
+
+# 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/
diff --git a/projects/apache-commons/GeometryObjFuzzer.java b/projects/apache-commons/GeometryObjFuzzer.java
new file mode 100644
index 000000000..6b8900f4b
--- /dev/null
+++ b/projects/apache-commons/GeometryObjFuzzer.java
@@ -0,0 +1,40 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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
+ }
+ }
+}
diff --git a/projects/apache-commons/GeometryStlBinaryFuzzer.java b/projects/apache-commons/GeometryStlBinaryFuzzer.java
new file mode 100644
index 000000000..3df154700
--- /dev/null
+++ b/projects/apache-commons/GeometryStlBinaryFuzzer.java
@@ -0,0 +1,40 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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
+ }
+ }
+}
diff --git a/projects/apache-commons/GeometryStlTextFuzzer.java b/projects/apache-commons/GeometryStlTextFuzzer.java
new file mode 100644
index 000000000..5bddb17d5
--- /dev/null
+++ b/projects/apache-commons/GeometryStlTextFuzzer.java
@@ -0,0 +1,55 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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;
+ }
+}
diff --git a/projects/apache-commons/GeometryTextFuzzer.java b/projects/apache-commons/GeometryTextFuzzer.java
new file mode 100644
index 000000000..ab318f2a8
--- /dev/null
+++ b/projects/apache-commons/GeometryTextFuzzer.java
@@ -0,0 +1,41 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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
+ }
+ }
+}
diff --git a/projects/apache-commons/ImagingBmpFuzzer.java b/projects/apache-commons/ImagingBmpFuzzer.java
new file mode 100644
index 000000000..c9071705f
--- /dev/null
+++ b/projects/apache-commons/ImagingBmpFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.bmp.BmpImageParser;
+
+public class ImagingBmpFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new BmpImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/ImagingGifFuzzer.java b/projects/apache-commons/ImagingGifFuzzer.java
new file mode 100644
index 000000000..6c59cf42d
--- /dev/null
+++ b/projects/apache-commons/ImagingGifFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.gif.GifImageParser;
+
+public class ImagingGifFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new GifImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/ImagingJpegFuzzer.java b/projects/apache-commons/ImagingJpegFuzzer.java
new file mode 100644
index 000000000..a40004e75
--- /dev/null
+++ b/projects/apache-commons/ImagingJpegFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.jpeg.JpegImageParser;
+
+public class ImagingJpegFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new JpegImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/ImagingPngFuzzer.java b/projects/apache-commons/ImagingPngFuzzer.java
new file mode 100644
index 000000000..406480dd0
--- /dev/null
+++ b/projects/apache-commons/ImagingPngFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.png.PngImageParser;
+
+public class ImagingPngFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new PngImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/ImagingTiffFuzzer.java b/projects/apache-commons/ImagingTiffFuzzer.java
new file mode 100644
index 000000000..683375196
--- /dev/null
+++ b/projects/apache-commons/ImagingTiffFuzzer.java
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.tiff.TiffImageParser;
+
+public class ImagingTiffFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new TiffImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/projects/apache-commons/build.sh b/projects/apache-commons/build.sh
new file mode 100755
index 000000000..6716afdfa
--- /dev/null
+++ b/projects/apache-commons/build.sh
@@ -0,0 +1,66 @@
+#!/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
+
+PROJECTS="compress imaging geometry"
+GEOMETRY_MODULE="commons-geometry-io-euclidean"
+
+for project in $PROJECTS; do
+ cd $SRC/commons-$project
+ MAVEN_ARGS="-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)
+
+ if [ $project = 'geometry' ]; then
+ # commons-geometry is a multi-module project and requires special handling in order
+ # to build and extract the proper module (commons-geometry-io-euclidean)
+ $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade -am -pl $GEOMETRY_MODULE $MAVEN_ARGS
+ cp "$GEOMETRY_MODULE/target/$GEOMETRY_MODULE-$CURRENT_VERSION.jar" $OUT/commons-$project.jar
+ else
+ $MVN package org.apache.maven.plugins:maven-shade-plugin:3.2.4:shade $MAVEN_ARGS
+ cp "target/commons-$project-$CURRENT_VERSION.jar" $OUT/commons-$project.jar
+ fi
+
+ ALL_JARS="commons-$project.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 "$project"'*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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
+ done
+done
diff --git a/projects/apache-commons/project.yaml b/projects/apache-commons/project.yaml
new file mode 100644
index 000000000..8d7aa5a14
--- /dev/null
+++ b/projects/apache-commons/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://commons.apache.org"
+language: jvm
+primary_contact: "boards@gmail.com"
+auto_ccs:
+ - "fuzz-testing@commons.apache.org"
+ - "brunodepaulak@gmail.com"
+ - "meumertzheim@code-intelligence.com"
+ - "peteralfredlee@gmail.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://gitbox.apache.org/repos/asf/commons-compress.git"
+sanitizers:
+ - address
diff --git a/projects/apache-httpd/Dockerfile b/projects/apache-httpd/Dockerfile
new file mode 100644
index 000000000..39b419e60
--- /dev/null
+++ b/projects/apache-httpd/Dockerfile
@@ -0,0 +1,34 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libpcre3 \
+ libpcre3-dev uuid-dev pkg-config libtool-bin
+
+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/
+COPY patches.diff $SRC/
diff --git a/projects/apache-httpd/build.sh b/projects/apache-httpd/build.sh
new file mode 100755
index 000000000..59cf78606
--- /dev/null
+++ b/projects/apache-httpd/build.sh
@@ -0,0 +1,45 @@
+#!/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
+unset CXX
+
+git apply --ignore-space-change --ignore-whitespace $SRC/patches.diff
+
+# 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
+
+# Build the fuzzers
+for fuzzname in utils parse tokenize addr_parse uri request preq; do
+ $CC $CFLAGS $LIB_FUZZING_ENGINE \
+ -I$SRC/fuzz-headers/lang/c -I./include -I./os/unix \
+ -I./srclib/apr/include -I./srclib/apr-util/include/ \
+ $SRC/fuzz_${fuzzname}.c -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 -lpcre -lcrypt -lexpat
+done
diff --git a/projects/gpac/fuzz_parse.c b/projects/apache-httpd/fuzz_addr_parse.c
index b7c9ac9a6..3fc00ab6b 100644
--- a/projects/gpac/fuzz_parse.c
+++ b/projects/apache-httpd/fuzz_addr_parse.c
@@ -9,28 +9,29 @@ WITHOUT 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 <stdio.h>
-#include <unistd.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
-#include <gpac/internal/isomedia_dev.h>
-#include <gpac/constants.h>
+#include "apr_network_io.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- char filename[256];
- sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+ apr_pool_t *pool;
+ apr_pool_initialize();
+ if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+ abort();
+ }
- FILE *fp = fopen(filename, "wb");
- if (!fp) {
- return 0;
- }
- fwrite(data, size, 1, fp);
- fclose(fp);
+ char *addr = NULL;
+ char *scope_id = NULL;
+ apr_port_t port = 0;
+ char *input_string = strndup((const char *)data, size);
- GF_ISOFile *movie = NULL;
- movie = gf_isom_open_file(filename, GF_ISOM_OPEN_READ_DUMP, NULL);
- if (movie != NULL) {
- gf_isom_close(movie);
- }
- unlink(filename);
- return 0;
+ apr_parse_addr_port(&addr, &scope_id, &port, input_string, pool);
+
+ free(input_string);
+ apr_pool_destroy(pool);
+ apr_terminate();
+
+ return 0;
}
diff --git a/projects/apache-httpd/fuzz_parse.c b/projects/apache-httpd/fuzz_parse.c
new file mode 100644
index 000000000..fb87db532
--- /dev/null
+++ b/projects/apache-httpd/fuzz_parse.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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;
+}
diff --git a/projects/apache-httpd/fuzz_preq.c b/projects/apache-httpd/fuzz_preq.c
new file mode 100644
index 000000000..2d8d9215f
--- /dev/null
+++ b/projects/apache-httpd/fuzz_preq.c
@@ -0,0 +1,84 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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;
+}
diff --git a/projects/apache-httpd/fuzz_request.c b/projects/apache-httpd/fuzz_request.c
new file mode 100644
index 000000000..05a42c69d
--- /dev/null
+++ b/projects/apache-httpd/fuzz_request.c
@@ -0,0 +1,138 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "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;
+}
diff --git a/projects/apache-httpd/fuzz_tokenize.c b/projects/apache-httpd/fuzz_tokenize.c
new file mode 100644
index 000000000..1de629558
--- /dev/null
+++ b/projects/apache-httpd/fuzz_tokenize.c
@@ -0,0 +1,34 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#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_terminate();
+
+ return 0;
+}
diff --git a/projects/apache-httpd/fuzz_uri.c b/projects/apache-httpd/fuzz_uri.c
new file mode 100644
index 000000000..789b96f05
--- /dev/null
+++ b/projects/apache-httpd/fuzz_uri.c
@@ -0,0 +1,65 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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;
+}
diff --git a/projects/apache-httpd/fuzz_utils.c b/projects/apache-httpd/fuzz_utils.c
new file mode 100644
index 000000000..8fb2d255e
--- /dev/null
+++ b/projects/apache-httpd/fuzz_utils.c
@@ -0,0 +1,182 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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"
+
+
+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) {
+
+ // Targets that do not require a pool
+ ap_cstr_casecmp(new_str, new_str);
+ ap_getparents(new_str);
+ ap_unescape_url(new_str);
+ ap_unescape_urlencoded(new_str);
+ ap_strcmp_match(new_str, new_dst);
+
+ char *ns3 = af_gb_get_null_terminated(&data2, &size2);
+ if (ns3 != NULL) {
+ ap_no2slash(ns3);
+ }
+
+ char *ns11 = af_gb_get_null_terminated(&data2, &size2);
+ if (ns11) {
+ char *ns10 = malloc(strlen(ns11)*3+1); // big enough for worst-case URL-escaped input.
+ ap_escape_path_segment_buffer(ns10, ns11);
+ free(ns10);
+ }
+
+ // Pool initialisation
+ if (apr_pool_initialize() == APR_SUCCESS) {
+ apr_pool_t *pool = NULL;
+ apr_pool_create(&pool, NULL);
+
+ // Targets that require a pool
+ ns3 = af_gb_get_null_terminated(&data2, &size2);
+ if (ns3 != NULL) {
+ ap_make_dirstr_parent(pool, ns3);
+ }
+
+ 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);
+
+ if (size > 2) {
+ ap_cstr_casecmpn(new_str, new_str + 2, size - 2);
+ }
+
+ char *d = malloc(size * 2);
+ ap_escape_errorlog_item(d, new_str, size * 2);
+ free(d);
+
+ // base64
+ char *decoded = NULL;
+ decoded = ap_pbase64decode(pool, new_str);
+ ap_pbase64encode(pool, new_str);
+
+ char *ns12 = af_gb_get_null_terminated(&data2, &size2);
+ if (ns12 != NULL) {
+ char *d;
+ apr_size_t dlen;
+ ap_pbase64decode_strict(pool, ns12, &d, &dlen);
+ }
+
+ char *tmp_s = new_str;
+ ap_getword_conf2(pool, &tmp_s);
+
+ // str functions
+ ap_strcasecmp_match(tmp_s, new_dst);
+ ap_strcasestr(tmp_s, new_dst);
+
+ // List functions
+ tmp_s = new_str;
+ ap_get_list_item(pool, &tmp_s);
+ tmp_s = new_str;
+ ap_find_list_item(pool, &tmp_s, "kjahsdfkj");
+ ap_find_token(pool, tmp_s, "klsjdfk");
+ ap_find_last_token(pool, tmp_s, "sdadf");
+ ap_is_chunked(pool, tmp_s);
+
+ apr_array_header_t *offers = NULL;
+ ap_parse_token_list_strict(pool, new_str, &offers, 0);
+
+ char *tmp_null = NULL;
+ ap_pstr2_alnum(pool, new_str, &tmp_null);
+
+ // Word functions
+ tmp_s = new_str;
+ ap_getword(pool, &tmp_s, 0);
+
+ tmp_s = new_str;
+ ap_getword_white_nc(pool, &tmp_s);
+
+ tmp_s = new_str;
+ ap_get_token(pool, &tmp_s, 1);
+
+ tmp_s = new_str;
+ ap_escape_urlencoded(pool, tmp_s);
+
+ apr_interval_time_t timeout;
+ ap_timeout_parameter_parse(new_str, &timeout, "ms");
+
+ tmp_s = new_str;
+ ap_content_type_tolower(tmp_s);
+
+
+ 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;
+}
diff --git a/projects/apache-httpd/patches.diff b/projects/apache-httpd/patches.diff
new file mode 100644
index 000000000..d93b12b98
--- /dev/null
+++ b/projects/apache-httpd/patches.diff
@@ -0,0 +1,44 @@
+diff --git a/server/apreq_parser_header.c b/server/apreq_parser_header.c
+index 19588be..7067e58 100644
+--- a/server/apreq_parser_header.c
++++ b/server/apreq_parser_header.c
+@@ -89,7 +89,7 @@ static apr_status_t split_header_line(apreq_param_t **p,
+ if (s != APR_SUCCESS)
+ return s;
+
+- assert(nlen >= len);
++ if (!(nlen >= len)) { return APR_EBADARG; } assert(nlen >= len);
+ end->iov_len = len;
+ nlen -= len;
+
+@@ -103,13 +103,13 @@ static apr_status_t split_header_line(apreq_param_t **p,
+ if (s != APR_SUCCESS)
+ return s;
+
+- assert(glen >= dlen);
++ if (!(glen >= dlen)) { return APR_EBADARG; } assert(glen >= dlen);
+ glen -= dlen;
+ e = APR_BUCKET_NEXT(e);
+ }
+
+ /* copy value */
+- assert(vlen > 0);
++ if (!(vlen > 0)) { return APR_EBADARG; } assert(vlen > 0);
+ dest = v->data;
+ while (vlen > 0) {
+
+@@ -119,12 +119,12 @@ static apr_status_t split_header_line(apreq_param_t **p,
+
+ memcpy(dest, data, dlen);
+ dest += dlen;
+- assert(vlen >= dlen);
++ if (!(vlen >= dlen)) { return APR_EBADARG; } assert(vlen >= dlen);
+ vlen -= dlen;
+ e = APR_BUCKET_NEXT(e);
+ }
+
+- assert(dest[-1] == '\n');
++ if (!(dest[-1] == '\n')) { return APR_EBADARG; } assert(dest[-1] == '\n');
+
+ if (dest[-2] == '\r')
+ --dest;
diff --git a/projects/apache-httpd/project.yaml b/projects/apache-httpd/project.yaml
new file mode 100644
index 000000000..4b7652b6e
--- /dev/null
+++ b/projects/apache-httpd/project.yaml
@@ -0,0 +1,8 @@
+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"
diff --git a/projects/assimp/Dockerfile b/projects/assimp/Dockerfile
index 88564a72a..cf7ccd6e8 100644
--- a/projects/assimp/Dockerfile
+++ b/projects/assimp/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2019 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/projects/assimp/build.sh b/projects/assimp/build.sh
index 55efcb7ce..4cb8bea37 100644
--- a/projects/assimp/build.sh
+++ b/projects/assimp/build.sh
@@ -1,5 +1,5 @@
#!/bin/bash -eu
-# Copyright 2019 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
################################################################################
# generate build env and build assimp
-cmake CMakeLists.txt -G "Ninja" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_ZLIB=ON -DASSIMP_BUILD_TESTS=OFF -DASSIMP_BUILD_ASSIMP_TOOLS=OFF -DASSIMP_BUILD_SAMPLES=OFF
+cmake CMakeLists.txt -G "Ninja" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_ZLIB=ON \
+ -DASSIMP_BUILD_TESTS=OFF -DASSIMP_BUILD_ASSIMP_TOOLS=OFF \
+ -DASSIMP_BUILD_SAMPLES=OFF
cmake --build .
-# build the fuzzer
-$CXX $CXXFLAGS -std=c++11 -I$SRC/assimp/include \
- fuzz/assimp_fuzzer.cc -o $OUT/assimp_fuzzer \
- $LIB_FUZZING_ENGINE $SRC/assimp/lib/libassimp.a $SRC/assimp/lib/libIrrXML.a $SRC/assimp/lib/libzlibstatic.a
+# Build the fuzzer
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -std=c++11 -I$SRC/assimp/include \
+ fuzz/assimp_fuzzer.cc -o $OUT/assimp_fuzzer \
+ ./lib/libassimp.a ./contrib/zlib/libzlibstatic.a
diff --git a/projects/assimp/project.yaml b/projects/assimp/project.yaml
index 834e912f7..10d056fd1 100644
--- a/projects/assimp/project.yaml
+++ b/projects/assimp/project.yaml
@@ -3,7 +3,8 @@ language: c++
primary_contact: "kim.kulling@googlemail.com"
sanitizers:
- address
- - memory:
- experimental: True
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+# experimental: True
- undefined
main_repo: 'https://github.com/assimp/assimp.git'
diff --git a/projects/assimp/project_proposed.yaml b/projects/assimp/project_proposed.yaml
deleted file mode 100644
index 612e75b98..000000000
--- a/projects/assimp/project_proposed.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-homepage: "https://github.com/assimp/assimp"
-primary_contact: "kim.kulling@googlemail.com"
-auto_ccs:
- - "kientzle@gmail.com"
- - "martin@matuska.org"
-sanitizers:
- - address
- - memory:
- experimental: True
- - undefined
diff --git a/projects/bazel-rules-fuzzing-test-java/Dockerfile b/projects/bazel-rules-fuzzing-test-java/Dockerfile
new file mode 100644
index 000000000..89e8b8759
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/bazelbuild/rules_fuzzing.git
+WORKDIR $SRC/rules_fuzzing/
+COPY build.sh $SRC/
diff --git a/projects/bazel-rules-fuzzing-test-java/build.sh b/projects/bazel-rules-fuzzing-test-java/build.sh
new file mode 100644
index 000000000..4698ebd92
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/build.sh
@@ -0,0 +1,27 @@
+#!/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.
+#
+################################################################################
+
+# Due to https://github.com/bazelbuild/bazel/issues/11128, affecting Bazel 4.0
+# or earlier, we cannot use the "@rules_fuzzing//" prefix for the label-typed
+# cc_engine configuration flag when fuzzing directly the rules_fuzzing workspace.
+#
+# This is NOT needed for any other Bazel repository that depends on
+# rules_fuzzing.
+export BAZEL_EXTRA_BUILD_FLAGS="--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine"
+
+bazel_build_fuzz_tests
diff --git a/projects/bazel-rules-fuzzing-test-java/project.yaml b/projects/bazel-rules-fuzzing-test-java/project.yaml
new file mode 100644
index 000000000..888c37f86
--- /dev/null
+++ b/projects/bazel-rules-fuzzing-test-java/project.yaml
@@ -0,0 +1,13 @@
+homepage: "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
diff --git a/projects/bazel-rules-fuzzing-test/build.sh b/projects/bazel-rules-fuzzing-test/build.sh
index 056e16b3d..4698ebd92 100644
--- a/projects/bazel-rules-fuzzing-test/build.sh
+++ b/projects/bazel-rules-fuzzing-test/build.sh
@@ -16,7 +16,12 @@
#
################################################################################
-# This is an example build script for projects using the rules_fuzzing library
-# for Bazel.
+# Due to https://github.com/bazelbuild/bazel/issues/11128, affecting Bazel 4.0
+# or earlier, we cannot use the "@rules_fuzzing//" prefix for the label-typed
+# cc_engine configuration flag when fuzzing directly the rules_fuzzing workspace.
+#
+# This is NOT needed for any other Bazel repository that depends on
+# rules_fuzzing.
+export BAZEL_EXTRA_BUILD_FLAGS="--//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine"
bazel_build_fuzz_tests
diff --git a/projects/bearssl/Dockerfile b/projects/bearssl/Dockerfile
index 2a5d3e76a..6f14e63ce 100644
--- a/projects/bearssl/Dockerfile
+++ b/projects/bearssl/Dockerfile
@@ -20,5 +20,5 @@ RUN git clone --depth 1 https://www.bearssl.org/git/BearSSL
RUN git clone --depth 1 https://github.com/randombit/botan.git
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
COPY build.sh $SRC/
diff --git a/projects/bearssl/project.yaml b/projects/bearssl/project.yaml
index d9b20ae0e..720d4577c 100644
--- a/projects/bearssl/project.yaml
+++ b/projects/bearssl/project.yaml
@@ -6,7 +6,8 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- i386
diff --git a/projects/bignum-fuzzer/Dockerfile b/projects/bignum-fuzzer/Dockerfile
index 6b7483642..b1c36eb66 100644
--- a/projects/bignum-fuzzer/Dockerfile
+++ b/projects/bignum-fuzzer/Dockerfile
@@ -15,12 +15,12 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y software-properties-common python-software-properties wget curl sudo mercurial autoconf bison texinfo libboost-all-dev cmake
+RUN apt-get update && apt-get install -y software-properties-common curl sudo mercurial autoconf bison texinfo libboost-all-dev cmake wget
-RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.0.tar.gz
+RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.tar.gz
RUN git clone --depth 1 https://github.com/guidovranken/bignum-fuzzer
RUN git clone --depth 1 https://github.com/openssl/openssl
RUN hg clone https://gmplib.org/repo/gmp/ libgmp/
RUN git clone https://boringssl.googlesource.com/boringssl
-RUN git clone --depth 1 https://github.com/ARMmbed/mbedtls
+RUN git clone --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls
COPY build.sh $SRC/
diff --git a/projects/bignum-fuzzer/build.sh b/projects/bignum-fuzzer/build.sh
index 8c29baff4..737120006 100755
--- a/projects/bignum-fuzzer/build.sh
+++ b/projects/bignum-fuzzer/build.sh
@@ -20,8 +20,8 @@
#source $HOME/.cargo/env
# Build libmpdec
-tar zxf mpdecimal-2.5.0.tar.gz
-cd mpdecimal-2.5.0
+tar zxf mpdecimal-2.5.1.tar.gz
+cd mpdecimal-2.5.1
./configure && make -j$(nproc)
cd $SRC/openssl
@@ -60,7 +60,7 @@ 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-2.5.0/libmpdec/libmpdec.a LIBMPDEC_INCLUDE_PATH=$SRC/mpdecimal-2.5.0/libmpdec make
+LIBMPDEC_A_PATH=$SRC/mpdecimal-2.5.1/libmpdec/libmpdec.a LIBMPDEC_INCLUDE_PATH=$SRC/mpdecimal-2.5.1/libmpdec make
BASE_CXXFLAGS=$CXXFLAGS
diff --git a/projects/binutils/build.sh b/projects/binutils/build.sh
index c5d903881..2b5142483 100755
--- a/projects/binutils/build.sh
+++ b/projects/binutils/build.sh
@@ -29,7 +29,9 @@ sed -i 's/vfprintf (stderr/\/\//' elfcomm.c
sed -i 's/fprintf (stderr/\/\//' elfcomm.c
cd ../
-./configure --disable-gdb --enable-targets=all
+./configure --disable-gdb --disable-gdbserver --disable-gdbsupport \
+ --disable-libdecnumber --disable-readline --disable-sim \
+ --enable-targets=all --disable-werror
make MAKEINFO=true && true
# Make fuzzer directory
@@ -58,13 +60,16 @@ for i in readelf; do
done
# Link the files
-## Readelf
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib -o fuzz_readelf fuzz_readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a
-mv fuzz_readelf $OUT/fuzz_readelf
+# Only link if they exist
+if ([ -f dwarf.o ] && [ -f elfcomm.o ] && [ -f version.o ]); then
+ ## Readelf
+ $CXX $CXXFLAGS $LIB_FUZZING_ENGINE -W -Wall -I./../zlib -o fuzz_readelf fuzz_readelf.o version.o unwind-ia64.o dwarf.o elfcomm.o ../libctf/.libs/libctf-nobfd.a -L/src/binutils-gdb/zlib -lz ../libiberty/libiberty.a
+ mv fuzz_readelf $OUT/fuzz_readelf
-### Set up seed corpus for readelf in the form of a single ELF file.
-zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf
-mv fuzz_readelf_seed_corpus.zip $OUT/
+ ### Set up seed corpus for readelf in the form of a single ELF file.
+ zip fuzz_readelf_seed_corpus.zip /src/fuzz_readelf_seed_corpus/simple_elf
+ mv fuzz_readelf_seed_corpus.zip $OUT/
-## Copy over the options file
-cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options
+ ## Copy over the options file
+ cp $SRC/fuzz_readelf.options $OUT/fuzz_readelf.options
+fi
diff --git a/projects/binutils/fuzz_readelf.c b/projects/binutils/fuzz_readelf.c
index a222e0c09..9df34fda5 100644
--- a/projects/binutils/fuzz_readelf.c
+++ b/projects/binutils/fuzz_readelf.c
@@ -28,18 +28,18 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
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;
+ 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;
// Main fuzz entrypoint
process_file(filename);
diff --git a/projects/bitcoin-core/Dockerfile b/projects/bitcoin-core/Dockerfile
new file mode 100644
index 000000000..61972719b
--- /dev/null
+++ b/projects/bitcoin-core/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+
+# 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 libtool autotools-dev automake pkg-config bsdmainutils python3 \
+ make automake cmake curl g++-multilib libtool binutils-gold bsdmainutils pkg-config patch bison \
+ 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
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN git clone --depth 1 https://github.com/trezor/trezor-firmware.git
+RUN git clone --depth 1 https://github.com/google/wycheproof.git
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+WORKDIR bitcoin-core
+COPY build.sh $SRC/
+COPY build_cryptofuzz.sh $SRC/
diff --git a/projects/bitcoin-core/build.sh b/projects/bitcoin-core/build.sh
new file mode 100755
index 000000000..a89691a38
--- /dev/null
+++ b/projects/bitcoin-core/build.sh
@@ -0,0 +1,97 @@
+#!/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/build_cryptofuzz.sh
+
+cd $SRC/bitcoin-core/
+
+# Build dependencies
+# This will also force static builds
+if [ "$ARCHITECTURE" = "i386" ]; then
+ export BUILD_TRIPLET="i686-pc-linux-gnu"
+else
+ export BUILD_TRIPLET="x86_64-pc-linux-gnu"
+fi
+(
+ cd depends
+ sed -i --regexp-extended '/.*rm -rf .*extract_dir.*/d' ./funcs.mk # Keep extracted source
+ make HOST=$BUILD_TRIPLET DEBUG=1 NO_QT=1 NO_WALLET=1 NO_ZMQ=1 NO_UPNP=1 NO_NATPMP=1 boost_cxxflags="-std=c++17 -fvisibility=hidden -fPIC ${CXXFLAGS}" libevent_cflags="${CFLAGS}" -j$(nproc)
+)
+
+# Build the fuzz targets
+
+sed -i "s|PROVIDE_FUZZ_MAIN_FUNCTION|NEVER_PROVIDE_MAIN_FOR_OSS_FUZZ|g" "./configure.ac"
+./autogen.sh
+
+# Temporarily compile with O2 to work around clang-13 (and later) UBSan
+# -fsanitize=vptr,object-size false positive that only happens with -O1
+if [ "$SANITIZER" = "undefined" ]; then
+ export CFLAGS="$CFLAGS -O2"
+ export CXXFLAGS="$CXXFLAGS -O2"
+fi
+
+# OSS-Fuzz will provide CC, CXX, etc. So only set:
+# * --enable-fuzz, see https://github.com/bitcoin/bitcoin/blob/master/doc/fuzzing.md
+# * CONFIG_SITE, see https://github.com/bitcoin/bitcoin/blob/master/depends/README.md
+if [ "$SANITIZER" = "memory" ]; then
+ CONFIG_SITE="$PWD/depends/$BUILD_TRIPLET/share/config.site" ./configure --enable-fuzz SANITIZER_LDFLAGS="$LIB_FUZZING_ENGINE" --with-asm=no
+else
+ CONFIG_SITE="$PWD/depends/$BUILD_TRIPLET/share/config.site" ./configure --enable-fuzz SANITIZER_LDFLAGS="$LIB_FUZZING_ENGINE"
+fi
+
+
+if [ "$SANITIZER" = "memory" ]; then
+ # MemorySanitizer (MSAN) does not support tracking memory initialization done by
+ # using the Linux getrandom syscall. Avoid using getrandom by undefining
+ # HAVE_SYS_GETRANDOM. See https://github.com/google/sanitizers/issues/852 for
+ # details.
+ grep -v HAVE_SYS_GETRANDOM src/config/bitcoin-config.h > src/config/bitcoin-config.h.tmp
+ mv src/config/bitcoin-config.h.tmp src/config/bitcoin-config.h
+fi
+
+make -j$(nproc)
+
+WRITE_ALL_FUZZ_TARGETS_AND_ABORT="/tmp/a" "./src/test/fuzz/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 'make'. This is slower,
+# so use the hack.
+export MAGIC_STR="b5813eee2abc9d3358151f298b75a72264ffa119d2f71ae7fefa15c4b70b4bc5b38e87e3107a730f25891ea428b2b4fabe7a84f5bfa73c79e0479e085e4ff157"
+sed -i "s|.*std::getenv(\"FUZZ\").*|std::string fuzz_target{\"$MAGIC_STR\"};|g" "./src/test/fuzz/fuzz.cpp"
+sed -i "s|.find(fuzz_target)|.find(fuzz_target.c_str())|g" "./src/test/fuzz/fuzz.cpp"
+make -j$(nproc)
+
+# Replace the magic string with the actual name of each fuzz target
+for fuzz_target in ${FUZZ_TARGETS[@]}; do
+ python3 -c "c_str_target=b\"${fuzz_target}\x00\";c_str_magic=b\"$MAGIC_STR\";c=open('./src/test/fuzz/fuzz','rb').read();c=c.replace(c_str_magic, c_str_target+c_str_magic[len(c_str_target):]);open(\"$OUT/$fuzz_target\",'wb').write(c)"
+ chmod +x "$OUT/$fuzz_target"
+ (
+ cd assets/fuzz_seed_corpus
+ if [ -d "$fuzz_target" ]; then
+ zip --recurse-paths --quiet --junk-paths "$OUT/${fuzz_target}_seed_corpus.zip" "${fuzz_target}"
+ fi
+ )
+done
diff --git a/projects/bitcoin-core/build_cryptofuzz.sh b/projects/bitcoin-core/build_cryptofuzz.sh
new file mode 100755
index 000000000..4e6d91ab4
--- /dev/null
+++ b/projects/bitcoin-core/build_cryptofuzz.sh
@@ -0,0 +1,175 @@
+#!/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_74_0.tar.bz2
+cd boost_1_74_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+export CXXFLAGS="$CXXFLAGS -I $SRC/boost_1_74_0/"
+
+# Preconfigure libsecp256k1
+cd $SRC/secp256k1/
+autoreconf -ivf
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SECP256K1"
+
+function build_libsecp256k1() {
+ # Build libsecp256k1
+ cd $SRC/secp256k1/
+
+ if test -f "Makefile"; then
+ # Remove old configuration if it exists
+ make clean
+
+ # Prevent the error:
+ # "configuration mismatch, invalid ECMULT_WINDOW_SIZE. Try deleting ecmult_static_pre_g.h before the build."
+ rm -f src/ecmult_static_pre_g.h
+ fi
+
+ SECP256K1_CONFIGURE_PARAMS="
+ --enable-static
+ --disable-tests
+ --disable-benchmark
+ --disable-exhaustive-tests
+ --enable-module-recovery
+ --enable-experimental
+ --enable-module-schnorrsig
+ --enable-module-ecdh"
+
+ if [[ $CFLAGS = *sanitize=memory* ]]
+ then
+ ./configure $SECP256K1_CONFIGURE_PARAMS --with-asm=no "$@"
+ else
+ ./configure $SECP256K1_CONFIGURE_PARAMS "$@"
+ fi
+ make
+
+ export SECP256K1_INCLUDE_PATH=$(realpath .)
+ export LIBSECP256K1_A_PATH=$(realpath .libs/libsecp256k1.a)
+
+ # Build libsecp256k1 Cryptofuzz module
+ cd $SRC/cryptofuzz/modules/secp256k1/
+ make -B -j$(nproc)
+}
+
+# Build Trezor firmware
+cd $SRC/trezor-firmware/crypto/
+# Rename blake2b_* functions to avoid symbol collisions with other libraries
+sed -i "s/\<blake2b_\([A-Za-z_]\)/trezor_blake2b_\1/g" *.c *.h
+sed -i 's/\<blake2b(/trezor_blake2b(/g' *.c *.h
+cd ../../
+export TREZOR_FIRMWARE_PATH=$(realpath trezor-firmware)
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_TREZOR_FIRMWARE"
+
+# 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"
+
+# Build Cryptofuzz
+cd $SRC/cryptofuzz
+python gen_repository.py
+rm extra_options.h
+echo -n '"' >>extra_options.h
+echo -n '--operations=' >>extra_options.h
+echo -n 'Digest,' >>extra_options.h
+echo -n 'HMAC,' >>extra_options.h
+echo -n 'KDF_HKDF,' >>extra_options.h
+echo -n 'SymmetricEncrypt,' >>extra_options.h
+echo -n 'SymmetricDecrypt,' >>extra_options.h
+echo -n 'ECC_PrivateToPublic,' >>extra_options.h
+echo -n 'ECC_ValidatePubkey,' >>extra_options.h
+echo -n 'ECC_Point_Add,' >>extra_options.h
+echo -n 'ECC_Point_Mul,' >>extra_options.h
+echo -n 'ECDSA_Sign,' >>extra_options.h
+echo -n 'ECDSA_Verify,' >>extra_options.h
+echo -n 'ECDSA_Recover,' >>extra_options.h
+echo -n 'Schnorr_Sign,' >>extra_options.h
+echo -n 'Schnorr_Verify,' >>extra_options.h
+echo -n 'ECDH_Derive,' >>extra_options.h
+echo -n 'BignumCalc_Mod_2Exp256 ' >>extra_options.h
+echo -n 'BignumCalc_Mod_SECP256K1 ' >>extra_options.h
+echo -n '--curves=secp256k1 ' >>extra_options.h
+echo -n '--digests=NULL,SHA1,SHA256,SHA512,RIPEMD160,SHA3-256,SIPHASH64 ' >>extra_options.h
+echo -n '--ciphers=CHACHA20,AES_256_CBC ' >>extra_options.h
+echo -n '--calcops=' >>extra_options.h
+# Bitcoin Core arith_uint256.cpp operations
+echo -n 'Add,And,Div,IsEq,IsGt,IsGte,IsLt,IsLte,IsOdd,Mul,NumBits,Or,Set,Sub,Xor,' >>extra_options.h
+# libsecp256k1 scalar operations
+echo -n 'IsZero,IsOne,IsEven,Add,Mul,InvMod,IsEq,CondSet,Bit,Set,RShift ' >>extra_options.h
+echo -n '"' >>extra_options.h
+cd modules/bitcoin/
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BITCOIN"
+make -B -j$(nproc)
+cd ../trezor/
+make -B -j$(nproc)
+cd ../botan/
+make -B -j$(nproc)
+
+cd ../schnorr_fun/
+export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SCHNORR_FUN"
+if [[ $CFLAGS != *-m32* ]]
+then
+ make
+else
+ make -f Makefile.i386
+fi
+
+cd ../../
+
+# Build with 3 configurations of libsecp256k1
+# Discussion: https://github.com/google/oss-fuzz/pull/5717#issuecomment-842765383
+
+build_libsecp256k1 "--with-ecmult-window=2" "--with-ecmult-gen-precision=2"
+cd $SRC/cryptofuzz/
+make -B -j$(nproc)
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w2-p2
+
+build_libsecp256k1 "--with-ecmult-window=15" "--with-ecmult-gen-precision=4"
+cd $SRC/cryptofuzz/
+rm cryptofuzz
+make
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w15-p4
+
+build_libsecp256k1 "--with-ecmult-window=20" "--with-ecmult-gen-precision=8"
+cd $SRC/cryptofuzz/
+rm cryptofuzz
+make
+cp cryptofuzz $OUT/cryptofuzz-bitcoin-cryptography-w20-p8
+
+# Convert Wycheproof test vectors to Cryptofuzz corpus format
+mkdir $SRC/corpus-cryptofuzz-wycheproof/
+find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_secp256k1_*' -exec $SRC/cryptofuzz/cryptofuzz --from-wycheproof={},$SRC/corpus-cryptofuzz-wycheproof/ \;
+# Pack the Wycheproof test vectors
+zip -j cryptofuzz-bitcoin-cryptography_seed_corpus.zip $SRC/corpus-cryptofuzz-wycheproof/*
+# Use them as the seed corpus for each of the fuzzers
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w2-p2_seed_corpus.zip
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w15-p4_seed_corpus.zip
+cp cryptofuzz-bitcoin-cryptography_seed_corpus.zip $OUT/cryptofuzz-bitcoin-cryptography-w20-p8_seed_corpus.zip
diff --git a/projects/bitcoin-core/project.yaml b/projects/bitcoin-core/project.yaml
new file mode 100644
index 000000000..9d6f33663
--- /dev/null
+++ b/projects/bitcoin-core/project.yaml
@@ -0,0 +1,22 @@
+homepage: "https://github.com/bitcoin/bitcoin"
+main_repo: 'https://github.com/bitcoin/bitcoin.git'
+language: c++
+primary_contact: "marco@chaincode.com"
+auto_ccs:
+ - "fanquake@gmail.com"
+ - "john@brink.dev"
+ - "jonas@chaincode.com"
+ - "laanwj@gmail.com"
+ - "pieter@chaincode.com"
+ - "thomas.j.bitcoin@protonmail.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+architectures:
+ - x86_64
+ - i386
+fuzzing_engines:
+ - libfuzzer
+ - honggfuzz
+ - afl
diff --git a/projects/blackfriday/Dockerfile b/projects/blackfriday/Dockerfile
new file mode 100644
index 000000000..66975f758
--- /dev/null
+++ b/projects/blackfriday/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+COPY build.sh render_fuzzer.go $SRC/
+WORKDIR $SRC/blackfriday
diff --git a/projects/libjpeg-turbo/build.sh b/projects/blackfriday/build.sh
index e500e20bc..791e35b18 100755..100644
--- a/projects/libjpeg-turbo/build.sh
+++ b/projects/blackfriday/build.sh
@@ -1,5 +1,5 @@
#!/bin/bash -eu
-# Copyright 2016 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,12 +15,9 @@
#
################################################################################
-cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC:bool=on
-make "-j$(nproc)"
-make install
+cp $SRC/render_fuzzer.go .
-$CXX $CXXFLAGS -std=c++11 -I. \
- $SRC/libjpeg_turbo_fuzzer.cc -o $OUT/libjpeg_turbo_fuzzer \
- $LIB_FUZZING_ENGINE "$WORK/lib/libturbojpeg.a"
+rm go.mod
+go mod init github.com/russross/blackfriday
-cp $SRC/libjpeg_turbo_fuzzer_seed_corpus.zip $OUT/
+compile_go_fuzzer github.com/russross/blackfriday Fuzz render_fuzzer
diff --git a/projects/blackfriday/project.yaml b/projects/blackfriday/project.yaml
new file mode 100644
index 000000000..749932648
--- /dev/null
+++ b/projects/blackfriday/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/russross/blackfriday"
+main_repo: "https://github.com/russross/blackfriday"
+primary_contact: "security-tps@google.com"
+auto_ccs :
+ - "jvoisin@google.com"
+ - "Adam@adalogics.com"
+language: go
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
diff --git a/projects/blackfriday/render_fuzzer.go b/projects/blackfriday/render_fuzzer.go
new file mode 100644
index 000000000..851f3ce55
--- /dev/null
+++ b/projects/blackfriday/render_fuzzer.go
@@ -0,0 +1,21 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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
+}
diff --git a/projects/bleach/Dockerfile b/projects/bleach/Dockerfile
index 1d31647a2..b5b1f43be 100644
--- a/projects/bleach/Dockerfile
+++ b/projects/bleach/Dockerfile
@@ -14,11 +14,11 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone \
--depth 1 \
- --branch master \
+ --branch main \
https://github.com/mozilla/bleach.git
WORKDIR bleach
diff --git a/projects/bleach/build.sh b/projects/bleach/build.sh
index b3b617975..5428291c8 100644
--- a/projects/bleach/build.sh
+++ b/projects/bleach/build.sh
@@ -30,5 +30,5 @@ for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
this_dir=\$(dirname \"\$0\")
ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/bleach/linkify_fuzzer.py b/projects/bleach/linkify_fuzzer.py
index 6a42b079c..7de97641f 100644
--- a/projects/bleach/linkify_fuzzer.py
+++ b/projects/bleach/linkify_fuzzer.py
@@ -16,7 +16,8 @@
import sys
import atheris
-import bleach
+with atheris.instrument_imports():
+ import bleach
def TestOneInput(input_bytes):
diff --git a/projects/bleach/sanitize_fuzzer.py b/projects/bleach/sanitize_fuzzer.py
index 33378167c..3ae4344ce 100644
--- a/projects/bleach/sanitize_fuzzer.py
+++ b/projects/bleach/sanitize_fuzzer.py
@@ -16,7 +16,8 @@
import sys
import atheris
-import bleach
+with atheris.instrument_imports():
+ import bleach
def TestOneInput(input_bytes):
diff --git a/projects/bloaty/Dockerfile b/projects/bloaty/Dockerfile
index 7a08527b2..e47be5674 100644
--- a/projects/bloaty/Dockerfile
+++ b/projects/bloaty/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake ninja-build g++
+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/
diff --git a/projects/bls-signatures/Dockerfile b/projects/bls-signatures/Dockerfile
new file mode 100644
index 000000000..5faedbb97
--- /dev/null
+++ b/projects/bls-signatures/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 lzip libgmp-dev
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN git clone --depth 1 https://github.com/supranational/blst
+RUN git clone --depth 1 https://github.com/Chia-Network/bls-signatures.git
+RUN git clone --depth 1 https://github.com/herumi/mcl.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz
+RUN wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz
+COPY build.sh $SRC/
diff --git a/projects/bls-signatures/build.sh b/projects/bls-signatures/build.sh
new file mode 100755
index 000000000..2ba7f97ed
--- /dev/null
+++ b/projects/bls-signatures/build.sh
@@ -0,0 +1,250 @@
+#!/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_74_0.tar.bz2
+cd boost_1_74_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 "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 '"' >>extra_options.h
+
+
+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
+ # Patch to disable assembly
+ touch new_no_asm.h
+ echo "#if LIMB_T_BITS==32" >>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
+ 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 Chia
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+ # Build and install libsodium
+ cd $SRC/
+ mkdir $SRC/libsodium-install
+ tar zxf libsodium-1.0.18-stable.tar.gz
+ cd $SRC/libsodium-stable/
+ autoreconf -ivf
+ ./configure --prefix="$SRC/libsodium-install/"
+ make -j$(nproc)
+ make install
+ export CXXFLAGS="$CXXFLAGS -I $SRC/libsodium-install/include/"
+ export LINK_FLAGS="$LINK_FLAGS $SRC/libsodium-install/lib/libsodium.a"
+
+ cd $SRC/bls-signatures/
+ mkdir build/
+ cd build/
+ if [[ $CFLAGS = *-m32* ]]
+ then
+ export CHIA_ARCH="X86"
+ else
+ export CHIA_ARCH="X64"
+ fi
+ cmake .. -DBUILD_BLS_PYTHON_BINDINGS=0 -DBUILD_BLS_TESTS=0 -DBUILD_BLS_BENCHMARKS=0 -DARCH=$CHIA_ARCH
+ make -j$(nproc)
+ export CHIA_BLS_LIBBLS_A_PATH=$(realpath src/libbls.a)
+ export CHIA_BLS_LIBRELIC_S_A_PATH=$(realpath _deps/relic-build/lib/librelic_s.a)
+ export CHIA_BLS_LIBSODIUM_A_PATH=$(realpath _deps/sodium-build/libsodium.a)
+ export CHIA_BLS_INCLUDE_PATH=$(realpath ../src/)
+ export CHIA_BLS_RELIC_INCLUDE_PATH_1=$(realpath _deps/relic-build/include/)
+ export CHIA_BLS_RELIC_INCLUDE_PATH_2=$(realpath _deps/relic-src/include/)
+ export LINK_FLAGS="$LINK_FLAGS -lgmp"
+ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_CHIA_BLS"
+fi
+
+# Build mcl
+if [[ "$SANITIZER" != "memory" ]]
+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,tls \
+ --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,tls \
+ --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/chia_bls/
+ make -B
+fi
+
+if [[ "$SANITIZER" != "memory" ]]
+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
diff --git a/projects/bls-signatures/project.yaml b/projects/bls-signatures/project.yaml
new file mode 100644
index 000000000..a96f270ac
--- /dev/null
+++ b/projects/bls-signatures/project.yaml
@@ -0,0 +1,20 @@
+homepage: "https://github.com/supranational/blst"
+language: c++
+primary_contact: "guidovranken@gmail.com"
+main_repo: "https://github.com/supranational/blst.git"
+sanitizers:
+ - address
+ - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - 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"
diff --git a/projects/boost-json/Dockerfile b/projects/boost-json/Dockerfile
new file mode 100644
index 000000000..5aaa1f658
--- /dev/null
+++ b/projects/boost-json/Dockerfile
@@ -0,0 +1,49 @@
+# 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++
+
+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/align/ \
+libs/assert \
+libs/config/ \
+libs/container \
+libs/container_hash/ \
+libs/core \
+libs/exception/ \
+libs/headers/ \
+libs/intrusive/ \
+libs/io \
+libs/move/ \
+libs/mp11/ \
+libs/smart_ptr/ \
+libs/static_assert \
+libs/system/ \
+libs/throw_exception/ \
+libs/type_traits/ \
+libs/utility/ \
+tools/boost_install \
+tools/build
+
+WORKDIR boost
+COPY build.sh $SRC/
+
diff --git a/projects/boost-json/build.sh b/projects/boost-json/build.sh
new file mode 100755
index 000000000..75c3a1066
--- /dev/null
+++ b/projects/boost-json/build.sh
@@ -0,0 +1,28 @@
+#!/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-libraries=json
+
+echo "using clang : ossfuzz : $CXX : <compileflags>\"$CXXFLAGS\" <linkflags>\"$CXXFLAGS\" <linkflags>\"${LIB_FUZZING_ENGINE}\" ;" >user-config.jam
+
+./b2 --user-config=user-config.jam --toolset=clang-ossfuzz --prefix=$OUT --with-json link=static install
+
+for i in libs/json/fuzzing/*.cpp; do
+ fuzzer=$(basename $i .cpp)
+ $CXX $CXXFLAGS -pthread libs/json/fuzzing/$fuzzer.cpp -I $OUT/include/ $OUT/lib/*.a $LIB_FUZZING_ENGINE -o $OUT/$fuzzer
+done
+
diff --git a/projects/boost-json/project.yaml b/projects/boost-json/project.yaml
new file mode 100644
index 000000000..43e6325ee
--- /dev/null
+++ b/projects/boost-json/project.yaml
@@ -0,0 +1,8 @@
+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'
diff --git a/projects/boost/Dockerfile b/projects/boost/Dockerfile
index ac2fe3768..f05e6bbb4 100644
--- a/projects/boost/Dockerfile
+++ b/projects/boost/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y g++
+RUN apt-get update && apt-get install -y g++ python
RUN git clone --recursive https://github.com/boostorg/boost.git
WORKDIR boost
diff --git a/projects/boost/boost_regex_fuzzer.cc b/projects/boost/boost_regex_fuzzer.cc
index 018a04b4b..dbc5ea831 100644
--- a/projects/boost/boost_regex_fuzzer.cc
+++ b/projects/boost/boost_regex_fuzzer.cc
@@ -1,3 +1,14 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES 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.
@@ -25,16 +36,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
size_t regex_length = fuzzed_data.ConsumeIntegral<uint8_t>();
// Second value is regexp string whose length is `regex_length`
std::string regex_string = fuzzed_data.ConsumeBytesAsString(regex_length);
- boost::regex e(regex_string);
- // Last value is the text to be matched
- std::string text = fuzzed_data.ConsumeRemainingBytesAsString();
+ 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
- try {
boost::match_results<std::string::const_iterator> what;
bool match = boost::regex_match(text, what, e,
boost::match_default | boost::match_partial);
diff --git a/projects/boost/build.sh b/projects/boost/build.sh
index b34d55f35..37552ed3b 100755
--- a/projects/boost/build.sh
+++ b/projects/boost/build.sh
@@ -16,7 +16,9 @@
################################################################################
# Build boost
-./bootstrap.sh && ./b2 headers
+CXXFLAGS="$CXXFLAGS -stdlib=libc++ -pthread" LDFLAGS="-stdlib=libc++" \
+ ./bootstrap.sh --with-toolset=clang --prefix=/usr;
+./b2 toolset=clang cxxflags="$CXXFLAGS -stdlib=libc++ -pthread" linkflags="-stdlib=libc++ -pthread" headers;
# Very simple build rule, but sufficient here.
#boost regexp
diff --git a/projects/botan/project.yaml b/projects/botan/project.yaml
index becbd8144..7a4c648c3 100644
--- a/projects/botan/project.yaml
+++ b/projects/botan/project.yaml
@@ -7,6 +7,7 @@ auto_ccs:
- "norritt@bytefortress.de"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/randombit/botan.git'
+main_repo: 'https://github.com/randombit/botan.git' \ No newline at end of file
diff --git a/projects/bs4/Dockerfile b/projects/bs4/Dockerfile
index 9a0de0749..9e7454a73 100644
--- a/projects/bs4/Dockerfile
+++ b/projects/bs4/Dockerfile
@@ -14,9 +14,9 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
-RUN apt install -y bzr python-lxml python-html5lib
+RUN apt-get install -y bzr python-lxml python-html5lib
RUN pip3 install 2to3 soupsieve html5lib lxml
RUN pip3 install bzr+lp:beautifulsoup
diff --git a/projects/bs4/bs4_fuzzer.py b/projects/bs4/bs4_fuzzer.py
index 119426174..b5125121a 100644
--- a/projects/bs4/bs4_fuzzer.py
+++ b/projects/bs4/bs4_fuzzer.py
@@ -14,12 +14,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import logging
import sys
-import warnings
import atheris
-from bs4 import BeautifulSoup
+with atheris.instrument_imports():
+ import logging
+ import warnings
+ from bs4 import BeautifulSoup
try:
@@ -33,6 +34,7 @@ except ImportError:
pass
+@atheris.instrument_func
def TestOneInput(data):
"""TestOneInput gets random data from the fuzzer, and throws it at bs4."""
if len(data) < 1:
diff --git a/projects/bs4/build.sh b/projects/bs4/build.sh
index 111be4645..2fec546b7 100644
--- a/projects/bs4/build.sh
+++ b/projects/bs4/build.sh
@@ -29,5 +29,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/caddy/Dockerfile b/projects/caddy/Dockerfile
new file mode 100644
index 000000000..95949c0e1
--- /dev/null
+++ b/projects/caddy/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 $GOPATH/src/github.com/caddyserver/caddy/v2
+
+COPY build.sh $SRC/
+WORKDIR $SRC/caddy
diff --git a/projects/caddy/build.sh b/projects/caddy/build.sh
new file mode 100644
index 000000000..add1a066d
--- /dev/null
+++ b/projects/caddy/build.sh
@@ -0,0 +1,36 @@
+#!/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/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
diff --git a/projects/caddy/project.yaml b/projects/caddy/project.yaml
new file mode 100644
index 000000000..d229dba34
--- /dev/null
+++ b/projects/caddy/project.yaml
@@ -0,0 +1,10 @@
+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" \ No newline at end of file
diff --git a/projects/cairo/Dockerfile b/projects/cairo/Dockerfile
index 7463bbd45..671fa74b3 100644
--- a/projects/cairo/Dockerfile
+++ b/projects/cairo/Dockerfile
@@ -14,8 +14,8 @@
#
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y python3-pip gtk-doc-tools libffi-dev
-RUN pip3 install -U meson==0.55.3 ninja
+RUN apt-get update && apt-get install -y python3-pip gtk-doc-tools libffi-dev autotools-dev libtool gperf
+RUN pip3 install -U meson==0.56.0 ninja
RUN git clone --depth 1 git://git.sv.nongnu.org/freetype/freetype2.git
ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
diff --git a/projects/capnproto/Dockerfile b/projects/capnproto/Dockerfile
index dffaa4580..b95cda7ec 100644
--- a/projects/capnproto/Dockerfile
+++ b/projects/capnproto/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake zlib1g-dev
+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/
diff --git a/projects/capnproto/build.sh b/projects/capnproto/build.sh
index 176418d05..8bb80635c 100755
--- a/projects/capnproto/build.sh
+++ b/projects/capnproto/build.sh
@@ -16,8 +16,9 @@
################################################################################
# build project
-mkdir build
-cd build
-cmake -DBUILD_SHARED_LIBS=OFF ..
+cd c++
+autoreconf -i
+./configure --disable-shared
make -j$(nproc)
-cp c++/src/capnp/*fuzzer* $OUT/
+make -j$(nproc) capnp-llvm-fuzzer-testcase
+cp *fuzzer* $OUT/
diff --git a/projects/capnproto/project.yaml b/projects/capnproto/project.yaml
index e8cffba08..5d9f841ff 100644
--- a/projects/capnproto/project.yaml
+++ b/projects/capnproto/project.yaml
@@ -3,6 +3,8 @@ 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'
diff --git a/projects/cascadia/Dockerfile b/projects/cascadia/Dockerfile
index 094b5e10e..6f4f5d7b2 100644
--- a/projects/cascadia/Dockerfile
+++ b/projects/cascadia/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/andybalholm/cascadia
COPY build.sh $SRC/
diff --git a/projects/casync/project.yaml b/projects/casync/project.yaml
index e2d38b870..e664b047d 100644
--- a/projects/casync/project.yaml
+++ b/projects/casync/project.yaml
@@ -4,9 +4,10 @@ primary_contact: "lennart@poettering.net"
sanitizers:
- address
- undefined
- - memory
+# 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'
+main_repo: 'https://github.com/systemd/casync' \ No newline at end of file
diff --git a/projects/cel-cpp/Dockerfile b/projects/cel-cpp/Dockerfile
index 6c4b67eef..a95e74048 100644
--- a/projects/cel-cpp/Dockerfile
+++ b/projects/cel-cpp/Dockerfile
@@ -16,6 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
+RUN apt-get update && apt-get install python 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/
@@ -23,5 +24,5 @@ COPY BUILD fuzz*.cc $SRC/cel-cpp/fuzz/
COPY WORKSPACE .bazelrc $SRC/
RUN cat WORKSPACE >> $SRC/cel-cpp/WORKSPACE
RUN cat .bazelrc >> $SRC/cel-cpp/.bazelrc
-RUN echo "4.0.0" > $SRC/cel-cpp/.bazelversion
+RUN echo "4.1.0" > $SRC/cel-cpp/.bazelversion
WORKDIR $SRC/cel-cpp
diff --git a/projects/cel-cpp/build.sh b/projects/cel-cpp/build.sh
index 5a6315a35..b204d1cb6 100755
--- a/projects/cel-cpp/build.sh
+++ b/projects/cel-cpp/build.sh
@@ -15,18 +15,4 @@
#
################################################################################
-declare -r QUERY='
- let all_fuzz_tests = attr(tags, "fuzz-test", "//...") in
- $all_fuzz_tests - attr(tags, "no-oss-fuzz", $all_fuzz_tests)
-'
-
-declare -r PACKAGE_SUFFIX="_oss_fuzz"
-declare -r OSS_FUZZ_TESTS="$(bazel query "${QUERY}" | sed "s/$/${PACKAGE_SUFFIX}/")"
-
-bazel build -c opt --config=oss-fuzz --linkopt=-lc++ \
- --action_env=CC="${CC}" --action_env=CXX="${CXX}" \
- ${OSS_FUZZ_TESTS[*]}
-
-for oss_fuzz_archive in $(find bazel-bin/ -name "*${PACKAGE_SUFFIX}.tar"); do
- tar -xvf "${oss_fuzz_archive}" -C "${OUT}"
-done
+bazel_build_fuzz_tests
diff --git a/projects/cel-cpp/fuzz_parse.cc b/projects/cel-cpp/fuzz_parse.cc
index f4755d319..8aaba0bba 100644
--- a/projects/cel-cpp/fuzz_parse.cc
+++ b/projects/cel-cpp/fuzz_parse.cc
@@ -16,14 +16,17 @@
#include <string>
+#include "parser/options.h"
#include "parser/parser.h"
#define MAX_RECURSION 0x100
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
std::string str (reinterpret_cast<const char*>(data), size);
+ google::api::expr::parser::ParserOptions options;
+ options.max_recursion_depth = MAX_RECURSION;
try {
- auto parse_status = google::api::expr::parser::Parse(str, "fuzzinput", MAX_RECURSION);
+ auto parse_status = google::api::expr::parser::Parse(str, "fuzzinput", options);
if (!parse_status.ok()) {
parse_status.status().message();
}
diff --git a/projects/cel-cpp/project.yaml b/projects/cel-cpp/project.yaml
index ad4bf90e3..14fb2f112 100644
--- a/projects/cel-cpp/project.yaml
+++ b/projects/cel-cpp/project.yaml
@@ -7,5 +7,6 @@ auto_ccs :
sanitizers:
- address
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
main_repo: 'https://github.com/google/cel-cpp'
diff --git a/projects/cel-go/Dockerfile b/projects/cel-go/Dockerfile
new file mode 100644
index 000000000..cac4a1e49
--- /dev/null
+++ b/projects/cel-go/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 get google.golang.org/protobuf/cmd/protoc-gen-go
+
+COPY go-lpm.cc $SRC/
+
+COPY fuzz*.go $SRC/cel-go/cel/
+COPY build.sh $SRC/
+COPY *.proto $SRC/
+WORKDIR $SRC/cel-go
diff --git a/projects/cel-go/build.sh b/projects/cel-go/build.sh
new file mode 100755
index 000000000..f27842b02
--- /dev/null
+++ b/projects/cel-go/build.sh
@@ -0,0 +1,36 @@
+#!/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 -c -I fuzzlpm/ -I $SRC/LPM/external.protobuf/include fuzzlpm/cel-go-lpm.pb.cc
+$CXX $CXXFLAGS -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 $SRC/LPM/external.protobuf/lib/libprotobuf.a -o $OUT/fuzz_lpm
+
+compile_go_fuzzer github.com/google/cel-go/cel FuzzCompile fuzz_compile
diff --git a/projects/rustls/persist.rs b/projects/cel-go/cel-go-lpm.proto
index 186cd9af6..5bcfeeb60 100644
--- a/projects/rustls/persist.rs
+++ b/projects/cel-go/cel-go-lpm.proto
@@ -10,21 +10,16 @@
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
-//limitations under the License.
+// limitations under the License.
//
-//################################################################################
-#![no_main]
-#[macro_use] extern crate libfuzzer_sys;
-extern crate rustls;
+////////////////////////////////////////////////////////////////////////////////
-use rustls::internal::msgs::persist;
-use rustls::internal::msgs::codec::{Reader, Codec};
+syntax = "proto3";
+package celgolpm;
-fn try_type<T>(data: &[u8]) where T: Codec {
- let mut rdr = Reader::init(data);
- T::read(&mut rdr);
-}
+option go_package = "github.com/google/cel-go/cel";
-fuzz_target!(|data: &[u8]| {
- try_type::<persist::ServerSessionValue>(data);
-});
+message FuzzVariables {
+ string expr = 1;
+ map<string,string> inputs = 2;
+}
diff --git a/projects/cel-go/fuzz_compile.go b/projects/cel-go/fuzz_compile.go
new file mode 100644
index 000000000..a7398da48
--- /dev/null
+++ b/projects/cel-go/fuzz_compile.go
@@ -0,0 +1,18 @@
+package cel
+
+func FuzzCompile(data []byte) int {
+ env, err := NewEnv()
+ 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
+}
diff --git a/projects/cel-go/fuzz_eval.go b/projects/cel-go/fuzz_eval.go
new file mode 100644
index 000000000..8b2764c60
--- /dev/null
+++ b/projects/cel-go/fuzz_eval.go
@@ -0,0 +1,39 @@
+package cel
+
+import (
+ "github.com/golang/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 := NewEnv(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
+}
diff --git a/projects/cel-go/go-lpm.cc b/projects/cel-go/go-lpm.cc
new file mode 100644
index 000000000..9a341bc7e
--- /dev/null
+++ b/projects/cel-go/go-lpm.cc
@@ -0,0 +1,31 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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);
+ }
+}
diff --git a/projects/cel-go/project.yaml b/projects/cel-go/project.yaml
new file mode 100644
index 000000000..ad7f632b5
--- /dev/null
+++ b/projects/cel-go/project.yaml
@@ -0,0 +1,10 @@
+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'
diff --git a/projects/cfengine/Dockerfile b/projects/cfengine/Dockerfile
new file mode 100644
index 000000000..24b70d8b2
--- /dev/null
+++ b/projects/cfengine/Dockerfile
@@ -0,0 +1,26 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 autoconf automake libssl-dev \
+ libpcre3 libpcre3-dev bison libbison-dev \
+ libacl1 libacl1-dev libpq-dev lmdb-utils \
+ liblmdb-dev libpam0g-dev flex libtool
+
+RUN git clone --depth 1 https://github.com/cfengine/core --recursive
+WORKDIR core
+COPY build.sh string_fuzzer.c $SRC/
diff --git a/projects/cfengine/build.sh b/projects/cfengine/build.sh
new file mode 100755
index 000000000..4a2d542c7
--- /dev/null
+++ b/projects/cfengine/build.sh
@@ -0,0 +1,28 @@
+#!/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.
+#
+################################################################################
+
+./autogen.sh
+./configure
+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
diff --git a/projects/cfengine/project.yaml b/projects/cfengine/project.yaml
new file mode 100644
index 000000000..4db793d6e
--- /dev/null
+++ b/projects/cfengine/project.yaml
@@ -0,0 +1,10 @@
+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"
+sanitizers:
+ - address
+ - undefined
+ - memory
diff --git a/projects/cfengine/string_fuzzer.c b/projects/cfengine/string_fuzzer.c
new file mode 100644
index 000000000..b7d5cfb83
--- /dev/null
+++ b/projects/cfengine/string_fuzzer.c
@@ -0,0 +1,40 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <string_expressions.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ if(size<4) {
+ return 0;
+ }
+ for (int i=0; i<size; i++) {
+ if(data[i]==0) {
+ 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 len = strlen(new_str);
+
+ StringParseResult res = ParseStringExpression(new_str, 0, len);
+
+ FreeStringExpression(res.result);
+ free(new_str);
+ return 0;
+}
diff --git a/projects/cilium/Dockerfile b/projects/cilium/Dockerfile
index 89f2f0016..e263f368d 100644
--- a/projects/cilium/Dockerfile
+++ b/projects/cilium/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-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 wget
RUN wget https://raw.githubusercontent.com/google/AFL/master/dictionaries/json.dict -O $OUT/fuzz.dict
diff --git a/projects/cilium/project.yaml b/projects/cilium/project.yaml
index 0d75f4422..ff788e206 100644
--- a/projects/cilium/project.yaml
+++ b/projects/cilium/project.yaml
@@ -2,9 +2,13 @@ homepage: "https://cilium.io"
language: go
primary_contact: "security@cilium.io"
auto_ccs:
-- "tom@isovalent.com"
+- "andre@isovalent.com"
+- "joe@isovalent.com"
- "natalia@isovalent.com"
+- "robin@isovalent.com"
+- "tom.payne@isovalent.com"
- "adam@adalogics.com"
+main_repo: "https://github.com/cilium/cilium.git"
fuzzing_engines:
- libfuzzer
sanitizers:
diff --git a/projects/civetweb/project.yaml b/projects/civetweb/project.yaml
index f191b2a7c..f09c3f8cb 100755
--- a/projects/civetweb/project.yaml
+++ b/projects/civetweb/project.yaml
@@ -4,7 +4,6 @@ language: c
fuzzing_engines:
- libfuzzer
- honggfuzz
- - dataflow
auto_ccs:
- "xt4ubq@gmail.com"
- "david@adalogics.com"
diff --git a/projects/clamav/Dockerfile b/projects/clamav/Dockerfile
index 0d4cc0338..629595880 100644
--- a/projects/clamav/Dockerfile
+++ b/projects/clamav/Dockerfile
@@ -28,7 +28,7 @@ RUN git clone --depth 1 https://github.com/Cisco-Talos/clamav-mussels-cookbook.g
RUN mkdir /mussels
RUN cd ${SRC}/clamav-mussels-cookbook && \
- msl build clamav_deps -t host-static -w /mussels/work -i /mussels/install
+ 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-devel.git
diff --git a/projects/clamav/build.sh b/projects/clamav/build.sh
index 1f7e902ed..826021bfe 100755
--- a/projects/clamav/build.sh
+++ b/projects/clamav/build.sh
@@ -42,7 +42,7 @@ cmake ${SRC}/clamav-devel \
-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" \
+ -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" \
diff --git a/projects/clib/Dockerfile b/projects/clib/Dockerfile
index 92e14901e..d46f75291 100644
--- a/projects/clib/Dockerfile
+++ b/projects/clib/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make cmake ninja libcurl4-gnutls-dev -qq
+RUN apt-get update && apt-get install -y make cmake libcurl4-gnutls-dev -qq
RUN git clone https://github.com/clibs/clib
WORKDIR $SRC/
COPY build.sh $SRC/
diff --git a/projects/clib/build.sh b/projects/clib/build.sh
index c48ba9d76..166ee45f7 100644
--- a/projects/clib/build.sh
+++ b/projects/clib/build.sh
@@ -29,8 +29,10 @@ $CC $CFLAGS -Wno-unused-function -U__STRICT_ANSI__ \
-I./deps/asprintf
$CC $CFLAGS $LIB_FUZZING_ENGINE fuzz_manifest.o \
- -o $OUT/fuzz_manifest src/common/clib-package.c \
+ -o $OUT/fuzz_manifest src/common/clib-settings.c src/common/clib-package.c \
src/common/clib-cache.c src/clib-configure.c \
-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
diff --git a/projects/clickhouse/Dockerfile b/projects/clickhouse/Dockerfile
new file mode 100644
index 000000000..cd835bea1
--- /dev/null
+++ b/projects/clickhouse/Dockerfile
@@ -0,0 +1,40 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 \
+ && 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 \
+ sudo \
+ tzdata
+
+RUN git clone -j 8 --recursive https://github.com/ClickHouse/ClickHouse $SRC/ClickHouse
+WORKDIR $SRC/ClickHouse
+
+COPY build.sh $SRC/
diff --git a/projects/clickhouse/build.sh b/projects/clickhouse/build.sh
new file mode 100755
index 000000000..a0415f085
--- /dev/null
+++ b/projects/clickhouse/build.sh
@@ -0,0 +1,107 @@
+#!/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 $SRC/ClickHouse/build
+cd $SRC/ClickHouse/build
+
+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 this manually will cause duplicate symbols at linker stage.
+CXXFLAGS=${CXXFLAGS//-stdlib=libc++/}
+
+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_EMBEDDED_COMPILER=0"
+ "-DENABLE_THINLTO=0"
+ "-DENABLE_TESTS=0"
+ "-DENABLE_EXAMPLES=0"
+ "-DENABLE_UTILS=0"
+ "-DENABLE_JEMALLOC=0"
+ "-DENABLE_FUZZING=1"
+ "-DENABLE_CLICKHOUSE_ODBC_BRIDGE=OFF"
+ "-DENABLE_LIBRARIES=0"
+ "-DENABLE_SSL=1"
+ "-DUSE_INTERNAL_SSL_LIBRARY=1"
+ "-DUSE_UNWIND=ON"
+ "-DGLIBC_COMPATIBILITY=OFF"
+)
+
+if [ "$SANITIZER" = "coverage" ]; then
+ cmake -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_C_FLAGS="$CFLAGS" -DWITH_COVERAGE=1
+else
+ cmake -G Ninja $SRC/ClickHouse ${CLICKHOUSE_CMAKE_FLAGS[@]} -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_C_FLAGS="$CFLAGS" -DWITH_COVERAGE=1 -DSANITIZE=$SANITIZER
+fi
+
+NUM_JOBS=$(($(nproc || grep -c ^processor /proc/cpuinfo) / 2))
+
+TARGETS=$(find $SRC/ClickHouse/src -name '*_fuzzer.cpp' -execdir basename {} .cpp ';' | tr '\n' ' ')
+
+for FUZZER_TARGET in $TARGETS
+do
+ ninja -j $NUM_JOBS $FUZZER_TARGET
+ # Find this binary in build directory and strip it
+ TEMP=$(find $SRC/ClickHouse/build -name $FUZZER_TARGET)
+ strip --strip-unneeded $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 $SRC/ClickHouse/tests/fuzz/lexer_fuzzer.in/
+mkdir $SRC/ClickHouse/tests/fuzz/select_parser_fuzzer.in/
+mkdir $SRC/ClickHouse/tests/fuzz/create_parser_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/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/
+
+# 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
+ cp -rL --parents $SRC/ClickHouse/programs $OUT
+fi
+
+# Just check binaries size
+BINARIES_SIZE=$(find $SRC/ClickHouse/build -name '*_fuzzer' -exec du -sh '{}' ';')
diff --git a/projects/clickhouse/project.yaml b/projects/clickhouse/project.yaml
index 9c0c7cf92..9e505f227 100644
--- a/projects/clickhouse/project.yaml
+++ b/projects/clickhouse/project.yaml
@@ -1,6 +1,18 @@
homepage: "https://clickhouse.tech/"
language: c++
-primary_contact: "clickhouse-feedback@yandex-team.com"
+primary_contact: "clickhouse-security@yandex-team.com"
auto_ccs:
- "security@yandex-team.com"
- "kyprizel@gmail.com"
+ - "jakalletti@gmail.com"
+ - "man2gm@gmail.com"
+ - "kochetovnicolai@gmail.com"
+ - "hq.zero.iq@gmail.com"
+ - "pn.cheremushkin@gmail.com"
+sanitizers:
+ - address
+ - memory
+ - undefined
+fuzzing_engines:
+ - libfuzzer
+main_repo: 'https://github.com/ClickHouse/ClickHouse.git'
diff --git a/projects/cmake/project.yaml b/projects/cmake/project.yaml
index 8ab35334c..17c5b3e8d 100644
--- a/projects/cmake/project.yaml
+++ b/projects/cmake/project.yaml
@@ -7,4 +7,5 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
diff --git a/projects/containerd/Dockerfile b/projects/containerd/Dockerfile
new file mode 100644
index 000000000..7ae42468b
--- /dev/null
+++ b/projects/containerd/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libc-dev pkg-config libseccomp-dev gcc wget libbtrfs-dev
+RUN git clone --depth 1 https://github.com/containerd/containerd
+COPY build.sh $SRC/
+WORKDIR $SRC/containerd
diff --git a/projects/containerd/build.sh b/projects/containerd/build.sh
new file mode 100644
index 000000000..e5a1e6b6b
--- /dev/null
+++ b/projects/containerd/build.sh
@@ -0,0 +1,19 @@
+#/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
+
diff --git a/projects/containerd/project.yaml b/projects/containerd/project.yaml
new file mode 100644
index 000000000..4875cd66a
--- /dev/null
+++ b/projects/containerd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/containerd/containerd"
+main_repo: "https://github.com/containerd/containerd"
+primary_contact: "security@containerd.io"
+auto_ccs :
+ - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/cosign/Dockerfile b/projects/cosign/Dockerfile
index f0282dd16..bb094925a 100644
--- a/projects/cosign/Dockerfile
+++ b/projects/cosign/Dockerfile
@@ -14,7 +14,8 @@
#
################################################################################
-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 pkg-config libpcsclite-dev
RUN git clone --depth 1 https://github.com/sigstore/cosign
COPY build.sh $SRC/
diff --git a/projects/cosmos-sdk/Dockerfile b/projects/cosmos-sdk/Dockerfile
new file mode 100644
index 000000000..0e5fe8b93
--- /dev/null
+++ b/projects/cosmos-sdk/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 --branch fuzz-packages https://github.com/cosmos/cosmos-sdk
+
+COPY build.sh $SRC
+WORKDIR $SRC/cosmos-sdk
diff --git a/projects/cosmos-sdk/build.sh b/projects/cosmos-sdk/build.sh
new file mode 100755
index 000000000..a86511424
--- /dev/null
+++ b/projects/cosmos-sdk/build.sh
@@ -0,0 +1,18 @@
+#!/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
diff --git a/projects/cosmos-sdk/project.yaml b/projects/cosmos-sdk/project.yaml
new file mode 100644
index 000000000..fbe2cd1d2
--- /dev/null
+++ b/projects/cosmos-sdk/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/cosmos/cosmos-sdk"
+primary_contact: "fuzzing@orijtech.com"
+auto_ccs:
+ - emmanuel@orijtech.com
+ - cuong@orijtech.com
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+main_repo: "https://github.com/cosmos/cosmos-sdk"
diff --git a/projects/cpp-httplib/project.yaml b/projects/cpp-httplib/project.yaml
index 0c90fa007..9043e407a 100644
--- a/projects/cpp-httplib/project.yaml
+++ b/projects/cpp-httplib/project.yaml
@@ -9,7 +9,7 @@ auto_ccs :
- "ankitlohia@google.com"
sanitizers:
- address
- - dataflow
- undefined
- - memory
-main_repo: 'https://github.com/yhirose/cpp-httplib.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'https://github.com/yhirose/cpp-httplib.git' \ No newline at end of file
diff --git a/projects/cpython3/Dockerfile b/projects/cpython3/Dockerfile
index 6ca60d408..972ed6f22 100644
--- a/projects/cpython3/Dockerfile
+++ b/projects/cpython3/Dockerfile
@@ -1,3 +1,18 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
diff --git a/projects/cpython3/project.yaml b/projects/cpython3/project.yaml
index 7edfd24b4..e454e36c9 100644
--- a/projects/cpython3/project.yaml
+++ b/projects/cpython3/project.yaml
@@ -6,5 +6,6 @@ auto_ccs:
- "ammar@ammaraskar.com"
sanitizers:
- address
- - memory
- - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+ - undefined \ No newline at end of file
diff --git a/projects/cras/Dockerfile b/projects/cras/Dockerfile
index 71b2b121f..3a533f6aa 100644
--- a/projects/cras/Dockerfile
+++ b/projects/cras/Dockerfile
@@ -19,7 +19,7 @@
################################################################################
# Defines a docker image that can build cras fuzzers.
#
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN apt-get -y update && \
apt-get install -y \
@@ -40,6 +40,7 @@ RUN apt-get -y update && \
libtool \
libudev-dev \
wget \
+ vim \
zip
RUN apt-get clean
RUN cd /tmp && git clone https://github.com/ndevilla/iniparser.git && \
diff --git a/projects/cras/build.sh b/projects/cras/build.sh
index 84f50b1d2..410ade7b6 100755
--- a/projects/cras/build.sh
+++ b/projects/cras/build.sh
@@ -44,3 +44,5 @@ done
zip -j ${OUT}/rclient_message_corpus.zip ${SRC}/adhd/cras/src/fuzz/corpus/*
cp "${SRC}/adhd/cras/src/fuzz/cras_hfp_slc.dict" "${OUT}/cras_hfp_slc.dict"
+# Add *.rs soft link for coverage build
+ln -s ${SRC}/adhd/cras/src/server/rust/src/* ${SRC}
diff --git a/projects/cras/project.yaml b/projects/cras/project.yaml
index 330b02549..3e0c9f6ac 100644
--- a/projects/cras/project.yaml
+++ b/projects/cras/project.yaml
@@ -1,12 +1,16 @@
homepage: "https://www.chromium.org"
language: c++
-primary_contact: "dgreid@chromium.org"
+primary_contact: "paulhsia@chromium.org"
auto_ccs:
- "hychao@chromium.org"
- "cychiang@chromium.org"
- - "paulhsia@chromium.org"
- "yuhsuan@chromium.org"
- "enshuo@chromium.org"
- - "tzungbi@chromium.org"
- "cujomalainey@chromium.org"
+ - "benzh@chromium.org"
+ - "judyhsiao@chromium.org"
+ - "johnylin@chromium.org"
+ - "aaronyu@chromium.org"
+ - "hunghsienchen@chromium.org"
+builds_per_day: 2
main_repo: 'https://chromium.googlesource.com/chromiumos/third_party/adhd'
diff --git a/projects/cryptofuzz/Dockerfile b/projects/cryptofuzz/Dockerfile
index 7ed5d425b..1a1cb9ac3 100644
--- a/projects/cryptofuzz/Dockerfile
+++ b/projects/cryptofuzz/Dockerfile
@@ -14,14 +14,13 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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 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/ xenial main' && \
- apt-get update && \
- apt-get install -y software-properties-common python-software-properties make autoconf automake libtool build-essential cmake mercurial gyp ninja-build zlib1g-dev libsqlite3-dev bison flex texinfo
+ 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
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
@@ -36,15 +35,14 @@ RUN git clone --depth 1 -b oss-fuzz https://github.com/project-everest/hacl-star
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/ARMmbed/mbedtls.git
+RUN git clone --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git
RUN hg clone https://hg.mozilla.org/projects/nspr
-RUN hg clone https://hg.mozilla.org/projects/nss
+#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 git clone --depth 1 https://git.lysator.liu.se/nettle/nettle
+#RUN git clone --depth 1 https://github.com/microsoft/SymCrypt.git
RUN hg clone https://gmplib.org/repo/gmp/ libgmp/
-RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.0.tar.gz
+RUN wget https://www.bytereef.org/software/mpdecimal/releases/mpdecimal-2.5.1.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
@@ -52,8 +50,14 @@ RUN git clone --depth 1 https://github.com/brix/crypto-js.git
RUN git clone --depth 1 https://github.com/LoupVaillant/Monocypher.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 install -y libssl-dev
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://nodejs.org/dist/v14.17.1/node-v14.17.1-linux-x64.tar.xz
COPY build.sh xxd.c $SRC/
diff --git a/projects/cryptofuzz/build.sh b/projects/cryptofuzz/build.sh
index 9aa3c948b..3df921820 100755
--- a/projects/cryptofuzz/build.sh
+++ b/projects/cryptofuzz/build.sh
@@ -20,6 +20,15 @@
export GO111MODULE=off
+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
@@ -50,9 +59,6 @@ go get golang.org/x/crypto/ripemd160
# This enables runtime checks for C++-specific undefined behaviour.
export CXXFLAGS="$CXXFLAGS -D_GLIBCXX_DEBUG"
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
export CXXFLAGS="$CXXFLAGS -I $SRC/cryptofuzz/fuzzing-headers/include"
if [[ $CFLAGS = *sanitize=memory* ]]
then
@@ -87,23 +93,23 @@ then
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/
-
- 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
+#if [[ $CFLAGS != *-m32* ]]
+#then
+# mkdir $SRC/nss-nspr
+# mv $SRC/nss $SRC/nss-nspr/
+# mv $SRC/nspr $SRC/nss-nspr/
+# cd $SRC/nss-nspr/
+#
+# 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
# Compile Monocypher
cd $SRC/Monocypher/
@@ -141,53 +147,93 @@ then
make -B
fi
-# Compile SymCrypt
-cd $SRC/SymCrypt/
-if [[ $CFLAGS != *sanitize=array-bounds* ]]
+## Build blst
+#cd $SRC/blst/
+## Patch to disable assembly
+## This is to prevent false positives, see:
+## https://github.com/google/oss-fuzz/issues/5914
+#touch new_no_asm.h
+#echo "#if LIMB_T_BITS==32" >>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
- # Unittests don't build with clang and are not needed anyway
- sed -i "s/^add_subdirectory(unittest)$//g" CMakeLists.txt
+ ./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)
- mkdir b/
- cd b/
- cmake ../
- make -j$(nproc)
+# Compile Cryptofuzz libsecp256k1 module
+cd $SRC/cryptofuzz/modules/secp256k1/
+make -B -j$(nproc)
- export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SYMCRYPT"
- export SYMCRYPT_INCLUDE_PATH=$(realpath ../inc/)
- export LIBSYMCRYPT_COMMON_A_PATH=$(realpath lib/x86_64/Generic/libsymcrypt_common.a)
- export SYMCRYPT_GENERIC_A_PATH=$(realpath lib/x86_64/Generic/symcrypt_generic.a)
+if [[ $CFLAGS != *sanitize=memory* && $CFLAGS != *-m32* ]]
+then
+ # noble-secp256k1
+ cd $SRC/cryptofuzz/modules/noble-secp256k1/
+ export NOBLE_SECP256K1_PATH="$SRC/noble-secp256k1/index.js"
+ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NOBLE_SECP256K1"
+ make -B
- # Compile Cryptofuzz SymCrypt module
- cd $SRC/cryptofuzz/modules/symcrypt
+ # 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
-fi
-# Compile Nettle
-mkdir $SRC/nettle-install/
-cd $SRC/nettle/
-bash .bootstrap
-if [[ $CFLAGS != *sanitize=memory* ]]
-then
- ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-install`
-else
- ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-install`
-fi
-make -j$(nproc)
-make install
-if [[ $CFLAGS != *-m32* ]]
-then
-export LIBNETTLE_A_PATH=`realpath ../nettle-install/lib/libnettle.a`
-export LIBHOGWEED_A_PATH=`realpath ../nettle-install/lib/libhogweed.a`
-else
-export LIBNETTLE_A_PATH=`realpath ../nettle-install/lib32/libnettle.a`
-export LIBHOGWEED_A_PATH=`realpath ../nettle-install/lib32/libhogweed.a`
+ # 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
-export NETTLE_INCLUDE_PATH=`realpath ../nettle-install/include`
-export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
-# Compile Cryptofuzz Nettle module
-cd $SRC/cryptofuzz/modules/nettle
-make -B
+
+## Compile SymCrypt
+#cd $SRC/SymCrypt/
+#if [[ $CFLAGS != *sanitize=array-bounds* ]]
+#then
+# # Unittests don't build with clang and are not needed anyway
+# sed -i "s/^add_subdirectory(unittest)$//g" CMakeLists.txt
+#
+# mkdir b/
+# cd b/
+# cmake ../
+# make -j$(nproc)
+#
+# export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_SYMCRYPT"
+# export SYMCRYPT_INCLUDE_PATH=$(realpath ../inc/)
+# export LIBSYMCRYPT_COMMON_A_PATH=$(realpath lib/x86_64/Generic/libsymcrypt_common.a)
+# export SYMCRYPT_GENERIC_A_PATH=$(realpath lib/x86_64/Generic/symcrypt_generic.a)
+#
+# # Compile Cryptofuzz SymCrypt module
+# cd $SRC/cryptofuzz/modules/symcrypt
+# make -B
+#fi
# Compile libgmp
if [[ $CFLAGS != *sanitize=memory* ]]
@@ -211,8 +257,8 @@ fi
# Compile mpdecimal
cd $SRC/
-tar zxf mpdecimal-2.5.0.tar.gz
-cd mpdecimal-2.5.0/
+tar zxf mpdecimal-2.5.1.tar.gz
+cd mpdecimal-2.5.1/
./configure
cd libmpdec/
make libmpdec.a -j$(nproc)
@@ -403,27 +449,27 @@ then
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
-
- # 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
+#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
+#
+# # 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
if [[ $CFLAGS != *sanitize=memory* ]]
then
diff --git a/projects/dart/project.yaml b/projects/dart/project.yaml
index 155fe23dd..fe43ad46c 100644
--- a/projects/dart/project.yaml
+++ b/projects/dart/project.yaml
@@ -6,4 +6,6 @@ auto_ccs :
sanitizers:
- address
+fuzzing_engines:
+- libfuzzer
main_repo: 'https://github.com/dart-lang/sdk.git'
diff --git a/projects/dav1d/Dockerfile b/projects/dav1d/Dockerfile
index 81a4e590a..0df0a5b3e 100644
--- a/projects/dav1d/Dockerfile
+++ b/projects/dav1d/Dockerfile
@@ -15,10 +15,6 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-
-ADD nasm.list /etc/apt/sources.list.d/nasm.list
-ADD nasm_apt.pin /etc/apt/preferences
-
RUN apt-get update && \
apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel nasm && \
pip3 install meson ninja
diff --git a/projects/dav1d/nasm.list b/projects/dav1d/nasm.list
deleted file mode 100644
index 673ee997b..000000000
--- a/projects/dav1d/nasm.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm from a newer ubuntu release
-deb http://archive.ubuntu.com/ubuntu/ focal universe
diff --git a/projects/dav1d/nasm_apt.pin b/projects/dav1d/nasm_apt.pin
deleted file mode 100644
index d1932e9dd..000000000
--- a/projects/dav1d/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=focal
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=focal
-Pin-Priority: 555
diff --git a/projects/dav1d/project.yaml b/projects/dav1d/project.yaml
index 76c2349eb..3ef83d8bf 100644
--- a/projects/dav1d/project.yaml
+++ b/projects/dav1d/project.yaml
@@ -6,8 +6,9 @@ auto_ccs:
- "kempfjb@gmail.com"
- "b@rr-dav.id.au"
- "dav1d-fuzz@videolan.org"
+ - "psilokos@twoorioles.com"
+ - "gramner@twoorioles.com"
vendor_ccs:
- - "negge@mozilla.com"
- "twsmith@mozilla.com"
sanitizers:
- address
diff --git a/projects/dgraph/Dockerfile b/projects/dgraph/Dockerfile
new file mode 100644
index 000000000..1f63ea49f
--- /dev/null
+++ b/projects/dgraph/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/dgraph-io/dgraph
+COPY build.sh $SRC/
+WORKDIR $SRC/dgraph
diff --git a/projects/dgraph/build.sh b/projects/dgraph/build.sh
new file mode 100644
index 000000000..f8c215b24
--- /dev/null
+++ b/projects/dgraph/build.sh
@@ -0,0 +1,18 @@
+#!/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/dgraph-io/dgraph/gql Fuzz parser_fuzzer
diff --git a/projects/dgraph/project.yaml b/projects/dgraph/project.yaml
new file mode 100644
index 000000000..74971bab7
--- /dev/null
+++ b/projects/dgraph/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://dgraph.io"
+main_repo: "https://github.com/dgraph-io/dgraph"
+primary_contact: "Adam@adalogics.com"
+auto_ccs :
+ - "pawan@dgraph.io"
+ - "manish@dgraph.io"
+ - "ibrahim@dgraph.io"
+ - "daniel@dgraph.io"
+ - "vvbalaji@dgraph.io"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/django/Dockerfile b/projects/django/Dockerfile
index a73872fca..25af43134 100644
--- a/projects/django/Dockerfile
+++ b/projects/django/Dockerfile
@@ -15,7 +15,8 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN 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 wget
+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 wget
RUN wget -q https://github.com/python/cpython/archive/v3.8.7.tar.gz
RUN git clone --depth 1 https://github.com/django/django-fuzzers.git
RUN git clone --depth 1 https://github.com/django/django.git
diff --git a/projects/django/build.sh b/projects/django/build.sh
index b4e25a48e..962b9f9e0 100755
--- a/projects/django/build.sh
+++ b/projects/django/build.sh
@@ -61,7 +61,7 @@ cp -R $CPYTHON_INSTALL_PATH $OUT/
rm -rf $OUT/django-dependencies
mkdir $OUT/django-dependencies
-$CPYTHON_INSTALL_PATH/bin/pip3 install asgiref pytz sqlparse -t $OUT/django-dependencies
+$CPYTHON_INSTALL_PATH/bin/pip3 install asgiref pytz sqlparse backports.zoneinfo -t $OUT/django-dependencies
cd $SRC/django-fuzzers
rm $CPYTHON_INSTALL_PATH/lib/python3.8/lib-dynload/_tkinter*.so
diff --git a/projects/dlplibs/project.yaml b/projects/dlplibs/project.yaml
index 7d3ed33ed..4e5b6d3de 100644
--- a/projects/dlplibs/project.yaml
+++ b/projects/dlplibs/project.yaml
@@ -3,5 +3,6 @@ language: c++
primary_contact: "dtardon@redhat.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
diff --git a/projects/dng_sdk/Dockerfile b/projects/dng_sdk/Dockerfile
new file mode 100644
index 000000000..976e9dd07
--- /dev/null
+++ b/projects/dng_sdk/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+RUN git clone https://android.googlesource.com/platform/external/dng_sdk/
+COPY build.sh $SRC/
+WORKDIR dng_sdk
diff --git a/projects/dng_sdk/build.sh b/projects/dng_sdk/build.sh
new file mode 100755
index 000000000..9d7af3805
--- /dev/null
+++ b/projects/dng_sdk/build.sh
@@ -0,0 +1,30 @@
+#!/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
+
+# move seeds
+cd ../fuzzer/seeds/CVE_2020_9589
+zip -q $OUT/dng_parser_fuzzer_seed_corpus.zip *.dng
diff --git a/projects/dng_sdk/project.yaml b/projects/dng_sdk/project.yaml
new file mode 100644
index 000000000..616b70fc2
--- /dev/null
+++ b/projects/dng_sdk/project.yaml
@@ -0,0 +1,6 @@
+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/'
diff --git a/projects/dnsmasq/Dockerfile b/projects/dnsmasq/Dockerfile
new file mode 100644
index 000000000..6ab50ce2f
--- /dev/null
+++ b/projects/dnsmasq/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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*.h $SRC/
+
+COPY fuzz_patch.patch $SRC/
diff --git a/projects/dnsmasq/build.sh b/projects/dnsmasq/build.sh
new file mode 100755
index 000000000..8fc7b21d9
--- /dev/null
+++ b/projects/dnsmasq/build.sh
@@ -0,0 +1,57 @@
+#!/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
+for fuzz_name in dhcp6 rfc1035 auth dhcp util; do
+ $CC $CFLAGS -c $SRC/fuzz_${fuzz_name}.c -I./ -I$SRC/ -DVERSION=\'\"UNKNOWN\"\' -g
+ $CC $CFLAGS $LIB_FUZZING_ENGINE ./fuzz_${fuzz_name}.o libdnsmasq.a -o $OUT/fuzz_${fuzz_name}
+done
diff --git a/projects/dnsmasq/fuzz_auth.c b/projects/dnsmasq/fuzz_auth.c
new file mode 100644
index 000000000..4a233e13e
--- /dev/null
+++ b/projects/dnsmasq/fuzz_auth.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp.c b/projects/dnsmasq/fuzz_dhcp.c
new file mode 100644
index 000000000..4ba61ca3b
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp.c
@@ -0,0 +1,87 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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(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;
+
+ 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.
+ if (daemon->dhcp_packet.iov_base == content) {
+ free(content);
+ }
+ else{
+ 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;
+}
diff --git a/projects/dnsmasq/fuzz_dhcp6.c b/projects/dnsmasq/fuzz_dhcp6.c
new file mode 100644
index 000000000..fd7a85839
--- /dev/null
+++ b/projects/dnsmasq/fuzz_dhcp6.c
@@ -0,0 +1,83 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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;
+}
diff --git a/projects/dnsmasq/fuzz_header.h b/projects/dnsmasq/fuzz_header.h
new file mode 100644
index 000000000..748e709fc
--- /dev/null
+++ b/projects/dnsmasq/fuzz_header.h
@@ -0,0 +1,579 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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_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;
+}
+
+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_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_null_terminated(&data, &size);
+ 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;
+}
diff --git a/projects/dnsmasq/fuzz_patch.patch b/projects/dnsmasq/fuzz_patch.patch
new file mode 100644
index 000000000..50f7cab38
--- /dev/null
+++ b/projects/dnsmasq/fuzz_patch.patch
@@ -0,0 +1,170 @@
+diff --git a/src/blockdata.c b/src/blockdata.c
+index 0986285..852c961 100644
+--- a/src/blockdata.c
++++ b/src/blockdata.c
+@@ -15,16 +15,22 @@
+ */
+
+ #include "dnsmasq.h"
++#include <assert.h>
+
+ static struct blockdata *keyblock_free;
+ static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
+
++void *total_allocated[200] = {0};
++static int fuzz_total_alloc_ptr = 0;
++
+ static void blockdata_expand(int n)
+ {
+ struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
+
+ if (new)
+ {
++ assert(fuzz_total_alloc_ptr < 200);
++ total_allocated[fuzz_total_alloc_ptr++] = (void*)new;
+ int i;
+
+ new[n-1].next = keyblock_free;
+@@ -45,11 +51,23 @@ void blockdata_init(void)
+ blockdata_count = 0;
+ blockdata_hwm = 0;
+
++ fuzz_total_alloc_ptr = 0;
++ for (int m = 0; m < 200; m++)
++ total_allocated[m] = NULL;
++
+ /* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
+ if (option_bool(OPT_DNSSEC_VALID))
+ blockdata_expand(daemon->cachesize);
+ }
+
++void fuzz_blockdata_cleanup() {
++ for (int i = 0; i < 200; i++) {
++ if (total_allocated[i] != NULL) {
++ free(total_allocated[i]);
++ }
++ }
++}
++
+ void blockdata_report(void)
+ {
+ my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"),
+diff --git a/src/dhcp.c b/src/dhcp.c
+index e500bc2..7215590 100644
+--- a/src/dhcp.c
++++ b/src/dhcp.c
+@@ -183,18 +183,26 @@ void dhcp_packet(time_t now, int pxe_fd)
+ recvtime = tv.tv_sec;
+
+ if (msg.msg_controllen >= sizeof(struct cmsghdr))
+- for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
+- if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
+- {
+- union {
+- unsigned char *c;
+- struct in_pktinfo *p;
+- } p;
+- p.c = CMSG_DATA(cmptr);
+- iface_index = p.p->ipi_ifindex;
+- if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
+- unicast_dest = 1;
+- }
++ {
++ int tmp_val = 0;
++ for (cmptr = CMSG_FIRSTHDR(&msg);
++ cmptr && tmp_val < 1;
++ tmp_val++) {
++ //cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++ tmp_val++;
++ if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
++ {
++ union {
++ unsigned char *c;
++ struct in_pktinfo *p;
++ } p;
++ p.c = CMSG_DATA(cmptr);
++ iface_index = p.p->ipi_ifindex;
++ if (p.p->ipi_addr.s_addr != INADDR_BROADCAST)
++ unicast_dest = 1;
++ }
++ }
++ }
+
+ #elif defined(HAVE_BSD_NETWORK)
+ if (msg.msg_controllen >= sizeof(struct cmsghdr))
+diff --git a/src/dhcp6.c b/src/dhcp6.c
+index ae1f5c1..ce7397d 100644
+--- a/src/dhcp6.c
++++ b/src/dhcp6.c
+@@ -116,10 +116,14 @@ void dhcp6_packet(time_t now)
+ msg.msg_iov = &daemon->dhcp_packet;
+ msg.msg_iovlen = 1;
+
+- if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
++ if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1){
+ return;
+-
+- for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
++ }
++
++ int tmp_val = 0;
++// for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
++ for (cmptr = CMSG_FIRSTHDR(&msg); cmptr && tmp_val < 1; tmp_val++) {
++ tmp_val++;
+ if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
+ {
+ union {
+@@ -131,9 +135,11 @@ void dhcp6_packet(time_t now)
+ if_index = p.p->ipi6_ifindex;
+ dst_addr = p.p->ipi6_addr;
+ }
++ }
+
+- if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
++ if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) {
+ return;
++ }
+
+ if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
+ {
+diff --git a/src/netlink.c b/src/netlink.c
+index 7840ef9..2419897 100644
+--- a/src/netlink.c
++++ b/src/netlink.c
+@@ -197,8 +197,13 @@ int iface_enumerate(int family, void *parm, int (*callback)())
+ if (errno != 0)
+ return 0;
+
++ int valval = 0;
+ while (1)
+ {
++ valval++;
++ if (valval > 300) {
++ return -1;
++ }
+ if ((len = netlink_recv(0)) == -1)
+ {
+ if (errno == ENOBUFS)
+diff --git a/src/network.c b/src/network.c
+index 296c7bd..c03961a 100644
+--- a/src/network.c
++++ b/src/network.c
+@@ -697,6 +697,7 @@ int enumerate_interfaces(int reset)
+ struct auth_zone *zone;
+ #endif
+ struct server *serv;
++ int iteration = 0;
+
+ /* Do this max once per select cycle - also inhibits netlink socket use
+ in TCP child processes. */
+@@ -734,6 +735,10 @@ int enumerate_interfaces(int reset)
+ }
+
+ again:
++ if (iteration > 100) {
++ return 0;
++ }
++ iteration += 1;
+ /* Mark interfaces for garbage collection */
+ for (iface = daemon->interfaces; iface; iface = iface->next)
+ iface->found = 0;
diff --git a/projects/dnsmasq/fuzz_rfc1035.c b/projects/dnsmasq/fuzz_rfc1035.c
new file mode 100644
index 000000000..fb563f804
--- /dev/null
+++ b/projects/dnsmasq/fuzz_rfc1035.c
@@ -0,0 +1,271 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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_null_terminated(&data, &size);
+ 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_null_terminated(&data, &size);
+
+ 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_null_terminated(&data, &size);
+ 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;
+}
diff --git a/projects/dnsmasq/fuzz_util.c b/projects/dnsmasq/fuzz_util.c
new file mode 100644
index 000000000..7ab723ccd
--- /dev/null
+++ b/projects/dnsmasq/fuzz_util.c
@@ -0,0 +1,66 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ // init fuzz garbage collector
+ gb_init();
+
+ int succ = init_daemon(&data, &size);
+ if (succ == 0) {
+ char *t1 = gb_get_null_terminated(&data, &size);
+ char *t2 = gb_get_null_terminated(&data, &size);
+ if (t1 != NULL && t2 != NULL) {
+
+ // 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);
+ 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 (strlen(t1) < strlen(t2)) {
+ wildcard_matchn(t1, t2, strlen(t1));
+ } else {
+ wildcard_matchn(t1, t2, strlen(t2));
+ }
+ hostname_issubdomain(t1, t2);
+
+ union all_addr addr1;
+ memset(&addr1, 0, sizeof(union all_addr));
+ is_name_synthetic(0, t1, &addr1);
+
+ if (size > sizeof(struct dns_header)) {
+ hash_questions(data, size, t2);
+
+ rrfilter(data, size, 0);
+ }
+ }
+
+ fuzz_blockdata_cleanup();
+ }
+
+ // cleanup
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/dnsmasq/project.yaml b/projects/dnsmasq/project.yaml
new file mode 100644
index 000000000..51d7e1e07
--- /dev/null
+++ b/projects/dnsmasq/project.yaml
@@ -0,0 +1,6 @@
+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"
diff --git a/projects/draco/project.yaml b/projects/draco/project.yaml
index 04ef12e18..96396bfe6 100644
--- a/projects/draco/project.yaml
+++ b/projects/draco/project.yaml
@@ -4,4 +4,7 @@ primary_contact: "fgalligan@google.com"
auto_ccs:
- "ostava@google.com"
- "vytyaz@google.com"
+fuzzing_engines:
+ - libfuzzer
+ - honggfuzz
main_repo: 'https://github.com/google/draco'
diff --git a/projects/dragonfly/Dockerfile b/projects/dragonfly/Dockerfile
index 46870a6db..1399802d1 100644
--- a/projects/dragonfly/Dockerfile
+++ b/projects/dragonfly/Dockerfile
@@ -14,20 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN go get github.com/go-openapi/swag \
- github.com/go-openapi/validate \
- gopkg.in/warnings.v0 \
- github.com/gorilla/mux \
- github.com/prometheus/client_golang/prometheus \
- github.com/pkg/errors \
- github.com/sirupsen/logrus \
- gopkg.in/gcfg.v1 \
- github.com/valyala/fasthttp \
- gopkg.in/natefinch/lumberjack.v2 \
- github.com/emirpasic/gods/maps/treemap \
- github.com/emirpasic/gods/utils \
- github.com/willf/bitset
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/dragonflyoss/Dragonfly
COPY build.sh $SRC/
WORKDIR $SRC/Dragonfly
diff --git a/projects/duckdb/Dockerfile b/projects/duckdb/Dockerfile
new file mode 100644
index 000000000..b084a7404
--- /dev/null
+++ b/projects/duckdb/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/duckdb/duckdb duckdb
+WORKDIR duckdb
+COPY build.sh $SRC/
+COPY parse_fuzz_test.cpp $SRC/duckdb/parse_fuzz_test.cpp
diff --git a/projects/duckdb/build.sh b/projects/duckdb/build.sh
new file mode 100755
index 000000000..096147346
--- /dev/null
+++ b/projects/duckdb/build.sh
@@ -0,0 +1,23 @@
+#!/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
+THIRD_PARTY_LIBS=$(find ./build/release/third_party/ -name "*.a")
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE ./parse_fuzz_test.cpp \
+ -o $OUT/parse_fuzz_test -I./ -I./src/include \
+ ./build/release/src/libduckdb_static.a \
+ ${THIRD_PARTY_LIBS}
diff --git a/projects/duckdb/parse_fuzz_test.cpp b/projects/duckdb/parse_fuzz_test.cpp
new file mode 100644
index 000000000..fdae6bdc3
--- /dev/null
+++ b/projects/duckdb/parse_fuzz_test.cpp
@@ -0,0 +1,23 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "duckdb/parser/parser.hpp"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ std::string input(reinterpret_cast<const char*>(data), size);
+ duckdb::Parser parser;
+ try {
+ parser.ParseQuery(input);
+ } catch (std::exception &e) {}
+
+ return 0;
+}
diff --git a/projects/duckdb/project.yaml b/projects/duckdb/project.yaml
new file mode 100644
index 000000000..3de096c0a
--- /dev/null
+++ b/projects/duckdb/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://duckdb.org/"
+language: c++
+primary_contact: "quack@duckdb.org"
+main_repo: "https://github.com/duckdb/duckdb/"
+auto_ccs:
+ - "hannes.muehleisen@gmail.com"
+ - "david@adalogics.com"
diff --git a/projects/easywsclient/project.yaml b/projects/easywsclient/project.yaml
index c3be9c4fd..d7822c854 100644
--- a/projects/easywsclient/project.yaml
+++ b/projects/easywsclient/project.yaml
@@ -3,9 +3,10 @@ language: c++
primary_contact: "dhbaird@gmail.com"
sanitizers:
- address
- - memory
+# 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'
+main_repo: 'https://github.com/dhbaird/easywsclient' \ No newline at end of file
diff --git a/projects/ecc-diff-fuzzer/Dockerfile b/projects/ecc-diff-fuzzer/Dockerfile
index 0ea8a4e4b..6defc0039 100644
--- a/projects/ecc-diff-fuzzer/Dockerfile
+++ b/projects/ecc-diff-fuzzer/Dockerfile
@@ -14,7 +14,10 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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
@@ -23,9 +26,9 @@ RUN bash nodesource_setup.sh
RUN apt install -y nodejs
RUN npm install -g browserify
RUN npm install elliptic
-RUN git clone --depth 1 https://github.com/horhof/quickjs quickjs
+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 https://github.com/ARMmbed/mbedtls.git mbedtls
+RUN git clone --recursive --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git mbedtls
RUN git clone --depth 1 https://github.com/ANSSI-FR/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
diff --git a/projects/ecc-diff-fuzzer/build.sh b/projects/ecc-diff-fuzzer/build.sh
index 9b951cae8..d05c14ae9 100755
--- a/projects/ecc-diff-fuzzer/build.sh
+++ b/projects/ecc-diff-fuzzer/build.sh
@@ -123,6 +123,7 @@ 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
diff --git a/projects/eigen/solver_fuzzer.cc b/projects/eigen/solver_fuzzer.cc
index 86651ecf0..0cd8b6c88 100644
--- a/projects/eigen/solver_fuzzer.cc
+++ b/projects/eigen/solver_fuzzer.cc
@@ -18,7 +18,6 @@
#include <string>
#include "Eigen/Core"
-#include "Eigen/src/Core/Matrix.h"
using ::Eigen::Matrix;
using ::Eigen::Dynamic;
diff --git a/projects/envoy/build.sh b/projects/envoy/build.sh
index 09086a2cc..6c188fc4e 100755
--- a/projects/envoy/build.sh
+++ b/projects/envoy/build.sh
@@ -38,9 +38,64 @@ fi
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=^.*antlr4_runtimes.*\.cpp\$@-fsanitize-coverage=0,-fno-sanitize=all"
+ 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=^.*googletest.*\.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_google_cel_cpp.*\.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"
+
+# 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
+)"
+
+
# Benchmark about 3 GB per CPU (10 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 \
+bazel build --verbose_failures --dynamic_mode=off ${DI} \
--spawn_strategy=standalone --genrule_strategy=standalone \
--local_cpu_resources=HOST_CPUS*0.32 \
--//source/extensions/wasm_runtime/v8:enabled=false \
diff --git a/projects/envoy/project.yaml b/projects/envoy/project.yaml
index 5fae1498a..bb9481c9c 100644
--- a/projects/envoy/project.yaml
+++ b/projects/envoy/project.yaml
@@ -12,11 +12,12 @@ auto_ccs:
- "asraa@google.com"
- "adip@google.com"
- "avd@google.com"
- - "skerner@google.com"
- - "rdsmith@google.com"
- "chaoqinli@google.com"
- "yanjunxiang@google.com"
- - "arquebus@appspot.gserviceaccount.com"
- "david@adalogics.com"
+ - "kbaichoo@google.com"
+ - "pcrao@google.com"
+ - "tyxia@google.com"
+ - "krajshiva@google.com"
coverage_extra_args: -ignore-filename-regex=.*\.cache.*envoy_deps_cache.*
main_repo: 'https://github.com/envoyproxy/envoy.git'
diff --git a/projects/espeak-ng/Dockerfile b/projects/espeak-ng/Dockerfile
new file mode 100644
index 000000000..674c629ca
--- /dev/null
+++ b/projects/espeak-ng/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 automake autoconf libtool pkg-config
+RUN git clone --depth 1 https://github.com/espeak-ng/espeak-ng
+COPY build.sh $SRC
+WORKDIR $SRC/espeak-ng
diff --git a/projects/espeak-ng/build.sh b/projects/espeak-ng/build.sh
new file mode 100755
index 000000000..079db4dc1
--- /dev/null
+++ b/projects/espeak-ng/build.sh
@@ -0,0 +1,25 @@
+#!/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 ASAN_OPTIONS=detect_leaks=0
+./autogen.sh
+./configure --with-libfuzzer=yes --disable-shared --with-speechplayer=no
+make check || true
+cp tests/ssml-fuzzer.test $OUT/ssml-fuzzer
+cp -r espeak-ng-data/ $OUT/
diff --git a/projects/espeak-ng/project.yaml b/projects/espeak-ng/project.yaml
new file mode 100644
index 000000000..142a78de5
--- /dev/null
+++ b/projects/espeak-ng/project.yaml
@@ -0,0 +1,14 @@
+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'
diff --git a/projects/etcd/Dockerfile b/projects/etcd/Dockerfile
new file mode 100644
index 000000000..789f755b7
--- /dev/null
+++ b/projects/etcd/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+COPY wal_fuzzer.go build.sh $SRC/
+WORKDIR $SRC/etcd
diff --git a/projects/etcd/build.sh b/projects/etcd/build.sh
new file mode 100644
index 000000000..6df485bc8
--- /dev/null
+++ b/projects/etcd/build.sh
@@ -0,0 +1,20 @@
+#!/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/wal_fuzzer.go $SRC/etcd/server/storage/wal/
+compile_go_fuzzer go.etcd.io/etcd/server/v3/storage/wal FuzzWalCreate fuzz_wal_create
+
diff --git a/projects/etcd/project.yaml b/projects/etcd/project.yaml
new file mode 100644
index 000000000..4470f5c58
--- /dev/null
+++ b/projects/etcd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://etcd.io"
+main_repo: "https://github.com/etcd-io/etcd"
+primary_contact: "ptab@google.com"
+auto_ccs :
+ - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/etcd/wal_fuzzer.go b/projects/etcd/wal_fuzzer.go
new file mode 100644
index 000000000..8b21e381a
--- /dev/null
+++ b/projects/etcd/wal_fuzzer.go
@@ -0,0 +1,58 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 wal
+
+import (
+ "bytes"
+ "io/ioutil"
+ "os"
+
+ "go.etcd.io/etcd/raft/v3/raftpb"
+ "go.etcd.io/etcd/server/v3/storage/wal/walpb"
+ "go.uber.org/zap"
+)
+
+func FuzzWalCreate(data []byte) int {
+ p, err := ioutil.TempDir("/tmp", "waltest")
+ if err != nil {
+ return -1
+ }
+ defer os.RemoveAll(p)
+ w, err := Create(zap.NewExample(), p, data)
+ if err != nil {
+ return 0
+ }
+ if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil {
+ return 0
+ }
+ if err = w.Save(raftpb.HardState{}, []raftpb.Entry{{Index: 0}}); err != nil {
+ return 0
+ }
+ w.Close()
+ neww, err := Open(zap.NewExample(), p, walpb.Snapshot{})
+ if err != nil {
+ return 0
+ }
+ defer neww.Close()
+ metadata, _, _, err := neww.ReadAll()
+ if err != nil {
+ return 0
+ }
+ if !bytes.Equal(data, metadata) {
+ panic("data and metadata are not equal, but they should be")
+ }
+ return 1
+}
diff --git a/projects/exiv2/Dockerfile b/projects/exiv2/Dockerfile
new file mode 100644
index 000000000..1540fe47f
--- /dev/null
+++ b/projects/exiv2/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 ccache python3 libexpat1-dev zlib1g-dev libssh-dev libcurl4-openssl-dev libxml2-utils
+RUN git clone https://github.com/Exiv2/exiv2 exiv2
+WORKDIR exiv2
+
+COPY build.sh $SRC/
diff --git a/projects/exiv2/build.sh b/projects/exiv2/build.sh
new file mode 100755
index 000000000..568d851a0
--- /dev/null
+++ b/projects/exiv2/build.sh
@@ -0,0 +1,38 @@
+#!/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}" ..
+make -j $(nproc)
+
+# Copy binary and dictionary to $OUT
+cp ./bin/fuzz-read-print-write $OUT
+cp ../fuzz/exiv2.dict $OUT/fuzz-read-print-write.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/*
diff --git a/projects/exiv2/project.yaml b/projects/exiv2/project.yaml
new file mode 100644
index 000000000..29838abe7
--- /dev/null
+++ b/projects/exiv2/project.yaml
@@ -0,0 +1,9 @@
+homepage: "https://www.exiv2.org"
+language: c++
+primary_contact: "kevinbackhouse@github.com"
+sanitizers:
+ - address
+ - undefined
+architectures:
+ - x86_64
+main_repo: 'https://github.com/Exiv2/exiv2'
diff --git a/projects/exprtk/project.yaml b/projects/exprtk/project.yaml
index ac0747e76..ec2f75010 100644
--- a/projects/exprtk/project.yaml
+++ b/projects/exprtk/project.yaml
@@ -10,5 +10,6 @@ fuzzing_engines:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
main_repo: 'https://github.com/ArashPartow/exprtk.git'
diff --git a/projects/fast-dds/Dockerfile b/projects/fast-dds/Dockerfile
index df5782e63..414d421d9 100644
--- a/projects/fast-dds/Dockerfile
+++ b/projects/fast-dds/Dockerfile
@@ -21,6 +21,5 @@ RUN git clone --depth 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 patch.diff $SRC
COPY build.sh $SRC
WORKDIR $SRC/Fast-DDS
diff --git a/projects/fast-dds/build.sh b/projects/fast-dds/build.sh
index 6831dffe3..74c460f52 100755
--- a/projects/fast-dds/build.sh
+++ b/projects/fast-dds/build.sh
@@ -18,6 +18,7 @@
(
cd ../tinyxml2
+make clean
make -j$(nproc) all
cp libtinyxml2.a /usr/local/lib/
cp *.h /usr/local/include/
@@ -46,7 +47,6 @@ cmake --build . --target install
)
# build project
-git apply ../patch.diff
mkdir build && cd build
cmake .. -DBUILD_SHARED_LIBS=OFF
make -j $(nproc)
diff --git a/projects/fast-dds/patch.diff b/projects/fast-dds/patch.diff
deleted file mode 100644
index e4f0ba2ed..000000000
--- a/projects/fast-dds/patch.diff
+++ /dev/null
@@ -1,74 +0,0 @@
-diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index b7fb777..615e955 100644
---- a/src/cpp/CMakeLists.txt
-+++ b/src/cpp/CMakeLists.txt
-@@ -484,6 +484,11 @@ elseif(NOT EPROSIMA_INSTALLER)
- endif()
- endif()
-
-+if(DEFINED ENV{LIB_FUZZING_ENGINE})
-+ add_executable(fuzz_processCDRMsg rtps/messages/fuzz_processCDRMsg.cpp)
-+ target_link_libraries(fuzz_processCDRMsg ${PROJECT_NAME} $ENV{LIB_FUZZING_ENGINE})
-+endif()
-+
- ###############################################################################
- # Packaging
- ###############################################################################
-diff --git a/src/cpp/rtps/messages/MessageReceiver.cpp b/src/cpp/rtps/messages/MessageReceiver.cpp
-index 962ca9b..0e82082 100644
---- a/src/cpp/rtps/messages/MessageReceiver.cpp
-+++ b/src/cpp/rtps/messages/MessageReceiver.cpp
-@@ -324,7 +324,11 @@ void MessageReceiver::processCDRMsg(
-
- reset();
-
-+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+ GuidPrefix_t participantGuidPrefix;
-+#else
- GuidPrefix_t participantGuidPrefix = participant_->getGuid().guidPrefix;
-+#endif
- dest_guid_prefix_ = participantGuidPrefix;
-
- msg->pos = 0; //Start reading at 0
-@@ -513,7 +517,9 @@ void MessageReceiver::processCDRMsg(
- submessage->pos = next_msg_pos;
- }
-
-+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- participant_->assert_remote_participant_liveliness(source_guid_prefix_);
-+#endif
- }
-
- bool MessageReceiver::checkRTPSHeader(
-diff --git a/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp b/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp
-new file mode 100644
-index 0000000..6a71817
---- /dev/null
-+++ b/src/cpp/rtps/messages/fuzz_processCDRMsg.cpp
-@@ -0,0 +1,26 @@
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <stdarg.h>
-+#include <string.h>
-+
-+#include <fastrtps/rtps/messages/MessageReceiver.h>
-+#include <fastdds/rtps/attributes/RTPSParticipantAttributes.h>
-+
-+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
-+ const eprosima::fastrtps::rtps::Locator_t remoteLocator;
-+ eprosima::fastrtps::rtps::MessageReceiver* rcv = new eprosima::fastrtps::rtps::MessageReceiver(NULL, 4096);
-+
-+ eprosima::fastrtps::rtps::CDRMessage_t msg(0);
-+ msg.wraps = true;
-+ msg.buffer = const_cast<eprosima::fastrtps::rtps::octet*>(data);
-+ msg.length = size;
-+ msg.max_size = size;
-+ msg.reserved_size = size;
-+
-+ // TODO: Should we unlock in case UnregisterReceiver is called from callback ?
-+ rcv->processCDRMsg(remoteLocator, &msg);
-+ delete rcv;
-+ return 0;
-+}
-+
diff --git a/projects/fasthttp/Dockerfile b/projects/fasthttp/Dockerfile
index 368470692..6edf310b2 100644
--- a/projects/fasthttp/Dockerfile
+++ b/projects/fasthttp/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/valyala/fasthttp
COPY build.sh $SRC/
diff --git a/projects/fastjson/Dockerfile b/projects/fastjson/Dockerfile
index 9c196148d..a61633303 100644
--- a/projects/fastjson/Dockerfile
+++ b/projects/fastjson/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/valyala/fastjson
COPY build.sh $SRC/
diff --git a/projects/fastjson2/Dockerfile b/projects/fastjson2/Dockerfile
index e8c9f4ec8..ba6eae0b2 100644
--- a/projects/fastjson2/Dockerfile
+++ b/projects/fastjson2/Dockerfile
@@ -15,7 +15,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/google/fuzzing && \
diff --git a/projects/fastjson2/build.sh b/projects/fastjson2/build.sh
index 121c3249a..56f2f2d6f 100644
--- a/projects/fastjson2/build.sh
+++ b/projects/fastjson2/build.sh
@@ -47,5 +47,5 @@ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
--target_class=$fuzzer_basename \
--jvm_args=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/ffmpeg/Dockerfile b/projects/ffmpeg/Dockerfile
index bb0bb58ac..552cd3229 100644
--- a/projects/ffmpeg/Dockerfile
+++ b/projects/ffmpeg/Dockerfile
@@ -15,11 +15,9 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-ADD bionic.list /etc/apt/sources.list.d/bionic.list
-ADD nasm_apt.pin /etc/apt/preferences
RUN apt-get update && apt-get install -y make autoconf automake libtool build-essential \
libass-dev libfreetype6-dev libsdl1.2-dev \
- libvdpau-dev libxcb1-dev libxcb-shm0-dev \
+ libvdpau-dev libxcb1-dev libxcb-shm0-dev libdrm-dev \
pkg-config texinfo libbz2-dev zlib1g-dev yasm cmake mercurial wget \
xutils-dev libpciaccess-dev nasm rsync
@@ -28,7 +26,6 @@ RUN git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
RUN wget https://www.alsa-project.org/files/pub/lib/alsa-lib-1.1.0.tar.bz2
RUN git clone --depth 1 https://github.com/mstorsjo/fdk-aac.git
RUN git clone --depth 1 git://anongit.freedesktop.org/xorg/lib/libXext
-RUN git clone --depth 1 git://anongit.freedesktop.org/git/xorg/lib/libXfixes
RUN git clone --depth 1 https://github.com/intel/libva
RUN git clone --depth 1 -b libvdpau-1.2 git://people.freedesktop.org/~aplattner/libvdpau
RUN git clone --depth 1 https://chromium.googlesource.com/webm/libvpx
diff --git a/projects/ffmpeg/bionic.list b/projects/ffmpeg/bionic.list
deleted file mode 100644
index 8621803a7..000000000
--- a/projects/ffmpeg/bionic.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm 2.13.02 from bionic
-deb http://archive.ubuntu.com/ubuntu/ bionic universe
diff --git a/projects/ffmpeg/build.sh b/projects/ffmpeg/build.sh
index 90da59c44..2e432428a 100755
--- a/projects/ffmpeg/build.sh
+++ b/projects/ffmpeg/build.sh
@@ -29,6 +29,7 @@ export LD_LIBRARY_PATH="$FFMPEG_DEPS_PATH/lib"
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 clean
@@ -50,13 +51,6 @@ make clean
make -j$(nproc)
make install
-cd $SRC/libXfixes
-./autogen.sh
-./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static
-make clean
-make -j$(nproc)
-make install
-
cd $SRC/libva
./autogen.sh
./configure --prefix="$FFMPEG_DEPS_PATH" --enable-static --disable-shared
@@ -145,7 +139,7 @@ PKG_CONFIG_PATH="$FFMPEG_DEPS_PATH/lib/pkgconfig" ./configure \
make clean
make -j$(nproc) install
-# Download test sampes, will be used as seed corpus.
+# 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
@@ -162,6 +156,10 @@ export TEMP_VAR_CODEC="AV_CODEC_ID_H264"
export TEMP_VAR_CODEC_TYPE="VIDEO"
CONDITIONALS=`grep 'BSF 1$' config.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=ffmpeg_BSF_${c}_fuzzer
symbol=`echo $c | sed "s/.*/\L\0/"`
@@ -172,6 +170,10 @@ done
# Build fuzzers for decoders.
CONDITIONALS=`grep 'DECODER 1$' config.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=ffmpeg_AV_CODEC_ID_${c}_fuzzer
symbol=`echo $c | sed "s/.*/\L\0/"`
@@ -192,6 +194,7 @@ 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
# Build fuzzer for demuxer fed at IO level
fuzzer_name=ffmpeg_IO_DEMUXER_fuzzer
@@ -229,6 +232,10 @@ PKG_CONFIG_PATH="$FFMPEG_DEPS_PATH/lib/pkgconfig" ./configure \
--disable-demuxer=rtp,rtsp,sdp \
CONDITIONALS=`grep 'DEMUXER 1$' config.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=ffmpeg_dem_${c}_fuzzer
symbol=`echo $c | sed "s/.*/\L\0/"`
diff --git a/projects/ffmpeg/nasm_apt.pin b/projects/ffmpeg/nasm_apt.pin
deleted file mode 100644
index 69099026b..000000000
--- a/projects/ffmpeg/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=bionic
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=bionic
-Pin-Priority: 555
diff --git a/projects/file/project.yaml b/projects/file/project.yaml
index d0518477b..e148c56a6 100644
--- a/projects/file/project.yaml
+++ b/projects/file/project.yaml
@@ -3,7 +3,8 @@ language: c++
primary_contact: "zoulasc@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- x86_64
diff --git a/projects/firefox/Dockerfile b/projects/firefox/Dockerfile
index 1d19ca82e..515e9df26 100644
--- a/projects/firefox/Dockerfile
+++ b/projects/firefox/Dockerfile
@@ -15,13 +15,16 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
-RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
- gawk \
- libstdc++6 \
- m4 \
- python \
- software-properties-common
+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 \
+ gawk \
+ libstdc++6 \
+ m4 \
+ python
# This wrapper of cargo seems to interfere with our build system.
RUN rm -f /usr/local/bin/cargo
diff --git a/projects/flac/build.sh b/projects/flac/build.sh
index c94ba22f7..3ccf5495d 100755
--- a/projects/flac/build.sh
+++ b/projects/flac/build.sh
@@ -53,7 +53,7 @@ cd $SRC/fuzzing-headers
# Build fuzzers
cd $SRC/flac-fuzzers/
-$CXX $CXXFLAGS -I $SRC/flac/include/ -I $SRC/ExoPlayer/extensions/flac/src/main/jni/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/ -I /usr/lib/jvm/java-8-openjdk-amd64/include/linux/ fuzzer_exo.cpp \
+$CXX $CXXFLAGS -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
$CXX $CXXFLAGS -I $SRC/flac/include/ fuzzer_decoder.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_decoder
$CXX $CXXFLAGS -I $SRC/flac/include/ fuzzer_encoder.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_encoder
diff --git a/projects/flatbuffers/Dockerfile b/projects/flatbuffers/Dockerfile
index d51dac792..83caf67c0 100644
--- a/projects/flatbuffers/Dockerfile
+++ b/projects/flatbuffers/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make cmake ninja
+RUN apt-get update && apt-get install -y make cmake
RUN git clone https://github.com/google/flatbuffers
WORKDIR $SRC/
diff --git a/projects/flate2-rs/Dockerfile b/projects/flate2-rs/Dockerfile
new file mode 100644
index 000000000..1309ff0fb
--- /dev/null
+++ b/projects/flate2-rs/Dockerfile
@@ -0,0 +1,19 @@
+# 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/
diff --git a/projects/flate2-rs/build.sh b/projects/flate2-rs/build.sh
new file mode 100644
index 000000000..c0ee06a9c
--- /dev/null
+++ b/projects/flate2-rs/build.sh
@@ -0,0 +1,20 @@
+#!/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
diff --git a/projects/flate2-rs/project.yaml b/projects/flate2-rs/project.yaml
new file mode 100644
index 000000000..05a29a9b8
--- /dev/null
+++ b/projects/flate2-rs/project.yaml
@@ -0,0 +1,10 @@
+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"
diff --git a/projects/fluent-bit/build.sh b/projects/fluent-bit/build.sh
index e68e5b819..bf5aac315 100755
--- a/projects/fluent-bit/build.sh
+++ b/projects/fluent-bit/build.sh
@@ -14,7 +14,11 @@
# limitations under the License.
#
################################################################################
-cd fluent-bit/build
+cd fluent-bit
+sed -i 's/malloc(/fuzz_malloc(/g' ./lib/msgpack-c/src/zone.c
+sed -i 's/struct msgpack_zone_chunk {/void *fuzz_malloc(size_t size) {if (size > 0xa00000) return NULL;\nreturn malloc(size);}\nstruct msgpack_zone_chunk {/g' ./lib/msgpack-c/src/zone.c
+
+cd build
export CFLAGS="$CFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON"
export CXXFLAGS="$CXXFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON"
@@ -23,8 +27,14 @@ export CXXFLAGS="$CXXFLAGS -fcommon -DFLB_TESTS_OSSFUZZ=ON"
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_STREAM_PROCESSOR=Off -DFLB_LUAJIT=OFF -DFLB_FILTER_GREP=OFF -DFLB_FILTER_REWRITE_TAG=OFF -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=OFF -DFLB_OUT_INFLUXDB=OFF -DFLB_OUT_KAFKA=OFF -DFLB_OUT_KAFKA_REST=OFF -DFLB_OUT_NATS=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=OFF -DFLB_OUT_TCP=OFF -DFLB_OUT_SYSLOG=OFF -DFLB_OUT_NRLOGS=OFF -DFLB_OUT_LOKI=OFF"
FILTER_PLUGINS="-DFLB_FILTER_PARSER=ON -DFLB_FILTER_RECORD_MODIFIER=OFF -DFLB_FILTER_MODIFY=OFF -DFLB_FILTER_THROTTLE=OFF -DFLB_FILTER_KUBERNETES=OFF -DFLB_FILTER_NEST=OFF -DFLB_FILTER_PARSER=OFF -DFLB_FILTER_AWS=OFF -DFLB_FILTER_ALTER_SIZE=OFF"
-
-cmake -DFLB_METRICS=ON -DFLB_DEBUG=On -DMBEDTLS_FATAL_WARNINGS=OFF -DFLB_TESTS_INTERNAL=ON -DFLB_TESTS_INTERNAL_FUZZ=ON -DFLB_TESTS_OSSFUZZ=ON ${INPUT_PLUGINS} ${FILTER_PLUGINS} ${OUTPUT_PLUGINS} ..
+EXTRA_FLAGS="-DFLB_BINARY=OFF -DFLB_EXAMPLES=OFF DFLB_METRICS=ON -DFLB_DEBUG=On -DMBEDTLS_FATAL_WARNINGS=OFF"
+cmake -DFLB_TESTS_INTERNAL=ON \
+ -DFLB_TESTS_INTERNAL_FUZZ=ON \
+ -DFLB_TESTS_OSSFUZZ=ON \
+ ${EXTRA_FLAGS} \
+ ${INPUT_PLUGINS} \
+ ${FILTER_PLUGINS} \
+ ${OUTPUT_PLUGINS} ..
make
# Create options files
diff --git a/projects/fluent-bit/project.yaml b/projects/fluent-bit/project.yaml
index aca7cccc6..968e23a0d 100755
--- a/projects/fluent-bit/project.yaml
+++ b/projects/fluent-bit/project.yaml
@@ -4,4 +4,5 @@ language: c++
auto_ccs:
- "david@adalogics.com"
- "wppttt@amazon.com"
+ - "zh0512xx@gmail.com"
main_repo: 'https://github.com/fluent/fluent-bit/'
diff --git a/projects/freeradius/Dockerfile b/projects/freeradius/Dockerfile
new file mode 100644
index 000000000..083532ebc
--- /dev/null
+++ b/projects/freeradius/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libtalloc-dev libkqueue-dev
+
+# OpenSSL 1.1
+ARG OPENSSL_VERSION=1.1.1g
+ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
+RUN set -ex \
+ && curl -s -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 --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
diff --git a/projects/freeradius/build.sh b/projects/freeradius/build.sh
new file mode 100755
index 000000000..17f2c0ae8
--- /dev/null
+++ b/projects/freeradius/build.sh
@@ -0,0 +1,45 @@
+#!/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-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
+ 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/
diff --git a/projects/freeradius/patch.diff b/projects/freeradius/patch.diff
new file mode 100644
index 000000000..5436820d8
--- /dev/null
+++ b/projects/freeradius/patch.diff
@@ -0,0 +1,64 @@
+diff --git a/configure.ac b/configure.ac
+index 56e9600..ad488e8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -21,7 +21,7 @@ dnl #
+ dnl #############################################################
+
+ AC_PREREQ([2.59])
+-export CFLAGS LIBS LDFLAGS CPPFLAGS
++#export CFLAGS LIBS LDFLAGS CPPFLAGS
+
+ AC_INIT([freeradius],[$]Id[$],[http://bugs.freeradius.org],,[http://www.freeradius.org])
+ AC_CONFIG_SRCDIR([src/bin/radiusd.c])
+@@ -185,7 +185,7 @@ dnl # -g3 so nice things like macro values are included. Other arguments are
+ dnl # added later when we know what compiler were using.
+ dnl #
+ if test "x$developer" = "xyes"; then
+- : ${CFLAGS=-g3}
++ : ${CFLAGS="$CFLAGS -g3"}
+ fi
+
+ dnl #
+
+diff --git a/src/bin/fuzzer.c b/src/bin/fuzzer.c
+index 9c2eb50..82d6fd6 100644
+--- a/src/bin/fuzzer.c
++++ b/src/bin/fuzzer.c
+@@ -125,7 +125,21 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
+ }
+ }
+
+- if (!dict_dir) dict_dir = DICTDIR;
++ int free_dict = 0;
++ int free_lib = 0;
++ if (!dict_dir) {
++ dict_dir = malloc(strlen((*argv)[0]) + 1);
++ memcpy(dict_dir, (*argv)[0], strlen((*argv)[0]) + 1);
++ snprintf(strrchr(dict_dir, '/'), 6, "/dict");
++ free_dict = 1;
++ }
++ if (!lib_dir) {
++ lib_dir = malloc(strlen((*argv)[0]) + 1);
++ memcpy(lib_dir, (*argv)[0], strlen((*argv)[0]) + 1);
++ snprintf(strrchr(lib_dir, '/'), 5, "/lib");
++ setenv("FR_LIBRARY_PATH", lib_dir, 1);
++ free_lib = 1;
++ }
+
+ /*
+ * When jobs=N is specified the fuzzer spawns worker processes via
+@@ -182,6 +196,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
+
+ init = true;
+
++ if (free_lib) {
++ free(lib_dir);
++ }
++ if (free_dict) {
++ free(dict_dir);
++ }
++
+ return 1;
+ }
+
diff --git a/projects/freeradius/project.yaml b/projects/freeradius/project.yaml
new file mode 100644
index 000000000..a04dae509
--- /dev/null
+++ b/projects/freeradius/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://freeradius.org"
+language: c++
+primary_contact: "a.cudbardb@gmail.com"
+auto_ccs:
+- "adekok@gmail.com"
+- "p.antoine@catenacyber.fr"
+main_repo: 'https://github.com/FreeRADIUS/freeradius-server.git'
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
diff --git a/projects/freetype2/project.yaml b/projects/freetype2/project.yaml
index 964977286..c747e1bd0 100644
--- a/projects/freetype2/project.yaml
+++ b/projects/freetype2/project.yaml
@@ -2,7 +2,6 @@ homepage: "https://www.freetype.org/"
language: c++
primary_contact: "lemzwerg@gmail.com"
auto_ccs:
- - "darnold@adobe.com"
- "lemzwerg@googlemail.com"
- "HinTak.Leung@gmail.com"
- "ewaldhew@gmail.com"
diff --git a/projects/fribidi/Dockerfile b/projects/fribidi/Dockerfile
new file mode 100644
index 000000000..b4d9ea75d
--- /dev/null
+++ b/projects/fribidi/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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.53.0 ninja
+RUN git clone --depth 1 https://github.com/fribidi/fribidi.git
+WORKDIR fribidi
+COPY build.sh $SRC/
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py b/projects/fribidi/build.sh
index f8407a668..aa8f60acc 100644..100755
--- a/infra/base-images/base-sanitizer-libs-builder/packages/gnutls28.py
+++ b/projects/fribidi/build.sh
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+#!/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.
@@ -15,23 +15,22 @@
#
################################################################################
-import os
-import shutil
+# setup
+build=$WORK/build
-import package
-import wrapper_utils
+# 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)
-class Package(package.Package):
- """gnutls28 package."""
+# Build the fuzzers.
+ninja -v -j$(nproc) -C $build bin/fribidi-fuzzer
+mv $build/bin/fribidi-fuzzer $OUT/
- def __init__(self, apt_version):
- super(Package, self).__init__('gnutls28', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- configure_wrapper = (
- '#!/bin/bash\n'
- '/usr/bin/dh_auto_configure "$@" --disable-hardware-acceleration')
-
- wrapper_utils.InstallWrapper(
- custom_bin_dir, 'dh_auto_configure', configure_wrapper)
+# Archive and copy to $OUT seed corpus if the build succeeded.
+zip $OUT/fribidi-fuzzer_seed_corpus.zip test/*.{input,reference} test/fuzzing/*
diff --git a/projects/fribidi/project.yaml b/projects/fribidi/project.yaml
new file mode 100644
index 000000000..7fbac3aa0
--- /dev/null
+++ b/projects/fribidi/project.yaml
@@ -0,0 +1,17 @@
+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'
diff --git a/infra/base-images/msan-libs-builder/Dockerfile b/projects/frr/Dockerfile
index 7780c1f33..3286cc63e 100644
--- a/infra/base-images/msan-libs-builder/Dockerfile
+++ b/projects/frr/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2017 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,32 +14,17 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-sanitizer-libs-builder
+FROM gcr.io/oss-fuzz-base/base-builder
-# Take all libraries from lib/msan
-RUN cp -R /usr/msan/lib/* /usr/lib/
+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
+RUN pip3 install pytest
+RUN git clone https://github.com/CESNET/libyang.git
-RUN mkdir /msan
-WORKDIR /msan
+RUN git clone --depth 1 --branch fuzz https://github.com/FRRouting/frr
-ENV PYTHONUNBUFFERED 1
-RUN msan_build.py --work-dir=$WORK \
- libarchive13 \
- libattr1 \
- libbz2-1.0 \
- libfontconfig1 \
- libfreetype6 \
- libfribidi0 \
- libglib2.0-0 \
- libicu55 \
- liblz4-1 \
- liblzma5 \
- liblzo2-2 \
- libnettle6 \
- libpcre2-posix0 \
- libpcre3 \
- libpng12-0 \
- libssl1.0.0 \
- libxml2 \
- zlib1g \
- /msan
+RUN git clone --depth 1 https://github.com/qlyoung/corpi
+COPY build.sh $SRC
+WORKDIR $SRC/frr
diff --git a/projects/frr/build.sh b/projects/frr/build.sh
new file mode 100755
index 000000000..ad1584e47
--- /dev/null
+++ b/projects/frr/build.sh
@@ -0,0 +1,63 @@
+#!/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/ || 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
+./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
+done
+
+patchelf --remove-needed libpcre2-8.so.0 $OUT/lib/libyang.so.2
diff --git a/projects/frr/project.yaml b/projects/frr/project.yaml
new file mode 100644
index 000000000..8955c4f0e
--- /dev/null
+++ b/projects/frr/project.yaml
@@ -0,0 +1,11 @@
+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"
+fuzzing_engines:
+ - libfuzzer
+main_repo: 'https://github.com/FRRouting/frr'
diff --git a/projects/gcloud-go/Dockerfile b/projects/gcloud-go/Dockerfile
index 1d2b38e53..fe2f3b253 100644
--- a/projects/gcloud-go/Dockerfile
+++ b/projects/gcloud-go/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
LABEL maintainer="codyoss@google.com"
RUN go get cloud.google.com/go/spanner
COPY build.sh $SRC/
diff --git a/projects/gdal/project.yaml b/projects/gdal/project.yaml
index d0bbfe4b3..447fe103c 100644
--- a/projects/gdal/project.yaml
+++ b/projects/gdal/project.yaml
@@ -9,6 +9,7 @@ auto_ccs:
- "athomas@thinkspatial.com.au"
- "ari.jolma@gmail.com"
- "bjorn.harrtell@gmail.com"
+ - "nyall.dawson@gmail.com"
architectures:
- x86_64
- i386
diff --git a/projects/gdbm/Dockerfile b/projects/gdbm/Dockerfile
new file mode 100644
index 000000000..69ade39ef
--- /dev/null
+++ b/projects/gdbm/Dockerfile
@@ -0,0 +1,32 @@
+# 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\
+ autoconf\
+ bison\
+ flex\
+ libtool\
+ texinfo\
+ gettext
+RUN git clone --depth 1 https://git.gnu.org.ua/gdbm.git
+WORKDIR gdbm
+COPY build.sh $SRC/
diff --git a/projects/gdbm/build.sh b/projects/gdbm/build.sh
new file mode 100644
index 000000000..9c21c8e96
--- /dev/null
+++ b/projects/gdbm/build.sh
@@ -0,0 +1,33 @@
+#!/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 -ogdbm_fuzzer.o gdbm_fuzzer.c
+$CXX $CFLAGS -ogdbm_fuzzer gdbm_fuzzer.o ../src/libgdbmapp.a ../src/.libs/libgdbm.a $LIB_FUZZING_ENGINE
+
+cp gdbm_fuzzer $OUT
+cp gdbm_fuzzer.rc $OUT
+
+# Create seed
+PATH=$SRC/gdbm/src:$PATH sh ./build_seed.sh -C seed
+zip -rj "$OUT/gdbm_fuzzer_seed_corpus.zip" seed/
diff --git a/projects/gdbm/project.yaml b/projects/gdbm/project.yaml
new file mode 100644
index 000000000..2169eeabf
--- /dev/null
+++ b/projects/gdbm/project.yaml
@@ -0,0 +1,6 @@
+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"
diff --git a/projects/geos/Dockerfile b/projects/geos/Dockerfile
new file mode 100644
index 000000000..a9db2a717
--- /dev/null
+++ b/projects/geos/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 build.sh $SRC
+COPY patch.diff $SRC
+WORKDIR $SRC/geos
diff --git a/projects/geos/build.sh b/projects/geos/build.sh
new file mode 100755
index 000000000..5d5c59afe
--- /dev/null
+++ b/projects/geos/build.sh
@@ -0,0 +1,24 @@
+#!/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
+git apply ../patch.diff
+mkdir build
+cd build
+cmake -DBUILD_SHARED_LIBS=OFF ..
+make -j$(nproc)
+cp bin/fuzz* $OUT/
diff --git a/projects/geos/patch.diff b/projects/geos/patch.diff
new file mode 100644
index 000000000..60c13f72d
--- /dev/null
+++ b/projects/geos/patch.diff
@@ -0,0 +1,106 @@
+diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
+index 14506516..2e236476 100644
+--- a/tests/CMakeLists.txt
++++ b/tests/CMakeLists.txt
+@@ -11,4 +11,5 @@
+ add_subdirectory(unit)
+ add_subdirectory(xmltester)
+ add_subdirectory(bigtest)
++add_subdirectory(fuzz)
+
+diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
+new file mode 100644
+index 00000000..d0bd7a02
+--- /dev/null
++++ b/tests/fuzz/CMakeLists.txt
+@@ -0,0 +1,15 @@
++################################################################################
++# Part of CMake configuration for GEOS
++#
++# Copyright (C) 2018 Mateusz Loskot <mateusz@loskot.net>
++#
++# 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 $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>)
++ 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 00000000..ceee7ea6
+--- /dev/null
++++ b/tests/fuzz/fuzz_geo2.c
+@@ -0,0 +1,69 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdarg.h>
++#include <string.h>
++
++#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;
++}
++
diff --git a/projects/geos/project.yaml b/projects/geos/project.yaml
new file mode 100644
index 000000000..91a71ebaa
--- /dev/null
+++ b/projects/geos/project.yaml
@@ -0,0 +1,12 @@
+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'
diff --git a/projects/ghostscript/project.yaml b/projects/ghostscript/project.yaml
index d1f91d415..6a4a2db9e 100644
--- a/projects/ghostscript/project.yaml
+++ b/projects/ghostscript/project.yaml
@@ -10,5 +10,6 @@ auto_ccs:
- "kdlee@chromium.org"
sanitizers:
- address
- - memory
-main_repo: 'git://git.ghostscript.com/ghostpdl.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'git://git.ghostscript.com/ghostpdl.git' \ No newline at end of file
diff --git a/projects/git/Dockerfile b/projects/git/Dockerfile
index 91c05e426..eb487434d 100644
--- a/projects/git/Dockerfile
+++ b/projects/git/Dockerfile
@@ -20,7 +20,7 @@ RUN apt-get update && \
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 \
- libtime-modules-perl libyaml-perl libz-dev python subversion tcl unzip \
+ perl-modules libyaml-perl libz-dev python subversion tcl unzip \
asciidoc docbook-xsl xmlto libssl-dev zip
RUN git clone https://github.com/git/git git
WORKDIR git
diff --git a/projects/gitea/Dockerfile b/projects/gitea/Dockerfile
index 940312337..2defa813c 100644
--- a/projects/gitea/Dockerfile
+++ b/projects/gitea/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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
diff --git a/projects/glib/Dockerfile b/projects/glib/Dockerfile
index 72449d549..25b520411 100644
--- a/projects/glib/Dockerfile
+++ b/projects/glib/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y python3-pip
-RUN pip3 install -U meson ninja
+RUN unset CFLAGS CXXFLAGS && pip3 install -U meson ninja
RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib
WORKDIR glib
COPY build.sh $SRC/
diff --git a/projects/glib/project.yaml b/projects/glib/project.yaml
index 64889c879..62cb33095 100644
--- a/projects/glib/project.yaml
+++ b/projects/glib/project.yaml
@@ -8,6 +8,7 @@ auto_ccs:
sanitizers:
- address
- undefined
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
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'
+main_repo: 'https://gitlab.gnome.org/GNOME/glib' \ No newline at end of file
diff --git a/projects/gnupg/Dockerfile b/projects/gnupg/Dockerfile
index 57dc9050d..5392d97b2 100644
--- a/projects/gnupg/Dockerfile
+++ b/projects/gnupg/Dockerfile
@@ -16,6 +16,11 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool gettext bzip2 gnupg bison flex
+# Install automake 1.16.3 from future. See:
+# * https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commit;h=6ca540715139899137e1f86c7e1dcbd0288f15b3
+# * https://packages.ubuntu.com/en/hirsute/automake
+RUN sed -i -e 's/focal/hirsute/g' /etc/apt/sources.list
+RUN apt-get update && apt-get install -y --reinstall automake
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
diff --git a/projects/gnupg/fuzzgnupg.diff b/projects/gnupg/fuzzgnupg.diff
index 226c86c4c..f736fae29 100644
--- a/projects/gnupg/fuzzgnupg.diff
+++ b/projects/gnupg/fuzzgnupg.diff
@@ -1,10 +1,10 @@
diff --git a/configure.ac b/configure.ac
-index 5bb366e76..ee9403149 100644
+index 7b398f3df..ee69b3063 100644
--- a/configure.ac
+++ b/configure.ac
-@@ -991,6 +991,15 @@ AC_CHECK_LIB(util, openpty,
- ])
- AC_SUBST(LIBUTIL_LIBS)
+@@ -991,6 +991,15 @@ if test x"$use_tofu" = xyes ; then
+ fi
+ fi
+# TODO choose when to build fuzzing with option ?
+AC_CHECK_LIB(FuzzingEngine, main,
@@ -15,19 +15,19 @@ index 5bb366e76..ee9403149 100644
+AC_CHECK_PROG(HAVE_CLANGXX, clang++, 1)
+AM_CONDITIONAL(HAVE_LIB_FUZZING_ENGINE, [test "$have_fuzz" = yes -a "$HAVE_CLANGXX" = 1])
+
- # shred is used to clean temporary plain text files.
- AC_PATH_PROG(SHRED, shred, /usr/bin/shred)
- AC_DEFINE_UNQUOTED(SHRED,
-@@ -2094,6 +2103,7 @@ tests/migrations/Makefile
- tests/gpgsm/Makefile
+ AM_CONDITIONAL(SQLITE3, test "$have_sqlite" = "yes")
+
+ if test x"$use_tofu" = xyes ; then
+@@ -2149,6 +2158,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 2b92daf33..505d98f5e 100644
+index eb23573b7..785ac2b4b 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -47,6 +47,7 @@ endif
@@ -38,14 +38,14 @@ index 2b92daf33..505d98f5e 100644
if !HAVE_W32CE_SYSTEM
noinst_PROGRAMS += gpgv
endif
-@@ -164,6 +165,9 @@ gpg_SOURCES = gpg.c \
+@@ -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)
+
- #gpgcompose_SOURCES = gpgcompose.c $(gpg_sources)
+
gpgv_SOURCES = gpgv.c \
$(common_source) \
diff --git a/g10/armor.c b/g10/armor.c
@@ -63,7 +63,7 @@ index eb2d28bca..594f5bd2d 100644
diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
-index 285c4cb4d..7af328c2a 100644
+index c0f1e0cec..52652a0e0 100644
--- a/g10/call-dirmngr.h
+++ b/g10/call-dirmngr.h
@@ -19,6 +19,8 @@
@@ -122,10 +122,10 @@ index e7a6f2b11..9a9ab5460 100644
} 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 2f92c1d2c..41e077a6a 100644
+index bb05eabb7..638d895d0 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
-@@ -738,7 +738,12 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
+@@ -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));
@@ -139,10 +139,10 @@ index 2f92c1d2c..41e077a6a 100644
if (out && pkttype)
diff --git a/g10/plaintext.c b/g10/plaintext.c
-index f9e0a4296..7b9709c08 100644
+index 3e169d93f..aa83ffbe0 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
-@@ -656,10 +656,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
+@@ -617,10 +617,16 @@ ask_for_detached_datafile (gcry_md_hd_t md, gcry_md_hd_t md2,
if (!fp)
{
@@ -160,10 +160,10 @@ index f9e0a4296..7b9709c08 100644
do_hash (md, md2, fp, textmode);
iobuf_close (fp);
diff --git a/g10/sig-check.c b/g10/sig-check.c
-index 4c172d692..bd87f00ad 100644
+index 8dd18b2e2..9f5db89f9 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
-@@ -760,8 +760,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
+@@ -783,8 +783,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
{
gcry_md_hd_t md;
@@ -176,15 +176,15 @@ index 4c172d692..bd87f00ad 100644
/* 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 b9be6aaa6..d6659eaf1 100644
+index f29b68a53..e788c9916 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
-@@ -18,7 +18,13 @@
-
- ## Process this file with automake to produce Makefile.in
+@@ -24,7 +24,13 @@ else
+ tpm2dtests =
+ endif
--SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits .
-+SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits
+-SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests) .
++SUBDIRS = gpgscm openpgp cms migrations gpgme pkits $(tpm2dtests)
+
+if MAINTAINER_MODE
+SUBDIRS += fuzz
@@ -196,7 +196,7 @@ index b9be6aaa6..d6659eaf1 100644
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
new file mode 100644
-index 000000000..3bf039a54
+index 000000000..eb2216d3e
--- /dev/null
+++ b/tests/fuzz/Makefile.am
@@ -0,0 +1,84 @@
diff --git a/projects/gnupg/project.yaml b/projects/gnupg/project.yaml
index c2c6ab2ca..516132eca 100644
--- a/projects/gnupg/project.yaml
+++ b/projects/gnupg/project.yaml
@@ -2,3 +2,6 @@ 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
diff --git a/projects/gnutls/Dockerfile b/projects/gnutls/Dockerfile
index 46304293d..5d902272e 100644
--- a/projects/gnutls/Dockerfile
+++ b/projects/gnutls/Dockerfile
@@ -38,7 +38,7 @@ 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 hg clone https://gmplib.org/repo/gmp/ gmp
-RUN git clone --depth=1 https://gitlab.com/gnutls/libtasn1.git
+RUN git clone https://gitlab.com/gnutls/libtasn1.git
RUN git clone --depth=1 https://git.lysator.liu.se/nettle/nettle.git
RUN git clone --depth=1 --recursive https://gitlab.com/gnutls/gnutls.git
diff --git a/projects/gnutls/build.sh b/projects/gnutls/build.sh
index a44282784..730838c54 100755
--- a/projects/gnutls/build.sh
+++ b/projects/gnutls/build.sh
@@ -16,9 +16,9 @@
################################################################################
export DEPS_PATH=$SRC/deps
-export PKG_CONFIG_PATH=$DEPS_PATH/lib/pkgconfig
+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 LDFLAGS="-L$DEPS_PATH/lib -L$DEPS_PATH/lib64"
export GNULIB_SRCDIR=$SRC/gnulib
cd $SRC/libunistring
diff --git a/projects/go-attestation/Dockerfile b/projects/go-attestation/Dockerfile
index 4e1651c92..33999bef3 100644
--- a/projects/go-attestation/Dockerfile
+++ b/projects/go-attestation/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN go get -u -d github.com/google/go-attestation/...
diff --git a/projects/go-coredns/Dockerfile b/projects/go-coredns/Dockerfile
index 7991879d2..8dab305c9 100644
--- a/projects/go-coredns/Dockerfile
+++ b/projects/go-coredns/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
ENV GO111MODULE=on
RUN git clone --depth 1 https://github.com/coredns/coredns $GOPATH/src/github.com/coredns/coredns
diff --git a/projects/go-dns/Dockerfile b/projects/go-dns/Dockerfile
index a5576e704..3819ff263 100644
--- a/projects/go-dns/Dockerfile
+++ b/projects/go-dns/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN go get -t github.com/miekg/dns
COPY build.sh $SRC/
diff --git a/projects/go-ethereum/Dockerfile b/projects/go-ethereum/Dockerfile
index 8323922d7..3904fced0 100644
--- a/projects/go-ethereum/Dockerfile
+++ b/projects/go-ethereum/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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)
diff --git a/projects/go-ethereum/project.yaml b/projects/go-ethereum/project.yaml
index a4c853230..062e5a1c7 100644
--- a/projects/go-ethereum/project.yaml
+++ b/projects/go-ethereum/project.yaml
@@ -4,6 +4,8 @@ auto_ccs :
- "fjl@ethereum.org"
- "martin.swende@ethereum.org"
- "marius.vanderwijden@ethereum.org"
+ - "garyrong@ethereum.org"
+ - "zsfelfoldi@ethereum.org"
language: go
fuzzing_engines:
- libfuzzer
diff --git a/projects/go-json-iterator/Dockerfile b/projects/go-json-iterator/Dockerfile
index 5d4cf02f3..fa3d9305a 100644
--- a/projects/go-json-iterator/Dockerfile
+++ b/projects/go-json-iterator/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/json-iterator/go json-iterator
COPY fuzz_json.go $SRC/json-iterator/
diff --git a/projects/go-redis/Dockerfile b/projects/go-redis/Dockerfile
index b0ad17734..0bcc651ed 100644
--- a/projects/go-redis/Dockerfile
+++ b/projects/go-redis/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/go-redis/redis redis
COPY build.sh $SRC/
WORKDIR $SRC/redis
diff --git a/projects/go-redis/build.sh b/projects/go-redis/build.sh
index e297cd37c..38c2db69f 100644
--- a/projects/go-redis/build.sh
+++ b/projects/go-redis/build.sh
@@ -13,5 +13,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-#github.com/go-redis/redis/fuzz is not a module, so needs local build
-compile_go_fuzzer ./fuzz Fuzz fuzz gofuzz
+compile_go_fuzzer github.com/go-redis/redis/v8/fuzz Fuzz fuzz gofuzz
diff --git a/projects/go-sftp/Dockerfile b/projects/go-sftp/Dockerfile
index 0269d8ee4..59c82b2ae 100644
--- a/projects/go-sftp/Dockerfile
+++ b/projects/go-sftp/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/pkg/sftp
COPY build.sh $SRC/
diff --git a/projects/go-snappy/Dockerfile b/projects/go-snappy/Dockerfile
index d6d08afd0..59ff120fd 100644
--- a/projects/go-snappy/Dockerfile
+++ b/projects/go-snappy/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/golang/snappy
COPY build.sh $SRC/
diff --git a/projects/go-snappy/project.yaml b/projects/go-snappy/project.yaml
index 8a732ccb3..42eca5303 100644
--- a/projects/go-snappy/project.yaml
+++ b/projects/go-snappy/project.yaml
@@ -8,3 +8,4 @@ fuzzing_engines:
sanitizers:
- address
main_repo: 'https://github.com/golang/snappy'
+disabled: true
diff --git a/projects/go-sqlite3/Dockerfile b/projects/go-sqlite3/Dockerfile
index f1b10e165..e2936b4a5 100644
--- a/projects/go-sqlite3/Dockerfile
+++ b/projects/go-sqlite3/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/
diff --git a/projects/golang-protobuf/Dockerfile b/projects/golang-protobuf/Dockerfile
index 1347a7691..8c7272eb7 100644
--- a/projects/golang-protobuf/Dockerfile
+++ b/projects/golang-protobuf/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
ENV GO111MODULE="on"
ENV GOFUZZ111MODULE="on"
diff --git a/projects/golang/Dockerfile b/projects/golang/Dockerfile
index 1118ce48d..ff5cd2fc1 100644
--- a/projects/golang/Dockerfile
+++ b/projects/golang/Dockerfile
@@ -14,14 +14,9 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
-RUN mkdir -p $GOPATH/src/github.com/dvyukov/ && \
- cd $GOPATH/src/github.com/dvyukov/ && \
- git clone https://github.com/dvyukov/go-fuzz-corpus
-
-COPY build.sh $SRC/
-
-ENV GO111MODULE="off"
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus golang
+COPY build.sh text_fuzzer.go math_big_fuzzer.go $SRC/
WORKDIR $SRC/golang
diff --git a/projects/golang/build.sh b/projects/golang/build.sh
index 064378aa5..99868c4ca 100755
--- a/projects/golang/build.sh
+++ b/projects/golang/build.sh
@@ -12,41 +12,37 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-function compile_fuzzer {
- fuzzer=$(basename $1)
+# These two dependencies cause build issues and are not used by oss-fuzz:
+rm -r sqlparser
+rm -r parser
- compile_go_fuzzer "github.com/dvyukov/go-fuzz-corpus/$fuzzer" Fuzz $fuzzer
+mkdir math && cp $SRC/math_big_fuzzer.go ./math/
- # Pack the seed corpus
- zip -r $OUT/fuzzer-${fuzzer}_seed_corpus.zip \
- $GOPATH/src/github.com/dvyukov/go-fuzz-corpus/$fuzzer/corpus
-}
-
-export -f compile_fuzzer
-
-# Use this to attempt to compile all
-#find $SRC/go-fuzz-corpus -mindepth 1 -maxdepth 1 -type d -exec bash -c 'compile_fuzzer "$@"' bash {} \;
-
-compile_fuzzer asn1
-#compile_fuzzer bzip2
-compile_fuzzer csv
-compile_fuzzer elliptic
-compile_fuzzer flate
-compile_fuzzer fmt
-#compile_fuzzer gif
-compile_fuzzer gzip
-compile_fuzzer httpreq
-compile_fuzzer httpresp
-compile_fuzzer jpeg
-compile_fuzzer json
-compile_fuzzer lzw
-compile_fuzzer mime
-compile_fuzzer multipart
-compile_fuzzer png
-compile_fuzzer tar
-compile_fuzzer time
-#compile_fuzzer url
-compile_fuzzer xml
-compile_fuzzer zip
-compile_fuzzer zlib
+go get -u golang.org/x/text
+mkdir text && cp $SRC/text_fuzzer.go ./text/
+go mod init "github.com/dvyukov/go-fuzz-corpus"
+export FUZZ_ROOT="github.com/dvyukov/go-fuzz-corpus"
+compile_go_fuzzer $FUZZ_ROOT/text FuzzAcceptLanguage accept_language_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/text FuzzCurrency currency_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp1 big_cmp_fuzzer1
+compile_go_fuzzer $FUZZ_ROOT/math FuzzBigIntCmp2 big_cmp_fuzzer2
+compile_go_fuzzer $FUZZ_ROOT/math FuzzRatSetString big_rat_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/asn1 Fuzz asn_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/csv Fuzz csv_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/elliptic Fuzz elliptic_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/flate Fuzz flate_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/fmt Fuzz fmt_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/gzip Fuzz gzip_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/httpreq Fuzz httpreq_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/jpeg Fuzz jpeg_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/json Fuzz json_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/lzw Fuzz lzw_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/mime Fuzz mime_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/multipart Fuzz multipart_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/png Fuzz png_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/tar Fuzz tar_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/time Fuzz time_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/xml Fuzz xml_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/zip Fuzz zip_fuzzer
+compile_go_fuzzer $FUZZ_ROOT/zlib Fuzz zlib_fuzzer
diff --git a/projects/golang/math_big_fuzzer.go b/projects/golang/math_big_fuzzer.go
new file mode 100644
index 000000000..60946bc46
--- /dev/null
+++ b/projects/golang/math_big_fuzzer.go
@@ -0,0 +1,63 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 "math/big"
+
+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 isDivisibleBy(n int, divisibleby int) bool {
+ return (n % divisibleby) == 0
+}
diff --git a/projects/golang/project.yaml b/projects/golang/project.yaml
index ed1e86329..0fe496b60 100644
--- a/projects/golang/project.yaml
+++ b/projects/golang/project.yaml
@@ -1,9 +1,11 @@
homepage: "https://golang.org/"
+main_repo: "https://github.com/golang/go"
primary_contact: "golang-fuzz@googlegroups.com"
auto_ccs:
- - "mmoroz@chromium.org"
- "josharian@gmail.com"
- "emmanuel@orijtech.com"
+ - "Adam@adalogics.com"
+ - "cuong.manhle.vn@gmail.com"
language: go
sanitizers:
- address
diff --git a/projects/golang/text_fuzzer.go b/projects/golang/text_fuzzer.go
new file mode 100644
index 000000000..d7686ae72
--- /dev/null
+++ b/projects/golang/text_fuzzer.go
@@ -0,0 +1,36 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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
+}
diff --git a/projects/gonids/Dockerfile b/projects/gonids/Dockerfile
index 66e9a8933..13175c904 100644
--- a/projects/gonids/Dockerfile
+++ b/projects/gonids/Dockerfile
@@ -14,10 +14,10 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN go get -t github.com/google/gonids
+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/
-WORKDIR $SRC/
+WORKDIR $SRC/gonids
diff --git a/projects/gonids/build.sh b/projects/gonids/build.sh
index 590045f9e..7397c5089 100755
--- a/projects/gonids/build.sh
+++ b/projects/gonids/build.sh
@@ -17,6 +17,7 @@
compile_go_fuzzer github.com/google/gonids FuzzParseRule fuzz_parserule
+cd $SRC
unzip emerging.rules.zip
cd rules
i=0
diff --git a/projects/gopacket/Dockerfile b/projects/gopacket/Dockerfile
index f8816e597..7f6c09a9e 100644
--- a/projects/gopacket/Dockerfile
+++ b/projects/gopacket/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN go get github.com/google/gopacket
COPY build.sh $SRC/
diff --git a/projects/gpac/Dockerfile b/projects/gpac/Dockerfile
index cf7fc8043..0784e48ad 100755
--- a/projects/gpac/Dockerfile
+++ b/projects/gpac/Dockerfile
@@ -16,8 +16,7 @@
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
+RUN git clone https://github.com/gpac/gpac && git clone https://github.com/gpac/testsuite
WORKDIR $SRC
COPY build.sh $SRC/
-COPY fuzz_parse.c $SRC/
diff --git a/projects/gpac/build.sh b/projects/gpac/build.sh
index 904f5f234..3bce7248e 100755
--- a/projects/gpac/build.sh
+++ b/projects/gpac/build.sh
@@ -18,8 +18,8 @@
cd gpac
./configure --static-build --extra-cflags="${CFLAGS}" --extra-ldflags="${CFLAGS}"
make
-cp $SRC/fuzz_parse.c .
+cp $SRC/testsuite/oss-fuzzers/fuzz_parse.c .
$CC $CFLAGS $LIB_FUZZING_ENGINE fuzz_parse.c -o $OUT/fuzz_parse \
-I./include -I./ ./bin/gcc/libgpac_static.a \
-lm -lz -lpthread -DGPAC_HAVE_CONFIG_H
diff --git a/projects/graphicsmagick/Dockerfile b/projects/graphicsmagick/Dockerfile
index 97f3a561d..7596b61a2 100644
--- a/projects/graphicsmagick/Dockerfile
+++ b/projects/graphicsmagick/Dockerfile
@@ -29,7 +29,7 @@ RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo
RUN git clone https://git.savannah.nongnu.org/r/freetype/freetype2.git/
RUN git clone --depth 1 https://github.com/pnggroup/libpng
RUN git clone --depth 1 https://github.com/mm2/Little-CMS
-RUN git clone https://git.ghostscript.com/ghostpdl.git
+RUN git clone http://git.ghostscript.com/ghostpdl.git
RUN git clone --depth 1 https://gitlab.com/federicomenaquintero/bzip2.git
RUN git clone --depth 1 https://github.com/jasper-software/jasper
RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
diff --git a/projects/graphicsmagick/project.yaml b/projects/graphicsmagick/project.yaml
index 7b16f6cb0..319db4429 100644
--- a/projects/graphicsmagick/project.yaml
+++ b/projects/graphicsmagick/project.yaml
@@ -8,7 +8,8 @@ auto_ccs:
sanitizers:
- address
- memory
- - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- i386
diff --git a/projects/grpc-gateway/Dockerfile b/projects/grpc-gateway/Dockerfile
index 9a7cad2f3..e6ef61cd7 100644
--- a/projects/grpc-gateway/Dockerfile
+++ b/projects/grpc-gateway/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/
diff --git a/projects/grpc-go/Dockerfile b/projects/grpc-go/Dockerfile
index dc00af586..fa10f6d32 100644
--- a/projects/grpc-go/Dockerfile
+++ b/projects/grpc-go/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
ENV GO111MODULE=on
RUN go get google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc
RUN git clone --depth 1 https://github.com/grpc/grpc-go $GOPATH/src/google.golang.org/grpc
diff --git a/projects/grpc-httpjson-transcoding/Dockerfile b/projects/grpc-httpjson-transcoding/Dockerfile
new file mode 100644
index 000000000..1746a42a4
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+MAINTAINER nareddyt@google.com
+
+RUN apt-get update && apt-get install python -y
+RUN git clone https://github.com/grpc-ecosystem/grpc-httpjson-transcoding.git
+WORKDIR $SRC/grpc-httpjson-transcoding/
+COPY build.sh $SRC/
diff --git a/projects/grpc-httpjson-transcoding/build.sh b/projects/grpc-httpjson-transcoding/build.sh
new file mode 100755
index 000000000..85e8e0b06
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/build.sh
@@ -0,0 +1,21 @@
+#!/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
diff --git a/projects/grpc-httpjson-transcoding/project.yaml b/projects/grpc-httpjson-transcoding/project.yaml
new file mode 100644
index 000000000..07997d252
--- /dev/null
+++ b/projects/grpc-httpjson-transcoding/project.yaml
@@ -0,0 +1,20 @@
+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 \ No newline at end of file
diff --git a/projects/grpc-swift/Dockerfile b/projects/grpc-swift/Dockerfile
new file mode 100644
index 000000000..981ebe9d2
--- /dev/null
+++ b/projects/grpc-swift/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
diff --git a/projects/grpc-swift/build.sh b/projects/grpc-swift/build.sh
new file mode 100755
index 000000000..a27f3719c
--- /dev/null
+++ b/projects/grpc-swift/build.sh
@@ -0,0 +1,31 @@
+#!/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
+)
diff --git a/projects/grpc-swift/project.yaml b/projects/grpc-swift/project.yaml
new file mode 100644
index 000000000..2b5c23049
--- /dev/null
+++ b/projects/grpc-swift/project.yaml
@@ -0,0 +1,13 @@
+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'
diff --git a/projects/grpc/Dockerfile b/projects/grpc/Dockerfile
index 6d2a31074..5999a2c59 100644
--- a/projects/grpc/Dockerfile
+++ b/projects/grpc/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y software-properties-common python-software-properties
+RUN apt-get update && apt-get install -y software-properties-common
RUN add-apt-repository ppa:webupd8team/java
RUN apt-get update && apt-get -y install \
vim \
@@ -38,6 +38,7 @@ RUN apt-get update && apt-get install -y \
# Install Python packages from PyPI
RUN pip install --upgrade pip==10.0.1
RUN pip install virtualenv
+RUN pip install incremental==16.10.1
RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
#========================
diff --git a/projects/gstreamer/Dockerfile b/projects/gstreamer/Dockerfile
index 46318a5c3..1a8834852 100644
--- a/projects/gstreamer/Dockerfile
+++ b/projects/gstreamer/Dockerfile
@@ -13,18 +13,23 @@
# limitations under the License.
#
################################################################################
-
FROM gcr.io/oss-fuzz-base/base-builder
-# Install the build dependencies
-# install the minimum
+RUN apt-get update && \
+ apt-get install -y make autoconf automake libtool build-essential pkg-config bison flex gettext \
+ libffi-dev liblzma-dev libtheora-dev libogg-dev zlib1g-dev libcairo2-dev \
+ python3-pip ninja-build && \
+ pip3 install meson==0.55.1
-RUN sed -i '/^#\sdeb-src /s/^#//' "/etc/apt/sources.list" && \
- apt-get update && \
- apt-get install -y build-essential pkg-config bison flex gettext \
- libffi-dev liblzma-dev libvorbis-dev libtheora-dev libogg-dev zlib1g-dev \
- python3-pip && \
- pip3 install meson==0.55.1 ninja==1.10.0.post2
+# We must install libvorbis from scratch as otherwise we will run into
+# undefined functions in Ubuntu 20.04
+RUN git clone --depth 1 https://gitlab.xiph.org/xiph/vorbis.git && \
+ cd $SRC/vorbis && \
+ ./autogen.sh && \
+ ./configure --enable-static && \
+ make clean && \
+ make -j$(nproc) && \
+ make install
ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
@@ -35,6 +40,8 @@ RUN \
git clone --depth 1 --recursive https://gitlab.freedesktop.org/gstreamer/gst-plugins-base.git gst-plugins-base && \
git clone --depth 1 --recursive https://gitlab.freedesktop.org/gstreamer/gst-ci.git gst-ci
+RUN sed -i 's/theoraenc theoradec theora/theoraenc theoradec theora cairo/g' $SRC/gst-ci/fuzzing/build-oss-fuzz.sh
+
ADD https://people.freedesktop.org/~bilboed/gst-discoverer_seed_corpus.zip $SRC
WORKDIR gstreamer
diff --git a/projects/gvisor/Dockerfile b/projects/gvisor/Dockerfile
new file mode 100644
index 000000000..598664ee2
--- /dev/null
+++ b/projects/gvisor/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 go https://github.com/google/gvisor
+COPY build.sh state_fuzzer.go $SRC/
+ENV GVISOR_ROOT $SRC/gvisor
+WORKDIR $GVISOR_ROOT
diff --git a/projects/gvisor/build.sh b/projects/gvisor/build.sh
new file mode 100644
index 000000000..7a1ee279a
--- /dev/null
+++ b/projects/gvisor/build.sh
@@ -0,0 +1,19 @@
+#!/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/state_fuzzer.go $GVISOR_ROOT/
+compile_go_fuzzer gvisor.dev/gvisor FuzzStateLoad state_load_fuzz
diff --git a/projects/gvisor/project.yaml b/projects/gvisor/project.yaml
new file mode 100644
index 000000000..b44a8adc2
--- /dev/null
+++ b/projects/gvisor/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/google/gvisor"
+main_repo: "https://github.com/google/gvisor"
+primary_contact: "krakauer@google.com"
+auto_ccs :
+ - "gvisor-dev@googlegroups.com"
+ - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/gvisor/state_fuzzer.go b/projects/gvisor/state_fuzzer.go
new file mode 100644
index 000000000..b44f07a50
--- /dev/null
+++ b/projects/gvisor/state_fuzzer.go
@@ -0,0 +1,30 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 (
+ "bytes"
+ "context"
+ "gvisor.dev/gvisor/pkg/buffer"
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func FuzzStateLoad(data []byte) int {
+ ctx := context.Background()
+ var toLoad *buffer.View
+ _, _ = state.Load(ctx, bytes.NewReader(data), toLoad)
+ return 1
+}
diff --git a/projects/h2o/build.sh b/projects/h2o/build.sh
index 96c10de64..22b655d02 100755
--- a/projects/h2o/build.sh
+++ b/projects/h2o/build.sh
@@ -22,6 +22,7 @@ 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/
diff --git a/projects/h2o/h2o-fuzzer-http3.options b/projects/h2o/h2o-fuzzer-http3.options
new file mode 100644
index 000000000..97ff13ba7
--- /dev/null
+++ b/projects/h2o/h2o-fuzzer-http3.options
@@ -0,0 +1,4 @@
+[libfuzzer]
+close_fd_mask = 3
+max_len = 16384
+dict = http.dict
diff --git a/projects/h2o/project.yaml b/projects/h2o/project.yaml
index 3c32e81ef..bc965024f 100644
--- a/projects/h2o/project.yaml
+++ b/projects/h2o/project.yaml
@@ -8,5 +8,10 @@ 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"
+
main_repo: 'https://github.com/h2o/h2o'
diff --git a/projects/libchewing/Dockerfile b/projects/h3/Dockerfile
index 4a77e243a..98f6e6ca4 100644
--- a/projects/libchewing/Dockerfile
+++ b/projects/h3/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2016 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,8 +15,8 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool texinfo
-
-RUN git clone --depth 1 https://github.com/chewing/libchewing.git
-WORKDIR libchewing
-COPY build.sh chewing_fuzzer_common.[ch] chewing_*_fuzzer.c $SRC/
+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 build.sh h3_fuzzer.c $SRC/
diff --git a/projects/h3/build.sh b/projects/h3/build.sh
new file mode 100755
index 000000000..126327e2f
--- /dev/null
+++ b/projects/h3/build.sh
@@ -0,0 +1,34 @@
+#!/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
+sed -i '21d' $SRC/h3/CMakeLists.txt
+cmake ..
+make -j$(nproc)
+$CC $CFLAGS -DH3_PREFIX="" \
+ -I/src/h3/src/apps/applib/include \
+ -I/src/h3/src/h3lib/include \
+ -I/src/h3/build/src/h3lib/include \
+ -o h3_fuzzer.o \
+ -c $SRC/h3_fuzzer.c
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE -rdynamic \
+ h3_fuzzer.o \
+ -o $OUT/h3_fuzzer \
+ lib/libh3.a
+
diff --git a/projects/h3/h3_fuzzer.c b/projects/h3/h3_fuzzer.c
new file mode 100644
index 000000000..5d6073380
--- /dev/null
+++ b/projects/h3/h3_fuzzer.c
@@ -0,0 +1,71 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "h3api.h"
+#include "utility.h"
+
+static const Direction DIGITS[7] = {CENTER_DIGIT, K_AXES_DIGIT, J_AXES_DIGIT,
+ JK_AXES_DIGIT, I_AXES_DIGIT, IK_AXES_DIGIT,
+ IJ_AXES_DIGIT};
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < sizeof(H3Index)) {
+ return 0;
+ }
+ H3Index h3;
+ memcpy(&h3, data, sizeof(H3Index));
+
+ H3Index input[] = {h3, h3};
+ int inputSize = sizeof(input) / sizeof(H3Index);
+
+ // fuzz compactCells
+ H3Index *compacted = calloc(inputSize, sizeof(H3Index));
+ H3Error errCompact = compactCells(input, compacted, inputSize);
+
+ // fuzz uncompactCells
+ int compactedCount = 0;
+ for (int i = 0; i < inputSize; i++) {
+ if (compacted[i] != 0) {
+ compactedCount++;
+ }
+ }
+ if (compactedCount < 2) {
+ int uncompactRes = 10;
+ int64_t uncompactedSize;
+ H3Error err2 =
+ uncompactCellsSize(compacted, inputSize, uncompactRes, &uncompactedSize);
+
+ H3Index *uncompacted = calloc(uncompactedSize, sizeof(H3Index));
+ H3Error err3 = uncompactCells(compacted, compactedCount, uncompacted,
+ uncompactedSize, uncompactRes);
+ free(uncompacted);
+ }
+
+ // fuzz h3NeighborRotations
+ int rotations = 0;
+ for (int i = 0; i < 7; i++) {
+ h3NeighborRotations(h3, DIGITS[i], &rotations);
+ }
+ free(compacted);
+ return 0;
+}
diff --git a/projects/h3/project.yaml b/projects/h3/project.yaml
new file mode 100644
index 000000000..fdfbbfbe6
--- /dev/null
+++ b/projects/h3/project.yaml
@@ -0,0 +1,13 @@
+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"
+sanitizers:
+ - address
+ - undefined
+ - memory
+main_repo: 'https://github.com/uber/h3'
diff --git a/projects/harfbuzz/build.sh b/projects/harfbuzz/build.sh
index 3509a67f8..c43b25312 100755
--- a/projects/harfbuzz/build.sh
+++ b/projects/harfbuzz/build.sh
@@ -41,9 +41,9 @@ mv $build/test/fuzzing/hb-{shape,draw,subset,set}-fuzzer $OUT/
# Archive and copy to $OUT seed corpus if the build succeeded.
mkdir all-fonts
for d in \
- test/shaping/data/in-house/fonts \
- test/shaping/data/aots/fonts \
- test/shaping/data/text-rendering-tests/fonts \
+ 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 \
diff --git a/projects/hcl/Dockerfile b/projects/hcl/Dockerfile
new file mode 100644
index 000000000..122beca6b
--- /dev/null
+++ b/projects/hcl/Dockerfile
@@ -0,0 +1,20 @@
+# 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 \ No newline at end of file
diff --git a/projects/hcl/build.sh b/projects/hcl/build.sh
new file mode 100644
index 000000000..986e1009f
--- /dev/null
+++ b/projects/hcl/build.sh
@@ -0,0 +1,36 @@
+#!/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_BASE=$SRC/hcl/hclsyntax/fuzz
+FUZZERS_PACKAGE=github.com/hashicorp/hcl/v2/hclsyntax/fuzz
+FUZZER_CLASS=Fuzz
+
+for THE_FUZZER in config expr template traversal
+do
+ THE_FUZZER_NAME="fuzz_"$THE_FUZZER
+ compile_go_fuzzer $FUZZERS_PACKAGE/$THE_FUZZER $FUZZER_CLASS $THE_FUZZER_NAME
+
+ OUTDIR=$OUT/$THE_FUZZER_NAME"_seed_corpus"
+ mkdir $OUTDIR
+ find $FUZZERS_BASE/$THE_FUZZER/corpus -type f | while read FNAME
+ do
+ SHASUM_NAME=$(shasum "$FNAME" | awk '{print $1}')
+ cp "$FNAME" $OUTDIR
+ done
+ zip -r $OUTDIR".zip" $OUTDIR
+ rm -rf $OUTDIR
+done \ No newline at end of file
diff --git a/projects/hcl/project.yaml b/projects/hcl/project.yaml
new file mode 100644
index 000000000..4abeeb5f5
--- /dev/null
+++ b/projects/hcl/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/hashicorp/hcl"
+language: go
+auto_ccs:
+ - federico.maggi@gmail.com
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+primary_contact: "security@hashicorp.com"
+main_repo: 'https://github.com/hashicorp/hcl' \ No newline at end of file
diff --git a/projects/hermes/Dockerfile b/projects/hermes/Dockerfile
index eb59a38da..70f4293fc 100644
--- a/projects/hermes/Dockerfile
+++ b/projects/hermes/Dockerfile
@@ -16,9 +16,16 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && \
- apt-get install -y make autoconf automake libtool wget libicu-dev \
- ninja-build python zip libreadline-dev libatomic-ops-dev
+ apt-get install -y make autoconf automake libtool wget \
+ python zip libreadline-dev libatomic-ops-dev
+
+RUN pip3 install meson ninja
+RUN ln -s /usr/local/bin/ninja /usr/bin/ninja
+
+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
-WORKDIR hermes
+WORKDIR $SRC
COPY build.sh $SRC/
diff --git a/projects/hermes/build.sh b/projects/hermes/build.sh
index 01c11f3c0..7bf7a9b4d 100755
--- a/projects/hermes/build.sh
+++ b/projects/hermes/build.sh
@@ -15,6 +15,23 @@
#
################################################################################
+# 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
+
+cd $SRC/hermes
+
if [ "${SANITIZER}" = address ]
then
CONFIGURE_FLAGS="--enable-asan"
diff --git a/projects/hermes/project.yaml b/projects/hermes/project.yaml
index 0e614fe6d..baeedb69a 100644
--- a/projects/hermes/project.yaml
+++ b/projects/hermes/project.yaml
@@ -2,8 +2,9 @@ homepage: "https://github.com/facebook/hermes"
language: c++
primary_contact: "neildhar@fb.com"
auto_ccs:
- - "dulinr@fb.com"
- "mhl@fb.com"
+ - "avp@fb.com"
+ - "jsx@fb.com"
vendor_ccs:
- "oss-fuzz@fb.com"
fuzzing_engines:
diff --git a/projects/hostap/project.yaml b/projects/hostap/project.yaml
index db978e157..9d95c6e2c 100644
--- a/projects/hostap/project.yaml
+++ b/projects/hostap/project.yaml
@@ -11,9 +11,10 @@ fuzzing_engines:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- dataflow
architectures:
- x86_64
- i386
-main_repo: 'git://w1.fi/srv/git/hostap.git'
+main_repo: 'git://w1.fi/srv/git/hostap.git' \ No newline at end of file
diff --git a/projects/http-pattern-matcher/Dockerfile b/projects/http-pattern-matcher/Dockerfile
new file mode 100644
index 000000000..ab029ccf3
--- /dev/null
+++ b/projects/http-pattern-matcher/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+################################################################################
+
+FROM gcr.io/oss-fuzz-base/base-builder
+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/
diff --git a/projects/http-pattern-matcher/build.sh b/projects/http-pattern-matcher/build.sh
new file mode 100755
index 000000000..85e8e0b06
--- /dev/null
+++ b/projects/http-pattern-matcher/build.sh
@@ -0,0 +1,21 @@
+#!/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
diff --git a/projects/http-pattern-matcher/project.yaml b/projects/http-pattern-matcher/project.yaml
new file mode 100644
index 000000000..40a541ea4
--- /dev/null
+++ b/projects/http-pattern-matcher/project.yaml
@@ -0,0 +1,20 @@
+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"
+
+fuzzing_engines:
+- libfuzzer
+- afl
+- honggfuzz
+
+sanitizers:
+- address
+- undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
diff --git a/projects/httparse/Dockerfile b/projects/httparse/Dockerfile
index cffcc9f12..9b7b32082 100644
--- a/projects/httparse/Dockerfile
+++ b/projects/httparse/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone https://github.com/seanmonstar/httparse
WORKDIR $SRC
diff --git a/projects/httplib2/Dockerfile b/projects/httplib2/Dockerfile
index f7dcaf210..55a17f9b8 100644
--- a/projects/httplib2/Dockerfile
+++ b/projects/httplib2/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone --depth 1 https://github.com/httplib2/httplib2
COPY build.sh $SRC/
diff --git a/projects/httplib2/build.sh b/projects/httplib2/build.sh
index 3a3d0eae7..ba9410d8e 100644
--- a/projects/httplib2/build.sh
+++ b/projects/httplib2/build.sh
@@ -15,7 +15,7 @@
#
################################################################################
-pip3 install six
+pip3 install six pytest
python3 setup.py install
# Build fuzzers in $OUT.
@@ -31,5 +31,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/hugo/Dockerfile b/projects/hugo/Dockerfile
index bfba1a283..351c19418 100644
--- a/projects/hugo/Dockerfile
+++ b/projects/hugo/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/gohugoio/hugo
COPY build.sh fuzz.go $SRC/
diff --git a/projects/hugo/fuzz.go b/projects/hugo/fuzz.go
index 7a22e6d50..bfb23cfb3 100644
--- a/projects/hugo/fuzz.go
+++ b/projects/hugo/fuzz.go
@@ -24,7 +24,6 @@ import (
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/langs"
"github.com/spf13/afero"
- "github.com/spf13/viper"
)
func newFuzzDeps(cfg config.Provider) *deps.Deps {
@@ -43,7 +42,7 @@ func newFuzzDeps(cfg config.Provider) *deps.Deps {
}
func FuzzMarkdownify(data []byte) int {
- v := viper.New()
+ v := config.New()
v.Set("contentDir", "content")
ns := New(newFuzzDeps(v))
diff --git a/projects/hunspell/project.yaml b/projects/hunspell/project.yaml
index 48c3f88af..248ffa272 100644
--- a/projects/hunspell/project.yaml
+++ b/projects/hunspell/project.yaml
@@ -8,9 +8,10 @@ vendor_ccs:
- "twsmith@mozilla.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- i386
- x86_64
-main_repo: 'https://github.com/hunspell/hunspell.git'
+main_repo: 'https://github.com/hunspell/hunspell.git' \ No newline at end of file
diff --git a/projects/hyperium/Dockerfile b/projects/hyperium/Dockerfile
new file mode 100644
index 000000000..419302358
--- /dev/null
+++ b/projects/hyperium/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/
diff --git a/projects/hyperium/build.sh b/projects/hyperium/build.sh
new file mode 100755
index 000000000..72c29e574
--- /dev/null
+++ b/projects/hyperium/build.sh
@@ -0,0 +1,31 @@
+#!/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
diff --git a/projects/hyperium/project.yaml b/projects/hyperium/project.yaml
new file mode 100644
index 000000000..c3d3d9fc2
--- /dev/null
+++ b/projects/hyperium/project.yaml
@@ -0,0 +1,12 @@
+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"
diff --git a/projects/ibmswtpm2/project.yaml b/projects/ibmswtpm2/project.yaml
index c1c6a969b..9af192dfc 100644
--- a/projects/ibmswtpm2/project.yaml
+++ b/projects/ibmswtpm2/project.yaml
@@ -7,5 +7,6 @@ auto_ccs:
- "david.wooten@ieee.org"
sanitizers:
- address
- - memory
- - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+ - undefined \ No newline at end of file
diff --git a/projects/icu/project.yaml b/projects/icu/project.yaml
index d38b523a2..4ad93fd0a 100644
--- a/projects/icu/project.yaml
+++ b/projects/icu/project.yaml
@@ -11,6 +11,7 @@ auto_ccs:
- ftang@google.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
-main_repo: 'https://github.com/unicode-org/icu.git'
+main_repo: 'https://github.com/unicode-org/icu.git' \ No newline at end of file
diff --git a/projects/image-png/Dockerfile b/projects/image-png/Dockerfile
index cb953de6d..48be67685 100644
--- a/projects/image-png/Dockerfile
+++ b/projects/image-png/Dockerfile
@@ -13,11 +13,10 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/
-COPY buf_independent.rs $SRC/image-png/fuzz/fuzz_targets/buf_independent.rs
diff --git a/projects/image-png/buf_independent.rs b/projects/image-png/buf_independent.rs
deleted file mode 100644
index f4a1f312c..000000000
--- a/projects/image-png/buf_independent.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-#![no_main]
-extern crate libfuzzer_sys;
-use libfuzzer_sys::fuzz_target;
-extern crate png;
-
-use std::io::{BufRead, Read, Result};
-
-/// A reader that reads at most `n` bytes.
-struct SmalBuf<R: BufRead> {
- inner: R,
- cap: usize,
-}
-
-impl<R: BufRead> SmalBuf<R> {
- fn new(inner: R, cap: usize) -> Self {
- SmalBuf { inner, cap }
- }
-}
-
-impl<R: BufRead> Read for SmalBuf<R> {
- fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
- let len = buf.len().min(self.cap);
- self.inner.read(&mut buf[..len])
- }
-}
-
-impl<R: BufRead> BufRead for SmalBuf<R> {
- fn fill_buf(&mut self) -> Result<&[u8]> {
- let buf = self.inner.fill_buf()?;
- let len = buf.len().min(self.cap);
- Ok(&buf[..len])
- }
-
- fn consume(&mut self, amt: usize) {
- assert!(amt <= self.cap);
- self.inner.consume(amt)
- }
-}
-
-fuzz_target!(|data: &[u8]| {
- // Small limits, we don't need them hopefully.
- let limits = png::Limits { bytes: 1 << 16 };
-
- let reference = png::Decoder::new_with_limits(data, limits);
- let smal = png::Decoder::new_with_limits(SmalBuf::new(data, 1), limits);
-
- let _ = png_compare(reference, smal);
-});
-
-#[inline(always)]
-fn png_compare<R: BufRead, S: BufRead>(reference: png::Decoder<R>, smal: png::Decoder<S>)
- -> std::result::Result<png::OutputInfo, ()>
-{
- let mut smal = Some(smal);
- let (info, mut reference) = reference.read_info().map_err(|_| {
- assert!(smal.take().unwrap().read_info().is_err());
- })?;
-
- let (sinfo, mut smal) = smal.take().unwrap().read_info().expect("Deviation");
- assert_eq!(info, sinfo);
-
- if info.buffer_size() > 5_000_000 {
- return Err(());
- }
-
- let mut ref_data = vec![0; info.buffer_size()];
- let mut smal_data = vec![0; info.buffer_size()];
-
- let _rref = reference.next_frame(&mut ref_data);
- let _rsmal = smal.next_frame(&mut smal_data);
-
- assert_eq!(smal_data, ref_data);
- return Ok(info);
-}
diff --git a/projects/image-rs/Dockerfile b/projects/image-rs/Dockerfile
new file mode 100644
index 000000000..636bc2b30
--- /dev/null
+++ b/projects/image-rs/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/
diff --git a/projects/image-rs/build.sh b/projects/image-rs/build.sh
new file mode 100755
index 000000000..c33f11cb7
--- /dev/null
+++ b/projects/image-rs/build.sh
@@ -0,0 +1,21 @@
+#!/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.
+#
+################################################################################
+
+cargo fuzz build -O
+cargo fuzz list | while read i; do
+ cp fuzz/target/x86_64-unknown-linux-gnu/release/$i $OUT/
+done
diff --git a/projects/image-rs/project.yaml b/projects/image-rs/project.yaml
new file mode 100644
index 000000000..62ae5800d
--- /dev/null
+++ b/projects/image-rs/project.yaml
@@ -0,0 +1,11 @@
+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:
+ - "fintelia@gmail.com"
+ - "p.antoine@catenacyber.fr"
diff --git a/projects/imageio/Dockerfile b/projects/imageio/Dockerfile
index 87c1811d5..eeef9140d 100644
--- a/projects/imageio/Dockerfile
+++ b/projects/imageio/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone https://github.com/imageio/imageio
COPY build.sh $SRC/
diff --git a/projects/imageio/build.sh b/projects/imageio/build.sh
index aeef84ec7..8bf0fe5ab 100644
--- a/projects/imageio/build.sh
+++ b/projects/imageio/build.sh
@@ -29,5 +29,5 @@ for fuzzer in $(find . -name 'fuzz_*.py'); do
this_dir=\$(dirname \"\$0\")
ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/imagemagick/project.yaml b/projects/imagemagick/project.yaml
index 509c8c1bc..ed95c7d34 100644
--- a/projects/imagemagick/project.yaml
+++ b/projects/imagemagick/project.yaml
@@ -7,7 +7,8 @@ auto_ccs:
- urban.warrior.fuzz@gmail.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- x86_64
diff --git a/projects/influxdb/Dockerfile b/projects/influxdb/Dockerfile
index e00af1465..d108fe892 100644
--- a/projects/influxdb/Dockerfile
+++ b/projects/influxdb/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
MAINTAINER william@influxdata.com
RUN go get github.com/influxdata/influxdb
RUN go get github.com/dgrijalva/jwt-go
diff --git a/projects/ipfs/Dockerfile b/projects/ipfs/Dockerfile
index aee4c4ce1..1deea86a0 100644
--- a/projects/ipfs/Dockerfile
+++ b/projects/ipfs/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/ipfs/go-datastore
COPY build.sh $SRC/
diff --git a/projects/istio/Dockerfile b/projects/istio/Dockerfile
index 4ba44e2a5..896268867 100644
--- a/projects/istio/Dockerfile
+++ b/projects/istio/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone https://github.com/istio/istio
COPY build.sh $SRC/
WORKDIR $SRC/istio
diff --git a/projects/istio/build.sh b/projects/istio/build.sh
index cb148e828..2ec972309 100644
--- a/projects/istio/build.sh
+++ b/projects/istio/build.sh
@@ -15,6 +15,5 @@
#
################################################################################
+$SRC/istio/tests/fuzz/oss_fuzz_build.sh
-compile_go_fuzzer ./tests/fuzz FuzzParseInputs fuzz_parse_inputs
-compile_go_fuzzer ./tests/fuzz FuzzParseAndBuildSchema fuzz_parse_and_build_schema
diff --git a/projects/jackson-core/Dockerfile b/projects/jackson-core/Dockerfile
index 1ff785046..73e630b2a 100644
--- a/projects/jackson-core/Dockerfile
+++ b/projects/jackson-core/Dockerfile
@@ -15,7 +15,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/google/fuzzing
diff --git a/projects/jackson-core/build.sh b/projects/jackson-core/build.sh
index 5cbf19c20..4023cf96d 100644
--- a/projects/jackson-core/build.sh
+++ b/projects/jackson-core/build.sh
@@ -53,5 +53,5 @@ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
--target_class=$fuzzer_basename \
--jvm_args=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/jackson-dataformat-xml/Dockerfile b/projects/jackson-dataformat-xml/Dockerfile
new file mode 100644
index 000000000..65f1195cc
--- /dev/null
+++ b/projects/jackson-dataformat-xml/Dockerfile
@@ -0,0 +1,39 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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://downloads.apache.org/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/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
+
+ENV JACKSON_BRANCH=2.13
+
+RUN git clone --depth 1 --branch=$JACKSON_BRANCH https://github.com/FasterXML/jackson-dataformat-xml
+
+COPY build.sh $SRC/
+COPY XmlFuzzer.java $SRC/
+WORKDIR $SRC/jackson-dataformat-xml
diff --git a/projects/jackson-dataformat-xml/XmlFuzzer.java b/projects/jackson-dataformat-xml/XmlFuzzer.java
new file mode 100644
index 000000000..aeb2e8e44
--- /dev/null
+++ b/projects/jackson-dataformat-xml/XmlFuzzer.java
@@ -0,0 +1,29 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import java.io.IOException;
+
+public class XmlFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ ObjectMapper mapper = new XmlMapper();
+ try {
+ mapper.readTree(input);
+ } catch (IOException ignored) {
+ }
+ }
+}
diff --git a/projects/jackson-dataformat-xml/build.sh b/projects/jackson-dataformat-xml/build.sh
new file mode 100644
index 000000000..9be88a954
--- /dev/null
+++ b/projects/jackson-dataformat-xml/build.sh
@@ -0,0 +1,52 @@
+#!/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=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/jackson-dataformat-xml-$CURRENT_VERSION.jar" $OUT/jackson-dataformat-xml.jar
+
+ALL_JARS="jackson-dataformat-xml.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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/jackson-dataformat-xml/project.yaml b/projects/jackson-dataformat-xml/project.yaml
new file mode 100644
index 000000000..7109fd04f
--- /dev/null
+++ b/projects/jackson-dataformat-xml/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/FasterXML/jackson-dataformat-xml"
+language: jvm
+primary_contact: "tatu@fasterxml.com"
+auto_ccs:
+ - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://github.com/FasterXML/jackson-dataformat-xml"
+sanitizers:
+ - address
diff --git a/projects/jackson-dataformats-binary/Dockerfile b/projects/jackson-dataformats-binary/Dockerfile
index 0e4ea8213..700e3ea9c 100644
--- a/projects/jackson-dataformats-binary/Dockerfile
+++ b/projects/jackson-dataformats-binary/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
RUN apt-get update && apt-get install -y maven
ENV JACKSON_BRANCH=2.13
diff --git a/projects/jackson-dataformats-binary/build.sh b/projects/jackson-dataformats-binary/build.sh
index 3c3c0afe6..7cfdbb143 100644
--- a/projects/jackson-dataformats-binary/build.sh
+++ b/projects/jackson-dataformats-binary/build.sh
@@ -62,5 +62,5 @@ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
--target_class=$fuzzer_basename \
--jvm_args=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/janet/build.sh b/projects/janet/build.sh
index 062730779..2279e80da 100755
--- a/projects/janet/build.sh
+++ b/projects/janet/build.sh
@@ -18,5 +18,5 @@ export CFLAGS="$CFLAGS -fPIC"
cd janet
make
-clang $CFLAGS -std=c99 -Isrc/include -Isrc/conf -fPIC -o fuzz_dostring.o -c ./test/fuzzers/fuzz_dostring.c
-clang++ $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_dostring.o build/libjanet.a -o $OUT/fuzz_dostring
+$CC $CFLAGS -std=c99 -Isrc/include -Isrc/conf -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
diff --git a/projects/janus-gateway/Dockerfile b/projects/janus-gateway/Dockerfile
index f0c56cd3b..6cf0e14f8 100644
--- a/projects/janus-gateway/Dockerfile
+++ b/projects/janus-gateway/Dockerfile
@@ -22,7 +22,7 @@ RUN apt-get update && apt-get install -y \
gtk-doc-tools \
libconfig-dev \
libglib2.0-dev \
- libgnutls-dev \
+ libgnutls28-dev \
libini-config-dev \
libjansson-dev \
libnice-dev \
diff --git a/projects/janus-gateway/project.yaml b/projects/janus-gateway/project.yaml
index f2a640aa5..db1b17886 100644
--- a/projects/janus-gateway/project.yaml
+++ b/projects/janus-gateway/project.yaml
@@ -5,7 +5,8 @@ auto_ccs:
- "lminiero@gmail.com"
sanitizers:
- address
- - memory
- 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'
diff --git a/projects/java-example/Dockerfile b/projects/java-example/Dockerfile
index 316e9a888..18ed9e1bc 100644
--- a/projects/java-example/Dockerfile
+++ b/projects/java-example/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
COPY build.sh $SRC/
diff --git a/projects/java-example/ExampleFuzzerNative.cpp b/projects/java-example/ExampleFuzzerNative.cpp
index 7ae0de80d..565f75cf9 100644
--- a/projects/java-example/ExampleFuzzerNative.cpp
+++ b/projects/java-example/ExampleFuzzerNative.cpp
@@ -16,15 +16,21 @@
#include "ExampleFuzzerNative.h"
+#include <limits>
#include <string>
// simple function containing a crash that requires coverage and string compare
// instrumentation for the fuzzer to find
-void parseInternal(const std::string &input) {
+__attribute__((optnone)) void parseInternal(const std::string &input) {
+ constexpr int bar = std::numeric_limits<int>::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) {
- // BOOM
- *(char *)1 = 2;
+ // Crashes with ASan.
+ [[maybe_unused]] char foo = input[input.size() + 2];
}
}
}
diff --git a/projects/java-example/build.sh b/projects/java-example/build.sh
index 63f4c95f9..c2fcd449b 100755
--- a/projects/java-example/build.sh
+++ b/projects/java-example/build.sh
@@ -17,8 +17,9 @@
# Build native library.
JVM_INCLUDES="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+mkdir $OUT/native
$CXX $CXXFLAGS $JVM_INCLUDES -fPIC -shared \
- ExampleFuzzerNative.cpp -o $OUT/libnative.so
+ ExampleFuzzerNative.cpp -o $OUT/native/libnative.so
BUILD_CLASSPATH=$JAZZER_API_PATH
@@ -31,7 +32,7 @@ for fuzzer in $(find $SRC -name '*Fuzzer.java' -or -name '*FuzzerNative.java');
cp $SRC/$fuzzer_basename.class $OUT/
if [[ $fuzzer_basename == *FuzzerNative ]]; then
- driver=jazzer_driver_asan
+ driver=jazzer_driver_with_sanitizer
else
driver=jazzer_driver
fi
@@ -41,12 +42,12 @@ for fuzzer in $(find $SRC -name '*Fuzzer.java' -or -name '*FuzzerNative.java');
echo "#!/bin/sh
# LLVMFuzzerTestOneInput for fuzzer detection.
this_dir=\$(dirname \"\$0\")
-LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
+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=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/java-example/default.options b/projects/java-example/default.options
index 59318037a..8cda4b283 100644
--- a/projects/java-example/default.options
+++ b/projects/java-example/default.options
@@ -1,3 +1,6 @@
[asan]
handle_segv=1
allow_user_segv_handler=1
+
+[ubsan]
+handle_segv=1
diff --git a/projects/java-example/project.yaml b/projects/java-example/project.yaml
index e71c40577..6401e228f 100644
--- a/projects/java-example/project.yaml
+++ b/projects/java-example/project.yaml
@@ -1,4 +1,5 @@
homepage: "https://github.com/CodeIntelligenceTesting/jazzer"
+disabled: true
language: jvm
primary_contact: "meumertzheim@code-intelligence.com"
fuzzing_engines:
@@ -6,3 +7,4 @@ fuzzing_engines:
main_repo: "https://github.com/CodeIntelligenceTesting/jazzer"
sanitizers:
- address
+ - undefined
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/tar.py b/projects/javaparser/Dockerfile
index 74abd5c72..d0b8a74d3 100644
--- a/infra/base-images/base-sanitizer-libs-builder/packages/tar.py
+++ b/projects/javaparser/Dockerfile
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,14 +14,13 @@
#
################################################################################
-import package
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
+RUN apt-get update && apt-get install -y maven
-class Package(package.Package):
- """tar package."""
+RUN git clone --depth 1 https://github.com/javaparser/javaparser
+COPY build.sh $SRC/
- def __init__(self, apt_version):
- super(Package, self).__init__('tar', apt_version)
+COPY *.java $SRC/
- def PreBuild(self, source_directory, env, custom_bin_dir):
- env['FORCE_UNSAFE_CONFIGURE'] = '1'
+WORKDIR $SRC/javaparser
diff --git a/projects/javaparser/build.sh b/projects/javaparser/build.sh
new file mode 100755
index 000000000..a93135018
--- /dev/null
+++ b/projects/javaparser/build.sh
@@ -0,0 +1,49 @@
+#!/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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/javaparser/parseFuzzer.java b/projects/javaparser/parseFuzzer.java
new file mode 100644
index 000000000..662f3fb47
--- /dev/null
+++ b/projects/javaparser/parseFuzzer.java
@@ -0,0 +1,41 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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<CompilationUnit> result = new JavaParser(configuration)
+ .parse(COMPILATION_UNIT, provider(datastream, configuration.getCharacterEncoding()));
+ } catch (Exception e) {
+ return;
+ }
+ }
+}
diff --git a/projects/javaparser/project.yaml b/projects/javaparser/project.yaml
new file mode 100644
index 000000000..f62cb7749
--- /dev/null
+++ b/projects/javaparser/project.yaml
@@ -0,0 +1,11 @@
+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
diff --git a/projects/jbig2dec/jbig2_fuzzer.cc b/projects/jbig2dec/jbig2_fuzzer.cc
index 4b94f2c7d..c10b871a3 100644
--- a/projects/jbig2dec/jbig2_fuzzer.cc
+++ b/projects/jbig2dec/jbig2_fuzzer.cc
@@ -27,7 +27,7 @@
#define KBYTE ((size_t) 1024)
#define MBYTE (1024 * KBYTE)
#define GBYTE (1024 * MBYTE)
-#define MAX_ALLOCATION (1 * GBYTE)
+#define MAX_ALLOCATION (32 * MBYTE)
static size_t used;
diff --git a/projects/json-patch/Dockerfile b/projects/json-patch/Dockerfile
new file mode 100644
index 000000000..81eabb40d
--- /dev/null
+++ b/projects/json-patch/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+
+COPY fuzz_*.go $SRC/json-patch/
+
+COPY build.sh $SRC/
+WORKDIR $SRC/json-patch
diff --git a/projects/json-patch/build.sh b/projects/json-patch/build.sh
new file mode 100755
index 000000000..d13e7abf8
--- /dev/null
+++ b/projects/json-patch/build.sh
@@ -0,0 +1,19 @@
+#!/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
diff --git a/projects/json-patch/fuzz_create_merge.go b/projects/json-patch/fuzz_create_merge.go
new file mode 100644
index 000000000..b7cb330e0
--- /dev/null
+++ b/projects/json-patch/fuzz_create_merge.go
@@ -0,0 +1,26 @@
+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
+}
diff --git a/projects/json-patch/fuzz_decode_apply.go b/projects/json-patch/fuzz_decode_apply.go
new file mode 100644
index 000000000..315955804
--- /dev/null
+++ b/projects/json-patch/fuzz_decode_apply.go
@@ -0,0 +1,25 @@
+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
+}
diff --git a/projects/json-patch/project.yaml b/projects/json-patch/project.yaml
new file mode 100644
index 000000000..a66ada930
--- /dev/null
+++ b/projects/json-patch/project.yaml
@@ -0,0 +1,10 @@
+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'
diff --git a/projects/json-sanitizer/Dockerfile b/projects/json-sanitizer/Dockerfile
index f36a13622..9d1052aed 100644
--- a/projects/json-sanitizer/Dockerfile
+++ b/projects/json-sanitizer/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-jvm
RUN apt-get update && apt-get install -y maven
diff --git a/projects/json-sanitizer/build.sh b/projects/json-sanitizer/build.sh
index 64df5e5c5..dd4063bbb 100755
--- a/projects/json-sanitizer/build.sh
+++ b/projects/json-sanitizer/build.sh
@@ -56,5 +56,5 @@ LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \
--target_class=$fuzzer_basename \
--jvm_args=\"-Xmx2048m\" \
\$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/json/project.yaml b/projects/json/project.yaml
index 83f48e222..927bfc52a 100644
--- a/projects/json/project.yaml
+++ b/projects/json/project.yaml
@@ -6,5 +6,6 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
-main_repo: 'https://github.com/nlohmann/json.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'https://github.com/nlohmann/json.git' \ No newline at end of file
diff --git a/projects/json5format/Dockerfile b/projects/json5format/Dockerfile
index c0117a59e..64c8793c9 100644
--- a/projects/json5format/Dockerfile
+++ b/projects/json5format/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone --depth 1 https://github.com/google/json5format
WORKDIR $SRC
diff --git a/projects/jsoncpp/project.yaml b/projects/jsoncpp/project.yaml
index 8dc8f020f..51795d443 100644
--- a/projects/jsoncpp/project.yaml
+++ b/projects/jsoncpp/project.yaml
@@ -6,5 +6,6 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
-main_repo: 'https://github.com/open-source-parsers/jsoncpp'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'https://github.com/open-source-parsers/jsoncpp' \ No newline at end of file
diff --git a/projects/jsonnet/build.sh b/projects/jsonnet/build.sh
index 5386efb14..d51c7048a 100644
--- a/projects/jsonnet/build.sh
+++ b/projects/jsonnet/build.sh
@@ -28,4 +28,5 @@ fuzzer=convert_jsonnet_fuzzer
$CXX $CXXFLAGS -I${INSTALL_DIR}/include $LIB_FUZZING_ENGINE \
$fuzzer.cc -o $OUT/$fuzzer \
${INSTALL_DIR}/build/libjsonnet.a \
- ${INSTALL_DIR}/build/libmd5.a
+ ${INSTALL_DIR}/build/libmd5.a \
+ ${INSTALL_DIR}/build/libryml.a
diff --git a/projects/jsonnet/project.yaml b/projects/jsonnet/project.yaml
index 4b33850c3..feec146c7 100644
--- a/projects/jsonnet/project.yaml
+++ b/projects/jsonnet/project.yaml
@@ -2,12 +2,12 @@ homepage: "https://github.com/google/jsonnet"
language: c++
primary_contact: "dcunnin@google.com"
auto_ccs:
- - "wwweiwang@google.com"
- "sparkprime@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
labels:
diff --git a/projects/jsonparser/Dockerfile b/projects/jsonparser/Dockerfile
index a5d91faf6..38f310fbe 100644
--- a/projects/jsonparser/Dockerfile
+++ b/projects/jsonparser/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/buger/jsonparser
COPY build.sh $SRC/
diff --git a/projects/jsonschema/Dockerfile b/projects/jsonschema/Dockerfile
index ffec717b1..007e01c11 100644
--- a/projects/jsonschema/Dockerfile
+++ b/projects/jsonschema/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN pip3 install hypothesis
RUN git clone --depth=1 https://github.com/Julian/jsonschema
diff --git a/projects/jsonschema/build.sh b/projects/jsonschema/build.sh
index 71d4ad600..3ba97abb3 100644
--- a/projects/jsonschema/build.sh
+++ b/projects/jsonschema/build.sh
@@ -30,5 +30,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/jsoup/Dockerfile b/projects/jsoup/Dockerfile
new file mode 100644
index 000000000..d83f7b5f7
--- /dev/null
+++ b/projects/jsoup/Dockerfile
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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://downloads.apache.org/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/html.dict $SRC/HtmlFuzzer.dict && \
+ 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/jhy/jsoup/
+
+COPY build.sh $SRC/
+COPY HtmlFuzzer.java XmlFuzzer.java $SRC/
+WORKDIR $SRC/jsoup
diff --git a/projects/jsoup/HtmlFuzzer.java b/projects/jsoup/HtmlFuzzer.java
new file mode 100644
index 000000000..5f2090e7f
--- /dev/null
+++ b/projects/jsoup/HtmlFuzzer.java
@@ -0,0 +1,25 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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());
+ }
+}
diff --git a/projects/jsoup/XmlFuzzer.java b/projects/jsoup/XmlFuzzer.java
new file mode 100644
index 000000000..ddce20beb
--- /dev/null
+++ b/projects/jsoup/XmlFuzzer.java
@@ -0,0 +1,26 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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());
+ }
+}
diff --git a/projects/jsoup/build.sh b/projects/jsoup/build.sh
new file mode 100755
index 000000000..4bbe473e3
--- /dev/null
+++ b/projects/jsoup/build.sh
@@ -0,0 +1,52 @@
+#!/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
+
+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/jsoup-$CURRENT_VERSION.jar" $OUT/jsoup.jar
+
+ALL_JARS="jsoup.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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/jsoup/project.yaml b/projects/jsoup/project.yaml
new file mode 100644
index 000000000..6f47c2974
--- /dev/null
+++ b/projects/jsoup/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/jhy/jsoup/"
+language: jvm
+primary_contact: "jonathan@hedley.net"
+auto_ccs:
+ - "wagner@code-intelligence.com"
+ - "ffrr33aakk@gmail.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://github.com/jhy/jsoup/"
+sanitizers:
+ - address
diff --git a/projects/juju/Dockerfile b/projects/juju/Dockerfile
new file mode 100644
index 000000000..e4c15cb86
--- /dev/null
+++ b/projects/juju/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+COPY build.sh storage_fuzzer.go $SRC/
+WORKDIR $SRC/juju
diff --git a/projects/juju/build.sh b/projects/juju/build.sh
new file mode 100644
index 000000000..7dc892c23
--- /dev/null
+++ b/projects/juju/build.sh
@@ -0,0 +1,25 @@
+#!/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/storage_fuzzer.go $SRC/juju/storage/
+
+if [[ $SANITIZER = *coverage* ]]; then
+ compile_go_fuzzer github.com/juju/juju/storage Fuzz storage_fuzzer
+ exit 0
+fi
+
+compile_go_fuzzer ./storage Fuzz storage_fuzzer
diff --git a/projects/juju/project.yaml b/projects/juju/project.yaml
new file mode 100644
index 000000000..709249ffb
--- /dev/null
+++ b/projects/juju/project.yaml
@@ -0,0 +1,10 @@
+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
diff --git a/projects/juju/storage_fuzzer.go b/projects/juju/storage_fuzzer.go
new file mode 100644
index 000000000..17e2a0e06
--- /dev/null
+++ b/projects/juju/storage_fuzzer.go
@@ -0,0 +1,24 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 storage
+
+func Fuzz(data []byte) int {
+ _, err := ParseConstraints(string(data))
+ if err != nil {
+ return 0
+ }
+ return 1
+}
diff --git a/projects/kamailio/build.sh b/projects/kamailio/build.sh
index 2b7c3735b..5d94cec47 100755
--- a/projects/kamailio/build.sh
+++ b/projects/kamailio/build.sh
@@ -22,7 +22,8 @@ export LD_EXTRA_OPTS="${CFLAGS}"
sed -i 's/int main(/int main2(/g' ./src/main.c
-make || true
+export MEMPKG=sys
+make Q=verbose || true
cd src
mkdir objects && find . -name "*.o" -exec cp {} ./objects/ \;
ar -r libkamilio.a ./objects/*.o
@@ -30,3 +31,7 @@ cd ../
$CC $CFLAGS $LIB_FUZZING_ENGINE ./misc/fuzz/fuzz_uri.c -o $OUT/fuzz_uri \
-DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \
-I./src/ -I./src/core/parser -ldl -lresolv -lm
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./misc/fuzz/fuzz_parse_msg.c -o $OUT/fuzz_parse_msg \
+ -DFAST_LOCK -D__CPU_i386 ./src/libkamilio.a \
+ -I./src/ -I./src/core/parser -ldl -lresolv -lm
diff --git a/projects/kamailio/project.yaml b/projects/kamailio/project.yaml
index 46020a0c6..ae2ce665d 100755
--- a/projects/kamailio/project.yaml
+++ b/projects/kamailio/project.yaml
@@ -5,3 +5,5 @@ language: c
auto_ccs:
- "miconda@gmail.com"
- "david@adalogics.com"
+ - "mail@gilawa.com"
+ - "qxork.droid@gmail.com"
diff --git a/projects/karchive/project.yaml b/projects/karchive/project.yaml
index 0e023cd43..2318ce540 100644
--- a/projects/karchive/project.yaml
+++ b/projects/karchive/project.yaml
@@ -3,6 +3,7 @@ language: c++
primary_contact: tsdgeos@gmail.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://invent.kde.org/frameworks/karchive.git'
+main_repo: 'https://invent.kde.org/frameworks/karchive.git' \ No newline at end of file
diff --git a/projects/kcodecs/Dockerfile b/projects/kcodecs/Dockerfile
index 3d70e831a..1c563cf0d 100644
--- a/projects/kcodecs/Dockerfile
+++ b/projects/kcodecs/Dockerfile
@@ -15,7 +15,8 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install --yes cmake gperf
+RUN apt-get install --yes cmake
+RUN curl -L http://ftp.gnu.org/pub/gnu/gperf/gperf-3.1.tar.gz -O
RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
RUN git clone --depth 1 https://invent.kde.org/frameworks/kcodecs.git
RUN git clone --depth 1 https://invent.kde.org/frameworks/extra-cmake-modules.git
diff --git a/projects/kcodecs/build.sh b/projects/kcodecs/build.sh
index 2f8c857b1..85f5be3d0 100644
--- a/projects/kcodecs/build.sh
+++ b/projects/kcodecs/build.sh
@@ -16,6 +16,20 @@
################################################################################
cd $SRC
+tar xzf gperf*.tar.gz && rm -f gperf*.tar.gz
+cd gperf*
+FUZZ_CFLAGS="${CFLAGS}"
+FUZZ_CXXFLAGS="${CXXFLAGS}"
+unset CFLAGS
+unset CXXFLAGS
+# gperf is a code generator, so no need to sanitize it
+./configure --prefix=/usr
+make -j$(nproc) install
+export CFLAGS="${FUZZ_CFLAGS}"
+export CXXFLAGS="${FUZZ_CXXFLAGS}"
+
+
+cd $SRC
cd extra-cmake-modules
cmake .
make install
diff --git a/projects/kcodecs/project.yaml b/projects/kcodecs/project.yaml
index 1b731e3f3..b698f6320 100644
--- a/projects/kcodecs/project.yaml
+++ b/projects/kcodecs/project.yaml
@@ -3,6 +3,7 @@ language: c++
primary_contact: tsdgeos@gmail.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://invent.kde.org/frameworks/kcodecs.git'
+main_repo: 'https://invent.kde.org/frameworks/kcodecs.git' \ No newline at end of file
diff --git a/projects/keystone/project.yaml b/projects/keystone/project.yaml
index 860313b1c..4bb1e0b1a 100644
--- a/projects/keystone/project.yaml
+++ b/projects/keystone/project.yaml
@@ -6,6 +6,7 @@ auto_ccs :
- "stalkr@stalkr.net"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/keystone-engine/keystone.git'
+main_repo: 'https://github.com/keystone-engine/keystone.git' \ No newline at end of file
diff --git a/projects/kimageformats/Dockerfile b/projects/kimageformats/Dockerfile
index 4acc31c91..060709fdd 100644
--- a/projects/kimageformats/Dockerfile
+++ b/projects/kimageformats/Dockerfile
@@ -22,8 +22,8 @@ RUN git clone --depth 1 https://invent.kde.org/frameworks/extra-cmake-modules.gi
RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
RUN git clone --depth 1 https://invent.kde.org/frameworks/karchive.git
RUN git clone --depth 1 https://invent.kde.org/frameworks/kimageformats.git
-RUN git clone --depth 1 -b v2.0.2 https://aomedia.googlesource.com/aom
-RUN git clone --depth 1 -b v0.9.0 https://github.com/AOMediaCodec/libavif.git
+RUN git clone --depth 1 -b v3.1.0 https://aomedia.googlesource.com/aom
+RUN git clone --depth 1 -b v0.9.1 https://github.com/AOMediaCodec/libavif.git
RUN git clone --depth 1 https://github.com/strukturag/libde265.git
RUN git clone --depth 1 https://github.com/strukturag/libheif.git
COPY build.sh $SRC
diff --git a/projects/kimageformats/build.sh b/projects/kimageformats/build.sh
index 0ffa60bbb..537056e47 100644
--- a/projects/kimageformats/build.sh
+++ b/projects/kimageformats/build.sh
@@ -103,7 +103,7 @@ echo "$HANDLER_TYPES" | while read class format; do
fuzz_target_name=kimgio_${format}_fuzzer
$SRC/qtbase/bin/moc $SRC/kimageformats/src/imageformats/$format.cpp -o $format.moc
- $CXX $CXXFLAGS -fPIC -DHANDLER=$class -std=c++14 $SRC/kimgio_fuzzer.cc $SRC/kimageformats/src/imageformats/$format.cpp -o $OUT/$fuzz_target_name -I $SRC/qtbase/include/QtCore/ -I $SRC/qtbase/include/ -I $SRC/qtbase/include//QtGui -I $SRC/kimageformats/src/imageformats/ -I $SRC/karchive/src/ -I $SRC/qtbase/mkspecs/linux-clang-libc++/ -I $SRC/libavif/include/ -I . -L $SRC/qtbase/lib $SRC/libavif/build/libavif.a /usr/local/lib/libheif.a /usr/local/lib/liblibde265.a $SRC/aom/build.libavif/libaom.a -lQt5Gui -lQt5Core -lqtlibpng -lqtharfbuzz -lm -lqtpcre2 -ldl -lpthread $LIB_FUZZING_ENGINE /usr/local/lib/libzip.a /usr/local/lib/libz.a -lKF5Archive /usr/local/lib/libz.a
+ $CXX $CXXFLAGS -fPIC -DHANDLER=$class -std=c++17 $SRC/kimgio_fuzzer.cc $SRC/kimageformats/src/imageformats/$format.cpp -o $OUT/$fuzz_target_name -I $SRC/qtbase/include/QtCore/ -I $SRC/qtbase/include/ -I $SRC/qtbase/include//QtGui -I $SRC/kimageformats/src/imageformats/ -I $SRC/karchive/src/ -I $SRC/qtbase/mkspecs/linux-clang-libc++/ -I $SRC/libavif/include/ -I . -L $SRC/qtbase/lib $SRC/libavif/build/libavif.a /usr/local/lib/libheif.a /usr/local/lib/liblibde265.a $SRC/aom/build.libavif/libaom.a -lQt5Gui -lQt5Core -lqtlibpng -lqtharfbuzz -lm -lqtpcre2 -ldl -lpthread $LIB_FUZZING_ENGINE /usr/local/lib/libzip.a /usr/local/lib/libz.a -lKF5Archive /usr/local/lib/libz.a
find . -name "*.${format}" | zip -q $OUT/${fuzz_target_name}_seed_corpus.zip -@
)
diff --git a/projects/kimageformats/project.yaml b/projects/kimageformats/project.yaml
index d2551a802..a36df366c 100644
--- a/projects/kimageformats/project.yaml
+++ b/projects/kimageformats/project.yaml
@@ -3,6 +3,7 @@ language: c++
primary_contact: tsdgeos@gmail.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
main_repo: 'https://invent.kde.org/frameworks/kimageformats.git'
diff --git a/projects/knot-dns/build.sh b/projects/knot-dns/build.sh
index e451813fe..b49aa69d1 100755
--- a/projects/knot-dns/build.sh
+++ b/projects/knot-dns/build.sh
@@ -20,7 +20,7 @@
# Cribbed from projects/wget2, thanks rockdaboot@gmail.com
export DEPS_PATH=$SRC/knot_deps
-export PKG_CONFIG_PATH=$DEPS_PATH/lib/pkgconfig
+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
@@ -75,6 +75,9 @@ make check
# Set up fuzzing seeds
git submodule update --init -- ./fuzz_packet.in
-find ./fuzz_packet.in/ -type f -exec zip -u $OUT/fuzz_packet_seed_corpus.zip {} \;
git submodule update --init -- ./fuzz_zscanner.in
-find ./fuzz_zscanner.in/ -type f -exec zip -u $OUT/fuzz_zscanner_seed_corpus.zip {} \;
+# ./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 {} \;
diff --git a/projects/kryo/DeserializeCollectionsFuzzer.java b/projects/kryo/DeserializeCollectionsFuzzer.java
new file mode 100644
index 000000000..f28e378ef
--- /dev/null
+++ b/projects/kryo/DeserializeCollectionsFuzzer.java
@@ -0,0 +1,69 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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<String> _emptyList = Collections.emptyList();
+ Set<String> _emptySet = Collections.emptySet();
+ Map<String, String> _emptyMap = Collections.emptyMap();
+ List<String> _singletonList = Collections.singletonList("foo");
+ Set<String> _singletonSet = Collections.emptySet();
+ Map<String, String> _singletonMap;
+ TreeSet<String> _treeSet;
+ TreeMap<String, Integer> _treeMap;
+ List<String> _arrayList;
+ Set<String> _hashSet;
+ Map<String, Integer> _hashMap;
+ List<Integer> _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;
+ }
+
+}
diff --git a/projects/kryo/DeserializeNumbersFuzzer.java b/projects/kryo/DeserializeNumbersFuzzer.java
new file mode 100644
index 000000000..80137c780
--- /dev/null
+++ b/projects/kryo/DeserializeNumbersFuzzer.java
@@ -0,0 +1,76 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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;
+ }
+}
diff --git a/projects/kryo/DeserializeStringFuzzer.java b/projects/kryo/DeserializeStringFuzzer.java
new file mode 100644
index 000000000..9fe77ec23
--- /dev/null
+++ b/projects/kryo/DeserializeStringFuzzer.java
@@ -0,0 +1,45 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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;
+ }
+}
diff --git a/projects/kryo/Dockerfile b/projects/kryo/Dockerfile
new file mode 100644
index 000000000..bf512f0d2
--- /dev/null
+++ b/projects/kryo/Dockerfile
@@ -0,0 +1,29 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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://downloads.apache.org/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/EsotericSoftware/kryo
+
+COPY build.sh $SRC/
+COPY DeserializeCollectionsFuzzer.java DeserializeNumbersFuzzer.java DeserializeStringFuzzer.java $SRC/
+WORKDIR $SRC/kryo
diff --git a/projects/kryo/build.sh b/projects/kryo/build.sh
new file mode 100644
index 000000000..9d53d396b
--- /dev/null
+++ b/projects/kryo/build.sh
@@ -0,0 +1,51 @@
+#!/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 15 -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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m;--enable-preview\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
+done
diff --git a/projects/kryo/project.yaml b/projects/kryo/project.yaml
new file mode 100644
index 000000000..8b747ac5f
--- /dev/null
+++ b/projects/kryo/project.yaml
@@ -0,0 +1,12 @@
+homepage: "http://esotericsoftware.com/"
+language: jvm
+primary_contact: "thomas@umschalt.com"
+auto_ccs:
+ - "meumertzheim@code-intelligence.com"
+ - "wagner@code-intelligence.com"
+ - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://github.com/EsotericSoftware/kryo"
+sanitizers:
+ - address
diff --git a/projects/kubernetes/Dockerfile b/projects/kubernetes/Dockerfile
index e4ebed882..e6391ad97 100644
--- a/projects/kubernetes/Dockerfile
+++ b/projects/kubernetes/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN go get github.com/ianlancetaylor/demangle
RUN git clone --depth 1 https://github.com/kubernetes/kubernetes.git
diff --git a/projects/lame/project.yaml b/projects/lame/project.yaml
index b6bd38292..630fd7647 100644
--- a/projects/lame/project.yaml
+++ b/projects/lame/project.yaml
@@ -5,7 +5,8 @@ auto_ccs:
- "bouvigne@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- - i386
+ - i386 \ No newline at end of file
diff --git a/projects/leveldb/project.yaml b/projects/leveldb/project.yaml
index 7eecedc2f..710887fd1 100644
--- a/projects/leveldb/project.yaml
+++ b/projects/leveldb/project.yaml
@@ -6,5 +6,6 @@ auto_ccs :
- "david@adalogics.com"
sanitizers:
- address
- - memory
-main_repo: 'https://github.com/google/leveldb.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'https://github.com/google/leveldb.git' \ No newline at end of file
diff --git a/projects/libaom/Dockerfile b/projects/libaom/Dockerfile
index a911f3367..2bfa6aaf2 100644
--- a/projects/libaom/Dockerfile
+++ b/projects/libaom/Dockerfile
@@ -18,5 +18,5 @@ 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 av1_dec_fuzzer.dict $SRC/
+COPY build.sh $SRC/
WORKDIR aom
diff --git a/projects/libaom/av1_dec_fuzzer.dict b/projects/libaom/av1_dec_fuzzer.dict
deleted file mode 100644
index fb1638864..000000000
--- a/projects/libaom/av1_dec_fuzzer.dict
+++ /dev/null
@@ -1,5 +0,0 @@
-# IVF Signature + version (bytes 0-5)
-kw1="DKIF\x00\x00"
-
-# AV1 codec fourCC (bytes 8-11)
-kw2="AV01"
diff --git a/projects/libaom/build.sh b/projects/libaom/build.sh
index fc25bbf4c..590b45ac5 100755
--- a/projects/libaom/build.sh
+++ b/projects/libaom/build.sh
@@ -65,5 +65,5 @@ $CXX $CXXFLAGS -std=c++11 \
# copy seed corpus.
cp $SRC/dec_fuzzer_seed_corpus.zip $OUT/${fuzzer_name}_seed_corpus.zip
-cp $SRC/av1_dec_fuzzer.dict $OUT/${fuzzer_name}.dict
+cp $SRC/aom/examples/av1_dec_fuzzer.dict $OUT/${fuzzer_name}.dict
diff --git a/projects/libaom/project.yaml b/projects/libaom/project.yaml
index dedc30485..02fe38768 100644
--- a/projects/libaom/project.yaml
+++ b/projects/libaom/project.yaml
@@ -6,10 +6,10 @@ sanitizers:
- memory
- undefined
auto_ccs:
-- huisu@google.com
- jaikk@google.com
- jzern@google.com
- wtc@google.com
+- yunqingwang@google.com
vendor_ccs:
- twsmith@mozilla.com
main_repo: 'https://aomedia.googlesource.com/aom'
diff --git a/projects/libarchive/Dockerfile b/projects/libarchive/Dockerfile
index bd076691e..c41e51ca7 100644
--- a/projects/libarchive/Dockerfile
+++ b/projects/libarchive/Dockerfile
@@ -16,12 +16,12 @@
FROM gcr.io/oss-fuzz-base/base-builder
-# Installing optional libraries can utilize more code path and/or improve
-# performance (avoid calling external programs).
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config \
libbz2-dev liblzo2-dev liblzma-dev liblz4-dev libz-dev \
- libxml2-dev libssl-dev libacl1-dev libattr1-dev lrzip \
- liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk
+ libssl-dev libacl1-dev libattr1-dev lrzip \
+ liblz4-tool lzop zstd lcab genisoimage jlha-utils rar default-jdk
RUN git clone --depth 1 https://github.com/libarchive/libarchive.git
-WORKDIR libarchive
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
+
COPY build.sh libarchive_fuzzer.cc $SRC/
+WORKDIR $SRC
diff --git a/projects/libarchive/build.sh b/projects/libarchive/build.sh
index 87587a57d..a46a44d2a 100755
--- a/projects/libarchive/build.sh
+++ b/projects/libarchive/build.sh
@@ -15,18 +15,35 @@
#
################################################################################
-# build the project
-./build/autogen.sh
-./configure
-make -j$(nproc) all
+# compile libxml2 from source so we can statically link
+DEPS=/deps
+mkdir ${DEPS}
+cd $SRC/libxml2
+./autogen.sh \
+ --without-debug \
+ --without-ftp \
+ --without-http \
+ --without-legacy \
+ --without-python
+make -j$(nproc)
+make install
+cp .libs/libxml2.a ${DEPS}/
+cd $SRC/libarchive
+
+sed -i 's/-Wall//g' ./CMakeLists.txt
+sed -i 's/-Werror//g' ./CMakeLists.txt
+
+mkdir build2
+cd build2
+cmake ../
+make
# build seed
cp $SRC/libarchive/contrib/oss-fuzz/corpus.zip\
- $OUT/libarchive_fuzzer_seed_corpus.zip
+ $OUT/libarchive_fuzzer_seed_corpus.zip
# build fuzzer(s)
-$CXX $CXXFLAGS -Ilibarchive \
+$CXX $CXXFLAGS -I../libarchive \
$SRC/libarchive_fuzzer.cc -o $OUT/libarchive_fuzzer \
- $LIB_FUZZING_ENGINE .libs/libarchive.a \
- -Wl,-Bstatic -lbz2 -llzo2 -lxml2 -llzma -lz -lcrypto -llz4 -licuuc \
- -licudata -Wl,-Bdynamic
+ $LIB_FUZZING_ENGINE ./libarchive/libarchive.a \
+ -lcrypto -lacl -llzma -llz4 -lbz2 -lz ${DEPS}/libxml2.a
diff --git a/projects/libass/Dockerfile b/projects/libass/Dockerfile
index b0758cef1..88801cc85 100644
--- a/projects/libass/Dockerfile
+++ b/projects/libass/Dockerfile
@@ -15,11 +15,10 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libfreetype6-dev libfontconfig1-dev python3-pip && \
+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.53.0 ninja
RUN git clone --depth 1 https://github.com/libass/libass.git
-RUN git clone --depth 1 https://github.com/behdad/fribidi.git
RUN git clone --depth 1 https://github.com/harfbuzz/harfbuzz.git
COPY build.sh libass_fuzzer.cc *.dict *.options $SRC/
diff --git a/projects/libass/build.sh b/projects/libass/build.sh
index 44006e37f..8e313fdfd 100755
--- a/projects/libass/build.sh
+++ b/projects/libass/build.sh
@@ -15,10 +15,6 @@
#
################################################################################
-cd $SRC/fribidi
-./autogen.sh --disable-docs --enable-static=yes --enable-shared=no --with-pic=yes --prefix=/work/
-make install
-
cd $SRC/harfbuzz
# setup
@@ -33,6 +29,7 @@ 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
@@ -44,10 +41,11 @@ export PKG_CONFIG_PATH=/work/lib/pkgconfig
./configure --disable-asm
make -j$(nproc)
-$CXX $CXXFLAGS -std=c++11 -I$SRC/libass -L/work/lib \
+$CXX $CXXFLAGS -std=c++11 -I$SRC/libass \
$SRC/libass_fuzzer.cc -o $OUT/libass_fuzzer \
$LIB_FUZZING_ENGINE libass/.libs/libass.a \
- -Wl,-Bstatic -lfontconfig -lfribidi -lfreetype -lharfbuzz -lz -lpng12 \
- -lexpat -Wl,-Bdynamic
+ -Wl,-Bstatic \
+ $(pkg-config --static --libs fontconfig freetype2 fribidi harfbuzz | sed 's/-lm //g') \
+ -Wl,-Bdynamic
cp $SRC/*.dict $SRC/*.options $OUT/
diff --git a/projects/libass/libass_fuzzer.cc b/projects/libass/libass_fuzzer.cc
index 5254faff4..8cb11a68c 100644
--- a/projects/libass/libass_fuzzer.cc
+++ b/projects/libass/libass_fuzzer.cc
@@ -1,3 +1,21 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdio.h>
#include <stdlib.h>
@@ -12,29 +30,35 @@ void msg_callback(int level, const char *fmt, va_list va, void *data) {
static const int kFrameWidth = 1280;
static const int kFrameHeight = 720;
-static bool init(int frame_w, int frame_h) {
- ass_library = ass_library_init();
- if (!ass_library) {
- printf("ass_library_init failed!\n");
- exit(1);
- }
+struct init {
+ init(int frame_w, int frame_h) {
+ ass_library = ass_library_init();
+ if (!ass_library) {
+ printf("ass_library_init failed!\n");
+ exit(1);
+ }
+
+ ass_set_message_cb(ass_library, msg_callback, NULL);
- ass_set_message_cb(ass_library, msg_callback, NULL);
+ ass_renderer = ass_renderer_init(ass_library);
+ if (!ass_renderer) {
+ printf("ass_renderer_init failed!\n");
+ exit(1);
+ }
- ass_renderer = ass_renderer_init(ass_library);
- if (!ass_renderer) {
- printf("ass_renderer_init failed!\n");
- exit(1);
+ ass_set_frame_size(ass_renderer, frame_w, frame_h);
+ ass_set_fonts(ass_renderer, nullptr, "sans-serif",
+ ASS_FONTPROVIDER_AUTODETECT, nullptr, 1);
}
- ass_set_frame_size(ass_renderer, frame_w, frame_h);
- ass_set_fonts(ass_renderer, nullptr, "sans-serif",
- ASS_FONTPROVIDER_AUTODETECT, nullptr, 1);
- return true;
-}
+ ~init() {
+ ass_renderer_done(ass_renderer);
+ ass_library_done(ass_library);
+ }
+};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- static bool initialized = init(kFrameWidth, kFrameHeight);
+ static init initialized(kFrameWidth, kFrameHeight);
ASS_Track *track = ass_read_memory(ass_library, (char *)data, size, nullptr);
if (!track) return 0;
diff --git a/projects/libass/project.yaml b/projects/libass/project.yaml
index bfcb93edc..9fdaf42f9 100644
--- a/projects/libass/project.yaml
+++ b/projects/libass/project.yaml
@@ -1,10 +1,9 @@
homepage: "https://github.com/libass/libass"
language: c++
-primary_contact: "greg@kinoho.net"
+primary_contact: "chortos@inbox.lv"
auto_ccs:
+ - "greg@kinoho.net"
- "rodger.combs@gmail.com"
- - "nfxjfg@gmail.com"
- - "chortos@inbox.lv"
- "vabnick@gmail.com"
sanitizers:
- address
diff --git a/projects/libavc/project.yaml b/projects/libavc/project.yaml
index 1f5422f5e..845e5230f 100644
--- a/projects/libavc/project.yaml
+++ b/projects/libavc/project.yaml
@@ -12,10 +12,12 @@ vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
architectures:
- x86_64
- i386
diff --git a/projects/libavif/Dockerfile b/projects/libavif/Dockerfile
index a1f030e95..c1d918b70 100644
--- a/projects/libavif/Dockerfile
+++ b/projects/libavif/Dockerfile
@@ -15,19 +15,11 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-
-ADD bionic.list /etc/apt/sources.list.d/bionic.list
-ADD nasm_apt.pin /etc/apt/preferences
-
RUN apt-get update && \
- apt-get install --no-install-recommends -y curl python3-pip python3-setuptools python3-wheel cmake git && \
+ 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
-RUN curl -L https://download.videolan.org/contrib/nasm/nasm-2.14.tar.gz | tar xvz
-RUN cd nasm-2.14 && ./configure && make -j2 && ln -s `pwd`/nasm /usr/bin/nasm && cd ..
-RUN nasm --version
-
COPY build.sh avif_decode_seed_corpus.zip $SRC/
diff --git a/projects/libavif/bionic.list b/projects/libavif/bionic.list
deleted file mode 100644
index 8621803a7..000000000
--- a/projects/libavif/bionic.list
+++ /dev/null
@@ -1,2 +0,0 @@
-# use nasm 2.13.02 from bionic
-deb http://archive.ubuntu.com/ubuntu/ bionic universe
diff --git a/projects/libavif/build.sh b/projects/libavif/build.sh
index 130709fb9..fe7eba079 100755
--- a/projects/libavif/build.sh
+++ b/projects/libavif/build.sh
@@ -16,7 +16,7 @@
################################################################################
# build dav1d
-cd ext && bash dav1d.cmd && cd ..
+cd ext && bash dav1d_oss_fuzz.sh && cd ..
# build libavif
mkdir build
diff --git a/projects/libavif/nasm_apt.pin b/projects/libavif/nasm_apt.pin
deleted file mode 100644
index 69099026b..000000000
--- a/projects/libavif/nasm_apt.pin
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: *
-Pin: release n=bionic
-Pin-Priority: 1
-
-Package: nasm
-Pin: release n=bionic
-Pin-Priority: 555
diff --git a/projects/libcacard/Dockerfile b/projects/libcacard/Dockerfile
index 5e280b94d..7d7a0abf6 100644
--- a/projects/libcacard/Dockerfile
+++ b/projects/libcacard/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
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
+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
diff --git a/projects/libcacard/build.sh b/projects/libcacard/build.sh
index 719502e90..f12cb416d 100755
--- a/projects/libcacard/build.sh
+++ b/projects/libcacard/build.sh
@@ -33,7 +33,11 @@ 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
-sed -i "s/Libs:.*/Libs: -L\${libdir} -lssl -lsmime -lnssdev -lnss_static -lpk11wrap_static -lcryptohi -lcerthi -lcertdb -lnssb -lnssutil -lnsspki -ldl -lm -lsqlite -lsoftokn_static -lfreebl_static -lgcm-aes-x86_c_lib -lhw-acc-crypto-avx -lhw-acc-crypto-avx2 /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/)
diff --git a/projects/libchewing/build.sh b/projects/libchewing/build.sh
deleted file mode 100755
index e721a0b28..000000000
--- a/projects/libchewing/build.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/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
-./configure --disable-shared --enable-static --without-sqlite3
-make clean
-make -j$(nproc) all
-
-# build your fuzzer(s)
-make -C test CFLAGS="$CFLAGS -Dmain=stress_main -Drand=get_fuzz_input" stress.o
-
-$CC $CFLAGS -c $SRC/chewing_fuzzer_common.c -o $WORK/chewing_fuzzer_common.o
-
-for variant in default random_init dynamic_config; do
- $CC $CFLAGS -c $SRC/chewing_${variant}_fuzzer.c -o $WORK/chewing_${variant}_fuzzer.o
- $CXX $CXXFLAGS \
- -o $OUT/chewing_${variant}_fuzzer \
- $WORK/chewing_${variant}_fuzzer.o $WORK/chewing_fuzzer_common.o \
- test/stress.o test/.libs/libtesthelper.a src/.libs/libchewing.a \
- $LIB_FUZZING_ENGINE
-done
-
-# install data files
-make -j$(nproc) -C data pkgdatadir=$OUT install
diff --git a/projects/libchewing/chewing_default_fuzzer.c b/projects/libchewing/chewing_default_fuzzer.c
deleted file mode 100644
index dd6fc7a84..000000000
--- a/projects/libchewing/chewing_default_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- fuzz_input = fuzz_ptr = data;
- fuzz_size = size;
-
- const char* stress_argv[] = {
- "./chewing_fuzzer", "-loop", "1", NULL,
- };
- stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
- (char**)stress_argv);
- return 0;
-}
diff --git a/projects/libchewing/chewing_dynamic_config_fuzzer.c b/projects/libchewing/chewing_dynamic_config_fuzzer.c
deleted file mode 100644
index 5479c1ee1..000000000
--- a/projects/libchewing/chewing_dynamic_config_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- fuzz_input = fuzz_ptr = data;
- fuzz_size = size;
-
- const char* stress_argv[] = {
- "./chewing_fuzzer", "-loop", "1", "-extra", NULL,
- };
- stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
- (char**)stress_argv);
- return 0;
-}
diff --git a/projects/libchewing/chewing_fuzzer_common.c b/projects/libchewing/chewing_fuzzer_common.c
deleted file mode 100644
index 34426ea37..000000000
--- a/projects/libchewing/chewing_fuzzer_common.c
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "chewing_fuzzer_common.h"
-
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static char userphrase_path[] = "/tmp/chewing_userphrase.db.XXXXXX";
-
-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);
-
- // Assume data files are at the same location as executable.
- setenv("CHEWING_PATH", dir, 0);
- free(exe_path_copy);
-
- // Specify user db of this process. So we can run multiple fuzzers at the
- // same time.
- mktemp(userphrase_path);
- setenv("TEST_USERPHRASE_PATH", userphrase_path, 0);
- return 0;
-}
-
-int get_fuzz_input() {
- if (fuzz_ptr - fuzz_input >= fuzz_size)
- return EOF;
- return *fuzz_ptr++;
-}
diff --git a/projects/libchewing/chewing_fuzzer_common.h b/projects/libchewing/chewing_fuzzer_common.h
deleted file mode 100644
index 5032d655c..000000000
--- a/projects/libchewing/chewing_fuzzer_common.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef CHEWING_FUZZER_COMMON_H
-#define CHEWING_FUZZER_COMMON_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-const uint8_t* fuzz_ptr;
-const uint8_t* fuzz_input;
-size_t fuzz_size;
-
-int stress_main(int argc, char** argv);
-
-#endif
diff --git a/projects/libchewing/chewing_random_init_fuzzer.c b/projects/libchewing/chewing_random_init_fuzzer.c
deleted file mode 100644
index e0d755f7d..000000000
--- a/projects/libchewing/chewing_random_init_fuzzer.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <stdio.h>
-
-#include "chewing_fuzzer_common.h"
-
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- fuzz_input = fuzz_ptr = data;
- fuzz_size = size;
-
- const char* stress_argv[] = {
- "./chewing_fuzzer", "-loop", "1", "-init", NULL,
- };
- stress_main(sizeof(stress_argv) / sizeof(stress_argv[0]) - 1,
- (char**)stress_argv);
- return 0;
-}
diff --git a/projects/libchewing/project.yaml b/projects/libchewing/project.yaml
deleted file mode 100644
index 1dd3e6e7f..000000000
--- a/projects/libchewing/project.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-homepage: "http://chewing.im/"
-language: c++
-disabled: true
-view_restrictions: none
-main_repo: 'https://github.com/chewing/libchewing.git'
diff --git a/projects/libecc/Dockerfile b/projects/libecc/Dockerfile
new file mode 100644
index 000000000..aaeed8e41
--- /dev/null
+++ b/projects/libecc/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 https://github.com/ANSSI-FR/libecc.git
+RUN git clone --depth 1 https://github.com/randombit/botan.git
+RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
+COPY build.sh $SRC/
diff --git a/projects/libecc/build.sh b/projects/libecc/build.sh
new file mode 100755
index 000000000..558b85260
--- /dev/null
+++ b/projects/libecc/build.sh
@@ -0,0 +1,69 @@
+#!/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_74_0.tar.bz2
+cd boost_1_74_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+cp -R boost/ /usr/include/
+
+# Build libecc
+cd $SRC/libecc
+git checkout cryptofuzz
+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
+ ./configure.py --cc-bin=$CXX --cc-abi-flags="$CXXFLAGS" --disable-shared --disable-modules=locking_allocator,x509,tls --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,tls --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 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,ECC_PrivateToPublic,ECDSA_Sign,ECDSA_Verify,ECGDSA_Sign,ECGDSA_Verify,ECRDSA_Sign,ECRDSA_Verify,ECC_Point_Add,ECC_Point_Mul,BignumCalc ' >>extra_options.h
+echo -n '--curves=brainpool224r1,brainpool256r1,brainpool384r1,brainpool512r1,secp192r1,secp224r1,secp256r1,secp384r1,secp521r1,secp256k1 ' >>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 ' >>extra_options.h
+echo -n '--calcops=Add,AddMod,And,Bit,GCD,InvMod,IsOdd,IsOne,IsZero,LShift1,Mod,Mul,MulMod,NumBits,Or,RShift,Sqr,Sub,SubMod,Xor ' >>extra_options.h
+echo -n '"' >>extra_options.h
+cd modules/libecc/
+make -B -j$(nproc)
+cd ../botan/
+make -B -j$(nproc)
+cd ../../
+make -B -j$(nproc)
+
+cp cryptofuzz $OUT/cryptofuzz-libecc
diff --git a/projects/libecc/project.yaml b/projects/libecc/project.yaml
new file mode 100644
index 000000000..2fe474fc8
--- /dev/null
+++ b/projects/libecc/project.yaml
@@ -0,0 +1,14 @@
+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
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+architectures:
+ - x86_64
+ - i386
diff --git a/projects/libevent/Dockerfile b/projects/libevent/Dockerfile
index 04fdc04f2..0c34bd755 100644
--- a/projects/libevent/Dockerfile
+++ b/projects/libevent/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool cmake
+RUN apt-get update && apt-get install -y make autoconf automake libtool cmake pkg-config
RUN git clone --depth 1 https://github.com/libevent/libevent.git libevent
WORKDIR libevent
COPY build.sh *.cc $SRC/
diff --git a/projects/libevent/project.yaml b/projects/libevent/project.yaml
index feb600c25..be4d8bd89 100644
--- a/projects/libevent/project.yaml
+++ b/projects/libevent/project.yaml
@@ -3,9 +3,10 @@ language: c++
primary_contact: "a3at.mail@gmail.com"
sanitizers:
- address
- - memory
+# 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'
+main_repo: 'https://github.com/libevent/libevent.git' \ No newline at end of file
diff --git a/projects/libfdk-aac/project.yaml b/projects/libfdk-aac/project.yaml
index 0613f7290..922606a14 100644
--- a/projects/libfdk-aac/project.yaml
+++ b/projects/libfdk-aac/project.yaml
@@ -1,4 +1,5 @@
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:
@@ -7,10 +8,12 @@ vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
fuzzing_engines:
- libfuzzer
- afl
diff --git a/projects/libfido2/project.yaml b/projects/libfido2/project.yaml
index 5a351a07c..d335eea9b 100644
--- a/projects/libfido2/project.yaml
+++ b/projects/libfido2/project.yaml
@@ -9,7 +9,8 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
fuzzing_engines:
- libfuzzer
-main_repo: 'https://github.com/Yubico/libfido2'
+main_repo: 'https://github.com/Yubico/libfido2' \ No newline at end of file
diff --git a/projects/libheif/build.sh b/projects/libheif/build.sh
index 70618a2d2..7c303ea72 100755
--- a/projects/libheif/build.sh
+++ b/projects/libheif/build.sh
@@ -74,7 +74,8 @@ PKG_CONFIG="pkg-config --static" PKG_CONFIG_PATH="$DEPS_PATH/lib/pkgconfig" ./co
--enable-static \
--disable-examples \
--disable-go \
- --enable-libfuzzer="$LIB_FUZZING_ENGINE"
+ --enable-libfuzzer="$LIB_FUZZING_ENGINE" \
+ CPPFLAGS="-I$DEPS_PATH/include"
make clean
make -j$(nproc)
diff --git a/projects/libhevc/project.yaml b/projects/libhevc/project.yaml
index 5d84b08e7..4af0cab3f 100644
--- a/projects/libhevc/project.yaml
+++ b/projects/libhevc/project.yaml
@@ -12,10 +12,12 @@ vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
architectures:
- x86_64
- i386
diff --git a/projects/libhtp/project.yaml b/projects/libhtp/project.yaml
index 3b861d5bd..753887a28 100644
--- a/projects/libhtp/project.yaml
+++ b/projects/libhtp/project.yaml
@@ -7,6 +7,7 @@ auto_ccs :
sanitizers:
- address
-- memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/OISF/libhtp.git'
+main_repo: 'https://github.com/OISF/libhtp.git' \ No newline at end of file
diff --git a/projects/libidn/Dockerfile b/projects/libidn/Dockerfile
index 3bb5413cf..e6aebff2b 100644
--- a/projects/libidn/Dockerfile
+++ b/projects/libidn/Dockerfile
@@ -22,7 +22,7 @@ RUN apt-get update && apt-get install -y \
autoconf-archive \
automake \
libtool \
- gettext gengetopt curl gperf
+ gettext gengetopt curl gperf wget
RUN git clone --depth=1 https://git.savannah.gnu.org/git/libidn.git
diff --git a/projects/libidn/build.sh b/projects/libidn/build.sh
index b66d8b940..5aa0ea3a8 100755
--- a/projects/libidn/build.sh
+++ b/projects/libidn/build.sh
@@ -18,10 +18,10 @@
# avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
export ASAN_OPTIONS=detect_leaks=0
-make CFGFLAGS="--enable-static --disable-doc"
-make clean
-make -j1
-make -j$(nproc) check
+./bootstrap
+./configure --enable-static --disable-doc
+make -j
+make -j check
cd fuzz
make oss-fuzz
diff --git a/projects/libigl/Dockerfile b/projects/libigl/Dockerfile
new file mode 100644
index 000000000..2fba95aa0
--- /dev/null
+++ b/projects/libigl/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/libigl/libigl
+WORKDIR $SRC/libigl
+COPY igl_fuzzer.cpp \
+ build.sh \
+ $SRC/
+
diff --git a/projects/libigl/build.sh b/projects/libigl/build.sh
new file mode 100755
index 000000000..d2a39f17e
--- /dev/null
+++ b/projects/libigl/build.sh
@@ -0,0 +1,39 @@
+#!/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_WITH_OPENGL=OFF \
+ -DLIBIGL_WITH_OPENGL_GLFW=OFF \
+ -DLIBIGL_WITH_OPENGL_GLFW_IMGUI=OFF \
+ -DLIBIGL_WITH_COMISO=OFF \
+ -DLIBIGL_WITH_EMBREE=OFF \
+ -DLIBIGL_WITH_PNG=OFF \
+ -DLIBIGL_WITH_TETGEN=OFF \
+ -DLIBIGL_WITH_TRIANGLE=OFF \
+ -DLIBIGL_WITH_PREDICATES=OFF \
+ -DLIBIGL_WITH_XML=OFF \
+ -DLIBIGL_BUILD_TESTS=OFF \
+ ..
+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/libigl.a
diff --git a/projects/libigl/igl_fuzzer.cpp b/projects/libigl/igl_fuzzer.cpp
new file mode 100644
index 000000000..34e4dfe9a
--- /dev/null
+++ b/projects/libigl/igl_fuzzer.cpp
@@ -0,0 +1,37 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <igl/MshLoader.h>
+#include <iostream>
+
+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;
+}
+
diff --git a/projects/libigl/project.yaml b/projects/libigl/project.yaml
new file mode 100644
index 000000000..411d0da3d
--- /dev/null
+++ b/projects/libigl/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://libigl.github.io"
+language: c++
+primary_contact: "github@jdumas.org"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+main_repo: "https://github.com/libigl/libigl"
diff --git a/projects/libjpeg-turbo/Dockerfile b/projects/libjpeg-turbo/Dockerfile
index 40c8f49f6..74f1249f9 100644
--- a/projects/libjpeg-turbo/Dockerfile
+++ b/projects/libjpeg-turbo/Dockerfile
@@ -15,12 +15,13 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool yasm curl cmake
+RUN apt-get update && apt-get install -y make yasm cmake
RUN git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo
-RUN mkdir afl-testcases
-RUN cd afl-testcases/ && curl https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz | tar -xz
-RUN zip libjpeg_turbo_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/libjpeg-turbo/seed-corpora
+RUN cd seed-corpora && zip -r ../decompress_fuzzer_seed_corpus.zip afl-testcases/jpeg* bugs/decompress* $SRC/libjpeg-turbo/testimages/*.jpg
+RUN cd seed-corpora && zip -r ../compress_fuzzer_seed_corpus.zip afl-testcases/bmp afl-testcases/gif* bugs/compress* $SRC/libjpeg-turbo/testimages/*.bmp $SRC/libjpeg-turbo/testimages/*.ppm
+RUN rm -rf seed-corpora
WORKDIR libjpeg-turbo
-COPY build.sh libjpeg_turbo_fuzzer.cc $SRC/
+RUN cp fuzz/build.sh $SRC/
diff --git a/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc b/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc
deleted file mode 100644
index 1b9ffd62f..000000000
--- a/projects/libjpeg-turbo/libjpeg_turbo_fuzzer.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-# 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 <stdint.h>
-#include <stdlib.h>
-
-#include <memory>
-
-#include <turbojpeg.h>
-
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- tjhandle jpegDecompressor = tjInitDecompress();
-
- int width, height, subsamp, colorspace;
- int res = tjDecompressHeader3(
- jpegDecompressor, data, size, &width, &height, &subsamp, &colorspace);
-
- // Bail out if decompressing the headers failed, the width or height is 0,
- // or the image is too large (avoids slowing down too much). Cast to size_t to
- // avoid overflows on the multiplication
- if (res != 0 || width == 0 || height == 0 || ((size_t)width * height > (1024 * 1024))) {
- tjDestroy(jpegDecompressor);
- return 0;
- }
-
- const int buffer_size = width * height * 3;
- std::unique_ptr<unsigned char[]> buf(new unsigned char[buffer_size]);
- tjDecompress2(
- jpegDecompressor, data, size, buf.get(), width, 0, height, TJPF_RGB, 0);
-
- // For memory sanitizer, test each output byte
- const unsigned char* raw_buf = buf.get();
- int count = 0;
- for( int i = 0; i < buffer_size; i++ )
- {
- if (raw_buf[i])
- {
- count ++;
- }
- }
- if (count == buffer_size)
- {
- // Do something with side effect, so that all the above tests don't
- // get removed by the optimizer.
- free(malloc(1));
- }
-
- tjDestroy(jpegDecompressor);
-
- return 0;
-}
diff --git a/projects/libjpeg-turbo/project.yaml b/projects/libjpeg-turbo/project.yaml
index 4ed2d5567..88d56ec28 100644
--- a/projects/libjpeg-turbo/project.yaml
+++ b/projects/libjpeg-turbo/project.yaml
@@ -1,5 +1,5 @@
-homepage: "https://github.com/libjpeg-turbo/libjpeg-turbo"
-language: c++
+homepage: "https://libjpeg-turbo.org"
+language: c
primary_contact: "drc@virtualgl.org"
vendor_ccs:
- "aosmond@mozilla.com"
diff --git a/projects/libjxl/Dockerfile b/projects/libjxl/Dockerfile
new file mode 100644
index 000000000..0d52e8809
--- /dev/null
+++ b/projects/libjxl/Dockerfile
@@ -0,0 +1,25 @@
+# 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
+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/highway third_party/lodepng third_party/skcms third_party/brotli
+
+WORKDIR libjxl
+COPY build.sh $SRC/
diff --git a/projects/libjxl/build.sh b/projects/libjxl/build.sh
new file mode 100755
index 000000000..091c55a6c
--- /dev/null
+++ b/projects/libjxl/build.sh
@@ -0,0 +1,73 @@
+#!/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
+ -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
+)
+
+# 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
+
+ mkdir -p ${WORK}/libjxl-corpus
+ cd ${WORK}/libjxl-corpus
+ cmake "${build_args[@]}" "${SRC}/libjxl"
+ ninja clean
+ ninja fuzzer_corpus
+
+ # Generate a fuzzer corpus.
+ mkdir -p djxl_fuzzer_corpus
+ tools/fuzzer_corpus -q -r djxl_fuzzer_corpus
+ zip -q -j "${OUT}/djxl_fuzzer_seed_corpus.zip" djxl_fuzzer_corpus/*
+)
+
+# Build the fuzzers in release mode but force the inclusion of JXL_DASSERT()
+# checks.
+export CXXFLAGS="${CXXFLAGS} -DJXL_IS_DEBUG_BUILD=1"
+
+mkdir -p ${WORK}/libjxl-fuzzer
+cd ${WORK}/libjxl-fuzzer
+cmake \
+ "${build_args[@]}" \
+ -DJPEGXL_FUZZER_LINK_FLAGS="${LIB_FUZZING_ENGINE}" \
+ "${SRC}/libjxl"
+
+fuzzers=(
+ color_encoding_fuzzer
+ djxl_fuzzer
+ fields_fuzzer
+ icc_codec_fuzzer
+ rans_fuzzer
+)
+
+ninja clean
+ninja "${fuzzers[@]}"
+for fuzzer in "${fuzzers[@]}"; do
+ cp tools/${fuzzer} "${OUT}/"
+done
diff --git a/projects/libjxl/project.yaml b/projects/libjxl/project.yaml
new file mode 100644
index 000000000..d3707f0a1
--- /dev/null
+++ b/projects/libjxl/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://github.com/libjxl/libjxl"
+language: c++
+primary_contact: "libjxl-security@google.com"
+auto_ccs:
+ - "deymo@google.com"
+ - "veluca@google.com"
+sanitizers:
+ - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+ - undefined
+main_repo: 'https://github.com/libjxl/libjxl.git' \ No newline at end of file
diff --git a/projects/libldac/project.yaml b/projects/libldac/project.yaml
index 189adf0bd..c850debe8 100644
--- a/projects/libldac/project.yaml
+++ b/projects/libldac/project.yaml
@@ -7,10 +7,12 @@ vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
fuzzing_engines:
- libfuzzer
- afl
diff --git a/projects/liblouis/Dockerfile b/projects/liblouis/Dockerfile
index 40a17c099..2d6649e44 100644
--- a/projects/liblouis/Dockerfile
+++ b/projects/liblouis/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool \
- pkg-config zlib1g-dev pciutils-dev libpci-dev
+ pkg-config zlib1g-dev libpci-dev
RUN git clone --depth 1 https://github.com/liblouis/liblouis
WORKDIR liblouis
COPY build.sh $SRC/
diff --git a/projects/libmpeg2/project.yaml b/projects/libmpeg2/project.yaml
index a3ec5d4ff..e88f915e4 100644
--- a/projects/libmpeg2/project.yaml
+++ b/projects/libmpeg2/project.yaml
@@ -12,10 +12,12 @@ vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
architectures:
- x86_64
- i386
diff --git a/projects/libpg_query/Dockerfile b/projects/libpg_query/Dockerfile
new file mode 100644
index 000000000..90f173b33
--- /dev/null
+++ b/projects/libpg_query/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 build.sh $SRC/
diff --git a/projects/libpg_query/build.sh b/projects/libpg_query/build.sh
new file mode 100755
index 000000000..0b5aa9f01
--- /dev/null
+++ b/projects/libpg_query/build.sh
@@ -0,0 +1,19 @@
+#!/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 $LIB_FUZZING_ENGINE ./test/fuzz/fuzz_parser.c ./libpg_query.a -I./ -o $OUT/fuzz_parser
diff --git a/projects/libpg_query/project.yaml b/projects/libpg_query/project.yaml
new file mode 100644
index 000000000..11d7e74c2
--- /dev/null
+++ b/projects/libpg_query/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://pganalyze.com/"
+language: c
+primary_contact: "team@pganalyze.com"
+main_repo: "https://github.com/pganalyze/pg_query"
+auto_ccs:
+ - "lukas@pganalyze.com"
+ - "david@adalogics.com"
diff --git a/projects/libphonenumber/Dockerfile b/projects/libphonenumber/Dockerfile
index c75d78c58..85f278ff3 100644
--- a/projects/libphonenumber/Dockerfile
+++ b/projects/libphonenumber/Dockerfile
@@ -15,12 +15,27 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake libtool g++ cmake-curses-gui libgtest-dev libre2-dev libicu-dev libboost-dev libboost-thread-dev libboost-system-dev binutils ninja-build liblzma-dev libz-dev pkg-config wget openjdk-8-jdk
-WORKDIR $SRC/
+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 apt-get install -y libgtest-dev && \
+ cd /usr/src/googletest/googletest && \
+ mkdir build && \
+ cd build && \
+ cmake .. && \
+ make && \
+ mkdir /usr/local/lib/googletest && \
+ ln -sn /usr/local/lib/googletest/libgtest.a /usr/lib/libgtest.a && \
+ ln -sn /usr/local/lib/googletest/libgtest_main.a /usr/lib/libgtest_main.a && \
+ rm /lib/x86_64-linux-gnu/libgtest.a && \
+ ln -sn /usr/local/lib/googletest/libgtest.a /lib/x86_64-linux-gnu/libgtest.a
+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/libphonenumber
-RUN wget https://github.com/unicode-org/icu/releases/download/release-55-2/icu4c-55_2-src.tgz && tar xzvf icu4c-55_2-src.tgz
-
COPY build.sh $SRC/
COPY phonefuzz.cc $SRC/
+WORKDIR $SRC/
diff --git a/projects/libphonenumber/build.sh b/projects/libphonenumber/build.sh
index ec67ec68e..768275e29 100755
--- a/projects/libphonenumber/build.sh
+++ b/projects/libphonenumber/build.sh
@@ -68,20 +68,18 @@ sed -i 's/set (BUILD_SHARED_LIB true)/set (BUILD_SHARED_LIB false)/g' CMakeLists
sed -i 's/list (APPEND CMAKE_C_FLAGS "-pthread")/string (APPEND CMAKE_C_FLAGS " -pthread")/g' CMakeLists.txt
mkdir build && cd build
-cmake -DUSE_BOOST=OFF -DBUILD_GEOCODER=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
+cmake -DUSE_BOOST=OFF -DBUILD_GEOCODER=OFF \
+ -DPROTOBUF_LIB="/src/protobuf/src/.libs/libprotobuf.a" \
+ -DBUILD_STATIC_LIB=ON \
-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 ../
+ -DICU_I18N_LIB=$DEPS_PATH/lib/libicui18n.a \
+ ../
make
-cd ../
# Build our fuzzer
-cp $SRC/*fuzz.cc .
-$CXX -I/src/libphonenumber/cpp/src $CXXFLAGS -o phonefuzz.o -c phonefuzz.cc
-
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE phonefuzz.o -o phonefuzz \
- build/libphonenumber.a $SRC/protobuf/src/.libs/libprotobuf.a \
+$CXX -I$SRC/libphonenumber/cpp/src $CXXFLAGS -o phonefuzz.o -c $SRC/phonefuzz.cc
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE phonefuzz.o -o $OUT/phonefuzz \
+ ./libphonenumber.a $SRC/protobuf/src/.libs/libprotobuf.a \
$DEPS_PATH/lib/libicu.a -lpthread
-
-cp phonefuzz $OUT/
diff --git a/projects/libpng/project.yaml b/projects/libpng/project.yaml
index 66b280b43..1e9d786a1 100644
--- a/projects/libpng/project.yaml
+++ b/projects/libpng/project.yaml
@@ -7,6 +7,7 @@ vendor_ccs:
- "twsmith@mozilla.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/glennrp/libpng.git'
+main_repo: 'https://github.com/glennrp/libpng.git' \ No newline at end of file
diff --git a/projects/libpsl/Dockerfile b/projects/libpsl/Dockerfile
index 303c5bba2..89dd36572 100644
--- a/projects/libpsl/Dockerfile
+++ b/projects/libpsl/Dockerfile
@@ -34,12 +34,8 @@ RUN apt-get update && apt-get install -y \
python
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 --depth=1 https://git.savannah.gnu.org/git/libunistring.git
-RUN git clone --depth=1 https://gitlab.com/libidn/libidn2.git && \
- rmdir libidn2/gnulib && ln -s $SRC/gnulib libidn2/gnulib
+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
diff --git a/projects/libpsl/build.sh b/projects/libpsl/build.sh
index 0dd93b532..8aba395c3 100755
--- a/projects/libpsl/build.sh
+++ b/projects/libpsl/build.sh
@@ -20,6 +20,9 @@ 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 \
@@ -30,29 +33,32 @@ CPPFLAGS="$CPPFLAGS -fno-sanitize=vptr" \
--disable-tests --disable-samples --with-data-packaging=static --prefix=$DEPS_PATH
# ugly hack to avoid build error
echo '#include <locale.h>' >>i18n/digitlst.h
-make -j$(nproc)
+
+# 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$(nproc)
+make -j
make install
cd $SRC/libidn
+./bootstrap
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
- make CFGFLAGS="--enable-static --disable-shared --disable-doc --prefix=$DEPS_PATH"
-make clean
-make -j1
-make -j$(nproc) check
+ ./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$(nproc)
+make -j
make install
@@ -82,8 +88,8 @@ for build in $builds; do
ASAN_OPTIONS=detect_leaks=0 UBSAN_OPTIONS=detect_leaks=0 \
./configure --enable-static --disable-shared --disable-gtk-doc $BUILD_FLAGS --prefix=$DEPS_PATH
make clean
- make -j$(nproc)
- make -j$(nproc) check
+ make -j
+ make -j check
make -C fuzz oss-fuzz
find fuzz -name '*_fuzzer' -exec cp -v '{}' $OUT ';'
done
diff --git a/projects/libra/Dockerfile b/projects/libra/Dockerfile
index 426e54792..cc541e3ac 100644
--- a/projects/libra/Dockerfile
+++ b/projects/libra/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
# google oss-fuzz stuff
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
# install other tools we might need
RUN apt-get update && apt-get install -y cmake curl
diff --git a/projects/librawspeed/Dockerfile b/projects/librawspeed/Dockerfile
index 54bb66d3a..a480f1542 100644
--- a/projects/librawspeed/Dockerfile
+++ b/projects/librawspeed/Dockerfile
@@ -18,7 +18,7 @@ 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/ xenial main' && \
+ 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
diff --git a/projects/libreoffice/Dockerfile b/projects/libreoffice/Dockerfile
index 6e8d21188..e6eeb4c65 100644
--- a/projects/libreoffice/Dockerfile
+++ b/projects/libreoffice/Dockerfile
@@ -20,156 +20,9 @@ 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
RUN apt-get install -y wget yasm locales && locale-gen en_US.UTF-8
-#xenial gperf too old
-RUN sed -i -e 's/xenial/bionic/g' /etc/apt/sources.list
-RUN apt-get update && apt-get install gperf
-#cache build dependencies
-ADD https://dev-www.libreoffice.org/src/c74b7223abe75949b4af367942d96c7a-crosextrafonts-carlito-20130920.tar.gz \
- https://dev-www.libreoffice.org/src/e7a384790b13c29113e22e596ade9687-LinLibertineG-20120116.zip \
- https://dev-www.libreoffice.org/src/Amiri-0.111.zip \
- https://dev-www.libreoffice.org/src/ReemKufi-0.7.zip \
- https://dev-www.libreoffice.org/src/edc4d741888bc0d38e32dbaa17149596-source-sans-pro-2.010R-ro-1.065R-it.tar.gz \
- https://dev-www.libreoffice.org/src/907d6e99f241876695c19ff3db0b8923-source-code-pro-2.030R-ro-1.050R-it.tar.gz \
- https://dev-www.libreoffice.org/src/134d8262145fc793c6af494dcace3e71-liberation-fonts-ttf-1.07.4.tar.gz \
- https://dev-www.libreoffice.org/src/1725634df4bb3dcb1b2c91a6175f8789-GentiumBasic_1102.zip \
- https://dev-www.libreoffice.org/src/33e1e61fab06a547851ed308b4ffef42-dejavu-fonts-ttf-2.37.zip \
- https://dev-www.libreoffice.org/src/368f114c078f94214a308a74c7e991bc-crosextrafonts-20130214.tar.gz \
- https://dev-www.libreoffice.org/src/5c781723a0d9ed6188960defba8e91cf-liberation-fonts-ttf-2.00.1.tar.gz \
- https://dev-www.libreoffice.org/extern/49a64f3bcf20a7909ba2751349231d6652ded9cd2840e961b5164d09de3ffa63-opens___.ttf \
- https://dev-www.libreoffice.org/src/noto-fonts-20171024.tar.gz \
- https://dev-www.libreoffice.org/src/amiri-0.109.zip \
- https://dev-www.libreoffice.org/src/ttf-kacst_2.01+mry.tar.gz \
- https://dev-www.libreoffice.org/src/ReemKufi-0.6.tar.gz \
- https://dev-www.libreoffice.org/src/Scheherazade-2.100.zip \
- https://dev-www.libreoffice.org/src/EmojiOneColor-SVGinOT-1.3.tar.gz \
- https://dev-www.libreoffice.org/src/culmus-0.131.tar.gz \
- https://dev-www.libreoffice.org/src/libre-hebrew-1.0.tar.gz \
- https://dev-www.libreoffice.org/src/alef-1.001.tar.gz \
- https://dev-www.libreoffice.org/src/a8c2c5b8f09e7ede322d5c602ff6a4b6-mythes-1.2.4.tar.gz \
- https://dev-www.libreoffice.org/src/5ade6ae2a99bc1e9e57031ca88d36dad-hyphen-2.8.8.tar.gz \
- https://dev-www.libreoffice.org/src/48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz \
- https://dev-www.libreoffice.org/src/boost_1_66_0.tar.bz2 \
- https://dev-www.libreoffice.org/src/expat-2.2.5.tar.bz2 \
- https://dev-www.libreoffice.org/src/libjpeg-turbo-1.5.2.tar.gz \
- https://dev-www.libreoffice.org/src/lcms2-2.8.tar.gz \
- https://dev-www.libreoffice.org/src/0168229624cfac409e766913506961a8-ucpp-1.3.2.tar.gz \
- https://dev-www.libreoffice.org/src/libexttextcat-3.4.5.tar.xz \
- https://dev-www.libreoffice.org/src/1f5def51ca0026cd192958ef07228b52-rasqal-0.9.33.tar.gz \
- https://dev-www.libreoffice.org/src/a39f6c07ddb20d7dd2ff1f95fa21e2cd-raptor2-2.0.15.tar.gz \
- https://dev-www.libreoffice.org/src/e5be03eda13ef68aabab6e42aa67715e-redland-1.0.17.tar.gz \
- https://dev-www.libreoffice.org/src/cppunit-1.14.0.tar.gz \
- https://dev-www.libreoffice.org/src/openldap-2.4.45.tgz \
- https://dev-www.libreoffice.org/src/neon-0.30.2.tar.gz \
- https://dev-www.libreoffice.org/src/e80ebae4da01e77f68744319f01d52a3-pixman-0.34.0.tar.gz \
- https://dev-www.libreoffice.org/src/cairo-1.15.12.tar.xz \
- https://dev-www.libreoffice.org/src/curl-7.60.0.tar.gz \
- https://dev-www.libreoffice.org/src/xmlsec1-1.2.26.tar.gz \
- https://dev-www.libreoffice.org/src/liblangtag-0.6.2.tar.bz2 \
- https://dev-www.libreoffice.org/src/libabw-0.1.2.tar.xz \
- https://dev-www.libreoffice.org/src/libcdr-0.1.4.tar.xz \
- https://dev-www.libreoffice.org/src/libcmis-0.5.1.tar.gz \
- https://dev-www.libreoffice.org/src/libe-book-0.1.3.tar.xz \
- https://dev-www.libreoffice.org/src/libetonyek-0.1.8.tar.xz \
- https://dev-www.libreoffice.org/src/libfreehand-0.1.2.tar.xz \
- https://dev-www.libreoffice.org/src/libmspub-0.1.4.tar.xz \
- https://dev-www.libreoffice.org/src/libmwaw-0.3.14.tar.xz \
- https://dev-www.libreoffice.org/src/libodfgen-0.1.6.tar.bz2 \
- https://dev-www.libreoffice.org/src/liborcus-0.13.4.tar.gz \
- https://dev-www.libreoffice.org/src/libpagemaker-0.0.4.tar.xz \
- https://dev-www.libreoffice.org/src/libpng-1.6.34.tar.xz \
- https://dev-www.libreoffice.org/src/librevenge-0.0.4.tar.bz2 \
- https://dev-www.libreoffice.org/src/libstaroffice-0.0.6.tar.xz \
- https://dev-www.libreoffice.org/src/libvisio-0.1.6.tar.xz \
- https://dev-www.libreoffice.org/src/libwpd-0.10.2.tar.xz \
- https://dev-www.libreoffice.org/src/libwpg-0.3.2.tar.xz \
- https://dev-www.libreoffice.org/src/libwps-0.4.10.tar.xz \
- https://dev-www.libreoffice.org/src/libzmf-0.0.2.tar.xz \
- https://dev-www.libreoffice.org/src/zlib-1.2.11.tar.xz \
- https://dev-www.libreoffice.org/src/poppler-0.66.0.tar.xz \
- https://dev-www.libreoffice.org/src/mdds-1.3.1.tar.bz2 \
- https://dev-www.libreoffice.org/src/openssl-1.0.2o.tar.gz \
- https://dev-www.libreoffice.org/src/language-subtag-registry-2018-04-23.tar.bz2 \
- https://dev-www.libreoffice.org/src/graphite2-minimal-1.3.10.tgz \
- https://dev-www.libreoffice.org/src/harfbuzz-1.8.4.tar.bz2 \
- https://dev-www.libreoffice.org/src/bae83fa5dc7f081768daace6e199adc3-glm-0.9.4.6-libreoffice.zip \
- https://dev-www.libreoffice.org/src/icu4c-62_1-src.tgz \
- https://dev-www.libreoffice.org/src/icu4c-62_1-data.zip \
- https://dev-www.libreoffice.org/src/libxml2-2.9.8.tar.gz \
- https://dev-www.libreoffice.org/src/libxslt-1.1.32.tar.gz \
- https://dev-www.libreoffice.org/src/hunspell-1.6.2.tar.gz \
- https://dev-www.libreoffice.org/src/lxml-4.1.1.tgz \
- https://dev-www.libreoffice.org/src/freetype-2.8.1.tar.bz2 \
- https://dev-www.libreoffice.org/src/fontconfig-2.12.6.tar.bz2 \
- https://dev-www.libreoffice.org/src/libepoxy-1.3.1.tar.bz2 \
- https://dev-www.libreoffice.org/src/gpgme-1.9.0.tar.bz2 \
- https://dev-www.libreoffice.org/src/libassuan-2.5.1.tar.bz2 \
- https://dev-www.libreoffice.org/src/libgpg-error-1.27.tar.bz2 \
- https://dev-www.libreoffice.org/src/libepubgen-0.1.1.tar.xz \
- https://dev-www.libreoffice.org/src/libnumbertext-1.0.4.tar.xz \
- https://dev-www.libreoffice.org/src/libqxp-0.0.1.tar.xz \
- https://dev-www.libreoffice.org/src/a233181e03d3c307668b4c722d881661-mariadb_client-2.0.0-src.tar.gz $SRC/
-#fuzzing dictionaries
-ADD https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/gif.dict \
- https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/jpeg.dict \
- https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/png.dict \
- https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/tiff.dict \
- https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/xml.dict \
- https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/html_tags.dict $SRC/
-#fuzzing corpuses
-ADD https://lcamtuf.coredump.cx/afl/demo/afl_testcases.tgz $SRC/
-RUN mkdir afl-testcases && cd afl-testcases/ && tar xf $SRC/afl_testcases.tgz && cd .. && \
- zip -q $SRC/jpgfuzzer_seed_corpus.zip afl-testcases/jpeg*/full/images/* && \
- zip -q $SRC/giffuzzer_seed_corpus.zip afl-testcases/gif*/full/images/* && \
- zip -q $SRC/bmpfuzzer_seed_corpus.zip afl-testcases/bmp*/full/images/* && \
- zip -q $SRC/pngfuzzer_seed_corpus.zip afl-testcases/png*/full/images/*
-RUN svn export https://github.com/khaledhosny/ots/trunk/tests/fonts $SRC/sample-sft-fonts/ots
-RUN svn export https://github.com/unicode-org/text-rendering-tests/trunk/fonts/ $SRC/sample-sft-fonts/unicode-org
-RUN svn export https://github.com/harfbuzz/harfbuzz/trunk/test/shaping/data/in-house/fonts $SRC/sample-sft-fonts/harfbuzz
-ADD https://github.com/adobe-fonts/adobe-variable-font-prototype/releases/download/1.001/AdobeVFPrototype.otf $SRC/sample-sft-fonts/adobe
-RUN zip -qr $SRC/sftfuzzer_seed_corpus.zip $SRC/sample-sft-fonts
-ADD https://dev-www.libreoffice.org/corpus/wmffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/xbmfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/xpmfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/svmfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/pcdfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/dxffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/metfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/ppmfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/psdfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/epsfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/pctfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/pcxfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/rasfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/tgafuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/tiffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/hwpfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/602fuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/lwpfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/pptfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/rtffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/olefuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/cgmfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/ww2fuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/ww6fuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/ww8fuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/qpwfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/slkfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/fodtfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/fodsfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/fodgfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/fodpfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/xlsfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/scrtffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/wksfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/diffuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/docxfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/xlsxfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/pptxfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/mmlfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/mtpfuzzer_seed_corpus.zip \
- https://dev-www.libreoffice.org/corpus/htmlfuzzer_seed_corpus.zip $SRC/
#clone source
-RUN git clone --depth 1 git://anongit.freedesktop.org/libreoffice/core libreoffice
+RUN git clone --depth 1 https://git.libreoffice.org/core libreoffice
WORKDIR libreoffice
+RUN ./bin/oss-fuzz-setup.sh
COPY build.sh $SRC/
diff --git a/projects/libreoffice/project.yaml b/projects/libreoffice/project.yaml
index bcf9a4fe6..43542a990 100644
--- a/projects/libreoffice/project.yaml
+++ b/projects/libreoffice/project.yaml
@@ -1,6 +1,16 @@
homepage: "https://www.libreoffice.org/"
language: c++
primary_contact: "caolanm@redhat.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:
- "officesecurity@lists.freedesktop.org"
- "damjan.jov@gmail.com"
diff --git a/projects/libressl/Dockerfile b/projects/libressl/Dockerfile
index 964569aaf..3861c8546 100644
--- a/projects/libressl/Dockerfile
+++ b/projects/libressl/Dockerfile
@@ -20,7 +20,7 @@ RUN git clone --depth 1 https://github.com/libressl-portable/portable.git libres
RUN git clone --depth 1 https://github.com/libressl-portable/fuzz.git libressl.fuzzers
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
WORKDIR libressl
RUN ./update.sh
COPY build.sh *.options $SRC/
diff --git a/projects/libressl/build.sh b/projects/libressl/build.sh
index 48cf9599c..5c639e63f 100755
--- a/projects/libressl/build.sh
+++ b/projects/libressl/build.sh
@@ -24,9 +24,6 @@ CFLAGS="" CXXFLAGS="" ./bootstrap.sh
CFLAGS="" CXXFLAGS="" ./b2 headers
cp -R boost/ /usr/include/
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
mkdir -p $WORK/libressl
cd $WORK/libressl
diff --git a/projects/libsass/project.yaml b/projects/libsass/project.yaml
index 7c1c2f365..fb5521b84 100644
--- a/projects/libsass/project.yaml
+++ b/projects/libsass/project.yaml
@@ -4,10 +4,11 @@ primary_contact: "xzyfer@gmail.com"
sanitizers:
- address
- - memory
+# 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'
+main_repo: 'https://github.com/sass/libsass.git' \ No newline at end of file
diff --git a/projects/libspectre/project.yaml b/projects/libspectre/project.yaml
index d98823235..8509ec6b0 100755
--- a/projects/libspectre/project.yaml
+++ b/projects/libspectre/project.yaml
@@ -7,10 +7,8 @@ fuzzing_engines:
- libfuzzer
- afl
- honggfuzz
- - dataflow
sanitizers:
- address
- undefined
- memory
- - dataflow
main_repo: 'https://gitlab.freedesktop.org/libspectre/libspectre.git'
diff --git a/projects/libssh/project.yaml b/projects/libssh/project.yaml
index 5c643216c..7cb24c4b9 100644
--- a/projects/libssh/project.yaml
+++ b/projects/libssh/project.yaml
@@ -7,6 +7,7 @@ auto_ccs:
- "anderson.sasaki@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://git.libssh.org/projects/libssh.git'
+main_repo: 'https://git.libssh.org/projects/libssh.git' \ No newline at end of file
diff --git a/projects/libssh2/build.sh b/projects/libssh2/build.sh
index decc46778..26bb4906c 100755
--- a/projects/libssh2/build.sh
+++ b/projects/libssh2/build.sh
@@ -15,5 +15,6 @@
#
################################################################################
+apt-get update
# Run the OSS-Fuzz script in the project.
./tests/ossfuzz/ossfuzz.sh
diff --git a/projects/libtasn1/project.yaml b/projects/libtasn1/project.yaml
index 9380ae94a..3490c8fb9 100644
--- a/projects/libtasn1/project.yaml
+++ b/projects/libtasn1/project.yaml
@@ -10,10 +10,8 @@ fuzzing_engines:
- afl
- libfuzzer
- honggfuzz
- - dataflow
sanitizers:
- address
- memory
- undefined
- - dataflow
main_repo: 'https://gitlab.com/gnutls/libtasn1.git'
diff --git a/projects/libtiff/project.yaml b/projects/libtiff/project.yaml
index 6c7666b48..000f9108f 100644
--- a/projects/libtiff/project.yaml
+++ b/projects/libtiff/project.yaml
@@ -5,9 +5,10 @@ auto_ccs:
- paul.l.kehrer@gmail.com
sanitizers:
- address
- - memory
+# 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'
+main_repo: 'https://gitlab.com/libtiff/libtiff' \ No newline at end of file
diff --git a/projects/libtpms/Dockerfile b/projects/libtpms/Dockerfile
index 50496fe6a..2f1800010 100644
--- a/projects/libtpms/Dockerfile
+++ b/projects/libtpms/Dockerfile
@@ -19,8 +19,8 @@ RUN \
apt-get update && \
apt-get install -y \
make autoconf automake libtool \
- libstdc++-5-dev \
- libssl-dev libseccomp-dev
+ libstdc++-9-dev \
+ libssl-dev libseccomp-dev pkg-config
RUN git clone --depth 1 https://github.com/stefanberger/libtpms libtpms
WORKDIR libtpms
COPY build.sh $SRC/
diff --git a/projects/libusb/libusb_fuzzer.cc b/projects/libusb/libusb_fuzzer.cc
index 8e543a725..ad6432112 100644
--- a/projects/libusb/libusb_fuzzer.cc
+++ b/projects/libusb/libusb_fuzzer.cc
@@ -21,29 +21,31 @@
#include "libusb/libusbi.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- struct libusb_transfer *transfer;
+ struct libusb_transfer *transfer = NULL;
FuzzedDataProvider stream(data, size);
uint8_t bmRequestType = stream.ConsumeIntegral<uint8_t>();
uint8_t bRequest = stream.ConsumeIntegral<uint8_t>();
uint16_t wValue = stream.ConsumeIntegral<uint16_t>();
uint16_t wIndex = stream.ConsumeIntegral<uint16_t>();
uint16_t wLength = stream.ConsumeIntegral<uint16_t>();
- std::vector<char> data_ = stream.ConsumeRemainingBytes<char>();
- unsigned char* buffer = reinterpret_cast<unsigned char*>(data_.data());
+ std::string input = stream.ConsumeRandomLengthString();
+ const char *d = input.c_str();
transfer = libusb_alloc_transfer(0);
if (!transfer) {
return LIBUSB_ERROR_NO_MEM;
}
- if (!buffer) {
- libusb_free_transfer(transfer);
- return LIBUSB_ERROR_NO_MEM;
- }
+ libusb_fill_control_setup((unsigned char *)d, bmRequestType, bRequest, wValue, wIndex, wLength);
- libusb_fill_control_setup(
- buffer, 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);
- libusb_free_transfer(transfer);
return 0;
}
diff --git a/projects/libvips/Dockerfile b/projects/libvips/Dockerfile
index e792dff45..378e6005b 100644
--- a/projects/libvips/Dockerfile
+++ b/projects/libvips/Dockerfile
@@ -16,29 +16,39 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y \
- curl \
automake \
+ autopoint \
cmake \
- nasm \
- gtk-doc-tools \
+ curl \
+ gettext \
+ glib2.0-dev \
gobject-introspection \
- libfftw3-dev \
+ gtk-doc-tools \
+ libbrotli-dev \
libexpat1-dev \
libffi-dev \
+ libfftw3-dev \
libselinux1-dev \
- glib2.0-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 git clone --depth 1 https://github.com/libvips/libvips
RUN git clone --depth 1 https://github.com/madler/zlib.git
RUN git clone --depth 1 https://github.com/libexif/libexif
+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
RUN git clone --depth 1 https://github.com/glennrp/libpng.git
-RUN git clone --depth 1 https://git.code.sf.net/p/giflib/code libgif
+RUN git clone --depth 1 https://github.com/randy408/libspng.git
RUN git clone --depth 1 https://chromium.googlesource.com/webm/libwebp
-RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff
+RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff
RUN git clone --depth 1 https://aomedia.googlesource.com/aom
RUN git clone --depth 1 https://github.com/strukturag/libheif
+RUN git clone --depth 1 --recursive 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
WORKDIR libvips
COPY build.sh $SRC/
diff --git a/projects/libvips/build.sh b/projects/libvips/build.sh
index 21505d6ed..17b496890 100755
--- a/projects/libvips/build.sh
+++ b/projects/libvips/build.sh
@@ -29,7 +29,8 @@ popd
pushd $SRC/libexif
autoreconf -fi
./configure \
- --enable-shared=no \
+ --enable-static \
+ --disable-shared \
--disable-docs \
--disable-dependency-tracking \
--prefix=$WORK
@@ -37,6 +38,18 @@ make -j$(nproc)
make install
popd
+# lcms
+pushd $SRC/lcms
+./autogen.sh
+./configure \
+ --enable-static \
+ --disable-shared \
+ --disable-dependency-tracking \
+ --prefix=$WORK
+make -j$(nproc)
+make install
+popd
+
# aom
pushd $SRC/aom
mkdir -p build/linux
@@ -45,7 +58,7 @@ cmake -G "Unix Makefiles" \
-DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX \
-DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
-DCMAKE_INSTALL_PREFIX=$WORK -DCMAKE_INSTALL_LIBDIR=lib \
- -DENABLE_SHARED:bool=off -DCONFIG_PIC=1 \
+ -DENABLE_SHARED=FALSE -DCONFIG_PIC=1 \
-DENABLE_EXAMPLES=0 -DENABLE_DOCS=0 -DENABLE_TESTS=0 \
-DCONFIG_SIZE_LIMIT=1 \
-DDECODE_HEIGHT_LIMIT=12288 -DDECODE_WIDTH_LIMIT=12288 \
@@ -66,7 +79,8 @@ autoreconf -fi
--enable-static \
--disable-examples \
--disable-go \
- --prefix=$WORK
+ --prefix=$WORK \
+ CPPFLAGS=-I$WORK/include
make clean
make -j$(nproc)
make install
@@ -74,14 +88,14 @@ popd
# libjpeg-turbo
pushd $SRC/libjpeg-turbo
-cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC:bool=on
+cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DENABLE_STATIC=TRUE -DENABLE_SHARED=FALSE -DWITH_TURBOJPEG=FALSE
make -j$(nproc)
make install
popd
# libpng
pushd $SRC/libpng
-sed -ie "s/option WARNING /option WARNING disabled/" scripts/pnglibconf.dfa
+sed -ie "s/option WARNING /& disabled/" scripts/pnglibconf.dfa
autoreconf -fi
./configure \
--prefix=$WORK \
@@ -91,9 +105,13 @@ make -j$(nproc)
make install
popd
-# libgif
-pushd $SRC/libgif
-make libgif.a libgif.so install-include install-lib OFLAGS="-O2" PREFIX=$WORK
+# libspng
+pushd $SRC/libspng
+cmake . -DCMAKE_INSTALL_PREFIX=$WORK -DSPNG_STATIC=TRUE -DSPNG_SHARED=FALSE -DZLIB_ROOT=$WORK
+make -j$(nproc)
+make install
+# Fix pkg-config file of libspng
+sed -i'.bak' "s/-lspng/&_static/" $WORK/lib/pkgconfig/libspng.pc
popd
# libwebp
@@ -127,9 +145,59 @@ make -j$(nproc)
make install
popd
+# jpeg-xl (libjxl)
+pushd $SRC/libjxl
+sed -i'.bak' "/add_subdirectory(tools)/d" CMakeLists.txt
+# Don't overwrite our linker flags
+sed -i'.bak' "/set(CMAKE_EXE_LINKER_FLAGS/{N;d;}" CMakeLists.txt
+cmake -G "Unix Makefiles" \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_C_COMPILER=$CC \
+ -DCMAKE_CXX_COMPILER=$CXX \
+ -DCMAKE_C_FLAGS="$CFLAGS" \
+ -DCMAKE_CXX_FLAGS="$CXXFLAGS" \
+ -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS" \
+ -DCMAKE_MODULE_LINKER_FLAGS="$LDFLAGS" \
+ -DCMAKE_INSTALL_PREFIX="$WORK" \
+ -DCMAKE_THREAD_LIBS_INIT="-lpthread" \
+ -DCMAKE_USE_PTHREADS_INIT=1 \
+ -DBUILD_SHARED_LIBS=0 \
+ -DBUILD_TESTING=0 \
+ -DJPEGXL_STATIC=1 \
+ -DJPEGXL_FORCE_SYSTEM_BROTLI=1 \
+ -DJPEGXL_ENABLE_FUZZERS=0 \
+ -DJPEGXL_ENABLE_MANPAGES=0 \
+ -DJPEGXL_ENABLE_BENCHMARK=0 \
+ -DJPEGXL_ENABLE_EXAMPLES=0 \
+ -DJPEGXL_ENABLE_SKCMS=0 \
+ -DJPEGXL_ENABLE_SJPEG=0 \
+ .
+make -j$(nproc)
+make install
+popd
+
+# libimagequant
+pushd $SRC/libimagequant
+meson setup --prefix=$WORK --libdir=lib --default-library=static build
+cd build
+ninja -j$(nproc)
+ninja install
+popd
+
+# cgif
+pushd $SRC/cgif
+meson setup --prefix=$WORK --libdir=lib --default-library=static build
+cd build
+ninja -j$(nproc)
+ninja install
+popd
+
# libvips
-./autogen.sh \
+sed -i'.bak' "/test/d" Makefile.am
+sed -i'.bak' "/tools/d" Makefile.am
+PKG_CONFIG="pkg-config --static" ./autogen.sh \
--disable-shared \
+ --disable-modules \
--disable-gtk-doc \
--disable-gtk-doc-html \
--disable-dependency-tracking \
@@ -156,20 +224,27 @@ for fuzzer in fuzz/*_fuzzer.cc; do
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
$WORK/lib/libvips.a \
$WORK/lib/libexif.a \
- $WORK/lib/libturbojpeg.a \
+ $WORK/lib/liblcms2.a \
+ $WORK/lib/libjpeg.a \
$WORK/lib/libpng.a \
+ $WORK/lib/libspng_static.a \
$WORK/lib/libz.a \
- $WORK/lib/libgif.a \
$WORK/lib/libwebpmux.a \
$WORK/lib/libwebpdemux.a \
$WORK/lib/libwebp.a \
$WORK/lib/libtiff.a \
$WORK/lib/libheif.a \
$WORK/lib/libaom.a \
+ $WORK/lib/libjxl.a \
+ $WORK/lib/libjxl_threads.a \
+ $WORK/lib/libhwy.a \
+ $WORK/lib/libimagequant.a \
+ $WORK/lib/libcgif.a \
$LIB_FUZZING_ENGINE \
-Wl,-Bstatic \
- -lfftw3 -lgmodule-2.0 -lgio-2.0 -lgobject-2.0 -lffi -lglib-2.0 -lpcre -lexpat \
- -lresolv -lsepol -lselinux \
+ -lfftw3 -lexpat -lbrotlienc -lbrotlidec -lbrotlicommon \
+ -lgmodule-2.0 -lgio-2.0 -lgobject-2.0 -lffi -lglib-2.0 \
+ -lresolv -lmount -lblkid -lselinux -lsepol -lpcre \
-Wl,-Bdynamic -pthread
ln -sf "seed_corpus.zip" "$OUT/${target}_seed_corpus.zip"
done
diff --git a/projects/libvips/project.yaml b/projects/libvips/project.yaml
index d4b27f81c..a00ccab31 100644
--- a/projects/libvips/project.yaml
+++ b/projects/libvips/project.yaml
@@ -2,7 +2,6 @@ homepage: "https://github.com/libvips/libvips"
language: c++
primary_contact: "jcupitt@gmail.com"
auto_ccs:
- - "oscar.mira@adevinta.com"
- "kleisauke@gmail.com"
- "lovell.fuller@gmail.com"
main_repo: 'https://github.com/libvips/libvips'
diff --git a/projects/libxml2/project.yaml b/projects/libxml2/project.yaml
index 873e81ee3..3b6abb925 100644
--- a/projects/libxml2/project.yaml
+++ b/projects/libxml2/project.yaml
@@ -1,6 +1,5 @@
homepage: "http://www.xmlsoft.org/"
language: c++
-primary_contact: "wellnhofer@aevum.de"
vendor_ccs:
- "akilsrin@apple.com"
- "ddkilzer@apple.com"
diff --git a/projects/libxslt/project.yaml b/projects/libxslt/project.yaml
index 09fc8306c..69e37c793 100644
--- a/projects/libxslt/project.yaml
+++ b/projects/libxslt/project.yaml
@@ -1,6 +1,5 @@
homepage: "http://www.xmlsoft.org/libxslt/"
language: c++
-primary_contact: "wellnhofer@aevum.de"
vendor_ccs:
- "ddkilzer@apple.com"
- "schenney@chromium.org"
diff --git a/projects/libyal/Dockerfile b/projects/libyal/Dockerfile
index c255806e9..3a2f067b4 100644
--- a/projects/libyal/Dockerfile
+++ b/projects/libyal/Dockerfile
@@ -21,6 +21,7 @@ RUN apt-get update && apt-get install -y make autoconf automake autopoint libtoo
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
@@ -49,11 +50,13 @@ 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/libluksde.git libluksde
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/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
diff --git a/projects/libyang/build.sh b/projects/libyang/build.sh
index cb5857dd8..9e1563216 100755
--- a/projects/libyang/build.sh
+++ b/projects/libyang/build.sh
@@ -16,7 +16,7 @@
################################################################################
cd libyang
-git checkout libyang2
+git checkout devel
sed -i 's/add_subdirectory/#add_subdirectory/g' ./tools/CMakeLists.txt
mkdir build && cd build
diff --git a/projects/libzip/project.yaml b/projects/libzip/project.yaml
index 2743d394f..916b01ad1 100644
--- a/projects/libzip/project.yaml
+++ b/projects/libzip/project.yaml
@@ -6,5 +6,6 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
-main_repo: 'https://github.com/nih-at/libzip.git'
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: 'https://github.com/nih-at/libzip.git' \ No newline at end of file
diff --git a/projects/lighttpd/build.sh b/projects/lighttpd/build.sh
index 5cd286a7b..33ef7dbb4 100755
--- a/projects/lighttpd/build.sh
+++ b/projects/lighttpd/build.sh
@@ -20,4 +20,4 @@
make
cd src
$CC $CFLAGS -c $SRC/fuzz_burl.c -I. -I../include
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_burl.o burl.o buffer.o base64.o -o $OUT/fuzz_burl
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_burl.o burl.o buffer.o base64.o ck.o -o $OUT/fuzz_burl
diff --git a/projects/linkerd2-proxy/Dockerfile b/projects/linkerd2-proxy/Dockerfile
new file mode 100644
index 000000000..1abb1d4f2
--- /dev/null
+++ b/projects/linkerd2-proxy/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/linkerd/linkerd2-proxy
+
+COPY build.sh $SRC/
+WORKDIR $SRC
diff --git a/projects/linkerd2-proxy/build.sh b/projects/linkerd2-proxy/build.sh
new file mode 100755
index 000000000..81044bcb0
--- /dev/null
+++ b/projects/linkerd2-proxy/build.sh
@@ -0,0 +1,48 @@
+#!/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.
+#
+################################################################################
+
+TARGET_PATH="./fuzz/target/x86_64-unknown-linux-gnu/release"
+BASE="$SRC/linkerd2-proxy/linkerd"
+BUILD_FUZZER="cargo +nightly fuzz build "
+
+cd ${BASE}/app/inbound
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_inbound
+
+cd ${BASE}/addr/
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_addr
+
+cd ${BASE}/dns
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_dns
+
+cd ${BASE}/proxy/http
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_http
+
+cd ${BASE}/tls
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_1 $OUT/fuzz_tls
+
+cd ${BASE}/transport-header
+${BUILD_FUZZER}
+cp ${TARGET_PATH}/fuzz_target_raw $OUT/fuzz_transport_raw
+cp ${TARGET_PATH}/fuzz_target_structured $OUT/fuzz_transport_structured
+
+echo "[libfuzzer]" > $OUT/fuzz_transport_raw.options
+echo "detect_leaks=0" >> $OUT/fuzz_transport_raw.options
diff --git a/projects/linkerd2-proxy/project.yaml b/projects/linkerd2-proxy/project.yaml
new file mode 100644
index 000000000..c7ce398ed
--- /dev/null
+++ b/projects/linkerd2-proxy/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://linkerd.io/"
+main_repo: "https://github.com/linkerd/linkerd2-proxy"
+primary_contact: "ver@buoyant.io"
+sanitizers:
+ - address
+fuzzing_engines:
+ - libfuzzer
+language: rust
+auto_ccs:
+ - "eliza@buoyant.io"
+ - "kevinl@buoyant.io"
+ - "david@adalogics.com"
diff --git a/projects/lldb-eval/Dockerfile b/projects/lldb-eval/Dockerfile
new file mode 100644
index 000000000..dc61ec34d
--- /dev/null
+++ b/projects/lldb-eval/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 git patchelf zlib1g-dev python libtinfo-dev --no-install-recommends
+
+RUN git clone --depth 1 https://github.com/google/lldb-eval
+
+COPY build.sh $SRC/
+COPY lldb_vs_lldb_eval_libfuzzer_test.options $SRC/
+
+WORKDIR $SRC/lldb-eval
diff --git a/projects/lldb-eval/build.sh b/projects/lldb-eval/build.sh
new file mode 100644
index 000000000..dee5c7cfe
--- /dev/null
+++ b/projects/lldb-eval/build.sh
@@ -0,0 +1,93 @@
+#!/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.
+#
+################################################################################
+
+(
+cd $SRC/
+GITHUB_RELEASE="https://github.com/google/lldb-eval/releases/download/oss-fuzz-ubuntu-20.04"
+
+if [ "$SANITIZER" = "address" ]
+then
+ LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release-address.tar.gz"
+elif [ "$SANITIZER" = "memory" ]
+then
+ LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release-memory.tar.gz"
+elif [ "$SANITIZER" = "undefined" ]
+then
+ LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release.tar.gz"
+elif [ "$SANITIZER" = "coverage" ]
+then
+ # For coverage we also need the original source code.
+ wget --quiet $GITHUB_RELEASE/llvm-12.0.1-source.tar.gz
+ tar -xzf llvm-12.0.1-source.tar.gz
+ wget --quiet $GITHUB_RELEASE/llvm-12.0.1-x86_64-linux-release-genfiles.tar.gz
+ tar -xzf llvm-12.0.1-x86_64-linux-release-genfiles.tar.gz
+
+ LLVM_ARCHIVE="llvm-12.0.1-x86_64-linux-release.tar.gz"
+else
+ echo "Unknown sanitizer: $SANITIZER"
+ exit 1
+fi
+
+wget --quiet $GITHUB_RELEASE/$LLVM_ARCHIVE
+mkdir -p llvm && tar -xzf $LLVM_ARCHIVE --strip-components 1 -C llvm
+)
+export LLVM_INSTALL_PATH=$SRC/llvm
+
+if [ "$SANITIZER" = "undefined" ]
+then
+ # Disable vptr because it's not allowed with '-fno-rtti'
+ CFLAGS="$CFLAGS -fno-sanitize=function,vptr"
+ CXXFLAGS="$CXXFLAGS -fno-sanitize=function,vptr"
+fi
+
+# Undefine NDEBUG to enable asserts.
+export BAZEL_EXTRA_BUILD_FLAGS="--copt=-UNDEBUG"
+
+# Run the build!
+bazel_build_fuzz_tests
+
+# OSS-Fuzz rule doesn't build data dependencies
+bazel build //testdata:fuzzer_binary_gen
+
+# OSS-Fuzz rule doesn't handle dynamic dependencies
+# Copy liblldb.so
+mkdir -p $OUT/lib
+cp $SRC/llvm/lib/liblldb.so* $OUT/lib
+
+# List of targets to fuzz.
+TARGETS=(
+ lldb_eval_libfuzzer_test
+ lldb_vs_lldb_eval_libfuzzer_test
+)
+
+# Preparation of each target.
+for target in ${TARGETS[@]}; do
+ # OSS-Fuzz rule doesn't package runfiles yet:
+ # https://github.com/bazelbuild/rules_fuzzing/issues/100
+ mkdir -p $OUT/$target.runfiles
+ # fuzzer_binary
+ mkdir -p $OUT/$target.runfiles/lldb_eval/testdata
+ cp $SRC/lldb-eval/bazel-bin/testdata/fuzzer_binary $OUT/$target.runfiles/lldb_eval/testdata/
+ cp $SRC/lldb-eval/testdata/fuzzer_binary.cc $OUT/$target.runfiles/lldb_eval/testdata/
+ # lldb-server
+ mkdir -p $OUT/$target.runfiles/llvm_project/bin
+ cp $SRC/llvm/bin/lldb-server $OUT/$target.runfiles/llvm_project/bin/lldb-server
+ # Patch RPATH of the fuzz target
+ patchelf --set-rpath '$ORIGIN/lib' $OUT/$target
+done
+
+cp $SRC/lldb_vs_lldb_eval_libfuzzer_test.options $OUT/
diff --git a/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options b/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options
new file mode 100644
index 000000000..f9d09656c
--- /dev/null
+++ b/projects/lldb-eval/lldb_vs_lldb_eval_libfuzzer_test.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/lldb-eval/project.yaml b/projects/lldb-eval/project.yaml
new file mode 100644
index 000000000..8568e7522
--- /dev/null
+++ b/projects/lldb-eval/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/google/lldb-eval"
+main_repo: "https://github.com/google/lldb-eval"
+language: c++
+primary_contact: "werat@google.com"
+auto_ccs:
+ - "tsabolcec@google.com"
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+ - undefined
diff --git a/projects/llhttp/Dockerfile b/projects/llhttp/Dockerfile
new file mode 100644
index 000000000..c7ab95889
--- /dev/null
+++ b/projects/llhttp/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
+RUN bash nodesource_setup.sh
+RUN apt install -y nodejs
+RUN git clone --depth 1 https://github.com/nodejs/llhttp llhttp
+WORKDIR llhttp
+COPY build.sh $SRC/
diff --git a/projects/llhttp/build.sh b/projects/llhttp/build.sh
new file mode 100755
index 000000000..a9a3a48f3
--- /dev/null
+++ b/projects/llhttp/build.sh
@@ -0,0 +1,23 @@
+#!/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.
+#
+################################################################################
+
+npm install -g typescript
+npm link typescript
+npm install .
+make
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./test/fuzzers/fuzz_parser.c -I./build/ ./build/libllhttp.a -o $OUT/fuzz_parser
diff --git a/projects/llhttp/project.yaml b/projects/llhttp/project.yaml
new file mode 100644
index 000000000..dda736aae
--- /dev/null
+++ b/projects/llhttp/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://llhttp.org/"
+main_repo: "https://github.com/nodejs/llhttp"
+language: c
+primary_contact: "fedor@indutny.com"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/loki/Dockerfile b/projects/loki/Dockerfile
index 2340618ec..b045f7972 100644
--- a/projects/loki/Dockerfile
+++ b/projects/loki/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/grafana/loki/
COPY build.sh $SRC/
WORKDIR $SRC/loki
diff --git a/projects/lotus/Dockerfile b/projects/lotus/Dockerfile
index 08dccff6a..bdbee4371 100644
--- a/projects/lotus/Dockerfile
+++ b/projects/lotus/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-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 mesa-opencl-icd ocl-icd-opencl-dev gcc \
git bzr jq pkg-config curl clang build-essential hwloc libhwloc-dev
RUN git clone --depth 1 https://github.com/filecoin-project/lotus
diff --git a/projects/matio/Dockerfile b/projects/matio/Dockerfile
index d69281cb8..1b8e927ea 100644
--- a/projects/matio/Dockerfile
+++ b/projects/matio/Dockerfile
@@ -18,6 +18,6 @@ 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/madler/zlib
RUN git clone --depth 1 git://git.code.sf.net/p/matio/matio matio
-ADD https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.0/src/hdf5-1.12.0.tar.gz hdf5-1.12.0.tar.gz
+ADD https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.12/hdf5-1.12.1/src/hdf5-1.12.1.tar.gz hdf5-1.12.1.tar.gz
WORKDIR matio
COPY build.sh $SRC/
diff --git a/projects/mbedtls/Dockerfile b/projects/mbedtls/Dockerfile
index 3a8908f94..f39ea2abb 100644
--- a/projects/mbedtls/Dockerfile
+++ b/projects/mbedtls/Dockerfile
@@ -17,7 +17,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
#TODO change
RUN apt-get update && apt-get install -y make cmake
-RUN git clone --recursive --depth 1 https://github.com/ARMmbed/mbedtls.git mbedtls
+RUN git clone --recursive --depth 1 -b development_2.x https://github.com/ARMmbed/mbedtls.git mbedtls
RUN git clone --depth 1 https://github.com/google/boringssl.git boringssl
RUN git clone --depth 1 https://github.com/openssl/openssl.git openssl
WORKDIR mbedtls
diff --git a/projects/mdbtools/build.sh b/projects/mdbtools/build.sh
index d3269bc62..048d4a176 100644
--- a/projects/mdbtools/build.sh
+++ b/projects/mdbtools/build.sh
@@ -17,7 +17,7 @@
################################################################################
autoreconf -f -i
-./configure --enable-static --disable-man --disable-glib
+./configure --enable-static --disable-man --disable-glib --disable-silent-rules
make clean
make
diff --git a/projects/mercurial/project.yaml b/projects/mercurial/project.yaml
index 2908b04b4..09674b145 100644
--- a/projects/mercurial/project.yaml
+++ b/projects/mercurial/project.yaml
@@ -6,8 +6,11 @@ auto_ccs:
- "kbullock@ringworld.org"
- "security@mercurial-scm.org"
- "martinvonz@google.com"
+ - "raphael.gomes@octobus.net"
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
coverage_extra_args: -ignore-filename-regex=.*/sanpy/.*
+main_repo: "https://www.mercurial-scm.org/repo/hg"
diff --git a/projects/minify/Dockerfile b/projects/minify/Dockerfile
index 3f3516ae5..20d75ad61 100644
--- a/projects/minify/Dockerfile
+++ b/projects/minify/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/tdewolff/minify
RUN git clone --depth 1 https://github.com/tdewolff/parse
COPY build.sh $SRC/
diff --git a/projects/monero/Dockerfile b/projects/monero/Dockerfile
index fe2dbbe91..d8f361983 100644
--- a/projects/monero/Dockerfile
+++ b/projects/monero/Dockerfile
@@ -44,7 +44,8 @@ RUN set -ex && \
libreadline-dev \
libudev-dev \
libprotobuf-dev \
- protobuf-compiler
+ protobuf-compiler \
+ libexpat-dev
WORKDIR monero
@@ -117,5 +118,8 @@ RUN set -ex \
&& make \
&& make install
+RUN git clone https://github.com/NLnetLabs/unbound && \
+ cd unbound && ./configure && make && make install
+
RUN git clone --depth 1 https://github.com/monero-project/monero.git monero
COPY build.sh $SRC/
diff --git a/projects/mp4parse-rust/Dockerfile b/projects/mp4parse-rust/Dockerfile
index 990fbbafa..f974759f4 100644
--- a/projects/mp4parse-rust/Dockerfile
+++ b/projects/mp4parse-rust/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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 --depth 1 --recursive https://github.com/mozilla/mp4parse-rust mp4parse-rust
diff --git a/projects/msgpack-c/Dockerfile b/projects/msgpack-c/Dockerfile
index 87efd7640..385767b2f 100644
--- a/projects/msgpack-c/Dockerfile
+++ b/projects/msgpack-c/Dockerfile
@@ -18,7 +18,7 @@ FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y cmake wget bzip2
RUN git clone --depth 1 --single-branch --branch cpp_master https://github.com/msgpack/msgpack-c.git msgpack-c
-RUN wget https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.bz2 && \
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.70.0/source/boost_1_70_0.tar.bz2 && \
tar xf boost_1_70_0.tar.bz2 && \
cd boost_1_70_0 && \
./bootstrap.sh --with-toolset=clang --prefix=/usr && \
diff --git a/projects/mtail/Dockerfile b/projects/mtail/Dockerfile
index 7861cbcd5..b61263a5c 100644
--- a/projects/mtail/Dockerfile
+++ b/projects/mtail/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/google/mtail $GOPATH/src/github.com/google/mtail
WORKDIR $GOPATH/src/github.com/google/mtail
COPY build.sh $SRC/
diff --git a/projects/mtail/build.sh b/projects/mtail/build.sh
index 2c769ad33..9e6eff2e3 100755
--- a/projects/mtail/build.sh
+++ b/projects/mtail/build.sh
@@ -15,6 +15,6 @@
#
################################################################################
-compile_go_fuzzer github.com/google/mtail/internal/vm Fuzz vm-fuzzer
+compile_go_fuzzer github.com/google/mtail/internal/runtime Fuzz vm-fuzzer
# Make the dictionary and seed corpus.
make --debug $OUT/vm-fuzzer.dict $OUT/vm-fuzzer_seed_corpus.zip
diff --git a/projects/muduo/Dockerfile b/projects/muduo/Dockerfile
new file mode 100644
index 000000000..d8ba22346
--- /dev/null
+++ b/projects/muduo/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libboost-dev
+RUN git clone --depth 1 https://github.com/chenshuo/muduo
+WORKDIR muduo
+COPY build.sh muduo_http_fuzzer.cpp $SRC/
diff --git a/projects/muduo/build.sh b/projects/muduo/build.sh
new file mode 100755
index 000000000..023146ec7
--- /dev/null
+++ b/projects/muduo/build.sh
@@ -0,0 +1,33 @@
+#!/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 '34 a $ENV{CXXFLAGS}' CMakeLists.txt
+mkdir -p build-dir && cd build-dir
+cmake -DCMAKE_BUILD_TYPE="release" \
+ ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -I/src/muduo \
+ -o muduo_http_fuzzer.o \
+ -c $SRC/muduo_http_fuzzer.cpp
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+ muduo_http_fuzzer.o \
+ -o $OUT/muduo_http_fuzzer \
+ ./lib/libmuduo_http.a \
+ ./lib/libmuduo_net.a \
+ ./lib/libmuduo_base.a
diff --git a/projects/muduo/muduo_http_fuzzer.cpp b/projects/muduo/muduo_http_fuzzer.cpp
new file mode 100644
index 000000000..d3eed6a23
--- /dev/null
+++ b/projects/muduo/muduo_http_fuzzer.cpp
@@ -0,0 +1,35 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "muduo/net/http/HttpContext.h"
+#include "muduo/net/Buffer.h"
+#include "muduo/base/Timestamp.h"
+
+extern "C" 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';
+
+ muduo::net::HttpContext context;
+ muduo::net::Buffer input;
+ input.append(new_str);
+ context.parseRequest(&input, muduo::Timestamp::now());
+ free(new_str);
+ return 0;
+}
diff --git a/projects/muduo/project.yaml b/projects/muduo/project.yaml
new file mode 100644
index 000000000..0a2249949
--- /dev/null
+++ b/projects/muduo/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/chenshuo/muduo"
+language: c++
+primary_contact: "chenshuo@chenshuo.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+main_repo: "https://github.com/chenshuo/muduo"
diff --git a/projects/mupdf/Dockerfile b/projects/mupdf/Dockerfile
index 160ce0ee9..8d1668ed3 100644
--- a/projects/mupdf/Dockerfile
+++ b/projects/mupdf/Dockerfile
@@ -22,5 +22,5 @@ RUN git clone --depth 1 https://github.com/mozilla/pdf.js pdf.js && \
rm -rf pdf.js
ADD https://raw.githubusercontent.com/rc0r/afl-fuzz/master/dictionaries/pdf.dict $SRC/pdf_fuzzer.dict
WORKDIR mupdf
-COPY *.cc source/fuzz/
+COPY *.cc $SRC/
COPY build.sh *.options $SRC/
diff --git a/projects/mupdf/build.sh b/projects/mupdf/build.sh
index d06190698..6a2613c4f 100755
--- a/projects/mupdf/build.sh
+++ b/projects/mupdf/build.sh
@@ -15,11 +15,14 @@
#
################################################################################
+# supp_size is unused in harfbuzz so we will avoid it being unused.
+sed -i 's/supp_size;/supp_size;(void)(supp_size);/g' ./thirdparty/harfbuzz/src/hb-subset-cff1.cc
+
LDFLAGS="$CXXFLAGS" make -j$(nproc) HAVE_GLUT=no build=debug OUT=$WORK
fuzz_target=pdf_fuzzer
$CXX $CXXFLAGS -std=c++11 -Iinclude \
- source/fuzz/pdf_fuzzer.cc -o $OUT/$fuzz_target \
+ $SRC/pdf_fuzzer.cc -o $OUT/$fuzz_target \
$LIB_FUZZING_ENGINE $WORK/libmupdf.a $WORK/libmupdf-third.a
mv $SRC/{*.zip,*.dict,*.options} $OUT
diff --git a/projects/myanmar-tools/build.sh b/projects/myanmar-tools/build.sh
index 771601bfc..e13632297 100644
--- a/projects/myanmar-tools/build.sh
+++ b/projects/myanmar-tools/build.sh
@@ -1,16 +1,19 @@
+#!/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
#
-# https://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT 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/myanmar-tools/clients/cpp
mkdir build
@@ -30,7 +33,7 @@ cp libmyanmartools.so $OUT/lib
# Copy libunwind since it isn't on the ClusterFuzz bot images.
cp /usr/lib/x86_64-linux-gnu/libunwind.so.8 $OUT/lib/
$CXX $CXXFLAGS -std=c++11 -I../public -L$OUT/lib \
- -Wl,-rpath,'$ORIGIN/lib' -lmyanmartools \
+ -Wl,-rpath,'$ORIGIN/lib' -lmyanmartools -lunwind \
-o $OUT/zawgyi_detector_fuzz_target \
../zawgyi_detector_fuzz_target.cpp \
$LIB_FUZZING_ENGINE
diff --git a/projects/myanmar-tools/project.yaml b/projects/myanmar-tools/project.yaml
index d2c7f3256..5d583adff 100644
--- a/projects/myanmar-tools/project.yaml
+++ b/projects/myanmar-tools/project.yaml
@@ -5,6 +5,7 @@ auto_ccs:
- "ccornelius@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
coverage_extra_args: -ignore-filename-regex=.*/\.hunter/.*
main_repo: 'https://github.com/google/myanmar-tools.git'
diff --git a/projects/mysql-server/build.sh b/projects/mysql-server/build.sh
index 6ea7b2712..ee4dfd0fe 100644
--- a/projects/mysql-server/build.sh
+++ b/projects/mysql-server/build.sh
@@ -25,7 +25,7 @@ if [[ $SANITIZER = *undefined* ]]; then
else
cmake .. -Dprotobuf_BUILD_SHARED_LIBS=OFF -DDOWNLOAD_BOOST=1 -DWITH_BOOST=. -DWITH_SSL=system -DFUZZING=1 -DCMAKE_INSTALL_PREFIX=$OUT/mysql
fi
-make install
+make -j$(nproc) install
mv $OUT/mysql/bin/fuzz* $OUT/
cp ../fuzz/fuzz*.options $OUT/
cp ../fuzz/fuzz*.dict $OUT/
diff --git a/projects/mysql-server/fix.diff b/projects/mysql-server/fix.diff
index cec23c2d2..b8f7825bd 100644
--- a/projects/mysql-server/fix.diff
+++ b/projects/mysql-server/fix.diff
@@ -1,8 +1,8 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 3667900243c..337344e124d 100644
+index 4a4bbfa72fa..0478561e66c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -597,6 +597,7 @@ IF(WITH_JEMALLOC AND (WITH_TCMALLOC OR WITH_TCMALLOC_DEBUG))
+@@ -688,6 +688,7 @@ IF(WITH_JEMALLOC AND (WITH_TCMALLOC OR WITH_TCMALLOC_DEBUG))
MESSAGE(FATAL_ERROR "Specify only *one* of WITH_TCMALLOC and WITH_JEMALLOC")
ENDIF()
@@ -10,8 +10,8 @@ index 3667900243c..337344e124d 100644
OPTION(ENABLED_PROFILING "Enable profiling" ON)
OPTION(WITHOUT_SERVER OFF)
-@@ -1587,6 +1588,10 @@ IF(NOT WITHOUT_SERVER AND WITH_UNIT_TESTS)
- TARGET_LINK_LIBRARIES(server_unittest_library ${ICU_LIBRARIES})
+@@ -1804,6 +1805,10 @@ IF(NOT WITHOUT_SERVER AND WITH_UNIT_TESTS)
+ ENDIF()
ENDIF()
+IF (FUZZING)
@@ -21,8 +21,22 @@ index 3667900243c..337344e124d 100644
# scripts/mysql_config depends on client and server targets loaded above.
# It is referenced by some of the directories below, so we insert it here.
ADD_SUBDIRECTORY(scripts)
+diff --git a/cmake/os/Linux.cmake b/cmake/os/Linux.cmake
+index 0e25e8eb..3ae74839 100644
+--- a/cmake/os/Linux.cmake
++++ b/cmake/os/Linux.cmake
+@@ -103,7 +103,8 @@ IF(NOT WITH_ASAN AND
+ NOT WITH_LSAN AND
+ NOT WITH_MSAN AND
+ NOT WITH_TSAN AND
+- NOT WITH_UBSAN)
++ NOT WITH_UBSAN AND
++ NOT FUZZING)
+ SET(LINK_FLAG_NO_UNDEFINED "-Wl,--no-undefined")
+ SET(LINK_FLAG_Z_DEFS "-z,defs")
+ ENDIF()
diff --git a/include/mysql.h b/include/mysql.h
-index b805bffdf88..23d2311299e 100644
+index 4700d74b853..bdf9b765ffb 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -262,7 +262,8 @@ enum mysql_protocol_type {
@@ -36,10 +50,10 @@ index b805bffdf88..23d2311299e 100644
enum mysql_ssl_mode {
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
-index ce785802ad9..4f048082335 100644
+index 39ebd0fcb93..c041cc4690f 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
-@@ -485,7 +485,8 @@ enum mysql_protocol_type {
+@@ -486,7 +486,8 @@ enum mysql_protocol_type {
MYSQL_PROTOCOL_TCP,
MYSQL_PROTOCOL_SOCKET,
MYSQL_PROTOCOL_PIPE,
@@ -50,7 +64,7 @@ index ce785802ad9..4f048082335 100644
enum mysql_ssl_mode {
SSL_MODE_DISABLED = 1,
diff --git a/include/violite.h b/include/violite.h
-index c04e82505a7..2498ba0053c 100644
+index a6ccd1a607d..8dc0d46dd7f 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -108,12 +108,14 @@ enum enum_vio_type : int {
@@ -91,13 +105,13 @@ index c04e82505a7..2498ba0053c 100644
+
#endif /* vio_violite_h_ */
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
-index 4956a0dc2d8..bab0aa3b504 100644
+index 334d1b7d3ef..c37c5ad930e 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
-@@ -353,11 +353,11 @@ IF(UNIX)
-
- ADD_INSTALL_RPATH_FOR_OPENSSL(libmysql)
+@@ -345,11 +345,11 @@ IF(LINUX_STANDALONE AND KERBEROS_CUSTOM_LIBRARY)
+ ENDIF()
+ IF(UNIX)
- IF(LINK_FLAG_Z_DEFS)
+ IF(LINK_FLAG_Z_DEFS AND NOT FUZZING)
MY_TARGET_LINK_OPTIONS(libmysql "LINKER:${LINK_FLAG_Z_DEFS}")
@@ -105,23 +119,11 @@ index 4956a0dc2d8..bab0aa3b504 100644
- IF(LINUX)
+ IF(LINUX AND NOT FUZZING)
+ CONFIGURE_FILE(libmysql.ver.in ${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver)
MY_TARGET_LINK_OPTIONS(libmysql
"LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/libmysql.ver")
- ENDIF()
-diff --git a/mysys/mf_tempfile.cc b/mysys/mf_tempfile.cc
-index f4f5dffba9a..26ab2ce0917 100644
---- a/mysys/mf_tempfile.cc
-+++ b/mysys/mf_tempfile.cc
-@@ -320,6 +320,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
- set_my_errno(ENAMETOOLONG);
- return file;
- }
-+ sprintf(prefix_buff, "%sXXXXXX", prefix ? prefix : "tmp.");
- my_stpcpy(convert_dirname(to, dir, NullS), prefix_buff);
- file = mkstemp(to);
- file_info::RegisterFilename(file, to, file_info::OpenType::FILE_BY_MKSTEMP);
diff --git a/mysys/my_rnd.cc b/mysys/my_rnd.cc
-index 8253e3967d4..034c71de600 100644
+index 2fc7820eaa3..248ea909db8 100644
--- a/mysys/my_rnd.cc
+++ b/mysys/my_rnd.cc
@@ -48,6 +48,9 @@
@@ -158,10 +160,10 @@ index 8253e3967d4..034c71de600 100644
*failed = true;
return 0;
diff --git a/sql-common/client.cc b/sql-common/client.cc
-index 61404be555b..721802cb60c 100644
+index b8050f2b1a7..9a65178c5c4 100644
--- a/sql-common/client.cc
+++ b/sql-common/client.cc
-@@ -5774,6 +5774,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) {
+@@ -5892,6 +5892,12 @@ static mysql_state_machine_status csm_begin_connect(mysql_async_connect *ctx) {
}
}
#endif /* _WIN32 */
@@ -175,12 +177,12 @@ index 61404be555b..721802cb60c 100644
if (!net->vio &&
(!mysql->options.protocol ||
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
-index 519926135ed..db75dc7f5e5 100644
+index 50b76e2fa75..871006c2d8f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
-@@ -6862,7 +6862,9 @@ int mysqld_main(int argc, char **argv)
- unireg_abort(MYSQLD_ABORT_EXIT); // Will do exit
- }
+@@ -6991,7 +6991,9 @@ int mysqld_main(int argc, char **argv)
+
+ keyring_lockable_init();
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
my_init_signals();
@@ -188,7 +190,7 @@ index 519926135ed..db75dc7f5e5 100644
size_t guardize = 0;
#ifndef _WIN32
-@@ -7347,8 +7349,10 @@ int mysqld_main(int argc, char **argv)
+@@ -7497,8 +7499,10 @@ int mysqld_main(int argc, char **argv)
unireg_abort(MYSQLD_ABORT_EXIT);
#ifndef _WIN32
@@ -199,7 +201,7 @@ index 519926135ed..db75dc7f5e5 100644
#endif
/* set all persistent options */
-@@ -7393,8 +7397,9 @@ int mysqld_main(int argc, char **argv)
+@@ -7543,8 +7547,9 @@ int mysqld_main(int argc, char **argv)
}
start_handle_manager();
@@ -210,7 +212,7 @@ index 519926135ed..db75dc7f5e5 100644
LogEvent()
.type(LOG_TYPE_ERROR)
-@@ -7441,6 +7446,10 @@ int mysqld_main(int argc, char **argv)
+@@ -7591,6 +7596,10 @@ int mysqld_main(int argc, char **argv)
(void)RUN_HOOK(server_state, before_handle_connection, (nullptr));
@@ -221,7 +223,7 @@ index 519926135ed..db75dc7f5e5 100644
#if defined(_WIN32)
if (mysqld_socket_acceptor != nullptr)
mysqld_socket_acceptor->check_and_spawn_admin_connection_handler_thread();
-@@ -10281,6 +10290,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) {
+@@ -10500,6 +10509,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) {
if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT;
@@ -232,10 +234,10 @@ index 519926135ed..db75dc7f5e5 100644
LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM);
return 1;
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
-index fba0684f322..8352dacbc03 100644
+index 7ecc10961ac..5f13f94eb02 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
-@@ -1487,18 +1487,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) {
+@@ -1476,18 +1476,14 @@ dberr_t buf_pool_init(ulint total_size, ulint n_instances) {
n = n_instances;
}
@@ -257,7 +259,7 @@ index fba0684f322..8352dacbc03 100644
err = errs[id];
}
diff --git a/vio/CMakeLists.txt b/vio/CMakeLists.txt
-index d44eebce63a..975bc878e17 100644
+index 35ab5f17f15..9b39bfdbdbf 100644
--- a/vio/CMakeLists.txt
+++ b/vio/CMakeLists.txt
@@ -27,6 +27,7 @@ SET(VIO_SOURCES
@@ -269,7 +271,7 @@ index d44eebce63a..975bc878e17 100644
IF(WIN32)
diff --git a/vio/vio.cc b/vio/vio.cc
-index 38e3d90f20e..abbc9a52478 100644
+index 368c8d7b581..50c3231a8b0 100644
--- a/vio/vio.cc
+++ b/vio/vio.cc
@@ -284,6 +284,26 @@ static bool vio_init(Vio *vio, enum enum_vio_type type, my_socket sd,
@@ -311,7 +313,7 @@ index 38e3d90f20e..abbc9a52478 100644
int *len) {
diff --git a/vio/viofuzz.cc b/vio/viofuzz.cc
new file mode 100644
-index 00000000000..83f22a5dbb9
+index 00000000000..5b368d685cb
--- /dev/null
+++ b/vio/viofuzz.cc
@@ -0,0 +1,124 @@
@@ -364,7 +366,7 @@ index 00000000000..83f22a5dbb9
+ DBUG_ENTER("vio_socket_connect");
+
+ /* Only for socket-based transport types. */
-+ DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
++ //DBUG_ASSERT(vio->type == VIO_TYPE_SOCKET || vio->type == VIO_TYPE_TCPIP);
+
+ /* Initiate the connection. */
+ return 0;
diff --git a/projects/mysql-server/project.yaml b/projects/mysql-server/project.yaml
index 68f04d294..893dfb092 100644
--- a/projects/mysql-server/project.yaml
+++ b/projects/mysql-server/project.yaml
@@ -9,7 +9,6 @@ auto_ccs:
fuzzing_engines:
- libfuzzer
- - honggfuzz
sanitizers:
- address
- undefined
diff --git a/projects/nats/Dockerfile b/projects/nats/Dockerfile
index a9dbcf4cf..e67288afc 100644
--- a/projects/nats/Dockerfile
+++ b/projects/nats/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/nats-io/nats-server
COPY build.sh $SRC/
WORKDIR $SRC/nats-server
diff --git a/projects/nats/build.sh b/projects/nats/build.sh
index 2235a6e4b..b9ce8fdf8 100755
--- a/projects/nats/build.sh
+++ b/projects/nats/build.sh
@@ -15,8 +15,5 @@
#
################################################################################
-
-
-compile_go_fuzzer ./conf Fuzz fuzz_conf
-compile_go_fuzzer ./server FuzzClient fuzz_client
-
+compile_go_fuzzer github.com/nats-io/nats-server/v2/conf Fuzz fuzz_conf
+compile_go_fuzzer github.com/nats-io/nats-server/v2/server FuzzClient fuzz_client
diff --git a/projects/ndpi/Dockerfile b/projects/ndpi/Dockerfile
index fafb08154..11d426d6c 100644
--- a/projects/ndpi/Dockerfile
+++ b/projects/ndpi/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake autogen pkg-config libtool flex bison cmake
+RUN apt-get update && apt-get install -y make autoconf automake autogen pkg-config libtool flex bison cmake libnuma-dev libgcrypt20-dev libpcre2-dev
RUN git clone --depth 1 https://github.com/json-c/json-c.git json-c
RUN git clone --depth 1 https://github.com/ntop/nDPI.git ndpi
ADD https://www.tcpdump.org/release/libpcap-1.9.1.tar.gz libpcap-1.9.1.tar.gz
diff --git a/projects/nestegg/project.yaml b/projects/nestegg/project.yaml
index 93165f38a..2e4b2e558 100644
--- a/projects/nestegg/project.yaml
+++ b/projects/nestegg/project.yaml
@@ -5,12 +5,10 @@ fuzzing_engines:
- afl
- libfuzzer
- honggfuzz
- - dataflow
sanitizers:
- address
- memory
- undefined
- - dataflow
vendor_ccs:
- "twsmith@mozilla.com"
main_repo: 'https://github.com/kinetiknz/nestegg.git'
diff --git a/projects/net-snmp/Dockerfile b/projects/net-snmp/Dockerfile
index c9e6a7925..324a732bf 100644
--- a/projects/net-snmp/Dockerfile
+++ b/projects/net-snmp/Dockerfile
@@ -15,11 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf libtool libssl-dev
-RUN git clone --depth 1 git://git.code.sf.net/p/net-snmp/code net-snmp
+RUN git clone -q --depth 1 https://github.com/net-snmp/net-snmp net-snmp
+RUN net-snmp/ci/install.sh
WORKDIR net-snmp
COPY build.sh $SRC/
-#
-# Until the project moves the fuzzers to the source tree
-COPY snmp_pdu_parse_fuzzer.c $SRC/
-COPY agentx_parse_fuzzer.c $SRC/
diff --git a/projects/net-snmp/agentx_parse_fuzzer.c b/projects/net-snmp/agentx_parse_fuzzer.c
deleted file mode 100644
index 436011208..000000000
--- a/projects/net-snmp/agentx_parse_fuzzer.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- *
- * This fuzzer exercises the agentx PDU parsing code.
- */
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-/* We build with the agent/mibgroup/agentx dir in an -I */
-#include <protocol.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
- if (getenv("NETSNMP_DEBUGGING") != NULL) {
- /*
- * Turn on all debugging, to help understand what
- * bits of the parser are running.
- */
- snmp_enable_stderrlog();
- snmp_set_do_debugging(1);
- debug_register_tokens("");
- }
- return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- netsnmp_pdu *pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu);
- netsnmp_session session;
-
- session.version = AGENTX_VERSION_1;
- agentx_parse(&session, pdu, (unsigned char *)data, size);
- snmp_free_pdu(pdu);
- return 0;
-}
diff --git a/projects/net-snmp/build.sh b/projects/net-snmp/build.sh
index b7bceda0b..3753b7638 100755
--- a/projects/net-snmp/build.sh
+++ b/projects/net-snmp/build.sh
@@ -15,21 +15,6 @@
#
################################################################################
-# build project
-./configure --with-openssl=/usr --with-defaults --with-logfile="/dev/null" --with-persistent-directory="/dev/null"
-# net-snmp build is not parallel-make safe; do not add -j
-make
-
-# build fuzzers (remember to link statically)
-$CC $CFLAGS -c -Iinclude $SRC/snmp_pdu_parse_fuzzer.c -o $WORK/snmp_pdu_parse_fuzzer.o
-$CXX $CXXFLAGS $WORK/snmp_pdu_parse_fuzzer.o \
- $LIB_FUZZING_ENGINE snmplib/.libs/libnetsnmp.a \
- -Wl,-Bstatic -lcrypto -Wl,-Bdynamic -lm \
- -o $OUT/snmp_pdu_parse_fuzzer
-
-$CC $CFLAGS -c -Iinclude -Iagent/mibgroup/agentx $SRC/agentx_parse_fuzzer.c -o $WORK/agentx_parse_fuzzer.o
-$CXX $CXXFLAGS $WORK/agentx_parse_fuzzer.o \
- $LIB_FUZZING_ENGINE snmplib/.libs/libnetsnmp.a \
- agent/.libs/libnetsnmpagent.a \
- -Wl,-Bstatic -lcrypto -Wl,-Bdynamic -lm \
- -o $OUT/agentx_parse_fuzzer
+# Configure and build Net-SNMP and the fuzzers.
+export CC CXX CFLAGS CXXFLAGS SRC WORK OUT LIB_FUZZING_ENGINE
+ci/build.sh
diff --git a/projects/net-snmp/project.yaml b/projects/net-snmp/project.yaml
index 339203860..5a27e2e7c 100644
--- a/projects/net-snmp/project.yaml
+++ b/projects/net-snmp/project.yaml
@@ -6,4 +6,5 @@ auto_ccs:
- "fenner@gmail.com"
- "bvanassche@acm.org"
- "magfr@lysator.liu.se"
+ - "david@adalogics.com"
main_repo: 'git://git.code.sf.net/p/net-snmp/code'
diff --git a/projects/net-snmp/snmp_pdu_parse_fuzzer.c b/projects/net-snmp/snmp_pdu_parse_fuzzer.c
deleted file mode 100644
index 6d45552db..000000000
--- a/projects/net-snmp/snmp_pdu_parse_fuzzer.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- *
- * This fuzzer exercises the SNMP PDU parsing code, including ASN.1.
- */
-#include <net-snmp/net-snmp-config.h>
-#include <net-snmp/net-snmp-includes.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-int LLVMFuzzerInitialize(int *argc, char ***argv) {
- if (getenv("NETSNMP_DEBUGGING") != NULL) {
- /*
- * Turn on all debugging, to help understand what
- * bits of the parser are running.
- */
- snmp_enable_stderrlog();
- snmp_set_do_debugging(1);
- debug_register_tokens("");
- }
- return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- size_t bytes_remaining = size;
- netsnmp_pdu *pdu = SNMP_MALLOC_TYPEDEF(netsnmp_pdu);
-
- snmp_pdu_parse(pdu, (unsigned char *)data, &bytes_remaining);
- snmp_free_pdu(pdu);
- return 0;
-}
diff --git a/projects/netcdf/Dockerfile b/projects/netcdf/Dockerfile
new file mode 100644
index 000000000..41f0aca6f
--- /dev/null
+++ b/projects/netcdf/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 m4 zlib1g-dev
+RUN git clone --depth 1 https://github.com/Unidata/netcdf-c
+COPY build.sh $SRC
+WORKDIR $SRC/netcdf-c
diff --git a/projects/netcdf/build.sh b/projects/netcdf/build.sh
new file mode 100755
index 000000000..eeae9cda7
--- /dev/null
+++ b/projects/netcdf/build.sh
@@ -0,0 +1,23 @@
+#!/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 -DENABLE_HDF5=OFF -DENABLE_DAP=OFF ..
+make -j$(nproc)
+cp fuzz/fuzz* $OUT/
diff --git a/projects/netcdf/project.yaml b/projects/netcdf/project.yaml
new file mode 100644
index 000000000..794e5cbd2
--- /dev/null
+++ b/projects/netcdf/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.unidata.ucar.edu/software/netcdf/docs/index.html"
+language: c++
+primary_contact: "wfisher@ucar.edu"
+auto_ccs:
+- "p.antoine@catenacyber.fr"
+- "dmh@ucar.edu"
+
+sanitizers:
+- address
+- undefined
+main_repo: 'https://github.com/Unidata/netcdf-c'
diff --git a/projects/nettle/Dockerfile b/projects/nettle/Dockerfile
index 5367c20f2..b7b987cb9 100644
--- a/projects/nettle/Dockerfile
+++ b/projects/nettle/Dockerfile
@@ -15,11 +15,11 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get install -y software-properties-common python-software-properties make autoconf build-essential wget lzip libtool
+RUN apt-get install -y software-properties-common make autoconf build-essential wget lzip libtool python
RUN git clone --depth 1 https://git.lysator.liu.se/nettle/nettle
RUN git clone --depth 1 https://github.com/randombit/botan.git
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz-corpora
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
RUN wget https://gmplib.org/download/gmp/gmp-6.2.0.tar.lz
COPY build.sh $SRC/
diff --git a/projects/nettle/build.sh b/projects/nettle/build.sh
index 01018312e..e10c5d7e0 100755
--- a/projects/nettle/build.sh
+++ b/projects/nettle/build.sh
@@ -56,24 +56,18 @@ then
cp -R $SRC/nettle $SRC/nettle-with-libgmp/
cd $SRC/nettle-with-libgmp/
bash .bootstrap
+ export NETTLE_LIBDIR=`realpath ../nettle-with-libgmp-install`/lib
if [[ $CFLAGS != *sanitize=memory* ]]
then
- ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-libgmp-install`
+ ./configure --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-libgmp-install` --libdir="$NETTLE_LIBDIR"
else
- ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-libgmp-install`
+ ./configure --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-libgmp-install` --libdir="$NETTLE_LIBDIR"
fi
make -j$(nproc)
make install
- if [[ $CFLAGS != *-m32* ]]
- then
- export LIBNETTLE_A_PATH=`realpath ../nettle-with-libgmp-install/lib/libnettle.a`
- export LIBHOGWEED_A_PATH=`realpath ../nettle-with-libgmp-install/lib/libhogweed.a`
- ls -l $LIBHOGWEED_A_PATH
- else
- export LIBNETTLE_A_PATH=`realpath ../nettle-with-libgmp-install/lib32/libnettle.a`
- export LIBHOGWEED_A_PATH=`realpath ../nettle-with-libgmp-install/lib32/libhogweed.a`
- fi
+ export LIBNETTLE_A_PATH=$NETTLE_LIBDIR/libnettle.a
+ export LIBHOGWEED_A_PATH=$NETTLE_LIBDIR/libhogweed.a
export NETTLE_INCLUDE_PATH=`realpath ../nettle-with-libgmp-install/include`
export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
export LINK_FLAGS="$LINK_FLAGS /usr/local/lib/libgmp.a"
@@ -121,24 +115,18 @@ fi
cp -R $SRC/nettle $SRC/nettle-with-mini-gmp/
cd $SRC/nettle-with-mini-gmp/
bash .bootstrap
+ export NETTLE_LIBDIR=`realpath ../nettle-with-mini-gmp-install`/lib
if [[ $CFLAGS != *sanitize=memory* ]]
then
- ./configure --enable-mini-gmp --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-mini-gmp-install`
+ ./configure --enable-mini-gmp --disable-documentation --disable-openssl --prefix=`realpath ../nettle-with-mini-gmp-install` --libdir="$NETTLE_LIBDIR"
else
- ./configure --enable-mini-gmp --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-mini-gmp-install`
+ ./configure --enable-mini-gmp --disable-documentation --disable-openssl --disable-assembler --prefix=`realpath ../nettle-with-mini-gmp-install` --libdir="$NETTLE_LIBDIR"
fi
make -j$(nproc)
make install
- if [[ $CFLAGS != *-m32* ]]
- then
- export LIBNETTLE_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib/libnettle.a`
- export LIBHOGWEED_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib/libhogweed.a`
- ls -l $LIBHOGWEED_A_PATH
- else
- export LIBNETTLE_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib32/libnettle.a`
- export LIBHOGWEED_A_PATH=`realpath ../nettle-with-mini-gmp-install/lib32/libhogweed.a`
- fi
+ export LIBNETTLE_A_PATH=$NETTLE_LIBDIR/libnettle.a
+ export LIBHOGWEED_A_PATH=$NETTLE_LIBDIR/libhogweed.a
export NETTLE_INCLUDE_PATH=`realpath ../nettle-with-mini-gmp-install/include`
export LINK_FLAGS=""
export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NETTLE"
diff --git a/projects/nettle/project.yaml b/projects/nettle/project.yaml
index 77b348cea..698d20b8b 100644
--- a/projects/nettle/project.yaml
+++ b/projects/nettle/project.yaml
@@ -6,7 +6,8 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- i386
diff --git a/projects/nginx/build.sh b/projects/nginx/build.sh
index fcfb70bac..88bfb59dc 100644
--- a/projects/nginx/build.sh
+++ b/projects/nginx/build.sh
@@ -25,7 +25,8 @@ cd ../..
auto/configure \
--with-ld-opt="-Wl,--wrap=listen -Wl,--wrap=setsockopt -Wl,--wrap=bind -Wl,--wrap=shutdown -Wl,--wrap=connect -Wl,--wrap=getpwnam -Wl,--wrap=getgrnam -Wl,--wrap=chmod -Wl,--wrap=chown" \
- --with-http_v2_module
+ --with-cc-opt='-DNGX_DEBUG_PALLOC=1' \
+ --with-http_v2_module
make -f objs/Makefile fuzzers
cp objs/*_fuzzer $OUT/
diff --git a/projects/nginx/fuzz/http_request_fuzzer.cc b/projects/nginx/fuzz/http_request_fuzzer.cc
index 8d69e82c8..317826c18 100644
--- a/projects/nginx/fuzz/http_request_fuzzer.cc
+++ b/projects/nginx/fuzz/http_request_fuzzer.cc
@@ -230,6 +230,9 @@ extern "C" int InitializeNginx(void) {
ngx_event_actions.init = init_event;
ngx_io.send_chain = send_chain;
ngx_event_flags = 1;
+ ngx_queue_init(&ngx_posted_accept_events);
+ ngx_queue_init(&ngx_posted_next_events);
+ ngx_queue_init(&ngx_posted_events);
ngx_event_timer_init(cycle->log);
return 0;
}
@@ -286,6 +289,7 @@ DEFINE_PROTO_FUZZER(const HttpProto &input) {
255, &ngx_log); // 255 - (hopefully unused) socket descriptor
c->shared = 1;
+ c->destroyed = 0;
c->type = SOCK_STREAM;
c->pool = ngx_create_pool(256, ngx_cycle->log);
c->sockaddr = ls->sockaddr;
@@ -301,10 +305,24 @@ DEFINE_PROTO_FUZZER(const HttpProto &input) {
c->socklen = ls->socklen;
c->local_sockaddr = ls->sockaddr;
c->local_socklen = ls->socklen;
+ c->data = NULL;
read_event1.ready = 1;
write_event1.ready = write_event1.delayed = 1;
// Will redirect to http parser
ngx_http_init_connection(c);
+
+ // We do not provide working timers or events, and thus we have to manually
+ // clean up the requests we created. We do this here.
+ // Cross-referencing: https://trac.nginx.org/nginx/ticket/2080#no1).I
+ // This is a fix that should be bettered in the future, by creating proper
+ // timers and events.
+ if (c->destroyed != 1) {
+ if (c->read->data != NULL) {
+ ngx_connection_t *c2 = (ngx_connection_t*)c->read->data;
+ ngx_http_free_request((ngx_http_request_t*)c2->data, 0);
+ }
+ ngx_http_close_connection(c);
+ }
}
diff --git a/projects/nginx/project.yaml b/projects/nginx/project.yaml
index 0aa90207a..0bbff0a74 100644
--- a/projects/nginx/project.yaml
+++ b/projects/nginx/project.yaml
@@ -1,8 +1,9 @@
homepage: "http://nginx.org"
+main_repo: "https://github.com/nginx/nginx"
language: c
primary_contact: "xim.andrew@gmail.com"
auto_ccs:
- - ouyangyunshu@google.com
- - mmoroz@google.com
+ - pluknet@gmail.com
+ - david@adalogics.com
sanitizers:
- address
diff --git a/projects/ninja/project.yaml b/projects/ninja/project.yaml
index d35fdc4b6..2f6baf4db 100644
--- a/projects/ninja/project.yaml
+++ b/projects/ninja/project.yaml
@@ -6,5 +6,6 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
-main_repo: "https://github.com/ninja-build/ninja"
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: "https://github.com/ninja-build/ninja" \ No newline at end of file
diff --git a/projects/njs/project.yaml b/projects/njs/project.yaml
index bd92434df..65b2bf8e4 100644
--- a/projects/njs/project.yaml
+++ b/projects/njs/project.yaml
@@ -1,12 +1,13 @@
homepage: "https://nginx.org/en/docs/njs/"
language: c++
-primary_contact: "xeioex@nginx.com"
+primary_contact: "xeioexception@gmail.com"
auto_ccs:
- - "alexander.borisov@nginx.com"
+ - "lex.borisov@gmail.com"
- "devrep@nginx.com"
- - "mmoroz@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
coverage_extra_args: -ignore-filename-regex=.*/pcre/.*
+main_repo: 'https://github.com/nginx/njs.git' \ No newline at end of file
diff --git a/projects/nom/Dockerfile b/projects/nom/Dockerfile
index 167550e33..793d785e1 100644
--- a/projects/nom/Dockerfile
+++ b/projects/nom/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone --depth 1 https://github.com/Geal/nom/
WORKDIR $SRC
diff --git a/projects/nss/Dockerfile b/projects/nss/Dockerfile
index 5ad8b5eb6..1bc729b23 100644
--- a/projects/nss/Dockerfile
+++ b/projects/nss/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make mercurial zlib1g-dev gyp ninja-build libssl-dev
+RUN apt-get update && apt-get install -y make mercurial zlib1g-dev gyp ninja-build libssl-dev python
RUN hg clone https://hg.mozilla.org/projects/nspr nspr
RUN hg clone https://hg.mozilla.org/projects/nss nss
diff --git a/projects/oak/Dockerfile b/projects/oak/Dockerfile
index e6f44f30a..16f774134 100644
--- a/projects/oak/Dockerfile
+++ b/projects/oak/Dockerfile
@@ -14,26 +14,34 @@
#
################################################################################
-# TODO(https://github.com/google/oss-fuzz/issues/3093): Stop specifying the
-# image SHA once the bug is fixed.
-FROM gcr.io/oss-fuzz-base/base-builder@sha256:276813aef0ce5972db43c0230f96162003994fa742fb1b2f4e66c67498575c65
+FROM gcr.io/oss-fuzz-base/base-builder-rust
-# Use a fixed Bazel version.
-# https://github.com/google/asylo/blob/088ea3490dd4579655bd5b65b0e31fe18de7f6dd/asylo/distrib/toolchain/Dockerfile#L48-L71
-ARG bazel_version=1.1.0
-ARG bazel_sha=138b47ffd54924e3c0264c65d31d3927803fb9025db4d5b18107df79ee3bda95
-ARG bazel_url=https://storage.googleapis.com/bazel-apt/pool/jdk1.8/b/bazel/bazel_${bazel_version}_amd64.deb
+RUN apt-get --yes update \
+ && apt-get install --no-install-recommends --yes \
+ libssl-dev \
+ pkg-config \
+ python \
+ && apt-get clean \
+ && rm --recursive --force /var/lib/apt/lists/*
-# Install Bazel.
-RUN apt-get update && \
- apt-get install -y wget && \
- wget "${bazel_url}" -nv -o- -O bazel.deb && \
- echo "${bazel_sha} bazel.deb" > bazel.sha256 && \
- sha256sum --check bazel.sha256 && \
- apt-get install -y ./bazel.deb && \
- rm bazel.deb bazel.sha256 && \
- apt-get clean
+# Install WebAssembly target for Rust.
+RUN rustup target add wasm32-unknown-unknown
+
+# Install Protobuf compiler.
+ARG protobuf_version=3.13.0
+ARG protobuf_sha256=4a3b26d1ebb9c1d23e933694a6669295f6a39ddc64c3db2adf671f0a6026f82e
+ARG protobuf_dir=/usr/local/protobuf
+ARG protobuf_temp=/tmp/protobuf.zip
+ENV PATH "${protobuf_dir}/bin:${PATH}"
+RUN curl --location https://github.com/protocolbuffers/protobuf/releases/download/v${protobuf_version}/protoc-${protobuf_version}-linux-x86_64.zip > ${protobuf_temp} \
+ && sha256sum --binary ${protobuf_temp} && echo "${protobuf_sha256} *${protobuf_temp}" | sha256sum --check \
+ && unzip ${protobuf_temp} -d ${protobuf_dir} \
+ && rm ${protobuf_temp} \
+ && chmod --recursive a+rwx ${protobuf_dir} \
+ && protoc --version
RUN git clone --depth 1 https://github.com/project-oak/oak oak
+
WORKDIR oak
COPY build.sh $SRC/
+COPY rustc.py $SRC/
diff --git a/projects/oak/build.sh b/projects/oak/build.sh
index 2e46c774f..8a2720852 100755
--- a/projects/oak/build.sh
+++ b/projects/oak/build.sh
@@ -15,62 +15,22 @@
#
################################################################################
-# Mostly copied from
-# https://github.com/google/oss-fuzz/blob/7f8013db108e62727fba1c3cbcccac07d543682b/projects/grpc/build.sh
+cd oak_functions/loader/
-# 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`.
-readonly 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" ]
+if [ "$SANITIZER" = "coverage" ]
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)"
+ export RUSTFLAGS="$RUSTFLAGS -C debug-assertions=no"
+ chmod +x $SRC/rustc.py
+ export RUSTC="$SRC/rustc.py"
fi
-)"
-# Temporary hack, see https://github.com/google/oss-fuzz/issues/383
-readonly NO_VPTR='--copt=-fno-sanitize=vptr --linkopt=-fno-sanitize=vptr'
+cargo fuzz build --release
-readonly FUZZER_TARGETS=()
-readonly ENABLED=false
-
-if [ "$ENABLED" = true ]; then
- bazel build \
- --client_env=CC=${CC} \
- --client_env=CXX=${CXX} \
- --dynamic_mode=off \
- --spawn_strategy=standalone \
- --genrule_strategy=standalone \
- ${NO_VPTR} \
- --strip=never \
- --linkopt=-lc++ \
- --linkopt=-pthread \
- --cxxopt=-std=c++11 \
- --copt=${LIB_FUZZING_ENGINE} \
- --linkopt=${LIB_FUZZING_ENGINE} \
- --remote_cache=https://storage.googleapis.com/oak-bazel-cache \
- --remote_upload_local_results=false \
- ${EXTRA_BAZEL_FLAGS} \
- ${FUZZER_TARGETS[@]}
+FUZZ_TARGET_OUTPUT_DIR=fuzz/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
- for target in ${FUZZER_TARGETS}; do
- # Replace : with /.
- fuzzer_name="${target/:/\/}"
- cp "./bazel-bin/${fuzzer_name}" "${OUT}/"
- done
- # Cleanup bazel- symlinks to avoid oss-fuzz trying to copy out of the build
- # cache.
- rm -f ./bazel-*
-fi
diff --git a/projects/oak/project.yaml b/projects/oak/project.yaml
index 3f79c7f9b..843689127 100644
--- a/projects/oak/project.yaml
+++ b/projects/oak/project.yaml
@@ -1,15 +1,15 @@
-disabled: True
homepage: "https://github.com/project-oak/oak"
-language: c++
+language: rust
primary_contact: "tzn@google.com"
auto_ccs:
- "project-oak-team@google.com"
- "benblaxill@google.com"
- - "drysdale@google.com"
- "grobler@google.com"
- "iovi@google.com"
- "ivanpetrov@google.com"
- - "mks@google.com"
+ - "razieh@google.com"
+sanitizers:
+ - address
fuzzing_engines:
- libfuzzer
main_repo: 'https://github.com/project-oak/oak'
diff --git a/projects/oak/rustc.py b/projects/oak/rustc.py
new file mode 100644
index 000000000..55ce4c40a
--- /dev/null
+++ b/projects/oak/rustc.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES 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 subprocess
+
+#Disable coverage for troubling crates.
+sys.argv[0] = "rustc"
+if "tokio_util" in sys.argv or "hyper" in sys.argv:
+ try:
+ sys.argv.remove("-Zinstrument-coverage")
+ except:
+ pass
+ print(sys.argv)
+subprocess.call(sys.argv)
diff --git a/projects/oatpp/Dockerfile b/projects/oatpp/Dockerfile
new file mode 100644
index 000000000..43ef579ca
--- /dev/null
+++ b/projects/oatpp/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/oatpp/oatpp.git oatpp
+WORKDIR oatpp
+COPY build.sh $SRC/
diff --git a/projects/oatpp/build.sh b/projects/oatpp/build.sh
new file mode 100755
index 000000000..8fc23cd6e
--- /dev/null
+++ b/projects/oatpp/build.sh
@@ -0,0 +1,23 @@
+#!/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 ../
+make
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE ../fuzzers/oatpp/parser/json/mapping/ObjectMapper.cpp -o $OUT/fuzz_mapper \
+ ./src/liboatpp.a -I../src
diff --git a/projects/oatpp/project.yaml b/projects/oatpp/project.yaml
new file mode 100644
index 000000000..47203f65f
--- /dev/null
+++ b/projects/oatpp/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://oatpp.io/"
+language: c++
+primary_contact: "bugs@oatpp.io"
+main_repo: "https://github.com/oatpp/oatpp"
+auto_ccs:
+ - "leonid@oatpp.io"
+ - "david@adalogics.com"
diff --git a/projects/open62541/build.sh b/projects/open62541/build.sh
index db59c1212..74051db21 100755
--- a/projects/open62541/build.sh
+++ b/projects/open62541/build.sh
@@ -27,7 +27,7 @@ cd $WORK/open62541
# <= 600 FATAL
# > 600 No LOG output
-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUA_ENABLE_AMALGAMATION=OFF \
+cmake -DCMAKE_BUILD_TYPE=Debug -DUA_ENABLE_AMALGAMATION=OFF \
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python2 \
-DBUILD_SHARED_LIBS=OFF -DUA_BUILD_EXAMPLES=OFF -DUA_LOGLEVEL=600 \
-DUA_ENABLE_ENCRYPTION=ON \
diff --git a/projects/open62541/project.yaml b/projects/open62541/project.yaml
index 7f0447c38..f5c0ef994 100644
--- a/projects/open62541/project.yaml
+++ b/projects/open62541/project.yaml
@@ -5,8 +5,11 @@ auto_ccs:
- "julius.pfrommer@gmail.com"
- "chris_paul.iatrou@tu-dresden.de"
- "ari.breitkreuz@gmail.com"
+fuzzing_engines:
+ - libfuzzer
+ - afl
sanitizers:
-- address
-- undefined
-- memory
+ - address
+ - undefined
+ - memory
main_repo: 'https://github.com/open62541/open62541.git'
diff --git a/projects/opencensus-cpp/.bazelrc b/projects/opencensus-cpp/.bazelrc
new file mode 100644
index 000000000..02f1b2408
--- /dev/null
+++ b/projects/opencensus-cpp/.bazelrc
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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++
+
+# Define the --config=asan-libfuzzer configuration.
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing_oss_fuzz//:oss_fuzz_engine
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz
+build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none
diff --git a/projects/opencensus-cpp/Dockerfile b/projects/opencensus-cpp/Dockerfile
new file mode 100644
index 000000000..8a3248cd7
--- /dev/null
+++ b/projects/opencensus-cpp/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/census-instrumentation/opencensus-cpp
+COPY WORKSPACE .bazelrc $SRC/
+RUN cat WORKSPACE >> $SRC/opencensus-cpp/WORKSPACE
+RUN cat .bazelrc >> $SRC/opencensus-cpp/.bazelrc
+COPY build.sh $SRC/
+WORKDIR $SRC/opencensus-cpp
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py b/projects/opencensus-cpp/WORKSPACE
index 9d200af6f..6a9ee93d9 100644
--- a/infra/base-images/base-sanitizer-libs-builder/packages/libgcrypt20.py
+++ b/projects/opencensus-cpp/WORKSPACE
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,23 +14,19 @@
#
################################################################################
-import os
-import shutil
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-import package
-import wrapper_utils
+http_archive(
+ name = "rules_fuzzing",
+ sha256 = "71fa2724c9802c597199a86111a0499fc4fb22426d322334d3f191dadeff5132",
+ strip_prefix = "rules_fuzzing-0.1.0",
+ urls = ["https://github.com/bazelbuild/rules_fuzzing/archive/v0.1.0.zip"],
+)
+load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
-class Package(package.Package):
- """libgcrypt20 package."""
+rules_fuzzing_dependencies()
- def __init__(self, apt_version):
- super(Package, self).__init__('libgcrypt20', apt_version)
+load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
- def PreBuild(self, source_directory, env, custom_bin_dir):
- configure_wrapper = (
- '#!/bin/bash\n'
- '/usr/bin/dh_auto_configure "$@" --disable-asm')
-
- wrapper_utils.InstallWrapper(
- custom_bin_dir, 'dh_auto_configure', configure_wrapper)
+rules_fuzzing_init()
diff --git a/projects/opencensus-cpp/build.sh b/projects/opencensus-cpp/build.sh
new file mode 100755
index 000000000..04b790367
--- /dev/null
+++ b/projects/opencensus-cpp/build.sh
@@ -0,0 +1,22 @@
+#!/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.
+#
+################################################################################
+
+git grep cc_fuzz_target.bzl | grep BUILD | cut -d: -f1 | uniq | while read i; do sed -i -e 's=//bazel:cc_fuzz_target.bzl=@rules_fuzzing//fuzzing:cc_defs.bzl=' $i; done
+
+git grep fuzz_target\( | grep BUILD | cut -d: -f1 | uniq | while read i; do sed -i -e 's/fuzz_target/fuzz_test/' $i; done
+
+bazel_build_fuzz_tests
diff --git a/projects/opencensus-cpp/project.yaml b/projects/opencensus-cpp/project.yaml
new file mode 100644
index 000000000..b84d07f31
--- /dev/null
+++ b/projects/opencensus-cpp/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://opencensus.io/"
+language: c++
+primary_contact: "joshuasuereth@google.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+
+sanitizers:
+- address
+- memory
+main_repo: 'https://github.com/census-instrumentation/opencensus-cpp'
diff --git a/projects/opencv/project.yaml b/projects/opencv/project.yaml
index e6b085c57..3062a9357 100644
--- a/projects/opencv/project.yaml
+++ b/projects/opencv/project.yaml
@@ -12,11 +12,12 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
labels:
imdecode_fuzzer:
- sundew
imread_fuzzer:
- sundew
-main_repo: 'https://github.com/opencv/opencv.git'
+main_repo: 'https://github.com/opencv/opencv.git' \ No newline at end of file
diff --git a/projects/opendnp3/project.yaml b/projects/opendnp3/project.yaml
index 47c72b613..cc6a30028 100644
--- a/projects/opendnp3/project.yaml
+++ b/projects/opendnp3/project.yaml
@@ -7,6 +7,7 @@ auto_ccs :
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
main_repo: 'https://github.com/dnp3/opendnp3.git'
diff --git a/projects/openexr/build.sh b/projects/openexr/build.sh
index 80a2e49a6..2b9e411cd 100755
--- a/projects/openexr/build.sh
+++ b/projects/openexr/build.sh
@@ -19,17 +19,16 @@ cd $WORK/
CMAKE_SETTINGS=(
"-D BUILD_SHARED_LIBS=OFF" # Build static libraries only
- "-D PYILMBASE_ENABLE=OFF" # Don't build Python support
"-D BUILD_TESTING=OFF" # Or tests
- "-D INSTALL_OPENEXR_EXAMPLES=OFF" # Or examples
+ "-D OPENEXR_INSTALL_EXAMPLES=OFF" # Or examples
"-D OPENEXR_LIB_SUFFIX=" # Don't append the version number to library files
- "-D ILMBASE_LIB_SUFFIX="
)
cmake $SRC/openexr ${CMAKE_SETTINGS[@]}
make -j$(nproc)
INCLUDES=(
"-I $SRC"
+ "-I $SRC/openexr/src/lib/OpenEXRCore"
"-I $SRC/openexr/src/lib/OpenEXR"
"-I $SRC/openexr/src/lib/OpenEXRUtil"
"-I $WORK/cmake"
@@ -38,6 +37,7 @@ INCLUDES=(
LIBS=(
"$WORK/src/lib/OpenEXRUtil/libOpenEXRUtil.a"
"$WORK/src/lib/OpenEXR/libOpenEXR.a"
+ "$WORK/src/lib/OpenEXRCore/libOpenEXRCore.a"
"$WORK/src/lib/IlmThread/libIlmThread.a"
"$WORK/src/lib/Iex/libIex.a"
"$WORK/_deps/imath-build/src/Imath/libImath*.a"
diff --git a/projects/openexr/project.yaml b/projects/openexr/project.yaml
index 521e76761..b4af565d4 100644
--- a/projects/openexr/project.yaml
+++ b/projects/openexr/project.yaml
@@ -4,4 +4,5 @@ primary_contact: "twodeecoda@gmail.com"
auto_ccs:
- "cbpilm@gmail.com"
- "security@openexr.org"
+ - "kdt3rd@gmail.com"
main_repo: 'https://github.com/AcademySoftwareFoundation/openexr'
diff --git a/projects/openh264/Dockerfile b/projects/openh264/Dockerfile
index f7cc71279..c32bdc88a 100644
--- a/projects/openh264/Dockerfile
+++ b/projects/openh264/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && \
- apt-get install -y libstdc++-5-dev libstdc++-5-dev:i386 nasm subversion
+ apt-get install -y libstdc++-9-dev libstdc++-9-dev:i386 nasm subversion
RUN git clone --depth 1 https://github.com/cisco/openh264.git openh264
WORKDIR openh264
COPY build.sh decoder_fuzzer.cpp $SRC/
diff --git a/projects/opensc/project.yaml b/projects/opensc/project.yaml
index 79d794ecb..03360d84d 100644
--- a/projects/opensc/project.yaml
+++ b/projects/opensc/project.yaml
@@ -8,4 +8,5 @@ auto_ccs:
- "andreas.schwier@cardcontact.de"
- "deengert@gmail.com"
- "jakuje@gmail.com"
+ - "xhanulik@gmail.com"
main_repo: 'https://github.com/OpenSC/OpenSC'
diff --git a/projects/opensips/Dockerfile b/projects/opensips/Dockerfile
new file mode 100755
index 000000000..c7b364a42
--- /dev/null
+++ b/projects/opensips/Dockerfile
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libssl-dev pkg-config
+RUN git clone https://github.com/OpenSIPS/opensips
+
+COPY patch.diff $SRC/
+COPY build.sh $SRC/
+COPY fuzz_*.c $SRC/opensips/parser/
+
+WORKDIR opensips
diff --git a/projects/opensips/build.sh b/projects/opensips/build.sh
new file mode 100755
index 000000000..6dc94ea07
--- /dev/null
+++ b/projects/opensips/build.sh
@@ -0,0 +1,28 @@
+#!/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.
+#
+################################################################################
+
+git apply --ignore-space-change --ignore-whitespace $SRC/patch.diff
+
+make static
+
+rm main.o
+mkdir objects && find . -name "*.o" -exec cp {} ./objects/ \;
+ar -r libopensips.a ./objects/*.o
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_msg_parser.o ./libopensips.a -ldl -lresolv -o $OUT/fuzz_msg_parser
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_uri_parser.o ./libopensips.a -ldl -lresolv -o $OUT/fuzz_uri_parser
+$CC $CFLAGS $LIB_FUZZING_ENGINE ./parser/fuzz_csv_parser.o ./libopensips.a -ldl -lresolv -o $OUT/fuzz_csv_parser
diff --git a/projects/opensips/fuzz_csv_parser.c b/projects/opensips/fuzz_csv_parser.c
new file mode 100644
index 000000000..810488193
--- /dev/null
+++ b/projects/opensips/fuzz_csv_parser.c
@@ -0,0 +1,54 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+#include "../ut.h"
+#include "../lib/csv.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+ // Ensure we have one byte for the "decider" variable
+ if (size == 0) {
+ return 0;
+ }
+ char *decider = *data;
+ data++;
+ size--;
+
+ ensure_global_context();
+ struct sip_uri u;
+
+ char *new_str = (char *)malloc(size + 1);
+ if (new_str == NULL) {
+ return 0;
+ }
+ memcpy(new_str, data, size);
+ new_str[size] = '\0';
+
+ csv_record *ret = NULL;
+ if (((int)decider % 2) == 0) {
+ ret = parse_csv_record(_str(new_str));
+ }
+ else {
+ ret = _parse_csv_record(_str(new_str), CSV_RFC_4180);
+ }
+ free_csv_record(ret);
+ free(new_str);
+}
diff --git a/projects/opensips/fuzz_msg_parser.c b/projects/opensips/fuzz_msg_parser.c
new file mode 100644
index 000000000..4daec4266
--- /dev/null
+++ b/projects/opensips/fuzz_msg_parser.c
@@ -0,0 +1,41 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "../parser/sdp/sdp.h"
+
+#include "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+ ensure_global_context();
+ struct sip_uri u;
+
+ if (size <= 1) {
+ return 0;
+ }
+
+ struct sip_msg orig_inv = {};
+ orig_inv.buf = (char *)data;
+ orig_inv.len = size;
+
+ parse_msg(orig_inv.buf, orig_inv.len, &orig_inv);
+ free_sip_msg(&orig_inv);
+ return 0;
+}
diff --git a/projects/opensips/fuzz_uri_parser.c b/projects/opensips/fuzz_uri_parser.c
new file mode 100644
index 000000000..1a1647458
--- /dev/null
+++ b/projects/opensips/fuzz_uri_parser.c
@@ -0,0 +1,40 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "../cachedb/test/test_cachedb.h"
+#include "../lib/test/test_csv.h"
+#include "../mem/test/test_malloc.h"
+#include "../str.h"
+
+#include "../context.h"
+#include "../dprint.h"
+#include "../globals.h"
+#include "../lib/list.h"
+#include "../sr_module.h"
+#include "../sr_module_deps.h"
+
+#include "parse_uri.h"
+
+int LLVMFuzzerTestOneInput(const char *data, size_t size) {
+ ensure_global_context();
+ struct sip_uri u;
+
+ char *new_str = (char *)malloc(size + 1);
+ if (new_str == NULL) {
+ return 0;
+ }
+ memcpy(new_str, data, size);
+ new_str[size] = '\0';
+
+ parse_uri(STR_L(new_str), &u);
+
+ free(new_str);
+}
diff --git a/projects/opensips/patch.diff b/projects/opensips/patch.diff
new file mode 100644
index 000000000..a382129ed
--- /dev/null
+++ b/projects/opensips/patch.diff
@@ -0,0 +1,57 @@
+diff --git a/Makefile.conf.template b/Makefile.conf.template
+index 5a76e0a35..2570db165 100644
+--- a/Makefile.conf.template
++++ b/Makefile.conf.template
+@@ -69,17 +69,19 @@ exclude_modules?= aaa_diameter aaa_radius auth_jwt b2b_logic_xml cachedb_cassand
+
+ include_modules?=
+
+-DEFS+= -DPKG_MALLOC #Use a faster malloc
+-DEFS+= -DSHM_MMAP #Use mmap instead of SYSV shared memory
+-DEFS+= -DUSE_MCAST #Compile in support for IP Multicast
++#DEFS+= -DPKG_MALLOC #Use a faster malloc
++#DEFS+= -DSHM_MMAP #Use mmap instead of SYSV shared memory
++#DEFS+= -DUSE_MCAST #Compile in support for IP Multicast
+ DEFS+= -DDISABLE_NAGLE #Disable the TCP NAgle Algorithm ( lower delay )
+ DEFS+= -DSTATISTICS #Enable the statistics manager
++DEFS+= -DSYSTEM_MALLOC
++DEFS+= -DSHM_MMAP
+ DEFS+= -DHAVE_RESOLV_RES #Support for changing some of the resolver parameters
+ # Specifying exactly 1 allocator will cause it to be inlined (fastest)
+-DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead
+-DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks
+-DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
+-DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors
++#DEFS+= -DF_MALLOC #Fast memory allocator with minimal runtime overhead
++#DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks
++#DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
++#DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors
+ #DEFS+= -DNO_DEBUG #Compile out all debug messages
+ #DEFS+= -DNO_LOG #Compile out all logging
+ #DEFS_GROUP_START
+diff --git a/parser/msg_parser.c b/parser/msg_parser.c
+index db09aff7f..99ea58435 100644
+--- a/parser/msg_parser.c
++++ b/parser/msg_parser.c
+@@ -263,7 +263,7 @@ error_bad_hdr:
+ set_err_reply(400, "bad headers");
+ error:
+ LM_DBG("error exit\n");
+- update_stat( bad_msg_hdr, 1);
++ //update_stat( bad_msg_hdr, 1);
+ hdr->type=HDR_ERROR_T;
+ hdr->len=tmp-hdr->name.s;
+ return tmp;
+diff --git a/parser/parse_uri.c b/parser/parse_uri.c
+index 364d91c1f..2f1ff1130 100644
+--- a/parser/parse_uri.c
++++ b/parser/parse_uri.c
+@@ -1628,7 +1628,7 @@ error_bug:
+ error_exit:
+ ser_error=E_BAD_URI;
+ uri->type=ERROR_URI_T;
+- update_stat(bad_URIs, 1);
++ //update_stat(bad_URIs, 1);
+ return E_BAD_URI;
+ }
+
diff --git a/projects/opensips/project.yaml b/projects/opensips/project.yaml
new file mode 100755
index 000000000..a4e118482
--- /dev/null
+++ b/projects/opensips/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://opensips.org/"
+main_repo: "https://github.com/OpenSIPS/opensips"
+primary_contact: "liviu@opensips.org"
+language: c
+auto_ccs:
+ - "david@adalogics.com"
+ - "liviu.chircu@gmail.com"
+ - "bogdan.andrei.iancu@gmail.com"
+ - "rvlad.patrascu@gmail.com"
+ - "razvan.crainea@gmail.com"
diff --git a/infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py b/projects/opensk/Dockerfile
index 3e1a1070f..b9b9810e2 100644
--- a/infra/base-images/base-sanitizer-libs-builder/packages/sqlite3.py
+++ b/projects/opensk/Dockerfile
@@ -1,5 +1,4 @@
-#!/usr/bin/env python
-# Copyright 2017 Google Inc.
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,19 +13,15 @@
# 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 uuid-runtime pkg-config libssl-dev
-import os
+RUN git clone --depth=1 --branch=develop https://github.com/google/OpenSK && \
+ cd OpenSK && \
+ ./setup.sh && \
+ ./fuzzing_setup.sh
-import package
+WORKDIR $SRC
-
-class Package(package.Package):
- """sqlite3 package."""
-
- def __init__(self, apt_version):
- super(Package, self).__init__('sqlite3', apt_version)
-
- def PreBuild(self, source_directory, env, custom_bin_dir):
- os.system(
- 'sed -i "s/package ifneeded sqlite3//" %s/debian/rules' %
- source_directory)
+COPY build.sh $SRC/
diff --git a/projects/opensk/build.sh b/projects/opensk/build.sh
new file mode 100755
index 000000000..4d2520946
--- /dev/null
+++ b/projects/opensk/build.sh
@@ -0,0 +1,40 @@
+#!/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.
+#
+################################################################################
+
+FUZZ_TARGET_OUTPUT_DIR=fuzz/target/x86_64-unknown-linux-gnu/release
+
+build_and_copy() {
+ pushd "$1"
+ cargo +nightly fuzz build --release --debug-assertions
+ for f in fuzz/fuzz_targets/*.rs
+ do
+ cp ${FUZZ_TARGET_OUTPUT_DIR}/$(basename ${f%.*}) $OUT/
+ done
+ popd
+}
+
+cd OpenSK
+
+# Main OpenSK fuzzing targets
+build_and_copy "."
+
+# persistent storage library
+build_and_copy libraries/persistent_store
+
+# CBOR crate
+build_and_copy libraries/cbor
+
diff --git a/projects/opensk/project.yaml b/projects/opensk/project.yaml
new file mode 100644
index 000000000..65f7a76b9
--- /dev/null
+++ b/projects/opensk/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/google/OpenSK"
+main_repo: "https://github.com/google/OpenSK"
+primary_contact: "opensk@google.com"
+sanitizers:
+ - address
+fuzzing_engines:
+ - libfuzzer
+language: rust
+auto_ccs:
+ - "jmichel@google.com"
+ - "kaczmarczyck@google.com"
+ - "cretin@google.com"
+ - "david@adalogics.com"
diff --git a/projects/openssh/Dockerfile b/projects/openssh/Dockerfile
index 929d57c2f..e2cf25774 100644
--- a/projects/openssh/Dockerfile
+++ b/projects/openssh/Dockerfile
@@ -16,7 +16,7 @@
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 libz-dev libssl1.0.0 libssl-dev libedit-dev zip
+RUN apt-get install -y libz-dev libssl1.1 libssl-dev libedit-dev zip
RUN git clone --depth 1 https://github.com/openssh/openssh-portable openssh
RUN git clone --depth 1 https://github.com/djmdjm/openssh-fuzz-cases
WORKDIR openssh
diff --git a/projects/openssh/project.yaml b/projects/openssh/project.yaml
index 53ac442f5..3bf759f60 100644
--- a/projects/openssh/project.yaml
+++ b/projects/openssh/project.yaml
@@ -2,6 +2,6 @@ homepage: https://www.openssh.com/
language: c++
primary_contact: "djm@mindrot.org"
auto_ccs:
- - "dtucker@dtucker.net.au"
+ - "dtucker@dtucker.net"
- "djm@google.com"
main_repo: 'https://github.com/openssh/openssh-portable'
diff --git a/projects/openthread/project.yaml b/projects/openthread/project.yaml
index c772d3b3c..5d93c49a9 100644
--- a/projects/openthread/project.yaml
+++ b/projects/openthread/project.yaml
@@ -8,5 +8,4 @@ fuzzing_engines:
sanitizers:
- address
- undefined
- - dataflow
main_repo: 'https://github.com/openthread/openthread'
diff --git a/projects/openvpn/Dockerfile b/projects/openvpn/Dockerfile
new file mode 100644
index 000000000..24397aef6
--- /dev/null
+++ b/projects/openvpn/Dockerfile
@@ -0,0 +1,28 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libssl-dev liblzo2-dev libpam-dev
+
+RUN git clone --depth 1 https://github.com/google/boringssl.git boringssl
+RUN git clone https://github.com/OpenVPN/openvpn openvpn
+WORKDIR openvpn
+COPY build.sh $SRC/
+COPY fuzz*.cpp $SRC/
+COPY fuzz*.c $SRC/
+COPY fuzz*.h $SRC/openvpn/src/openvpn/
+
+COPY crypto_patch.txt $SRC/crypto_patch.txt
diff --git a/projects/openvpn/build.sh b/projects/openvpn/build.sh
new file mode 100755
index 000000000..f83f6b95f
--- /dev/null
+++ b/projects/openvpn/build.sh
@@ -0,0 +1,83 @@
+#!/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.
+#
+################################################################################
+
+BASE=${SRC}/openvpn/src/openvpn
+
+apply_sed_changes() {
+ sed -i 's/read(/fuzz_read(/g' ${BASE}/console_systemd.c
+ sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/console_builtin.c
+ sed -i 's/fgets(/fuzz_fgets(/g' ${BASE}/misc.c
+ sed -i 's/#include "forward.h"/#include "fuzz_header.h"\n#include "forward.h"/g' ${BASE}/proxy.c
+ sed -i 's/select(/fuzz_select(/g' ${BASE}/proxy.c
+ sed -i 's/send(/fuzz_send(/g' ${BASE}/proxy.c
+ sed -i 's/recv(/fuzz_recv(/g' ${BASE}/proxy.c
+ sed -i 's/isatty/fuzz_isatty/g' ${BASE}/console_builtin.c
+
+ sed -i 's/fopen/fuzz_fopen/g' ${BASE}/console_builtin.c
+ sed -i 's/fclose/fuzz_fclose/g' ${BASE}/console_builtin.c
+
+ sed -i 's/sendto/fuzz_sendto/g' ${BASE}/socket.h
+ sed -i 's/#include "misc.h"/#include "misc.h"\nextern size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen);/g' ${BASE}/socket.h
+
+ sed -i 's/fp = (flags/fp = stdout;\n\/\//g' ${BASE}/error.c
+
+ sed -i 's/crypto_msg(M_FATAL/crypto_msg(M_WARN/g' ${BASE}/crypto_openssl.c
+ sed -i 's/msg(M_FATAL, \"Cipher/return;msg(M_FATAL, \"Cipher/g' ${BASE}/crypto.c
+ sed -i 's/msg(M_FATAL/msg(M_WARN/g' ${BASE}/crypto.c
+
+ sed -i 's/= write/= fuzz_write/g' ${BASE}/packet_id.c
+}
+
+# Changes in the code so we can fuzz it.
+git apply $SRC/crypto_patch.txt
+
+echo "" >> ${BASE}/openvpn.c
+echo "#include \"fake_fuzz_header.h\"" >> ${BASE}/openvpn.c
+echo "ssize_t fuzz_get_random_data(void *buf, size_t len) { return 0; }" >> ${BASE}/fake_fuzz_header.h
+echo "int fuzz_success;" >> ${BASE}/fake_fuzz_header.h
+
+# Apply hooking changes
+apply_sed_changes
+
+# Copy corpuses out
+zip -r $OUT/fuzz_verify_cert_seed_corpus.zip $SRC/boringssl/fuzz/cert_corpus
+
+# Build openvpn
+autoreconf -ivf
+./configure --disable-lz4 --with-crypto-library=openssl OPENSSL_LIBS="-L/usr/local/ssl/ -lssl -lcrypto" OPENSSL_CFLAGS="-I/usr/local/ssl/include/"
+make
+
+# Make openvpn object files into a library we can link fuzzers to
+cd src/openvpn
+rm openvpn.o
+ar r libopenvpn.a *.o
+
+# Compile our fuzz helper
+$CXX $CXXFLAGS -g -c $SRC/fuzz_randomizer.cpp -o $SRC/fuzz_randomizer.o
+
+# Compile the fuzzers
+for fuzzname in dhcp misc base64 proxy buffer route packet_id mroute list verify_cert forward crypto; do
+ $CC -DHAVE_CONFIG_H -I. -I../.. -I../../include -I../../src/compat \
+ -DPLUGIN_LIBDIR=\"/usr/local/lib/openvpn/plugins\" -std=c99 $CFLAGS \
+ -c $SRC/fuzz_${fuzzname}.c -o $SRC/fuzz_${fuzzname}.o
+
+ # Link with CXX
+ $CXX ${CXXFLAGS} ${LIB_FUZZING_ENGINE} $SRC/fuzz_${fuzzname}.o -o $OUT/fuzz_${fuzzname} $SRC/fuzz_randomizer.o \
+ libopenvpn.a ../../src/compat/.libs/libcompat.a /usr/lib/x86_64-linux-gnu/libnsl.a \
+ /usr/lib/x86_64-linux-gnu/libresolv.a /usr/lib/x86_64-linux-gnu/liblzo2.a \
+ -lssl -lcrypto -ldl
+done
diff --git a/projects/openvpn/crypto_patch.txt b/projects/openvpn/crypto_patch.txt
new file mode 100644
index 000000000..8caedaf26
--- /dev/null
+++ b/projects/openvpn/crypto_patch.txt
@@ -0,0 +1,109 @@
+diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
+index b9c95225..7adff4bb 100644
+--- a/src/openvpn/crypto.c
++++ b/src/openvpn/crypto.c
+@@ -133,7 +133,10 @@ openvpn_encrypt_aead(struct buffer *buf, struct buffer work,
+ ASSERT(buf_inc_len(&work, outlen));
+
+ /* Flush the encryption buffer */
+- ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
++ //ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
++ if (!(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen))) {
++ goto err;
++ }
+ ASSERT(buf_inc_len(&work, outlen));
+
+ /* Write authentication tag */
+@@ -737,6 +740,7 @@ warn_insecure_key_type(const char *ciphername, const cipher_kt_t *cipher)
+ /*
+ * Build a struct key_type.
+ */
++extern int fuzz_success;
+ void
+ init_key_type(struct key_type *kt, const char *ciphername,
+ const char *authname, bool tls_mode, bool warn)
+@@ -752,6 +756,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ kt->cipher = cipher_kt_get(ciphername);
+ if (!kt->cipher)
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "Cipher %s not supported", ciphername);
+ }
+
+@@ -766,11 +771,13 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ #endif
+ ))
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "Cipher '%s' mode not supported", ciphername);
+ }
+
+ if (OPENVPN_MAX_CIPHER_BLOCK_SIZE < cipher_kt_block_size(kt->cipher))
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "Cipher '%s' not allowed: block size too big.", ciphername);
+ }
+ if (warn)
+@@ -782,6 +789,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ {
+ if (warn)
+ {
++ fuzz_success = 0;
+ msg(M_WARN, "******* WARNING *******: '--cipher none' was specified. "
+ "This means NO encryption will be performed and tunnelled "
+ "data WILL be transmitted in clear text over the network! "
+@@ -797,6 +805,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+
+ if (OPENVPN_MAX_HMAC_SIZE < kt->hmac_length)
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "HMAC '%s' not allowed: digest size too big.", authname);
+ }
+ }
+@@ -805,6 +814,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ {
+ if (warn)
+ {
++ fuzz_success = 0;
+ msg(M_WARN, "******* WARNING *******: '--auth none' was specified. "
+ "This means no authentication will be performed on received "
+ "packets, meaning you CANNOT trust that the data received by "
+@@ -812,6 +822,7 @@ init_key_type(struct key_type *kt, const char *ciphername,
+ "PLEASE DO RECONSIDER THIS SETTING!");
+ }
+ }
++ fuzz_success = 1;
+ }
+
+ /* given a key and key_type, build a key_ctx */
+@@ -1037,6 +1048,7 @@ generate_key_random(struct key *key, const struct key_type *kt)
+ if (!rand_bytes(key->cipher, cipher_len)
+ || !rand_bytes(key->hmac, hmac_len))
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation");
+ }
+
+@@ -1050,6 +1062,7 @@ generate_key_random(struct key *key, const struct key_type *kt)
+ } while (kt && !check_key(key, kt));
+
+ gc_free(&gc);
++ fuzz_success = 1;
+ }
+
+ /*
+@@ -1390,10 +1403,14 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags)
+
+ if (state != PARSE_FINISHED)
+ {
++ fuzz_success = 0;
+ msg(M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",
+ print_key_filename(file, flags & RKF_INLINE), count, onekeylen,
+ keylen);
+ }
++ else {
++ fuzz_success = 1;
++ }
+ }
+
+ /* zero file read buffer if not an inline file */
diff --git a/projects/openvpn/fuzz.h b/projects/openvpn/fuzz.h
new file mode 100644
index 000000000..10e33c3ee
--- /dev/null
+++ b/projects/openvpn/fuzz.h
@@ -0,0 +1,47 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <fuzzer/FuzzedDataProvider.h>
+
+// Returns a NULL-terminated C string that should be freed by the caller.
+char *get_modifiable_string(FuzzedDataProvider &provider) {
+ std::string s1 = provider.ConsumeRandomLengthString();
+ char *tmp = (char *)malloc(s1.size() + 1);
+ memcpy(tmp, s1.c_str(), s1.size());
+ tmp[s1.size()] = '\0';
+ return tmp;
+}
+
+FuzzedDataProvider *prov = NULL;
+
+
+extern "C" ssize_t fuzz_get_random_data(void *buf, size_t len) {
+ size_t ret_val;
+ char *cbuf = (char*)buf;
+
+ if (prov->remaining_bytes() == 0) {
+ return -1;
+ }
+
+ double prob = prov->ConsumeProbability<double>();
+ if (prob < 0.05) {
+ return 0;
+ }
+
+ if (len == 1) {
+ ret_val = prov->ConsumeData(buf, 1);
+ return ret_val;
+ }
+ ret_val = prov->ConsumeData(buf, len);
+ return ret_val;
+}
+
diff --git a/projects/openvpn/fuzz_base64.c b/projects/openvpn/fuzz_base64.c
new file mode 100644
index 000000000..c9c45b84b
--- /dev/null
+++ b/projects/openvpn/fuzz_base64.c
@@ -0,0 +1,43 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base64.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size > 500) {
+ return 0;
+ }
+
+ char *new_str = (char *)malloc(size + 1);
+ if (new_str == NULL) {
+ return 0;
+ }
+ memcpy(new_str, data, size);
+ new_str[size] = '\0';
+
+ char *str = NULL;
+ openvpn_base64_encode(data, size, &str);
+ if(str != NULL) {
+ free(str);
+ }
+
+ uint16_t outsize = 10000;
+ char *output_buf = (char *)malloc(outsize);
+ openvpn_base64_decode(new_str, output_buf, outsize);
+ free(output_buf);
+
+ free(new_str);
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_buffer.c b/projects/openvpn/fuzz_buffer.c
new file mode 100644
index 000000000..af114ec5a
--- /dev/null
+++ b/projects/openvpn/fuzz_buffer.c
@@ -0,0 +1,266 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data,size);
+
+ struct gc_arena gc;
+ struct buffer *bufp;
+ struct buffer buf, buf2;
+ struct buffer_list *buflistp = NULL;
+ ssize_t generic_ssizet, _size;
+ char *tmp;
+ char *tmp2;
+ char match;
+
+ gc = gc_new();
+ bufp = NULL;
+
+ int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+ for (int i = 0; i < total_to_fuzz; i++) {
+ if (bufp == NULL) {
+ generic_ssizet = fuzz_randomizer_get_int(0, 1);
+ if (generic_ssizet == 0) {
+ _size = fuzz_randomizer_get_int(0, 100);
+ buf = alloc_buf_gc(_size, &gc);
+ bufp = &buf;
+ } else {
+ tmp = get_random_string();
+ buf = string_alloc_buf(tmp, &gc);
+ bufp = &buf;
+ free(tmp);
+ tmp = NULL;
+ }
+ } else {
+#define NUM_TARGETS 32
+ generic_ssizet = fuzz_randomizer_get_int(0, NUM_TARGETS);
+ switch (generic_ssizet) {
+ case 0:
+ buf_clear(bufp);
+ break;
+ case 1:
+ buf2 = clone_buf(bufp);
+ free_buf(&buf2);
+ break;
+ case 2:
+ buf_defined(bufp);
+ break;
+ case 3:
+ buf_valid(bufp);
+ break;
+ case 4:
+ buf_bptr(bufp);
+ break;
+ case 5:
+ buf_len(bufp);
+ break;
+ case 6:
+ buf_bend(bufp);
+ break;
+ case 7:
+ buf_blast(bufp);
+ break;
+ case 8:
+ buf_str(bufp);
+ break;
+ case 9:
+ generic_ssizet = fuzz_randomizer_get_int(0, 255);
+ buf_rmtail(bufp, (uint8_t)generic_ssizet);
+ break;
+ case 10:
+ buf_chomp(bufp);
+ break;
+ case 11:
+ tmp = get_random_string();
+ skip_leading_whitespace(tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 12:
+ tmp = get_random_string();
+ chomp(tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 13:
+ tmp = get_random_string();
+ tmp2 = get_random_string();
+ rm_trailing_chars(tmp, tmp2);
+ free(tmp);
+ free(tmp2);
+ tmp = NULL;
+ tmp2 = NULL;
+ break;
+ case 14:
+ tmp = get_random_string();
+ string_clear(tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 15:
+ tmp = get_random_string();
+ buf_string_match_head_str(bufp, tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 16:
+ tmp = get_random_string();
+ buf_string_compare_advance(bufp, tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 17:
+ generic_ssizet = fuzz_randomizer_get_int(0, 255);
+
+ tmp = get_random_string();
+ if (strlen(tmp) > 0) {
+ buf_parse(bufp, (int)generic_ssizet, tmp, strlen(tmp));
+ }
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 18:
+ tmp = get_random_string();
+ string_mod(tmp, fuzz_randomizer_get_int(0, 12312),
+ fuzz_randomizer_get_int(0, 23141234),
+ (char)fuzz_randomizer_get_int(0, 255));
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 19:
+ tmp = get_random_string();
+ match = (char)fuzz_randomizer_get_int(0, 255);
+ if (match != 0) {
+ string_replace_leading(tmp, match, (char)fuzz_randomizer_get_int(0, 255));
+ }
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 20:
+ tmp = get_random_string();
+ buf_write(bufp, tmp, strlen(tmp));
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 21:
+ tmp = get_random_string();
+
+ buf_write_prepend(bufp, tmp, strlen(tmp));
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 22:
+ buf_write_u8(bufp, fuzz_randomizer_get_int(0, 255));
+ break;
+ case 23:
+ buf_write_u16(bufp, fuzz_randomizer_get_int(0, 1024));
+ break;
+ case 24:
+ buf_write_u32(bufp, fuzz_randomizer_get_int(0, 12312));
+ break;
+ case 25:
+ tmp = get_random_string();
+ buf_catrunc(bufp, tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 26:
+ convert_to_one_line(bufp);
+ break;
+ case 27:
+ buf_advance(bufp, fuzz_randomizer_get_int(0, 25523));
+ break;
+ case 28:
+ buf_prepend(bufp, fuzz_randomizer_get_int(0, 251235));
+ break;
+ case 29:
+ buf_reverse_capacity(bufp);
+ break;
+ case 30:
+ buf_forward_capacity_total(bufp);
+ break;
+ case 31:
+ buf_forward_capacity(bufp);
+ break;
+ case 32:
+ tmp = get_random_string();
+ buf_puts(bufp, tmp);
+ free(tmp);
+ tmp = NULL;
+ break;
+ }
+ }
+
+ if (buflistp == NULL) {
+ buflistp = buffer_list_new(fuzz_randomizer_get_int(0, 200));
+ } else {
+#define NUM_LIST_TARGETS 6
+ generic_ssizet = fuzz_randomizer_get_int(0, NUM_LIST_TARGETS);
+ switch (generic_ssizet) {
+ case 0:
+ buffer_list_free(buflistp);
+ buflistp = NULL;
+ break;
+ case 1:
+ buffer_list_defined(buflistp);
+ break;
+ case 2:
+ tmp = get_random_string();
+ if (strlen(tmp) < BUF_SIZE_MAX) {
+ buffer_list_push(buflistp, tmp);
+ }
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 3:
+ buffer_list_peek(buflistp);
+ break;
+ case 4:
+ buffer_list_pop(buflistp);
+ break;
+ case 5:
+ tmp = get_random_string();
+ buffer_list_aggregate_separator(
+ buflistp, fuzz_randomizer_get_int(0, 1024), tmp);
+
+ free(tmp);
+ tmp = NULL;
+ break;
+ case 6:
+ buffer_list_aggregate(buflistp,
+ fuzz_randomizer_get_int(0, 1024));
+ break;
+ }
+ }
+ }
+
+ // Cleanup
+ buffer_list_free(buflistp);
+ gc_free(&gc);
+
+ fuzz_random_destroy();
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_crypto.c b/projects/openvpn/fuzz_crypto.c
new file mode 100644
index 000000000..e9a851be0
--- /dev/null
+++ b/projects/openvpn/fuzz_crypto.c
@@ -0,0 +1,257 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "fuzz_verify_cert.h"
+#include "misc.h"
+#include "manage.h"
+#include "otime.h"
+#include "base64.h"
+#include "ssl_verify.h"
+#include "ssl_verify_backend.h"
+
+#include "fuzz_randomizer.h"
+
+static void key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
+ size_t key_len) {
+ const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
+
+ /* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
+ if (cipher_kt_mode_aead(cipher_kt)) {
+ size_t impl_iv_len = 0;
+ ASSERT(cipher_kt_iv_size(cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN);
+ impl_iv_len = cipher_kt_iv_size(cipher_kt) - sizeof(packet_id_type);
+ ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
+ ASSERT(impl_iv_len <= key_len);
+ memcpy(ctx->implicit_iv, key, impl_iv_len);
+ ctx->implicit_iv_len = impl_iv_len;
+ }
+}
+
+static int init_frame(struct frame *frame) {
+ frame->link_mtu = fuzz_randomizer_get_int(100, 1000);
+ frame->extra_buffer = fuzz_randomizer_get_int(100, 1000);
+ frame->link_mtu_dynamic = fuzz_randomizer_get_int(100, 1000);
+ frame->extra_frame = fuzz_randomizer_get_int(100, 1000);
+ frame->extra_tun = fuzz_randomizer_get_int(100, 1000);
+ frame->extra_link = fuzz_randomizer_get_int(100, 1000);
+ frame->align_flags = 0;
+ frame->align_adjust = 0;
+ if (TUN_MTU_SIZE(frame) <= 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ OPENSSL_malloc_init();
+ SSL_library_init();
+ ERR_load_crypto_strings();
+
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_ssl_algorithms();
+
+ SSL_load_error_strings();
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data, size);
+ fuzz_success = 1;
+ bool key_ctx_dec_initialized = false;
+ bool key_ctx_enc_initialized = false;
+ struct key_ctx key_ctx_dec;
+ memset(&key_ctx_dec, 0, sizeof(struct key_ctx));
+ struct key_ctx key_ctx_enc;
+ memset(&key_ctx_enc, 0, sizeof(struct key_ctx));
+
+ struct gc_arena gc;
+ struct tls_session *session = NULL;
+ X509 *x509 = NULL;
+ gc = gc_new();
+
+ gb_init();
+
+ // Read key file
+ struct key2 key2;
+ char *keydata = gb_get_random_string();
+ read_key_file(&key2, keydata, RKF_INLINE);
+
+ // init key type
+ struct key_type kt;
+ memset(&kt, 0, sizeof(struct key_type));
+
+ char *ciphername = gb_get_random_string();
+ char *authname = gb_get_random_string();
+ bool key_type_initialized = false;
+
+ if (strcmp(ciphername, "AES-256-GCM") == 0 ||
+ strcmp(ciphername, "AES-128-GCM") == 0 ||
+ strcmp(ciphername, "AES-192-GCM") == 0 ||
+ strcmp(ciphername, "CAMELLIA-128-CFB128") == 0) {
+
+ int v = fuzz_randomizer_get_int(0, 1);
+ if (v == 0) {
+ init_key_type(&kt, ciphername, authname, true, 0);
+ } else {
+ init_key_type(&kt, ciphername, authname, false, 0);
+ }
+ key_type_initialized = true;
+ }
+
+ if (fuzz_success == 0) {
+ goto cleanup;
+ }
+
+ // Generate key.
+ // Identify which one we should do, read or generate a random key.
+ int c = fuzz_randomizer_get_int(0, 1);
+ const uint8_t d[1024];
+ int key_read = 0;
+ struct key key;
+ if (c == 0) {
+ if (fuzz_get_random_data(d, 1024) != 1024) {
+ struct buffer buf = alloc_buf(1024);
+ buf_write(&buf, d, 1024);
+ if (read_key(&key, &kt, &buf) == 1) {
+ key_read = 1;
+ }
+ free_buf(&buf);
+ }
+ }
+ else {
+ if (key_type_initialized == true) {
+ generate_key_random(&key, &kt);
+ }
+ }
+
+ if (fuzz_success == 0) {
+ goto cleanup;
+ }
+ key_read = 1;
+
+ // init decryption context
+ if (key_type_initialized && key_read) {
+ init_key_ctx(&key_ctx_dec, &key, &kt, OPENVPN_OP_DECRYPT, "x");
+ key_ctx_update_implicit_iv(&key_ctx_dec, &(key.hmac), MAX_HMAC_KEY_LENGTH);
+ key_ctx_dec_initialized = true;
+ }
+
+ // init encryption context
+ if (key_type_initialized && key_read) {
+ init_key_ctx(&key_ctx_enc, &key, &kt, OPENVPN_OP_DECRYPT, "x");
+ key_ctx_update_implicit_iv(&key_ctx_enc, &(key.hmac), MAX_HMAC_KEY_LENGTH);
+ key_ctx_enc_initialized = true;
+ }
+
+ // perform encryption
+ struct frame frame;
+ memset(&frame, 0, sizeof(struct frame));
+ if (key_ctx_enc_initialized == true && key_ctx_dec_initialized == true &&
+ init_frame(&frame) == 0) {
+ struct crypto_options opt;
+ memset(&opt, 0, sizeof(opt));
+ opt.pid_persist = NULL;
+ opt.key_ctx_bi.encrypt = key_ctx_enc;
+ opt.key_ctx_bi.decrypt = key_ctx_dec;
+ opt.key_ctx_bi.initialized = true;
+ opt.packet_id.rec.initialized = true;
+ opt.packet_id.rec.seq_list = NULL;
+ opt.packet_id.rec.name = NULL;
+
+ void *buf_p;
+
+ struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+ struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+ struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
+ struct buffer buf = clear_buf();
+
+ int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
+
+ ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
+ ASSERT(buf_init(&src, 0));
+ src.len = x;
+ ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
+
+ buf = work;
+ buf_p = buf_write_alloc(&buf, BLEN(&src));
+ ASSERT(buf_p);
+ memcpy(buf_p, BPTR(&src), BLEN(&src));
+
+ ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(&(frame))));
+
+ openvpn_encrypt(&buf, encrypt_workspace, &opt);
+ }
+
+ // perform decryption
+ memset(&frame, 0, sizeof(struct frame));
+ if (key_ctx_dec_initialized == true && key_ctx_enc_initialized == true &&
+ init_frame(&frame) == 0) {
+ struct crypto_options opt;
+ memset(&opt, 0, sizeof(opt));
+ opt.pid_persist = NULL;
+ opt.key_ctx_bi.encrypt = key_ctx_enc;
+ opt.key_ctx_bi.decrypt = key_ctx_dec;
+ opt.key_ctx_bi.initialized = true;
+ opt.packet_id.rec.initialized = true;
+ opt.packet_id.rec.seq_list = NULL;
+ opt.packet_id.rec.name = NULL;
+
+ void *buf_p;
+
+ struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+ struct buffer work = alloc_buf_gc(BUF_SIZE(&(frame)), &gc);
+ struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(&(frame)), &gc);
+ struct buffer buf = clear_buf();
+
+ int x = fuzz_randomizer_get_int(1, TUN_MTU_SIZE(&frame));
+
+ ASSERT(buf_init(&work, FRAME_HEADROOM(&(frame))));
+ ASSERT(buf_init(&src, 0));
+ src.len = x;
+ ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
+
+ buf = work;
+ buf_p = buf_write_alloc(&buf, BLEN(&src));
+ ASSERT(buf_p);
+ memcpy(buf_p, BPTR(&src), BLEN(&src));
+
+ ASSERT(buf_init(&decrypt_workspace, FRAME_HEADROOM(&(frame))));
+
+ openvpn_decrypt(&buf, decrypt_workspace, &opt, &frame, BPTR(&buf));
+ }
+
+cleanup:
+ // cleanup
+ gc_free(&gc);
+
+ if (key_ctx_dec_initialized == true) {
+ free_key_ctx(&key_ctx_dec);
+ }
+
+ if (key_ctx_enc_initialized == true) {
+ free_key_ctx(&key_ctx_enc);
+ }
+ fuzz_random_destroy();
+
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_dhcp.c b/projects/openvpn/fuzz_dhcp.c
new file mode 100644
index 000000000..1368ac2a1
--- /dev/null
+++ b/projects/openvpn/fuzz_dhcp.c
@@ -0,0 +1,37 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "dhcp.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ struct buffer ipbuf;
+ in_addr_t ret;
+
+ fuzz_random_init(data, size);
+ char *ran_val = get_random_string();
+
+ ipbuf = alloc_buf(strlen(ran_val));
+ if (buf_write(&ipbuf, ran_val, strlen(ran_val)) != false) {
+ ret = dhcp_extract_router_msg(&ipbuf);
+ }
+ free_buf(&ipbuf);
+
+ fuzz_random_destroy();
+ free(ran_val);
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_forward.c b/projects/openvpn/fuzz_forward.c
new file mode 100644
index 000000000..dff3e93d3
--- /dev/null
+++ b/projects/openvpn/fuzz_forward.c
@@ -0,0 +1,228 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "init.h"
+#include "buffer.h"
+#include "forward.h"
+
+#include "fuzz_randomizer.h"
+
+
+static int init_c2_outgoing_link(struct context_2 *c2, struct gc_arena *gc) {
+ struct link_socket_actual *to_link_addr = NULL;
+ struct link_socket *link_socket = NULL;
+ struct socks_proxy_info *socks_proxy = NULL;
+ struct buffer buf;
+
+ c2->tun_write_bytes = 0;
+ ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+ memset(link_socket, 0, sizeof(*link_socket));
+
+ c2->link_socket = link_socket;
+
+ if (fuzz_randomizer_get_int(0, 2) != 0) {
+ c2->link_socket->info.proto = PROTO_UDP;
+ } else {
+ c2->link_socket->info.proto = PROTO_TCP_SERVER;
+ }
+
+ ALLOC_ARRAY_GC(socks_proxy, struct socks_proxy_info, 1, gc);
+ memset(socks_proxy, 0, sizeof(*socks_proxy));
+ c2->link_socket->socks_proxy = socks_proxy;
+
+ c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff);
+ c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff);
+ c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+ c2->frame.link_mtu = fuzz_randomizer_get_int(0, 0xfffffff);
+
+ ALLOC_ARRAY_GC(to_link_addr, struct link_socket_actual, 1, gc);
+ memset(to_link_addr, 0, sizeof(*to_link_addr));
+ c2->to_link_addr = to_link_addr;
+
+ c2->to_link_addr->dest.addr.sa.sa_family = AF_INET;
+ c2->to_link_addr->dest.addr.in4.sin_addr.s_addr = 1;
+
+ char *tmp = get_random_string();
+ buf = alloc_buf_gc(strlen(tmp), gc);
+ buf_write(&buf, tmp, strlen(tmp));
+ int val = fuzz_randomizer_get_int(0, strlen(tmp));
+ buf.offset = val;
+ free(tmp);
+
+ c2->link_socket->stream_buf.maxlen = BLEN(&buf);
+ c2->to_link = buf;
+
+ if (buf.offset < 10) {
+ return -1;
+ }
+ return 0;
+}
+
+void fuzz_process_outgoing_link(const uint8_t *data, size_t size) {
+ struct context ctx;
+ struct gc_arena gc = gc_new();
+ memset(&ctx, 0, sizeof(ctx));
+
+ if (init_c2_outgoing_link(&ctx.c2, &gc) == 0) {
+ process_outgoing_link(&ctx);
+ }
+
+ gc_free(&gc);
+}
+
+static int _init_options(struct options *options, struct client_nat_entry **cne,
+ struct gc_arena *gc) {
+ options->passtos = false;
+ options->mode = MODE_POINT_TO_POINT;
+ options->allow_recursive_routing = true;
+ options->client_nat = new_client_nat_list(gc);
+
+ struct client_nat_entry *_cne;
+ ALLOC_ARRAY_GC(cne[0], struct client_nat_entry, 1, gc);
+ _cne = cne[0];
+ memset(_cne, 0, sizeof(struct client_nat_entry));
+
+ struct client_nat_option_list clist;
+ clist.n = 1;
+ clist.entries[0] = *_cne;
+ copy_client_nat_option_list(options->client_nat, &clist);
+ options->route_gateway_via_dhcp = false;
+
+ return 0;
+}
+
+static int init_c2_incoming_tun(struct context_2 *c2, struct gc_arena *gc) {
+ struct buffer buf;
+ memset(&buf, 0, sizeof(buf));
+
+ struct link_socket *link_socket = NULL;
+ ALLOC_ARRAY_GC(link_socket, struct link_socket, 1, gc);
+ c2->link_socket = link_socket;
+
+ ALLOC_OBJ_GC(c2->link_socket_info, struct link_socket_info, gc);
+ ALLOC_OBJ_GC(c2->link_socket_info->lsa, struct link_socket_addr, gc);
+ c2->link_socket_info->lsa->bind_local = NULL;
+ c2->link_socket_info->lsa->remote_list = NULL;
+ c2->link_socket_info->lsa->current_remote = NULL;
+ c2->link_socket_info->lsa->remote_list = NULL;
+ c2->es = env_set_create(gc);
+
+ c2->frame.link_mtu_dynamic = 0;
+ c2->frame.extra_frame = 0;
+ c2->frame.extra_tun = 0;
+ c2->to_link_addr = NULL;
+
+ char *tmp = get_random_string();
+ buf = alloc_buf(strlen(tmp));
+ buf_write(&buf, tmp, strlen(tmp));
+
+ int retval;
+ if (strlen(tmp) > 5) {
+ retval = 0;
+ } else {
+ retval = 1;
+ }
+
+ free(tmp);
+
+ c2->buf = buf;
+ c2->buffers = init_context_buffers(&c2->frame);
+ c2->log_rw = false;
+
+ return retval;
+}
+
+int run_process_incoming_tun(const uint8_t *data, size_t size) {
+ struct gc_arena gc;
+ struct context ctx;
+ struct client_nat_entry *cne[MAX_CLIENT_NAT];
+ struct route_list route_list;
+
+ memset(&ctx, 0, sizeof(ctx));
+ memset(cne, 0, sizeof(cne));
+
+ gc = gc_new();
+
+ _init_options(&ctx.options, cne, &gc);
+
+ // Init tuntap
+ struct tuntap tuntap;
+ tuntap.type = DEV_TYPE_TAP;
+
+ ctx.c1.tuntap = &tuntap;
+
+ int retval = init_c2_incoming_tun(&ctx.c2, &gc);
+ ctx.c1.route_list = &route_list;
+ if (retval == 0) {
+ process_incoming_tun(&ctx);
+ }
+
+ free(ctx.c2.buf.data);
+ free_context_buffers(ctx.c2.buffers);
+ gc_free(&gc);
+}
+
+static int init_c2_outgoing_tun(struct context_2 *c2, struct gc_arena *gc) {
+ struct buffer buf;
+
+ c2->tun_write_bytes = 0;
+ c2->frame.link_mtu_dynamic = fuzz_randomizer_get_int(0, 0xfffffff);
+ c2->frame.extra_frame = fuzz_randomizer_get_int(0, 0xfffffff);
+ c2->frame.extra_tun = fuzz_randomizer_get_int(0, 0xfffffff);
+
+ char *tmp = get_random_string();
+ buf = alloc_buf_gc(strlen(tmp), gc);
+ buf_write(&buf, tmp, strlen(tmp));
+ free(tmp);
+
+ c2->to_tun = buf;
+ return 0;
+}
+
+void run_process_outgoing_tun(uint8_t *data, size_t size) {
+ struct gc_arena gc;
+ struct context ctx;
+ struct tuntap tuntap;
+
+ memset(&ctx, 0, sizeof(ctx));
+ gc = gc_new();
+
+ tuntap.type = DEV_TYPE_TAP;
+ ctx.c1.tuntap = &tuntap;
+
+ init_c2_outgoing_tun(&ctx.c2, &gc);
+ process_outgoing_tun(&ctx);
+
+ gc_free(&gc);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data, size);
+
+ int dec = fuzz_randomizer_get_int(0, 2);
+ if (dec == 0) {
+ run_process_incoming_tun(data, size);
+ }
+ else if (dec == 1) {
+ run_process_outgoing_tun(data, size);
+ }
+ else {
+ fuzz_process_outgoing_link(data, size);
+ }
+
+ fuzz_random_destroy();
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_header.h b/projects/openvpn/fuzz_header.h
new file mode 100644
index 000000000..e86b70c62
--- /dev/null
+++ b/projects/openvpn/fuzz_header.h
@@ -0,0 +1,79 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 FUZZ_H
+#define FUZZ_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+// Forward declared because we want to use FuzzedDataProvider,
+// which requires CPP.
+extern ssize_t fuzz_get_random_data(void *buf, size_t len);
+
+ssize_t fuzz_recv(int sockfd, void *buf, size_t len, int flags){
+ return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_read(int sockfd, void *buf, size_t len){
+ return fuzz_get_random_data(buf, len);
+}
+
+ssize_t fuzz_write(int fd, const void *buf, size_t count) {
+ return count;
+}
+
+int fuzz_isatty(int fd) {
+ return 1;
+}
+
+char *fuzz_fgets(char *s, int size, FILE *stream) {
+ ssize_t v = fuzz_get_random_data(s, size-1);
+ // We use fgets to get trusted input. As such, assume we have
+ // an ascii printable char at the beginning.
+ printf("Calling into fgets\n");
+ if (s[0] <= 0x21 || s[0] >= 0x7f) {
+ s[0] = 'A';
+ }
+ s[size-1] = '\0';
+ return s;
+}
+
+int fuzz_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout) {
+ char val;
+ ssize_t c = fuzz_get_random_data(&val, 1);
+ return c;
+}
+
+ssize_t fuzz_send(int sockfd, const void *buf, size_t len, int flags) {
+ return len;
+}
+
+FILE *fp_p = NULL;
+FILE *fuzz_fopen(const char *pathname, const char *mode) {
+ if (mode == NULL) return fp_p;
+ return fp_p;
+}
+
+int fuzz_fclose(FILE *stream) {
+ if (stream == NULL) return 1;
+ return 2;
+}
+
+size_t fuzz_sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen) {
+ if (buf == NULL) {
+ return len;
+ }
+ return len;
+}
+
+#endif
diff --git a/projects/openvpn/fuzz_list.c b/projects/openvpn/fuzz_list.c
new file mode 100644
index 000000000..1e8fe621c
--- /dev/null
+++ b/projects/openvpn/fuzz_list.c
@@ -0,0 +1,135 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "list.h"
+
+#include "fuzz_randomizer.h"
+
+#define KEY_SIZE 23
+
+/* Required for hash_init() */
+static uint32_t word_hash_function(const void *key, uint32_t iv) {
+ return hash_func(key, KEY_SIZE, iv);
+}
+
+/* Required for hash_init() */
+static bool word_compare_function(const void *key1, const void *key2) {
+ return ((size_t)key1 & 0xFFF) == ((size_t)key1 & 0xFFF);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ struct gc_arena gc;
+ struct hash *hash = NULL;
+ ssize_t generic_ssizet, generic_ssizet2, num_loops;
+
+ fuzz_random_init(data, size);
+
+ gc = gc_new();
+
+ int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+ for (int i = 0; i < total_to_fuzz; i++) {
+ generic_ssizet = fuzz_randomizer_get_int(0, 8);
+
+ switch (generic_ssizet) {
+ case 0:
+ if (hash == NULL) {
+ int n_buckets = fuzz_randomizer_get_int(1, 1000);
+ uint32_t iv;
+
+ hash =
+ hash_init(n_buckets, iv, word_hash_function, word_compare_function);
+ }
+ break;
+ case 1:
+ if (hash) {
+ hash_free(hash);
+ hash = NULL;
+ }
+ break;
+ case 2:
+ if (hash) {
+ struct hash_iterator hi;
+ struct hash_element *he;
+ hash_iterator_init(hash, &hi);
+ while ((he = hash_iterator_next(&hi))) {
+ void *w = he->value;
+ }
+ hash_iterator_free(&hi);
+ }
+ break;
+ case 3:
+ if (hash) {
+ void *key;
+ void *value;
+ char arr[KEY_SIZE];
+ memset(arr, 0, KEY_SIZE);
+ fuzz_get_random_data(arr, KEY_SIZE);
+ key = (void *)arr;
+ if (!hash_lookup(hash, key)) {
+ generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+ value = (void *)generic_ssizet;
+ hash_add(hash, key, value, false);
+ }
+ }
+ break;
+ case 4:
+ if (hash) {
+ hash_n_elements(hash);
+ }
+ break;
+ case 5:
+ if (hash) {
+ hash_n_buckets(hash);
+ }
+ break;
+ case 6:
+ if (hash) {
+ uint32_t hv;
+ generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+ hv = generic_ssizet;
+ hash_bucket(hash, hv);
+ }
+ break;
+ case 7:
+ if (hash) {
+ void *key;
+ char arr[KEY_SIZE];
+ memset(arr, 0, KEY_SIZE);
+ fuzz_get_random_data(arr, KEY_SIZE);
+ key = (void *)arr;
+ hash_remove(hash, key);
+ }
+ break;
+ case 8:
+ if (hash) {
+ void *value;
+ generic_ssizet = fuzz_randomizer_get_int(0, 0xfffffff);
+ value = (void *)generic_ssizet;
+ hash_remove_by_value(hash, value);
+ }
+ default:
+ break;
+ }
+ }
+
+ if (hash) {
+ hash_free(hash);
+ }
+
+ gc_free(&gc);
+
+ fuzz_random_destroy();
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_misc.c b/projects/openvpn/fuzz_misc.c
new file mode 100644
index 000000000..06d7b3259
--- /dev/null
+++ b/projects/openvpn/fuzz_misc.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "misc.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data, size);
+
+ struct gc_arena gc;
+ struct env_set *es;
+ gc = gc_new();
+ es = env_set_create(&gc);
+
+ int total_to_fuzz = fuzz_randomizer_get_int(1, 9);
+ for (int i = 0; i <total_to_fuzz; i++) {
+ int type = fuzz_randomizer_get_int(0, 5);
+ char *tmp1 = get_random_string();
+ char *tmp2 = get_random_string();
+
+ switch (type) {
+ case 0:
+ env_set_del(es, tmp1);
+ break;
+ case 1:
+ env_set_add(es, tmp1);
+ break;
+ case 2:
+ env_set_get(es, tmp1);
+ break;
+ case 3:
+ if (strlen(tmp1) > 1 && strlen(tmp2) > 1) {
+ setenv_str(es, tmp2, tmp1);
+ }
+ break;
+ case 4:
+ hostname_randomize(tmp1, &gc);
+ break;
+ case 5:
+ if (strlen(tmp1) > 0) {
+ get_auth_challenge(tmp1, &gc);
+ }
+ break;
+ default:
+ sanitize_control_message(tmp1, &gc);
+ }
+ free(tmp1);
+ free(tmp2);
+ }
+
+ env_set_destroy(es);
+ gc_free(&gc);
+
+ fuzz_random_destroy();
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_mroute.c b/projects/openvpn/fuzz_mroute.c
new file mode 100644
index 000000000..63d0ce23d
--- /dev/null
+++ b/projects/openvpn/fuzz_mroute.c
@@ -0,0 +1,70 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "init.h"
+#include "mroute.h"
+
+#include "fuzz_randomizer.h"
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ fuzz_random_init(data, size);
+ struct buffer buf;
+ struct gc_arena gc;
+
+ gc = gc_new();
+
+ char *tmp = get_random_string();
+ buf = string_alloc_buf(tmp, &gc);
+ free(tmp);
+
+ struct mroute_addr src_addr;
+ struct mroute_addr dst_addr;
+ mroute_addr_init(&src_addr);
+ mroute_addr_init(&dst_addr);
+ unsigned int ret = mroute_extract_addr_ip(&src_addr, &dst_addr, &buf);
+
+ if (ret & MROUTE_EXTRACT_SUCCEEDED) {
+ mroute_addr_mask_host_bits(&src_addr);
+ mroute_addr_print(&src_addr, &gc);
+ mroute_learnable_address(&src_addr, &gc);
+ }
+
+ uint16_t vid;
+ struct mroute_addr a1, a2;
+ mroute_addr_init(&a1);
+ mroute_addr_init(&a2);
+ mroute_extract_addr_ether(&a1, &a2, vid, &buf);
+
+ if (size > sizeof(struct openvpn_sockaddr)) {
+ struct openvpn_sockaddr local_sock;
+ memcpy(&local_sock, data, sizeof(struct openvpn_sockaddr));
+ mroute_extract_openvpn_sockaddr(&a1, &local_sock, true);
+ mroute_extract_openvpn_sockaddr(&a1, &local_sock, false);
+ }
+
+ struct mroute_helper *mhelper = NULL;
+ mhelper = mroute_helper_init(fuzz_randomizer_get_int(0, 0xfffffff));
+ if (mhelper != NULL) {
+ mroute_helper_add_iroute46(mhelper, fuzz_randomizer_get_int(0, MR_HELPER_NET_LEN-1));
+ mroute_helper_free(mhelper);
+ }
+
+ gc_free(&gc);
+
+ fuzz_random_destroy();
+ return 0;
+}
+
diff --git a/projects/openvpn/fuzz_packet_id.c b/projects/openvpn/fuzz_packet_id.c
new file mode 100644
index 000000000..9297d0be5
--- /dev/null
+++ b/projects/openvpn/fuzz_packet_id.c
@@ -0,0 +1,104 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "init.h"
+#include "packet_id.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data, size);
+
+ struct packet_id pid;
+ struct packet_id_net pin;
+ const int seq_backtrack = 10;
+ const int time_backtrack = 10;
+
+ packet_id_init(&pid, seq_backtrack, time_backtrack, "name", 0);
+
+ int total_sends = fuzz_randomizer_get_int(0, 10);
+ for (int i = 0; i < total_sends; i++) {
+ update_time();
+ pin.time = fuzz_randomizer_get_int(0, 0xfffffff);
+ pin.id = fuzz_randomizer_get_int(0, 0xfffffff);
+
+ packet_id_reap_test(&pid.rec);
+ bool test = packet_id_test(&pid.rec, &pin);
+ if (test) {
+ packet_id_add(&pid.rec, &pin);
+ }
+ }
+ packet_id_free(&pid);
+
+ // packet id send
+ char *tmp2 = get_random_string();
+ if (strlen(tmp2) > sizeof(struct packet_id_send)) {
+ struct packet_id_send pidsend;
+ memcmp(&pidsend, tmp2, sizeof(struct packet_id_send));
+
+ struct timeval tv;
+ tv.tv_sec = pidsend.time;
+ tv.tv_usec = 0;
+ if (localtime(&tv)) {
+ struct buffer iv_buffer;
+ buf_set_write(&iv_buffer, tmp2, strlen(tmp2));
+ packet_id_write(&pidsend, &iv_buffer, false, false);
+ packet_id_write(&pidsend, &iv_buffer, false, true);
+ packet_id_write(&pidsend, &iv_buffer, true, true);
+ packet_id_write(&pidsend, &iv_buffer, true, false);
+ }
+ }
+ free(tmp2);
+
+ struct gc_arena gc;
+ gc = gc_new();
+ struct buffer buf;
+ char *tmp = get_random_string();
+ buf = string_alloc_buf(tmp, &gc);
+ free(tmp);
+ packet_id_read(&pid, &buf, false);
+ packet_id_read(&pid, &buf, true);
+ gc_free(&gc);
+
+ 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);
+
+ struct packet_id_persist p;
+ memset(&p, 0, sizeof(struct packet_id_persist));
+ packet_id_persist_init(&p);
+ packet_id_persist_load(&p, filename);
+ //p.time = NULL;
+ struct timeval tv;
+ tv.tv_sec = p.time;
+ tv.tv_usec = 0;
+ if (localtime(&tv) != NULL) {
+ gc = gc_new();
+ p.id_last_written = fuzz_randomizer_get_int(0, 0xfffffff);
+ //packet_id_persist_print(&p, &gc);
+ packet_id_persist_save(&p);
+ gc_free(&gc);
+ }
+
+ packet_id_persist_close(&p);
+
+ fuzz_random_destroy();
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_proxy.c b/projects/openvpn/fuzz_proxy.c
new file mode 100644
index 000000000..128a6d077
--- /dev/null
+++ b/projects/openvpn/fuzz_proxy.c
@@ -0,0 +1,144 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <sys/time.h>
+#include "syshead.h"
+#include "interval.h"
+#include "proxy.h"
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerInitialize(int *argc, char ***argv)
+{
+ OPENSSL_malloc_init();
+ SSL_library_init();
+ ERR_load_crypto_strings();
+
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_ssl_algorithms();
+ OpenSSL_add_all_digests();
+
+ SSL_load_error_strings();
+ return 1;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ char *tmp = NULL;
+ char *tmp2 = NULL;
+
+ if (size < 500) {
+ return 0;
+ }
+ fuzz_random_init(data, size);
+
+ struct gc_arena gc = gc_new();
+ struct http_proxy_info pi;
+ ssize_t generic_ssizet;
+ int signal_received = 0;
+ struct buffer lookahead = alloc_buf(1024);
+ struct event_timeout evt;
+
+ memset(&evt, 0, sizeof(struct event_timeout));
+ memset(&pi, 0, sizeof(struct http_proxy_info));
+ memset(&pi, 0, sizeof(pi));
+
+ generic_ssizet = 0;
+ char *fuzz_usrnm = fuzz_random_get_string_max_length(USER_PASS_LEN);
+ strcpy(pi.up.username, fuzz_usrnm);
+ if (strlen(pi.up.username) == 0) {
+ gc_free(&gc);
+ free_buf(&lookahead);
+ free(fuzz_usrnm);
+ fuzz_random_destroy();
+ return 0;
+ }
+
+ char *pswd = fuzz_random_get_string_max_length(USER_PASS_LEN);
+ strcpy(pi.up.password, pswd);
+ if (strlen(pi.up.password) == 0) {
+ gc_free(&gc);
+ free_buf(&lookahead);
+
+ free(pswd);
+ free(fuzz_usrnm);
+ fuzz_random_destroy();
+ return 0;
+ }
+
+ generic_ssizet = fuzz_randomizer_get_int(0, 4);
+ switch (generic_ssizet) {
+ case 0:
+ pi.auth_method = HTTP_AUTH_NONE;
+ break;
+ case 1:
+ pi.auth_method = HTTP_AUTH_BASIC;
+ break;
+ case 2:
+ pi.auth_method = HTTP_AUTH_DIGEST;
+ break;
+ case 3:
+ pi.auth_method = HTTP_AUTH_NTLM;
+ break;
+ case 4:
+ pi.auth_method = HTTP_AUTH_NTLM2;
+ break;
+ }
+ pi.options.http_version = "1.1";
+
+ generic_ssizet = fuzz_randomizer_get_int(0, 4);
+ switch (generic_ssizet) {
+ case 0:
+ pi.options.auth_retry = PAR_NO;
+ break;
+ case 1:
+ pi.options.auth_retry = PAR_ALL;
+ break;
+ case 2:
+ pi.options.auth_retry = PAR_NCT;
+ break;
+ }
+
+ char *tmp_authenticate = get_random_string();
+ pi.proxy_authenticate = tmp_authenticate;
+
+ //if (provider.ConsumeProbability<double>() < 0.5) {
+ //tmp = get_modifiable_string(provider);
+ tmp = get_random_string();
+ pi.options.custom_headers[0].name = tmp;
+ //if (provider.ConsumeProbability<double>() < 0.5) {
+ //tmp2 = get_modifiable_string(provider);
+ tmp2 = get_random_string();
+ pi.options.custom_headers[0].content = tmp2;
+ //}
+ //}
+
+ establish_http_proxy_passthru(&pi, 0, "1.2.3.4", "777", &evt, &lookahead,
+ &signal_received);
+ free(pi.proxy_authenticate);
+ gc_free(&gc);
+ free_buf(&lookahead);
+
+ if (tmp != NULL) free(tmp);
+ if (tmp2 != NULL) free(tmp2);
+
+ free(pswd);
+ free(fuzz_usrnm);
+ fuzz_random_destroy();
+
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_randomizer.cpp b/projects/openvpn/fuzz_randomizer.cpp
new file mode 100644
index 000000000..367c55862
--- /dev/null
+++ b/projects/openvpn/fuzz_randomizer.cpp
@@ -0,0 +1,107 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <fuzzer/FuzzedDataProvider.h>
+#include <assert.h>
+
+FuzzedDataProvider *prov = NULL;
+
+extern "C" void fuzz_random_init(const uint8_t *data, size_t size) {
+ assert(prov == NULL);
+ prov = new FuzzedDataProvider(data, size);
+}
+
+extern "C" void fuzz_random_destroy() {
+ assert(prov != NULL);
+ delete prov;
+ prov = NULL;
+}
+
+extern "C" char *get_random_string() {
+ assert(prov != NULL);
+
+ std::string s1 = prov->ConsumeRandomLengthString();
+ char *tmp = (char *)malloc(s1.size() + 1);
+ memcpy(tmp, s1.c_str(), s1.size());
+ tmp[s1.size()] = '\0';
+ return tmp;
+}
+
+extern "C" int fuzz_randomizer_get_int(int min, int max) {
+ assert(prov != NULL);
+ return prov->ConsumeIntegralInRange<int>(min, max);
+}
+
+extern "C" char *fuzz_random_get_string_max_length(int max_len) {
+ assert(prov != NULL);
+
+ std::string s1 = prov->ConsumeBytesAsString(
+ prov->ConsumeIntegralInRange<uint32_t>(1, max_len));
+ char *tmp123 = (char*)malloc(s1.size()+1);
+ memcpy(tmp123, s1.c_str(), s1.size());
+ tmp123[s1.size()] = '\0';
+
+ return tmp123;
+}
+
+extern "C" size_t fuzz_get_random_data(void *buf, size_t len) {
+ assert(prov != NULL);
+ size_t ret_val;
+ char *cbuf = (char*)buf;
+
+ if (prov->remaining_bytes() == 0) {
+ return -1;
+ }
+
+ double prob = prov->ConsumeProbability<double>();
+ if (prob < 0.05) {
+ return 0;
+ }
+
+ //if (len == 1) {
+ // ret_val = prov->ConsumeData(buf, 1);
+ // return ret_val;
+ //}
+ ret_val = prov->ConsumeData(buf, len);
+ return ret_val;
+}
+
+
+// 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.
+extern "C" void gb_init() {
+ pointer_idx = 0;
+
+ for (int i = 0; i < GB_SIZE; i++) {
+ pointer_arr[i] = NULL;
+ }
+}
+
+extern "C" void gb_cleanup() {
+ for(int i = 0; i < GB_SIZE; i++) {
+ if (pointer_arr[i] != NULL) {
+ free(pointer_arr[i]);
+ }
+ }
+}
+
+extern "C" char *gb_get_random_string() {
+ char *tmp = get_random_string();
+ pointer_arr[pointer_idx++] = (void*)tmp;
+ return tmp;
+}
+
diff --git a/projects/openvpn/fuzz_randomizer.h b/projects/openvpn/fuzz_randomizer.h
new file mode 100644
index 000000000..a063ecac6
--- /dev/null
+++ b/projects/openvpn/fuzz_randomizer.h
@@ -0,0 +1,27 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdio.h>
+#include <stdint.h>
+
+void fuzz_random_init(const uint8_t *data, size_t size);
+void fuzz_random_destroy();
+char *get_random_string();
+int fuzz_randomizer_get_int(int min, int max);
+size_t fuzz_get_random_data(void *buf, size_t len);
+char *fuzz_random_get_string_max_length(int max_len);
+
+void gb_init();
+void gb_cleanup();
+char *gb_get_random_string();
+
+int fuzz_success;
diff --git a/projects/openvpn/fuzz_route.c b/projects/openvpn/fuzz_route.c
new file mode 100644
index 000000000..2ca27a39a
--- /dev/null
+++ b/projects/openvpn/fuzz_route.c
@@ -0,0 +1,201 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+#include "init.h"
+#include "proxy.h"
+#include "interval.h"
+#include "route.h"
+#include "buffer.h"
+
+#include "fuzz_randomizer.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ fuzz_random_init(data, size);
+
+ gb_init();
+
+ struct route_option_list *opt;
+ struct route_list rl;
+
+ int route_list_inited = 0;
+ int route_list_ipv6_inited = 0;
+
+ struct context c;
+ memset(&c, 0, sizeof(struct context));
+ gc_init(&c.gc);
+ c.es = env_set_create(&c.gc);
+ init_options(&c.options, true);
+ net_ctx_init(&c, &c.net_ctx);
+ init_verb_mute(&c, IVM_LEVEL_1);
+
+ init_options_dev(&c.options);
+
+ // options_postprocess(&c.options);
+ pre_setup(&c.options);
+
+ setenv_settings(c.es, &c.options);
+
+ ALLOC_OBJ_CLEAR_GC(c.options.connection_list, struct connection_list,
+ &c.options.gc);
+ context_init_1(&c);
+
+ in_addr_t remote_host;
+ ssize_t default_metric;
+
+ struct route_ipv6_list rl6;
+ struct route_ipv6_option_list *opt6;
+
+ memset(&rl, 0, sizeof(rl));
+ memset(&rl6, 0, sizeof(rl6));
+ memset(&opt, 0, sizeof(opt));
+ memset(&opt6, 0, sizeof(opt6));
+
+ opt6 = new_route_ipv6_option_list(&c.gc);
+ opt = new_route_option_list(&c.gc);
+
+ int total_to_fuzz = fuzz_randomizer_get_int(1, 20);
+ for (int i = 0; i < total_to_fuzz; i++) {
+ int selector = fuzz_randomizer_get_int(0, 13);
+ switch (selector) {
+ case 0:
+ if (route_list_inited == 0) {
+ const char *remote_endpoint = gb_get_random_string();
+ memset(&rl, 0, sizeof(struct route_list));
+ rl.flags = fuzz_randomizer_get_int(0, 0xffffff);
+
+ init_route_list(&rl, opt, remote_endpoint, default_metric, remote_host,
+ c.es, &c);
+ route_list_inited = 1;
+ }
+ break;
+ case 1:
+ if (route_list_inited) {
+ in_addr_t addr;
+ route_list_add_vpn_gateway(&rl, c.es, addr);
+ }
+ break;
+ case 2:
+ if (route_list_inited && route_list_ipv6_inited) {
+ struct tuntap tt;
+ memset(&tt, 0, sizeof(tt));
+ add_routes(&rl, &rl6, &tt, 0, c.es, &c);
+ }
+ break;
+ case 3:
+ if (route_list_inited) {
+ setenv_routes(c.es, &rl);
+ }
+ break;
+ case 4:
+ if (route_list_inited) {
+ struct route_ipv4 r;
+ struct route_option ro;
+ ro.network = gb_get_random_string();
+ ro.netmask = gb_get_random_string();
+ ro.gateway = gb_get_random_string();
+ ro.metric = gb_get_random_string();
+ ro.next = NULL;
+
+ memset(&r, 0, sizeof(struct route_ipv4));
+ r.option = &ro;
+ r.flags = RT_DEFINED;
+ add_route(&r, NULL, 0, NULL, c.es, &c);
+ }
+ break;
+ case 5:
+ if (route_list_inited) {
+ char *s1 = get_random_string();
+ is_special_addr(s1);
+ free(s1);
+ }
+ break;
+ case 6:
+ if (route_list_ipv6_inited == 0) {
+ const char *remote_endpoint = gb_get_random_string();
+ memset(&rl, 0, sizeof(struct route_list));
+ struct in6_addr remote_host;
+
+ rl6.rgi6.flags = fuzz_randomizer_get_int(0, 0xffffff);
+ fuzz_get_random_data(&rl6.rgi6.hwaddr, 6);
+
+ char *t1 = gb_get_random_string();
+ if (strlen(t1) > 16) {
+ memcpy(rl6.rgi6.iface, t1, 16);
+ } else {
+ memcpy(rl6.rgi6.iface, t1, strlen(t1));
+ }
+
+ init_route_ipv6_list(&rl6, opt6, remote_endpoint, 0, &remote_host, c.es,
+ &c);
+ route_list_ipv6_inited = 1;
+ }
+ break;
+ case 7: {
+ unsigned int flags;
+ struct route_ipv6 r6;
+ struct tuntap tt;
+ memset(&tt, 0, sizeof(tt));
+ tt.actual_name = gb_get_random_string();
+ r6.iface = gb_get_random_string();
+ r6.flags = fuzz_randomizer_get_int(0, 0xfffff);
+ r6.netbits = fuzz_randomizer_get_int(0, 0xfffff);
+ r6.metric = fuzz_randomizer_get_int(0, 0xfffff);
+
+ r6.next = NULL;
+
+ add_route_ipv6(&r6, &tt, 0, c.es, &c);
+ } break;
+ case 8:
+ if (route_list_ipv6_inited && route_list_inited) {
+ delete_routes(&rl, &rl6, NULL, 0, c.es, &c);
+ route_list_ipv6_inited = 0;
+ route_list_inited = 0;
+ }
+ break;
+ case 9:
+ if (route_list_ipv6_inited) {
+ setenv_routes_ipv6(c.es, &rl6);
+ }
+ break;
+ case 10: {
+ add_route_ipv6_to_option_list(opt6, gb_get_random_string(),
+ gb_get_random_string(),
+ gb_get_random_string());
+ } break;
+ case 11: {
+ print_route_options(opt, M_NONFATAL);
+ } break;
+ case 12: {
+ add_route_to_option_list(opt, gb_get_random_string(),
+ gb_get_random_string(), gb_get_random_string(),
+ gb_get_random_string());
+ } break;
+ default:
+ break;
+ }
+ }
+
+ if (route_list_inited) {
+ gc_free(&rl.gc);
+ }
+ env_set_destroy(c.es);
+ context_gc_free(&c);
+
+ fuzz_random_destroy();
+
+ gb_cleanup();
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_verify_cert.c b/projects/openvpn/fuzz_verify_cert.c
new file mode 100644
index 000000000..c73a6ac82
--- /dev/null
+++ b/projects/openvpn/fuzz_verify_cert.c
@@ -0,0 +1,167 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "syshead.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "fuzz_verify_cert.h"
+#include "misc.h"
+#include "manage.h"
+#include "otime.h"
+#include "base64.h"
+#include "ssl_verify.h"
+#include "ssl_verify_backend.h"
+
+#include "fuzz_randomizer.h"
+
+
+static int parse_x509(const uint8_t *data, size_t size, X509 **out) {
+ *out = d2i_X509(NULL, (const unsigned char **)&data, size);
+ if (*out == NULL) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ OPENSSL_malloc_init();
+ SSL_library_init();
+ ERR_load_crypto_strings();
+
+ OpenSSL_add_all_algorithms();
+ OpenSSL_add_ssl_algorithms();
+
+ SSL_load_error_strings();
+ return 1;
+}
+
+
+static int init_session_opt(struct tls_options **_opt, struct gc_arena *gc) {
+ ssize_t nid;
+ ssize_t generic_ssizet;
+ struct tls_options *opt;
+ int r;
+
+ ALLOC_OBJ_GC(*_opt, struct tls_options, gc);
+ if (opt == NULL) {
+ return -1;
+ }
+
+ opt = *_opt;
+
+ memset(opt, 0xFE, sizeof(struct tls_options));
+
+ opt->es = env_set_create(gc);
+ opt->x509_username_field[0] = NULL;
+ opt->remote_cert_eku = NULL;
+
+ /* Prevents failure if x509 sha1 hashes do not match */
+ opt->verify_hash = NULL;
+
+ /* Prevent attempt to run --tls-verify script */
+ opt->verify_command = NULL;
+
+ /* Do not verify against CRL file */
+ opt->crl_file = NULL;
+
+ /* Do not run --tls-verify plugins */
+ opt->plugins = NULL;
+
+ r = fuzz_randomizer_get_int(0, 1);
+ if (r == 0) {
+ opt->x509_username_field[0] = nidstrs[fuzz_randomizer_get_int(0, (sizeof(nidstrs)/sizeof(nidstrs[0])) - 1)];
+ }
+ else {
+ opt->x509_username_field[0] = "ext:subjectAltName";
+ }
+ opt->x509_username_field[1] = NULL;
+
+ r = fuzz_randomizer_get_int(0, 2);
+ if (r == 0)
+ opt->ns_cert_type = NS_CERT_CHECK_CLIENT;
+ else if (r == 1)
+ opt->ns_cert_type = NS_CERT_CHECK_SERVER;
+ else
+ opt->ns_cert_type = NS_CERT_CHECK_NONE;
+
+ opt->x509_track = NULL;
+
+ r = fuzz_randomizer_get_int(0, 1);
+ if (r == 0)
+ opt->remote_cert_eku = NULL;
+ else
+ opt->remote_cert_eku = get_random_string();
+
+ return 0;
+}
+
+
+static int init_session(struct tls_session **_session, struct gc_arena *gc) {
+ struct tls_session *session;
+
+ ALLOC_OBJ_GC(*_session, struct tls_session, gc);
+ if (*_session == NULL) {
+ return -1;
+ }
+
+ session = *_session;
+ memset(session, 0xFE, sizeof(struct tls_session));
+
+ /* Accessed in set_common_name() */
+ session->common_name = get_random_string();;
+
+ /* Initialize the session->opt structure */
+ if (init_session_opt(&(session->opt), gc) == -1) {
+ free(session->common_name);
+ return -1;
+ }
+
+ /* Accessed in server_untrusted() */
+ session->untrusted_addr.dest.addr.sa.sa_family = AF_UNSPEC;
+
+ return 0;
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ fuzz_random_init(data, size);
+
+ struct gc_arena gc;
+ struct tls_session *session = NULL;
+ X509 *x509 = NULL;
+ gc = gc_new();
+
+ if (parse_x509(data, size, &x509) == 0) {
+ if (init_session(&session, &gc) == 0) {
+ verify_cert(session, x509, 100);
+ if (session->opt->remote_cert_eku != NULL) {
+ free(session->opt->remote_cert_eku);
+ }
+ free(session->common_name);
+ }
+
+ }
+
+ X509_free(x509);
+ gc_free(&gc);
+
+ fuzz_random_destroy();
+
+ return 0;
+}
diff --git a/projects/openvpn/fuzz_verify_cert.h b/projects/openvpn/fuzz_verify_cert.h
new file mode 100644
index 000000000..8a53669b3
--- /dev/null
+++ b/projects/openvpn/fuzz_verify_cert.h
@@ -0,0 +1,1065 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+static char* nidstrs[] = {
+"AD_DVCS",
+"AES-128-CBC",
+"AES-128-CBC-HMAC-SHA1",
+"AES-128-CBC-HMAC-SHA256",
+"AES-128-CFB",
+"AES-128-CFB1",
+"AES-128-CFB8",
+"AES-128-CTR",
+"AES-128-ECB",
+"AES-128-OCB",
+"AES-128-OFB",
+"AES-128-XTS",
+"AES-192-CBC",
+"AES-192-CBC-HMAC-SHA1",
+"AES-192-CBC-HMAC-SHA256",
+"AES-192-CFB",
+"AES-192-CFB1",
+"AES-192-CFB8",
+"AES-192-CTR",
+"AES-192-ECB",
+"AES-192-OCB",
+"AES-192-OFB",
+"AES-256-CBC",
+"AES-256-CBC-HMAC-SHA1",
+"AES-256-CBC-HMAC-SHA256",
+"AES-256-CFB",
+"AES-256-CFB1",
+"AES-256-CFB8",
+"AES-256-CTR",
+"AES-256-ECB",
+"AES-256-OCB",
+"AES-256-OFB",
+"AES-256-XTS",
+"AuthDSS",
+"AuthECDSA",
+"AuthGOST01",
+"AuthGOST12",
+"AuthNULL",
+"AuthPSK",
+"AuthRSA",
+"AuthSRP",
+"BF-CBC",
+"BF-CFB",
+"BF-ECB",
+"BF-OFB",
+"BLAKE2b512",
+"BLAKE2s256",
+"C",
+"CAMELLIA-128-CBC",
+"CAMELLIA-128-CCM",
+"CAMELLIA-128-CFB",
+"CAMELLIA-128-CFB1",
+"CAMELLIA-128-CFB8",
+"CAMELLIA-128-CMAC",
+"CAMELLIA-128-CTR",
+"CAMELLIA-128-ECB",
+"CAMELLIA-128-GCM",
+"CAMELLIA-128-OFB",
+"CAMELLIA-192-CBC",
+"CAMELLIA-192-CCM",
+"CAMELLIA-192-CFB",
+"CAMELLIA-192-CFB1",
+"CAMELLIA-192-CFB8",
+"CAMELLIA-192-CMAC",
+"CAMELLIA-192-CTR",
+"CAMELLIA-192-ECB",
+"CAMELLIA-192-GCM",
+"CAMELLIA-192-OFB",
+"CAMELLIA-256-CBC",
+"CAMELLIA-256-CCM",
+"CAMELLIA-256-CFB",
+"CAMELLIA-256-CFB1",
+"CAMELLIA-256-CFB8",
+"CAMELLIA-256-CMAC",
+"CAMELLIA-256-CTR",
+"CAMELLIA-256-ECB",
+"CAMELLIA-256-GCM",
+"CAMELLIA-256-OFB",
+"CAST5-CBC",
+"CAST5-CFB",
+"CAST5-ECB",
+"CAST5-OFB",
+"CMAC",
+"CN",
+"CRLReason",
+"CSPName",
+"ChaCha20",
+"ChaCha20-Poly1305",
+"CrlID",
+"DC",
+"DES-CBC",
+"DES-CDMF",
+"DES-CFB",
+"DES-CFB1",
+"DES-CFB8",
+"DES-ECB",
+"DES-EDE",
+"DES-EDE-CBC",
+"DES-EDE-CFB",
+"DES-EDE-OFB",
+"DES-EDE3",
+"DES-EDE3-CBC",
+"DES-EDE3-CFB",
+"DES-EDE3-CFB1",
+"DES-EDE3-CFB8",
+"DES-EDE3-OFB",
+"DES-OFB",
+"DESX-CBC",
+"DOD",
+"DSA",
+"DSA-SHA",
+"DSA-SHA1",
+"DSA-SHA1-old",
+"DSA-old",
+"DVCS",
+"GN",
+"HKDF",
+"HMAC",
+"HMAC-MD5",
+"HMAC-SHA1",
+"IANA",
+"IDEA-CBC",
+"IDEA-CFB",
+"IDEA-ECB",
+"IDEA-OFB",
+"INN",
+"ISO",
+"ISO-US",
+"ITU-T",
+"JOINT-ISO-ITU-T",
+"KISA",
+"KxDHE",
+"KxDHE-PSK",
+"KxECDHE",
+"KxECDHE-PSK",
+"KxGOST",
+"KxPSK",
+"KxRSA",
+"KxRSA_PSK",
+"KxSRP",
+"L",
+"LocalKeySet",
+"MD2",
+"MD4",
+"MD5",
+"MD5-SHA1",
+"MDC2",
+"MGF1",
+"Mail",
+"NULL",
+"Netscape",
+"Nonce",
+"O",
+"OCSP",
+"OCSPSigning",
+"OGRN",
+"ORG",
+"OU",
+"Oakley-EC2N-3",
+"Oakley-EC2N-4",
+"PBE-MD2-DES",
+"PBE-MD2-RC2-64",
+"PBE-MD5-DES",
+"PBE-MD5-RC2-64",
+"PBE-SHA1-2DES",
+"PBE-SHA1-3DES",
+"PBE-SHA1-DES",
+"PBE-SHA1-RC2-128",
+"PBE-SHA1-RC2-40",
+"PBE-SHA1-RC2-64",
+"PBE-SHA1-RC4-128",
+"PBE-SHA1-RC4-40",
+"PBES2",
+"PBKDF2",
+"PBMAC1",
+"PKIX",
+"PSPECIFIED",
+"RC2-40-CBC",
+"RC2-64-CBC",
+"RC2-CBC",
+"RC2-CFB",
+"RC2-ECB",
+"RC2-OFB",
+"RC4",
+"RC4-40",
+"RC4-HMAC-MD5",
+"RC5-CBC",
+"RC5-CFB",
+"RC5-ECB",
+"RC5-OFB",
+"RIPEMD160",
+"RSA",
+"RSA-MD2",
+"RSA-MD4",
+"RSA-MD5",
+"RSA-MDC2",
+"RSA-NP-MD5",
+"RSA-RIPEMD160",
+"RSA-SHA",
+"RSA-SHA1",
+"RSA-SHA1-2",
+"RSA-SHA224",
+"RSA-SHA256",
+"RSA-SHA384",
+"RSA-SHA512",
+"RSAES-OAEP",
+"RSASSA-PSS",
+"SEED-CBC",
+"SEED-CFB",
+"SEED-ECB",
+"SEED-OFB",
+"SHA",
+"SHA1",
+"SHA224",
+"SHA256",
+"SHA384",
+"SHA512",
+"SMIME",
+"SMIME-CAPS",
+"SN",
+"SNILS",
+"ST",
+"SXNetID",
+"TLS1-PRF",
+"UID",
+"UNDEF",
+"X25519",
+"X448",
+"X500",
+"X500algorithms",
+"X509",
+"X9-57",
+"X9cm",
+"ZLIB",
+"aRecord",
+"aaControls",
+"ac-auditEntity",
+"ac-proxying",
+"ac-targeting",
+"acceptableResponses",
+"account",
+"ad_timestamping",
+"algorithm",
+"ansi-X9-62",
+"anyExtendedKeyUsage",
+"anyPolicy",
+"archiveCutoff",
+"associatedDomain",
+"associatedName",
+"audio",
+"authorityInfoAccess",
+"authorityKeyIdentifier",
+"authorityRevocationList",
+"basicConstraints",
+"basicOCSPResponse",
+"biometricInfo",
+"brainpoolP160r1",
+"brainpoolP160t1",
+"brainpoolP192r1",
+"brainpoolP192t1",
+"brainpoolP224r1",
+"brainpoolP224t1",
+"brainpoolP256r1",
+"brainpoolP256t1",
+"brainpoolP320r1",
+"brainpoolP320t1",
+"brainpoolP384r1",
+"brainpoolP384t1",
+"brainpoolP512r1",
+"brainpoolP512t1",
+"buildingName",
+"businessCategory",
+"c2onb191v4",
+"c2onb191v5",
+"c2onb239v4",
+"c2onb239v5",
+"c2pnb163v1",
+"c2pnb163v2",
+"c2pnb163v3",
+"c2pnb176v1",
+"c2pnb208w1",
+"c2pnb272w1",
+"c2pnb304w1",
+"c2pnb368w1",
+"c2tnb191v1",
+"c2tnb191v2",
+"c2tnb191v3",
+"c2tnb239v1",
+"c2tnb239v2",
+"c2tnb239v3",
+"c2tnb359v1",
+"c2tnb431r1",
+"cACertificate",
+"cNAMERecord",
+"caIssuers",
+"caRepository",
+"capwapAC",
+"capwapWTP",
+"caseIgnoreIA5StringSyntax",
+"certBag",
+"certicom-arc",
+"certificateIssuer",
+"certificatePolicies",
+"certificateRevocationList",
+"challengePassword",
+"characteristic-two-field",
+"clearance",
+"clientAuth",
+"codeSigning",
+"contentType",
+"countersignature",
+"crlBag",
+"crlDistributionPoints",
+"crlNumber",
+"crossCertificatePair",
+"cryptocom",
+"cryptopro",
+"ct_cert_scts",
+"ct_precert_poison",
+"ct_precert_scts",
+"ct_precert_signer",
+"dITRedirect",
+"dNSDomain",
+"dSAQuality",
+"data",
+"dcobject",
+"deltaCRL",
+"deltaRevocationList",
+"description",
+"destinationIndicator",
+"dh-cofactor-kdf",
+"dh-std-kdf",
+"dhKeyAgreement",
+"dhSinglePass-cofactorDH-sha1kdf-scheme",
+"dhSinglePass-cofactorDH-sha224kdf-scheme",
+"dhSinglePass-cofactorDH-sha256kdf-scheme",
+"dhSinglePass-cofactorDH-sha384kdf-scheme",
+"dhSinglePass-cofactorDH-sha512kdf-scheme",
+"dhSinglePass-stdDH-sha1kdf-scheme",
+"dhSinglePass-stdDH-sha224kdf-scheme",
+"dhSinglePass-stdDH-sha256kdf-scheme",
+"dhSinglePass-stdDH-sha384kdf-scheme",
+"dhSinglePass-stdDH-sha512kdf-scheme",
+"dhpublicnumber",
+"directory",
+"distinguishedName",
+"dmdName",
+"dnQualifier",
+"document",
+"documentAuthor",
+"documentIdentifier",
+"documentLocation",
+"documentPublisher",
+"documentSeries",
+"documentTitle",
+"documentVersion",
+"domain",
+"domainRelatedObject",
+"dsa_with_SHA224",
+"dsa_with_SHA256",
+"ecdsa-with-Recommended",
+"ecdsa-with-SHA1",
+"ecdsa-with-SHA224",
+"ecdsa-with-SHA256",
+"ecdsa-with-SHA384",
+"ecdsa-with-SHA512",
+"ecdsa-with-Specified",
+"emailAddress",
+"emailProtection",
+"enhancedSearchGuide",
+"enterprises",
+"experimental",
+"extReq",
+"extendedCertificateAttributes",
+"extendedKeyUsage",
+"extendedStatus",
+"facsimileTelephoneNumber",
+"favouriteDrink",
+"freshestCRL",
+"friendlyCountry",
+"friendlyCountryName",
+"friendlyName",
+"generationQualifier",
+"gost-mac",
+"gost-mac-12",
+"gost2001",
+"gost2001cc",
+"gost2012_256",
+"gost2012_512",
+"gost89",
+"gost89-cbc",
+"gost89-cnt",
+"gost89-cnt-12",
+"gost89-ctr",
+"gost89-ecb",
+"gost94",
+"gost94cc",
+"grasshopper-cbc",
+"grasshopper-cfb",
+"grasshopper-ctr",
+"grasshopper-ecb",
+"grasshopper-mac",
+"grasshopper-ofb",
+"hmacWithMD5",
+"hmacWithSHA1",
+"hmacWithSHA224",
+"hmacWithSHA256",
+"hmacWithSHA384",
+"hmacWithSHA512",
+"holdInstructionCallIssuer",
+"holdInstructionCode",
+"holdInstructionNone",
+"holdInstructionReject",
+"homePostalAddress",
+"homeTelephoneNumber",
+"host",
+"houseIdentifier",
+"iA5StringSyntax",
+"id-DHBasedMac",
+"id-Gost28147-89-CryptoPro-A-ParamSet",
+"id-Gost28147-89-CryptoPro-B-ParamSet",
+"id-Gost28147-89-CryptoPro-C-ParamSet",
+"id-Gost28147-89-CryptoPro-D-ParamSet",
+"id-Gost28147-89-CryptoPro-KeyMeshing",
+"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+"id-Gost28147-89-None-KeyMeshing",
+"id-Gost28147-89-TestParamSet",
+"id-Gost28147-89-cc",
+"id-GostR3410-2001-CryptoPro-A-ParamSet",
+"id-GostR3410-2001-CryptoPro-B-ParamSet",
+"id-GostR3410-2001-CryptoPro-C-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+"id-GostR3410-2001-ParamSet-cc",
+"id-GostR3410-2001-TestParamSet",
+"id-GostR3410-2001DH",
+"id-GostR3410-94-CryptoPro-A-ParamSet",
+"id-GostR3410-94-CryptoPro-B-ParamSet",
+"id-GostR3410-94-CryptoPro-C-ParamSet",
+"id-GostR3410-94-CryptoPro-D-ParamSet",
+"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+"id-GostR3410-94-TestParamSet",
+"id-GostR3410-94-a",
+"id-GostR3410-94-aBis",
+"id-GostR3410-94-b",
+"id-GostR3410-94-bBis",
+"id-GostR3410-94DH",
+"id-GostR3411-94-CryptoProParamSet",
+"id-GostR3411-94-TestParamSet",
+"id-GostR3411-94-with-GostR3410-2001",
+"id-GostR3411-94-with-GostR3410-2001-cc",
+"id-GostR3411-94-with-GostR3410-94",
+"id-GostR3411-94-with-GostR3410-94-cc",
+"id-HMACGostR3411-94",
+"id-PasswordBasedMAC",
+"id-aca",
+"id-aca-accessIdentity",
+"id-aca-authenticationInfo",
+"id-aca-chargingIdentity",
+"id-aca-encAttrs",
+"id-aca-group",
+"id-aca-role",
+"id-ad",
+"id-aes128-CCM",
+"id-aes128-GCM",
+"id-aes128-wrap",
+"id-aes128-wrap-pad",
+"id-aes192-CCM",
+"id-aes192-GCM",
+"id-aes192-wrap",
+"id-aes192-wrap-pad",
+"id-aes256-CCM",
+"id-aes256-GCM",
+"id-aes256-wrap",
+"id-aes256-wrap-pad",
+"id-alg",
+"id-alg-PWRI-KEK",
+"id-alg-des40",
+"id-alg-dh-pop",
+"id-alg-dh-sig-hmac-sha1",
+"id-alg-noSignature",
+"id-camellia128-wrap",
+"id-camellia192-wrap",
+"id-camellia256-wrap",
+"id-cct",
+"id-cct-PKIData",
+"id-cct-PKIResponse",
+"id-cct-crs",
+"id-ce",
+"id-characteristic-two-basis",
+"id-cmc",
+"id-cmc-addExtensions",
+"id-cmc-confirmCertAcceptance",
+"id-cmc-dataReturn",
+"id-cmc-decryptedPOP",
+"id-cmc-encryptedPOP",
+"id-cmc-getCRL",
+"id-cmc-getCert",
+"id-cmc-identification",
+"id-cmc-identityProof",
+"id-cmc-lraPOPWitness",
+"id-cmc-popLinkRandom",
+"id-cmc-popLinkWitness",
+"id-cmc-queryPending",
+"id-cmc-recipientNonce",
+"id-cmc-regInfo",
+"id-cmc-responseInfo",
+"id-cmc-revokeRequest",
+"id-cmc-senderNonce",
+"id-cmc-statusInfo",
+"id-cmc-transactionId",
+"id-ct-asciiTextWithCRLF",
+"id-ct-xml",
+"id-ecPublicKey",
+"id-hex-multipart-message",
+"id-hex-partial-message",
+"id-it",
+"id-it-caKeyUpdateInfo",
+"id-it-caProtEncCert",
+"id-it-confirmWaitTime",
+"id-it-currentCRL",
+"id-it-encKeyPairTypes",
+"id-it-implicitConfirm",
+"id-it-keyPairParamRep",
+"id-it-keyPairParamReq",
+"id-it-origPKIMessage",
+"id-it-preferredSymmAlg",
+"id-it-revPassphrase",
+"id-it-signKeyPairTypes",
+"id-it-subscriptionRequest",
+"id-it-subscriptionResponse",
+"id-it-suppLangTags",
+"id-it-unsupportedOIDs",
+"id-kp",
+"id-mod-attribute-cert",
+"id-mod-cmc",
+"id-mod-cmp",
+"id-mod-cmp2000",
+"id-mod-crmf",
+"id-mod-dvcs",
+"id-mod-kea-profile-88",
+"id-mod-kea-profile-93",
+"id-mod-ocsp",
+"id-mod-qualified-cert-88",
+"id-mod-qualified-cert-93",
+"id-mod-timestamp-protocol",
+"id-on",
+"id-on-permanentIdentifier",
+"id-on-personalData",
+"id-pda",
+"id-pda-countryOfCitizenship",
+"id-pda-countryOfResidence",
+"id-pda-dateOfBirth",
+"id-pda-gender",
+"id-pda-placeOfBirth",
+"id-pe",
+"id-pkinit",
+"id-pkip",
+"id-pkix-mod",
+"id-pkix1-explicit-88",
+"id-pkix1-explicit-93",
+"id-pkix1-implicit-88",
+"id-pkix1-implicit-93",
+"id-ppl",
+"id-ppl-anyLanguage",
+"id-ppl-independent",
+"id-ppl-inheritAll",
+"id-qcs",
+"id-qcs-pkixQCSyntax-v1",
+"id-qt",
+"id-qt-cps",
+"id-qt-unotice",
+"id-regCtrl",
+"id-regCtrl-authenticator",
+"id-regCtrl-oldCertID",
+"id-regCtrl-pkiArchiveOptions",
+"id-regCtrl-pkiPublicationInfo",
+"id-regCtrl-protocolEncrKey",
+"id-regCtrl-regToken",
+"id-regInfo",
+"id-regInfo-certReq",
+"id-regInfo-utf8Pairs",
+"id-scrypt",
+"id-set",
+"id-smime-aa",
+"id-smime-aa-contentHint",
+"id-smime-aa-contentIdentifier",
+"id-smime-aa-contentReference",
+"id-smime-aa-dvcs-dvc",
+"id-smime-aa-encapContentType",
+"id-smime-aa-encrypKeyPref",
+"id-smime-aa-equivalentLabels",
+"id-smime-aa-ets-CertificateRefs",
+"id-smime-aa-ets-RevocationRefs",
+"id-smime-aa-ets-archiveTimeStamp",
+"id-smime-aa-ets-certCRLTimestamp",
+"id-smime-aa-ets-certValues",
+"id-smime-aa-ets-commitmentType",
+"id-smime-aa-ets-contentTimestamp",
+"id-smime-aa-ets-escTimeStamp",
+"id-smime-aa-ets-otherSigCert",
+"id-smime-aa-ets-revocationValues",
+"id-smime-aa-ets-sigPolicyId",
+"id-smime-aa-ets-signerAttr",
+"id-smime-aa-ets-signerLocation",
+"id-smime-aa-macValue",
+"id-smime-aa-mlExpandHistory",
+"id-smime-aa-msgSigDigest",
+"id-smime-aa-receiptRequest",
+"id-smime-aa-securityLabel",
+"id-smime-aa-signatureType",
+"id-smime-aa-signingCertificate",
+"id-smime-aa-smimeEncryptCerts",
+"id-smime-aa-timeStampToken",
+"id-smime-alg",
+"id-smime-alg-3DESwrap",
+"id-smime-alg-CMS3DESwrap",
+"id-smime-alg-CMSRC2wrap",
+"id-smime-alg-ESDH",
+"id-smime-alg-ESDHwith3DES",
+"id-smime-alg-ESDHwithRC2",
+"id-smime-alg-RC2wrap",
+"id-smime-cd",
+"id-smime-cd-ldap",
+"id-smime-ct",
+"id-smime-ct-DVCSRequestData",
+"id-smime-ct-DVCSResponseData",
+"id-smime-ct-TDTInfo",
+"id-smime-ct-TSTInfo",
+"id-smime-ct-authData",
+"id-smime-ct-authEnvelopedData",
+"id-smime-ct-compressedData",
+"id-smime-ct-contentCollection",
+"id-smime-ct-contentInfo",
+"id-smime-ct-publishCert",
+"id-smime-ct-receipt",
+"id-smime-cti",
+"id-smime-cti-ets-proofOfApproval",
+"id-smime-cti-ets-proofOfCreation",
+"id-smime-cti-ets-proofOfDelivery",
+"id-smime-cti-ets-proofOfOrigin",
+"id-smime-cti-ets-proofOfReceipt",
+"id-smime-cti-ets-proofOfSender",
+"id-smime-mod",
+"id-smime-mod-cms",
+"id-smime-mod-ess",
+"id-smime-mod-ets-eSigPolicy-88",
+"id-smime-mod-ets-eSigPolicy-97",
+"id-smime-mod-ets-eSignature-88",
+"id-smime-mod-ets-eSignature-97",
+"id-smime-mod-msg-v3",
+"id-smime-mod-oid",
+"id-smime-spq",
+"id-smime-spq-ets-sqt-unotice",
+"id-smime-spq-ets-sqt-uri",
+"id-tc26",
+"id-tc26-agreement",
+"id-tc26-agreement-gost-3410-2012-256",
+"id-tc26-agreement-gost-3410-2012-512",
+"id-tc26-algorithms",
+"id-tc26-cipher",
+"id-tc26-cipher-constants",
+"id-tc26-constants",
+"id-tc26-digest",
+"id-tc26-digest-constants",
+"id-tc26-gost-28147-constants",
+"id-tc26-gost-28147-param-Z",
+"id-tc26-gost-3410-2012-512-constants",
+"id-tc26-gost-3410-2012-512-paramSetA",
+"id-tc26-gost-3410-2012-512-paramSetB",
+"id-tc26-gost-3410-2012-512-paramSetTest",
+"id-tc26-hmac-gost-3411-2012-256",
+"id-tc26-hmac-gost-3411-2012-512",
+"id-tc26-mac",
+"id-tc26-sign",
+"id-tc26-sign-constants",
+"id-tc26-signwithdigest",
+"id-tc26-signwithdigest-gost3410-2012-256",
+"id-tc26-signwithdigest-gost3410-2012-512",
+"identified-organization",
+"info",
+"inhibitAnyPolicy",
+"initials",
+"international-organizations",
+"internationaliSDNNumber",
+"invalidityDate",
+"ipsecEndSystem",
+"ipsecIKE",
+"ipsecTunnel",
+"ipsecUser",
+"issuerAltName",
+"issuerSignTool",
+"issuingDistributionPoint",
+"janetMailbox",
+"jurisdictionC",
+"jurisdictionL",
+"jurisdictionST",
+"keyBag",
+"keyUsage",
+"lastModifiedBy",
+"lastModifiedTime",
+"localKeyID",
+"mXRecord",
+"mail",
+"mailPreferenceOption",
+"manager",
+"md_gost12_256",
+"md_gost12_512",
+"md_gost94",
+"member",
+"member-body",
+"messageDigest",
+"mgmt",
+"mime-mhs",
+"mime-mhs-bodies",
+"mime-mhs-headings",
+"mobileTelephoneNumber",
+"msCTLSign",
+"msCodeCom",
+"msCodeInd",
+"msEFS",
+"msExtReq",
+"msSGC",
+"msSmartcardLogin",
+"msUPN",
+"nSRecord",
+"name",
+"nameConstraints",
+"noCheck",
+"noRevAvail",
+"nsBaseUrl",
+"nsCaPolicyUrl",
+"nsCaRevocationUrl",
+"nsCertExt",
+"nsCertSequence",
+"nsCertType",
+"nsComment",
+"nsDataType",
+"nsRenewalUrl",
+"nsRevocationUrl",
+"nsSGC",
+"nsSslServerName",
+"onBasis",
+"organizationalStatus",
+"otherMailbox",
+"owner",
+"pagerTelephoneNumber",
+"path",
+"pbeWithMD5AndCast5CBC",
+"personalSignature",
+"personalTitle",
+"photo",
+"physicalDeliveryOfficeName",
+"pilot",
+"pilotAttributeSyntax",
+"pilotAttributeType",
+"pilotAttributeType27",
+"pilotDSA",
+"pilotGroups",
+"pilotObject",
+"pilotObjectClass",
+"pilotOrganization",
+"pilotPerson",
+"pkInitClientAuth",
+"pkInitKDC",
+"pkcs",
+"pkcs1",
+"pkcs3",
+"pkcs5",
+"pkcs7",
+"pkcs7-data",
+"pkcs7-digestData",
+"pkcs7-encryptedData",
+"pkcs7-envelopedData",
+"pkcs7-signedAndEnvelopedData",
+"pkcs7-signedData",
+"pkcs8ShroudedKeyBag",
+"pkcs9",
+"policyConstraints",
+"policyMappings",
+"postOfficeBox",
+"postalAddress",
+"postalCode",
+"ppBasis",
+"preferredDeliveryMethod",
+"presentationAddress",
+"prf-gostr3411-94",
+"prime-field",
+"prime192v1",
+"prime192v2",
+"prime192v3",
+"prime239v1",
+"prime239v2",
+"prime239v3",
+"prime256v1",
+"private",
+"privateKeyUsagePeriod",
+"protocolInformation",
+"proxyCertInfo",
+"pseudonym",
+"pss",
+"qcStatements",
+"qualityLabelledData",
+"rFC822localPart",
+"registeredAddress",
+"role",
+"roleOccupant",
+"room",
+"roomNumber",
+"rsaEncryption",
+"rsaOAEPEncryptionSET",
+"rsaSignature",
+"rsadsi",
+"sOARecord",
+"safeContentsBag",
+"sbgp-autonomousSysNum",
+"sbgp-ipAddrBlock",
+"sbgp-routerIdentifier",
+"sdsiCertificate",
+"searchGuide",
+"secp112r1",
+"secp112r2",
+"secp128r1",
+"secp128r2",
+"secp160k1",
+"secp160r1",
+"secp160r2",
+"secp192k1",
+"secp224k1",
+"secp224r1",
+"secp256k1",
+"secp384r1",
+"secp521r1",
+"secretBag",
+"secretary",
+"sect113r1",
+"sect113r2",
+"sect131r1",
+"sect131r2",
+"sect163k1",
+"sect163r1",
+"sect163r2",
+"sect193r1",
+"sect193r2",
+"sect233k1",
+"sect233r1",
+"sect239k1",
+"sect283k1",
+"sect283r1",
+"sect409k1",
+"sect409r1",
+"sect571k1",
+"sect571r1",
+"secureShellClient",
+"secureShellServer",
+"security",
+"seeAlso",
+"selected-attribute-types",
+"sendOwner",
+"sendProxiedOwner",
+"sendProxiedRouter",
+"sendRouter",
+"serialNumber",
+"serverAuth",
+"serviceLocator",
+"set-addPolicy",
+"set-attr",
+"set-brand",
+"set-brand-AmericanExpress",
+"set-brand-Diners",
+"set-brand-IATA-ATA",
+"set-brand-JCB",
+"set-brand-MasterCard",
+"set-brand-Novus",
+"set-brand-Visa",
+"set-certExt",
+"set-ctype",
+"set-msgExt",
+"set-policy",
+"set-policy-root",
+"set-rootKeyThumb",
+"setAttr-Cert",
+"setAttr-GenCryptgrm",
+"setAttr-IssCap",
+"setAttr-IssCap-CVM",
+"setAttr-IssCap-Sig",
+"setAttr-IssCap-T2",
+"setAttr-PGWYcap",
+"setAttr-SecDevSig",
+"setAttr-T2Enc",
+"setAttr-T2cleartxt",
+"setAttr-TokICCsig",
+"setAttr-Token-B0Prime",
+"setAttr-Token-EMV",
+"setAttr-TokenType",
+"setCext-IssuerCapabilities",
+"setCext-PGWYcapabilities",
+"setCext-TokenIdentifier",
+"setCext-TokenType",
+"setCext-Track2Data",
+"setCext-cCertRequired",
+"setCext-certType",
+"setCext-hashedRoot",
+"setCext-merchData",
+"setCext-setExt",
+"setCext-setQualf",
+"setCext-tunneling",
+"setct-AcqCardCodeMsg",
+"setct-AcqCardCodeMsgTBE",
+"setct-AuthReqTBE",
+"setct-AuthReqTBS",
+"setct-AuthResBaggage",
+"setct-AuthResTBE",
+"setct-AuthResTBEX",
+"setct-AuthResTBS",
+"setct-AuthResTBSX",
+"setct-AuthRevReqBaggage",
+"setct-AuthRevReqTBE",
+"setct-AuthRevReqTBS",
+"setct-AuthRevResBaggage",
+"setct-AuthRevResData",
+"setct-AuthRevResTBE",
+"setct-AuthRevResTBEB",
+"setct-AuthRevResTBS",
+"setct-AuthTokenTBE",
+"setct-AuthTokenTBS",
+"setct-BCIDistributionTBS",
+"setct-BatchAdminReqData",
+"setct-BatchAdminReqTBE",
+"setct-BatchAdminResData",
+"setct-BatchAdminResTBE",
+"setct-CRLNotificationResTBS",
+"setct-CRLNotificationTBS",
+"setct-CapReqTBE",
+"setct-CapReqTBEX",
+"setct-CapReqTBS",
+"setct-CapReqTBSX",
+"setct-CapResData",
+"setct-CapResTBE",
+"setct-CapRevReqTBE",
+"setct-CapRevReqTBEX",
+"setct-CapRevReqTBS",
+"setct-CapRevReqTBSX",
+"setct-CapRevResData",
+"setct-CapRevResTBE",
+"setct-CapTokenData",
+"setct-CapTokenSeq",
+"setct-CapTokenTBE",
+"setct-CapTokenTBEX",
+"setct-CapTokenTBS",
+"setct-CardCInitResTBS",
+"setct-CertInqReqTBS",
+"setct-CertReqData",
+"setct-CertReqTBE",
+"setct-CertReqTBEX",
+"setct-CertReqTBS",
+"setct-CertResData",
+"setct-CertResTBE",
+"setct-CredReqTBE",
+"setct-CredReqTBEX",
+"setct-CredReqTBS",
+"setct-CredReqTBSX",
+"setct-CredResData",
+"setct-CredResTBE",
+"setct-CredRevReqTBE",
+"setct-CredRevReqTBEX",
+"setct-CredRevReqTBS",
+"setct-CredRevReqTBSX",
+"setct-CredRevResData",
+"setct-CredRevResTBE",
+"setct-ErrorTBS",
+"setct-HODInput",
+"setct-MeAqCInitResTBS",
+"setct-OIData",
+"setct-PANData",
+"setct-PANOnly",
+"setct-PANToken",
+"setct-PCertReqData",
+"setct-PCertResTBS",
+"setct-PI",
+"setct-PI-TBS",
+"setct-PIData",
+"setct-PIDataUnsigned",
+"setct-PIDualSignedTBE",
+"setct-PIUnsignedTBE",
+"setct-PInitResData",
+"setct-PResData",
+"setct-RegFormReqTBE",
+"setct-RegFormResTBS",
+"setext-cv",
+"setext-genCrypt",
+"setext-miAuth",
+"setext-pinAny",
+"setext-pinSecure",
+"setext-track2",
+"signingTime",
+"simpleSecurityObject",
+"singleLevelQuality",
+"snmpv2",
+"street",
+"subjectAltName",
+"subjectDirectoryAttributes",
+"subjectInfoAccess",
+"subjectKeyIdentifier",
+"subjectSignTool",
+"subtreeMaximumQuality",
+"subtreeMinimumQuality",
+"supportedAlgorithms",
+"supportedApplicationContext",
+"targetInformation",
+"telephoneNumber",
+"teletexTerminalIdentifier",
+"telexNumber",
+"textEncodedORAddress",
+"textNotice",
+"timeStamping",
+"title",
+"tlsfeature",
+"tpBasis",
+"trustRoot",
+"ucl",
+"uid",
+"uniqueMember",
+"unstructuredAddress",
+"unstructuredName",
+"userCertificate",
+"userClass",
+"userPassword",
+"valid",
+"wap",
+"wap-wsg",
+"wap-wsg-idm-ecid-wtls1",
+"wap-wsg-idm-ecid-wtls10",
+"wap-wsg-idm-ecid-wtls11",
+"wap-wsg-idm-ecid-wtls12",
+"wap-wsg-idm-ecid-wtls3",
+"wap-wsg-idm-ecid-wtls4",
+"wap-wsg-idm-ecid-wtls5",
+"wap-wsg-idm-ecid-wtls6",
+"wap-wsg-idm-ecid-wtls7",
+"wap-wsg-idm-ecid-wtls8",
+"wap-wsg-idm-ecid-wtls9",
+"whirlpool",
+"x121Address",
+"x500UniqueIdentifier",
+"x509Certificate",
+"x509Crl",
+};
diff --git a/projects/openvpn/project.yaml b/projects/openvpn/project.yaml
new file mode 100644
index 000000000..ee352d920
--- /dev/null
+++ b/projects/openvpn/project.yaml
@@ -0,0 +1,6 @@
+homepage: "http://community.openvpn.net"
+language: c
+primary_contact: "arne@rfc2549.org"
+main_repo: "https://github.com/OpenVPN/openvpn"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/openvswitch/Dockerfile b/projects/openvswitch/Dockerfile
index f7c149f86..65a4ea463 100644
--- a/projects/openvswitch/Dockerfile
+++ b/projects/openvswitch/Dockerfile
@@ -17,7 +17,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake \
libtool python python3-pip \
- libz-dev libssl-dev libssl1.0.0 wget
+ libz-dev libssl-dev libssl1.1 wget
RUN pip3 install six
RUN git clone --depth 1 https://github.com/openvswitch/ovs.git openvswitch
RUN git clone --depth 1 https://github.com/openvswitch/ovs-fuzzing-corpus.git \
diff --git a/projects/openvswitch/project.yaml b/projects/openvswitch/project.yaml
index 4ee3e96a4..5a25f13b0 100644
--- a/projects/openvswitch/project.yaml
+++ b/projects/openvswitch/project.yaml
@@ -11,6 +11,7 @@ auto_ccs:
- "ilya.maximets@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/openvswitch/ovs.git'
+main_repo: 'https://github.com/openvswitch/ovs.git' \ No newline at end of file
diff --git a/projects/openweave/Dockerfile b/projects/openweave/Dockerfile
new file mode 100644
index 000000000..2c940a4e7
--- /dev/null
+++ b/projects/openweave/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 python-setuptools bridge-utils \
+ libglib2.0-dev libdbus-1-dev libudev-dev \
+ libical-dev libreadline-dev udev \
+ libtool autoconf automake systemd
+RUN pip3 install --user google-cloud googleapis-common-protos grpcio protobuf pycryptodomex
+RUN cpan -i Text::Template
+RUN git clone --depth 1 https://github.com/openweave/openweave-core
+WORKDIR $SRC/openweave-core
+COPY build.sh $SRC/
+COPY patch.diff $SRC/
diff --git a/projects/openweave/build.sh b/projects/openweave/build.sh
new file mode 100755
index 000000000..9b366d2ba
--- /dev/null
+++ b/projects/openweave/build.sh
@@ -0,0 +1,66 @@
+#!/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.
+#
+################################################################################
+
+git apply --ignore-space-change --ignore-whitespace $SRC/patch.diff
+
+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
+
+if [ "$SANITIZER" = "coverage" ]
+then
+ # so that we do not get openssl
+ export CXXFLAGS="$CXXFLAGS -fsanitize=fuzzer-no-link,address"
+ export CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link,address"
+fi
+
+# build project
+./bootstrap
+# java fails with Source option 6 is no longer supported. Use 7 or later.
+./configure --disable-java --enable-fuzzing --disable-shared
+
+# patch bluez
+sed -i 's/sys\/socket.h>/sys\/socket.h>\n#include <linux\/sockios.h>/g' ./third_party/bluez/repo/tools/l2test.c
+sed -i 's/sys\/stat.h>/sys\/stat.h>\n#include <linux\/sockios.h>/g' ./third_party/bluez/repo/tools/rctest.c
+
+# OpenSSL now declares RAND_bytes so we must patch
+find ./src/test-apps/fuzz/ -name "FuzzP*.cpp" -exec sed -i 's/RAND_bytes/RAND_bytes2/g' {} \;
+
+make -j$(nproc)
+
+find src/test-apps/fuzz/ -type f -executable -name "Fuzz*" | while read i; do
+ patchelf --set-rpath '$ORIGIN/lib' ${i}
+ copy_lib ${i} libglib
+ copy_lib ${i} libdbus
+ cp ${i} $OUT/
+done
+
+# build corpus
+ls $SRC/openweave-core/src/test-apps/fuzz/corpus/ | while read f; do
+ zip -j $OUT/${f}_seed_corpus.zip $SRC/openweave-core/src/test-apps/fuzz/corpus/${f}/*;
+done
+
+cd $OUT/
+ls *_seed_corpus.zip | grep PASE | while read c; do
+ cp $c Fuzz$c;
+done
+
diff --git a/projects/openweave/patch.diff b/projects/openweave/patch.diff
new file mode 100644
index 000000000..c1ce5201a
--- /dev/null
+++ b/projects/openweave/patch.diff
@@ -0,0 +1,48 @@
+diff --git a/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp b/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
+index 7a6cb42..c05caae 100644
+--- a/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
++++ b/src/lib/support/crypto/WeaveRNG-OpenSSL.cpp
+@@ -53,8 +53,9 @@ WEAVE_ERROR InitSecureRandomDataSource(nl::Weave::Crypto::EntropyFunct entropyFu
+
+ WEAVE_ERROR GetSecureRandomData(uint8_t *buf, uint16_t len)
+ {
+- if (RAND_bytes((unsigned char *)buf, (int)len) != 1)
+- return WEAVE_ERROR_RANDOM_DATA_UNAVAILABLE;
++ //if (RAND_bytes((unsigned char *)buf, (int)len) != 1)
++ // return WEAVE_ERROR_RANDOM_DATA_UNAVAILABLE;
++ memset((unsigned char *)buf, 'A', (int)len);
+
+ return WEAVE_NO_ERROR;
+ }
+diff --git a/src/tools/weave/CertUtils.cpp b/src/tools/weave/CertUtils.cpp
+index 2bd8097..a1dce36 100644
+--- a/src/tools/weave/CertUtils.cpp
++++ b/src/tools/weave/CertUtils.cpp
+@@ -695,8 +695,9 @@ bool SetCertSerialNumber(X509 *cert)
+ ASN1_INTEGER *snInt = X509_get_serialNumber(cert);
+
+ // Generate a random value to be used as the serial number.
+- if (!RAND_bytes(reinterpret_cast<uint8_t *>(&rnd), sizeof(rnd)))
+- ReportOpenSSLErrorAndExit("RAND_bytes", res = false);
++ //if (!RAND_bytes(reinterpret_cast<uint8_t *>(&rnd), sizeof(rnd)))
++ // ReportOpenSSLErrorAndExit("RAND_bytes", res = false);
++ memset(reinterpret_cast<uint8_t *>(&rnd), 'A', sizeof(rnd));
+
+ // Avoid negative numbers.
+ rnd &= 0x7FFFFFFFFFFFFFFF;
+diff --git a/src/tools/weave/Cmd_GenProvisioningData.cpp b/src/tools/weave/Cmd_GenProvisioningData.cpp
+index 85ca2e2..bd5c18b 100644
+--- a/src/tools/weave/Cmd_GenProvisioningData.cpp
++++ b/src/tools/weave/Cmd_GenProvisioningData.cpp
+@@ -543,8 +543,9 @@ char *GeneratePairingCode(uint32_t pairingCodeLen)
+ }
+
+ // Generate random data for the pairing code, excluding the check digit at the end.
+- if (!RAND_bytes((uint8_t *)pairingCode, pairingCodeLen - 1))
+- ReportOpenSSLErrorAndExit("Failed to get random data", pairingCode = NULL);
++ //if (!RAND_bytes((uint8_t *)pairingCode, pairingCodeLen - 1))
++ // ReportOpenSSLErrorAndExit("Failed to get random data", pairingCode = NULL);
++ memset((uint8_t *)pairingCode, 'A', pairingCodeLen - 1);
+
+ // Convert the random data to characters in the range 0-9, A-H, J-N, P, R-Y (base-32 alphanumeric, excluding I, O, Q and Z).
+ for (uint32_t i = 0; i < pairingCodeLen - 1; i++)
diff --git a/projects/openweave/project.yaml b/projects/openweave/project.yaml
new file mode 100644
index 000000000..93a53b0d7
--- /dev/null
+++ b/projects/openweave/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://openweave.io"
+language: c++
+primary_contact: "szewczyk@google.com"
+auto_ccs:
+ - "p.antoine@catenacyber.fr"
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+main_repo: 'https://github.com/openweave/openweave-core'
diff --git a/projects/osquery/Dockerfile b/projects/osquery/Dockerfile
index c1c8ff513..dc8a7156d 100755
--- a/projects/osquery/Dockerfile
+++ b/projects/osquery/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update
-RUN apt-get install -y --no-install-recommends python python3 bison flex make wget xz-utils libunwind-dev
+RUN apt-get install -y --no-install-recommends python python3 bison flex make wget xz-utils libunwind-dev lsb-release build-essential libssl-dev
RUN git clone --depth 1 https://github.com/osquery/osquery osquery
diff --git a/projects/osquery/build.sh b/projects/osquery/build.sh
index 6b4ae9b80..936301156 100755
--- a/projects/osquery/build.sh
+++ b/projects/osquery/build.sh
@@ -17,6 +17,9 @@
PROJECT=osquery
+# Ensure xlocale.h is found.
+ln -s /usr/include/locale.h /usr/include/xlocale.h
+
# Move the project content into the current overlay.
# CMake builtin 'rename' will attempt a hardlink.
( cd / &&\
@@ -39,6 +42,10 @@ cmake \
"-DCMAKE_EXE_LINKER_FLAGS=${LIB_FUZZING_ENGINE} -Wl,-rpath,'\$ORIGIN/lib'" \
..
+# Fix circular definitions
+# See: https://github.com/osquery/osquery/issues/6551
+sed -i 's/AUDIT_FILTER_EXCLUDE/AUDIT_FILTER_EXCLUDE1/g' /src/osquery/libraries/cmake/source/libaudit/src/lib/libaudit.h
+
# Build harnesses
cmake --build . -j$(nproc) --target osqueryfuzz-config
cmake --build . -j$(nproc) --target osqueryfuzz-sqlquery
diff --git a/projects/ots/project.yaml b/projects/ots/project.yaml
index 559eed3ef..b2d1d7677 100644
--- a/projects/ots/project.yaml
+++ b/projects/ots/project.yaml
@@ -12,7 +12,6 @@ fuzzing_engines:
- libfuzzer
- afl
- honggfuzz
- - dataflow
sanitizers:
- address
- undefined
diff --git a/projects/p11-kit/Dockerfile b/projects/p11-kit/Dockerfile
index 5ae785811..d3636ecf8 100644
--- a/projects/p11-kit/Dockerfile
+++ b/projects/p11-kit/Dockerfile
@@ -15,9 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libtasn1-6-dev libffi-dev
-RUN echo deb http://archive.ubuntu.com/ubuntu/ bionic main >> /etc/apt/sources.list
-RUN apt-get update && apt-get install -y -t bionic gettext autopoint
+RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libtasn1-6-dev libffi-dev gettext autopoint
RUN git clone --depth 1 https://github.com/p11-glue/p11-kit.git p11-kit
WORKDIR p11-kit
COPY build.sh $SRC/
diff --git a/projects/p9/Dockerfile b/projects/p9/Dockerfile
index fbbe65a46..05163263d 100644
--- a/projects/p9/Dockerfile
+++ b/projects/p9/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
MAINTAINER s@sevki.org
RUN go get -v -u github.com/hugelgupf/p9/...
diff --git a/projects/perfetto/project.yaml b/projects/perfetto/project.yaml
index 898419312..97c517562 100644
--- a/projects/perfetto/project.yaml
+++ b/projects/perfetto/project.yaml
@@ -1,21 +1,26 @@
homepage: "https://perfetto.dev"
language: c++
-primary_contact: "fmayer@google.com"
+primary_contact: "hjd@google.com"
auto_ccs:
- "hjd@google.com"
- "lalitm@google.com"
+ - "octaviant@google.com"
- "perfetto-oss-fuzz@google.com"
- "primiano@google.com"
- "rsavitski@google.com"
- "eseckler@google.com"
+ - "altimin@google.com"
+ - "ddiproietto@google.com"
vendor_ccs:
- bcreasey@google.com
- hamzeh@google.com
- geuteneier@google.com
- - hollyhall@google.com
- - mikelogan@google.com
- maverickm@google.com
- warrenwright@google.com
+ - ailport@google.com
+ - kimtony@google.com
+ - faerber@google.com
+ - greendonald@google.com
fuzzing_engines:
- libfuzzer
- honggfuzz
diff --git a/projects/pffft/Dockerfile b/projects/pffft/Dockerfile
index 944245900..f0faf12f4 100644
--- a/projects/pffft/Dockerfile
+++ b/projects/pffft/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y mercurial python-numpy
+RUN apt-get update && apt-get install -y mercurial python-numpy python
RUN git clone https://bitbucket.org/jpommier/pffft $SRC/pffft
WORKDIR pffft
COPY build.sh $SRC
diff --git a/projects/phmap/Dockerfile b/projects/phmap/Dockerfile
new file mode 100755
index 000000000..e32199aa9
--- /dev/null
+++ b/projects/phmap/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/greg7mdp/parallel-hashmap
+
+WORKDIR $SRC/parallel-hashmap
+COPY build.sh $SRC/
+COPY phashmap_fuzz.cc $SRC/
diff --git a/projects/phmap/build.sh b/projects/phmap/build.sh
new file mode 100755
index 000000000..ac7cb32d3
--- /dev/null
+++ b/projects/phmap/build.sh
@@ -0,0 +1,19 @@
+#!/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.
+#
+################################################################################
+
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE $SRC/phashmap_fuzz.cc -I./ -o $OUT/phashmap_fuzz
diff --git a/projects/phmap/phashmap_fuzz.cc b/projects/phmap/phashmap_fuzz.cc
new file mode 100644
index 000000000..d7530d425
--- /dev/null
+++ b/projects/phmap/phashmap_fuzz.cc
@@ -0,0 +1,66 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <iostream>
+#include <bitset>
+#include <cinttypes>
+#include <unistd.h>
+#include "parallel_hashmap/phmap_dump.h"
+#include <fuzzer/FuzzedDataProvider.h>
+
+using phmap::flat_hash_map;
+using namespace std;
+
+void serialise_test(const uint8_t *data, size_t size) {
+ phmap::flat_hash_map<unsigned int, int> table;
+ FuzzedDataProvider fuzzed_data(data, size);
+ const int num_items = fuzzed_data.ConsumeIntegral<int16_t>();
+
+ for (int i=0; i < num_items; ++i) {
+ table.insert(typename phmap::flat_hash_map<unsigned int, int>::value_type(
+ fuzzed_data.ConsumeIntegral<uint32_t>(),
+ fuzzed_data.ConsumeIntegral<int32_t>()));
+ }
+
+ phmap::BinaryOutputArchive ar_out("/dump.data");
+ table.dump(ar_out);
+
+ //MapType table_in;
+ phmap::flat_hash_map<unsigned int, int> table_in;
+ phmap::BinaryInputArchive ar_in("/dump.data");
+ table_in.load(ar_in);
+
+ if(table == table_in) {
+ unlink("/dump.data");
+ return;
+ }
+ unlink("/dump.data");
+}
+
+void
+test_assignments(const uint8_t *data, size_t size) {
+ phmap::flat_hash_map<std::string, std::string> email;
+ FuzzedDataProvider fuzzed_data(data, size);
+ const int num_items = fuzzed_data.ConsumeIntegral<int16_t>();
+ for (int i=0; i < num_items; ++i) {
+ phmap::flat_hash_map<std::string, std::string>::value_type(
+ fuzzed_data.ConsumeRandomLengthString(),
+ fuzzed_data.ConsumeRandomLengthString());
+ }
+ // Iterate through all of the items.
+ for (const auto& n: email) {}
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ serialise_test(data, size);
+ test_assignments(data, size);
+ return 0;
+}
diff --git a/projects/phmap/project.yaml b/projects/phmap/project.yaml
new file mode 100755
index 000000000..614a5cf14
--- /dev/null
+++ b/projects/phmap/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://github.com/greg7mdp/parallel-hashmap"
+main_repo: 'https://github.com/greg7mdp/parallel-hashmap'
+primary_contact: "greg7mdp@gmail.com"
+language: c++
+auto_ccs :
+ - "david@adalogics.com"
diff --git a/projects/php/Dockerfile b/projects/php/Dockerfile
index a2cb115e1..eaae4fd4b 100644
--- a/projects/php/Dockerfile
+++ b/projects/php/Dockerfile
@@ -18,6 +18,5 @@ FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && \
apt-get install -y autoconf automake libtool bison re2c pkg-config
RUN git clone --depth 1 --branch master https://github.com/php/php-src.git php-src
-RUN git clone https://github.com/kkos/oniguruma.git php-src/oniguruma
WORKDIR php-src
COPY build.sh *.options $SRC/
diff --git a/projects/php/build.sh b/projects/php/build.sh
index fbef4895c..18a861f91 100755
--- a/projects/php/build.sh
+++ b/projects/php/build.sh
@@ -15,28 +15,28 @@
#
################################################################################
-# build oniguruma and link statically
-pushd oniguruma
-autoreconf -vfi
-./configure
-make -j$(nproc)
-popd
-export ONIG_CFLAGS="-I$PWD/oniguruma/src"
-export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a"
-
# PHP's zend_function union is incompatible with the object-size sanitizer
export CFLAGS="$CFLAGS -fno-sanitize=object-size"
export CXXFLAGS="$CXXFLAGS -fno-sanitize=object-size"
+# Disable JIT profitability checks.
+export CFLAGS="$CFLAGS -DPROFITABILITY_CHECKS=0"
+
+# Make sure the right assembly files are picked
+BUILD_FLAG=""
+if [ "$ARCHITECTURE" = "i386" ]; then
+ BUILD_FLAG="--build=i686-pc-linux-gnu"
+fi
+
# build project
./buildconf
-./configure \
+./configure $BUILD_FLAG \
--disable-all \
--enable-debug-assertions \
--enable-option-checking=fatal \
--enable-fuzzer \
--enable-exif \
- --enable-mbstring \
+ --enable-opcache \
--without-pcre-jit \
--disable-phpdbg \
--disable-cgi \
@@ -53,7 +53,6 @@ cp sapi/fuzzer/json.dict $OUT/php-fuzz-json.dict
FUZZERS="php-fuzz-json
php-fuzz-exif
-php-fuzz-mbstring
php-fuzz-unserialize
php-fuzz-unserializehash
php-fuzz-parser
@@ -61,6 +60,19 @@ php-fuzz-execute"
for fuzzerName in $FUZZERS; do
cp sapi/fuzzer/$fuzzerName $OUT/
done
+
+# The JIT fuzzer is fundamentally incompatible with memory sanitizer,
+# as that would require the JIT to emit msan instrumentation itself.
+# In practice it is currently also incompatible with ubsan.
+if [ "$SANITIZER" != "memory" ] && [ "$SANITIZER" != "undefined" ]; then
+ cp sapi/fuzzer/php-fuzz-function-jit $OUT/
+ cp sapi/fuzzer/php-fuzz-tracing-jit $OUT/
+
+ # Copy opcache.so extension, which does not support static linking.
+ mkdir -p $OUT/modules
+ cp modules/opcache.so $OUT/modules
+fi
+
# copy corpora from source
for fuzzerName in `ls sapi/fuzzer/corpus`; do
zip -j $OUT/php-fuzz-${fuzzerName}_seed_corpus.zip sapi/fuzzer/corpus/${fuzzerName}/*
diff --git a/projects/pidgin/Dockerfile b/projects/pidgin/Dockerfile
new file mode 100644
index 000000000..aa93e960d
--- /dev/null
+++ b/projects/pidgin/Dockerfile
@@ -0,0 +1,38 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 \
+ make autoconf automake libtool pkg-config \
+ zlib1g-dev zlib1g-dev:i386 liblzma-dev liblzma-dev:i386 \
+ wget intltool sasl2-bin python3-pip
+RUN pip3 install -U meson ninja
+
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/glib
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
+RUN wget https://sourceforge.net/projects/pidgin/files/Pidgin/2.14.5/pidgin-2.14.5.tar.bz2
+RUN wget ftp://sourceware.org/pub/libffi/libffi-3.2.1.tar.gz
+
+RUN git clone --depth 1 https://github.com/dvyukov/go-fuzz-corpus
+RUN git clone --depth 1 https://github.com/google/fuzzing
+
+WORKDIR $SRC
+
+COPY build.sh \
+ pidgin_xml_fuzzer.c \
+ pidgin_utils_fuzzer.c \
+ $SRC/
diff --git a/projects/pidgin/build.sh b/projects/pidgin/build.sh
new file mode 100644
index 000000000..33bcf367e
--- /dev/null
+++ b/projects/pidgin/build.sh
@@ -0,0 +1,127 @@
+#!/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.
+#
+################################################################################
+
+# Place to keep dependencies for static linking
+DEPS=/deps
+mkdir ${DEPS}
+
+
+# Build libffi
+cd $SRC
+tar xvfz libffi-3.2.1.tar.gz
+cd libffi-3.2.1
+./configure --disable-shared
+make -j$(nproc)
+export LIBFFI_LIBS="-L/src/libffi-3.2.1 libraries/ -lffi"
+cp ./x86_64-unknown-linux-gnu/.libs/libffi.a ${DEPS}/
+
+
+# Build libxml2
+cd $SRC/libxml2
+./autogen.sh \
+ --disable-shared \
+ --without-debug \
+ --without-ftp \
+ --without-http \
+ --without-legacy \
+ --without-python
+make -j$(nproc)
+make install
+cp .libs/libxml2.a ${DEPS}/
+
+
+# Build glib
+cd $SRC/glib
+GLIB_BUILD=$WORK/meson
+rm -rf $GLIB_BUILD
+mkdir $GLIB_BUILD
+meson $GLIB_BUILD \
+ -Db_lundef=false \
+ -Ddefault_library=static \
+ -Dlibmount=disabled
+ninja -C $GLIB_BUILD
+ninja -C $GLIB_BUILD install
+
+cp ${GLIB_BUILD}/gobject/libgobject-2.0.a ${DEPS}/
+cp ${GLIB_BUILD}/gmodule/libgmodule-2.0.a ${DEPS}/
+cp ${GLIB_BUILD}/glib/libglib-2.0.a ${DEPS}/
+
+
+# Build Pidgin
+cd $SRC
+tar -xf pidgin-2.14.5.tar.bz2
+mv pidgin-2.14.5 pidgin
+cd pidgin
+./configure --disable-consoleui \
+ --disable-shared \
+ --disable-screensaver \
+ --disable-sm \
+ --disable-gtkspell \
+ --disable-gevolution \
+ --enable-gnutls=no \
+ --disable-gstreamer \
+ --disable-vv \
+ --disable-idn \
+ --disable-meanwhile \
+ --disable-avahi \
+ --disable-dbus \
+ --disable-perl \
+ --disable-tcl \
+ --disable-cyrus-sasl \
+ --disable-gtkui \
+ --enable-nss=no
+make -j$(nproc)
+
+
+# Build fuzzers
+readonly FUZZERS=( \
+ pidgin_xml_fuzzer
+ pidgin_utils_fuzzer
+)
+
+cd libpurple
+cp $SRC/*fuzzer.c .
+
+for fuzzer in "${FUZZERS[@]}"; do
+ $CC $CFLAGS -DHAVE_CONFIG_H \
+ -I. \
+ -I.. \
+ -I${SRC}/glib \
+ -I${SRC}/glib/glib \
+ -I${SRC}/glib/gmodule \
+ -I${GLIB_BUILD} \
+ -I${GLIB_BUILD}/glib \
+ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include \
+ -I/src/pidgin/libpurple/protocols/jabber \
+ -I/usr/local/include/libxml2 \
+ -c $fuzzer.c \
+ -o $fuzzer.o
+
+ $CC $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.o \
+ -o $OUT/$fuzzer \
+ /src/pidgin/libpurple/protocols/jabber/.libs/libjabber.a \
+ ./.libs/libpurple.a \
+ ${DEPS}/libxml2.a \
+ ${DEPS}/libgobject-2.0.a \
+ ${DEPS}/libgmodule-2.0.a \
+ ${DEPS}/libglib-2.0.a \
+ ${DEPS}/libffi.a \
+ -lresolv -lz -llzma
+done
+
+zip $OUT/pidgin_xml_fuzzer_seed_corpus.zip $SRC/go-fuzz-corpus/xml/corpus/*
+cp $SRC/fuzzing/dictionaries/xml.dict $OUT/pidgin_xml_fuzzer.dict
diff --git a/projects/pidgin/pidgin_utils_fuzzer.c b/projects/pidgin/pidgin_utils_fuzzer.c
new file mode 100644
index 000000000..ce386bb77
--- /dev/null
+++ b/projects/pidgin/pidgin_utils_fuzzer.c
@@ -0,0 +1,78 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ char *nstr = (char *)malloc(size + 1);
+ if (nstr == NULL) {
+ return 0;
+ }
+ memcpy(nstr, data, size);
+ nstr[size] = '\0';
+
+ guchar *tmp = NULL;
+ gsize retlen;
+
+ if (size % 2 == 0 && strlen(nstr) > 0) {
+ tmp = purple_base16_decode(nstr, &retlen);
+ if (tmp != NULL) {
+ g_free(tmp);
+ }
+ }
+
+ tmp = NULL;
+ tmp = purple_quotedp_decode(nstr, &retlen);
+ if (tmp != NULL) {
+ g_free(tmp);
+ }
+
+ char *tmp2 = NULL;
+ tmp2 = purple_mime_decode_field(nstr);
+ if (tmp2 != NULL) {
+ free(tmp2);
+ }
+
+ purple_str_to_time(nstr, TRUE, NULL, NULL, NULL);
+
+ gchar *xhtml = NULL;
+ gchar *plaintext = NULL;
+ purple_markup_html_to_xhtml(nstr, &xhtml, &plaintext);
+
+ if (xhtml != NULL) {
+ g_free(xhtml);
+ }
+
+ if (plaintext != NULL) {
+ g_free(plaintext);
+ }
+
+ char *tmp3 = purple_markup_strip_html(nstr);
+ if (tmp3 != NULL) {
+ free(tmp3);
+ }
+
+ purple_markup_is_rtl(nstr);
+
+ free(nstr);
+ return 0;
+}
diff --git a/projects/pidgin/pidgin_xml_fuzzer.c b/projects/pidgin/pidgin_xml_fuzzer.c
new file mode 100644
index 000000000..a91034a5e
--- /dev/null
+++ b/projects/pidgin/pidgin_xml_fuzzer.c
@@ -0,0 +1,55 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xmlnode.h"
+#include "caps.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ char *malicious_xml = (char *)malloc(size + 1);
+ if (malicious_xml == NULL) {
+ return 0;
+ }
+ memcpy(malicious_xml, data, size);
+ malicious_xml[size] = '\0';
+
+ xmlnode *isc = xmlnode_from_str(malicious_xml, size+1);
+ if (isc != NULL) {
+ xmlnode_set_attrib(isc, "name", "query");
+
+ // Parse Jabber caps
+ JabberCapsClientInfo *info = jabber_caps_parse_client_info(isc);
+ gchar *got_hash = jabber_caps_calculate_hash(info, ("sha1"));
+
+ // Insert a child
+ xmlnode *child = xmlnode_new_child(isc, "query");
+ xmlnode_insert_child(isc, child);
+
+ // Get data
+ char *retrieved_data = xmlnode_get_data(isc);
+ char *retrieved_data_unescaped = xmlnode_get_data_unescaped(isc);
+
+ xmlnode_free(isc);
+ }
+
+ free(malicious_xml);
+ return 0;
+} \ No newline at end of file
diff --git a/projects/pidgin/project.yaml b/projects/pidgin/project.yaml
index d94a2688d..6756a8cc7 100644
--- a/projects/pidgin/project.yaml
+++ b/projects/pidgin/project.yaml
@@ -1,2 +1,7 @@
homepage: "https://www.pidgin.im/"
primary_contact: "gary.kramlich@gmail.com"
+language: c
+auto_ccs:
+ - "quantum.analyst@gmail.com"
+ - "rekkanoryo.guifications@gmail.com"
+main_repo: 'https://sourceforge.net/projects/pidgin/files/Pidgin/2.14.4/pidgin-2.14.4.tar.bz2'
diff --git a/projects/pillow/Dockerfile b/projects/pillow/Dockerfile
index ab9089553..fc4b30653 100644
--- a/projects/pillow/Dockerfile
+++ b/projects/pillow/Dockerfile
@@ -14,32 +14,20 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN git clone --depth 1 https://github.com/google/fuzzing
-RUN cat fuzzing/dictionaries/bmp.dict \
- fuzzing/dictionaries/dds.dict \
- fuzzing/dictionaries/gif.dict \
- fuzzing/dictionaries/icns.dict \
- fuzzing/dictionaries/jpeg.dict \
- fuzzing/dictionaries/jpeg2000.dict \
- fuzzing/dictionaries/pbm.dict \
- fuzzing/dictionaries/png.dict \
- fuzzing/dictionaries/psd.dict \
- fuzzing/dictionaries/tiff.dict \
- fuzzing/dictionaries/webp.dict \
- > $OUT/fuzz_pillow.dict
+FROM gcr.io/oss-fuzz-base/base-builder-python
# library build dependencies
RUN apt-get update && \
apt-get install -y \
libxau-dev \
pkg-config \
- rsync \
- zlib1g-dev
+ rsync
RUN git clone --depth 1 https://github.com/python-pillow/Pillow
RUN git clone --depth 1 https://github.com/python-pillow/pillow-wheels
+RUN $SRC/Pillow/Tests/oss-fuzz/build_dictionaries.sh
+
COPY build_depends.sh $SRC
RUN ln -s /usr/local/bin/python3 /usr/local/bin/python \
@@ -58,6 +46,6 @@ COPY build.sh $SRC/
RUN apt-get install -y \
python3-tk \
tcl8.6-dev \
- tk8.6-dev
+ tk8.6-dev
WORKDIR $SRC/Pillow
diff --git a/projects/pillow/build.sh b/projects/pillow/build.sh
index e7dac3463..4656c7cab 100644
--- a/projects/pillow/build.sh
+++ b/projects/pillow/build.sh
@@ -15,33 +15,4 @@
#
################################################################################
-python3 setup.py build --build-base=/tmp/build install
-
-# Build fuzzers in $OUT.
-for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
- fuzzer_basename=$(basename -s .py $fuzzer)
- fuzzer_package=${fuzzer_basename}.pkg
- pyinstaller \
- --add-binary /usr/local/lib/libjpeg.so.9:. \
- --add-binary /usr/local/lib/libfreetype.so.6:. \
- --add-binary /usr/local/lib/liblcms2.so.2:. \
- --add-binary /usr/local/lib/libopenjp2.so.7:. \
- --add-binary /usr/local/lib/libpng16.so.16:. \
- --add-binary /usr/local/lib/libtiff.so.5:. \
- --add-binary /usr/local/lib/libwebp.so.7:. \
- --add-binary /usr/local/lib/libwebpdemux.so.2:. \
- --add-binary /usr/local/lib/libwebpmux.so.3:. \
- --add-binary /usr/local/lib/libxcb.so.1:. \
- --distpath $OUT --onefile --name $fuzzer_package $fuzzer
-
- # Create execution wrapper.
- 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 u+x $OUT/$fuzzer_basename
-done
-
-find Tests/images Tests/icc Tests/fonts -print | zip -q $OUT/fuzz_pillow_seed_corpus.zip -@
+./Tests/oss-fuzz/build.sh
diff --git a/projects/pistache/Dockerfile b/projects/pistache/Dockerfile
new file mode 100644
index 000000000..7071af9a5
--- /dev/null
+++ b/projects/pistache/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 pip3 install meson==0.53.0 ninja
+RUN git clone --depth 1 https://github.com/pistacheio/pistache pistache
+WORKDIR pistache
+COPY build.sh $SRC/
diff --git a/projects/pistache/build.sh b/projects/pistache/build.sh
new file mode 100755
index 000000000..ea8fd177e
--- /dev/null
+++ b/projects/pistache/build.sh
@@ -0,0 +1,22 @@
+#!/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
+meson --default-library=static ../
+ninja
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzz_parsers \
+ -std=c++17 -I../include/ ../tests/fuzzers/fuzz_parser.cpp ./src/libpistache.a
diff --git a/projects/pistache/project.yaml b/projects/pistache/project.yaml
new file mode 100644
index 000000000..8da315c3a
--- /dev/null
+++ b/projects/pistache/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://pistache.io"
+language: c++
+primary_contact: "kip@thevertigo.com"
+main_repo: "https://github.com/pistacheio/pistache"
+auto_ccs:
+ - "dennis.jenkins.75@gmail.com"
+ - "andrea@pappacoda.it"
+ - "hyperxor@protonmail.com"
+ - "auquetal@gmail.com"
+ - "david@adalogics.com"
diff --git a/projects/poco/Dockerfile b/projects/poco/Dockerfile
new file mode 100644
index 000000000..c9f0b2f1a
--- /dev/null
+++ b/projects/poco/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 openssl libssl-dev git make cmake libssl-dev
+RUN git clone --depth 1 -b poco-1.11.0 https://github.com/pocoproject/poco
+WORKDIR $SRC/poco
+COPY build.sh \
+ json_parse_fuzzer.cc \
+ $SRC/
diff --git a/projects/poco/build.sh b/projects/poco/build.sh
new file mode 100755
index 000000000..6d0d79268
--- /dev/null
+++ b/projects/poco/build.sh
@@ -0,0 +1,37 @@
+#!/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 cmake-build
+cd cmake-build
+cmake -DBUILD_SHARED_LIBS=OFF \
+ -DENABLE_TESTS=OFF \
+ ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DPOCO_ENABLE_CPP11 -DPOCO_ENABLE_CPP14 \
+ -DPOCO_HAVE_FD_EPOLL -DPOCO_OS_FAMILY_UNIX \
+ -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE \
+ -D_REENTRANT -D_THREAD_SAFE -D_XOPEN_SOURCE=500 \
+ -I/src/poco/JSON/include \
+ -I/src/poco/Foundation/include \
+ -O2 -g -DNDEBUG -std=gnu++14 \
+ -o json_fuzzer.o -c $SRC/json_parse_fuzzer.cc
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE json_fuzzer.o \
+ ./lib/libPocoJSON.a \
+ ./lib/libPocoFoundation.a \
+ -o $OUT/json_parser_fuzzer -lpthread -ldl -lrt
diff --git a/projects/poco/json_parse_fuzzer.cc b/projects/poco/json_parse_fuzzer.cc
new file mode 100644
index 000000000..e03ff2fa9
--- /dev/null
+++ b/projects/poco/json_parse_fuzzer.cc
@@ -0,0 +1,30 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 "Poco/JSON/JSON.h"
+#include "Poco/JSON/Parser.h"
+#include "Poco/JSON/ParserImpl.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ std::string json(reinterpret_cast<const char *>(data), size);
+ Poco::JSON::Parser parser;
+
+ Poco::Dynamic::Var result;
+ try {
+ result = parser.parse(json);
+ } catch (Poco::Exception &e) {
+ return 0;
+ } catch (const std::exception &e) {
+ return 0;
+ }
+ return 0;
+}
diff --git a/projects/poco/project.yaml b/projects/poco/project.yaml
new file mode 100644
index 000000000..79e07d7d5
--- /dev/null
+++ b/projects/poco/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/pocoproject/poco"
+main_repo: "https://github.com/pocoproject/poco"
+language: c++
+primary_contact: "guenter@pocoproject.org"
+auto_ccs:
+ - "Adam@adalogics.com"
+ - "alex@pocoproject.org"
+sanitizers:
+ - address
+ - undefined
+ - memory
diff --git a/projects/poppler/Dockerfile b/projects/poppler/Dockerfile
index c1b0355cf..dd7160d65 100644
--- a/projects/poppler/Dockerfile
+++ b/projects/poppler/Dockerfile
@@ -26,10 +26,10 @@ RUN git clone --depth 1 https://github.com/glennrp/libpng.git
RUN git clone --depth 1 https://gitlab.freedesktop.org/fontconfig/fontconfig.git
RUN git clone --depth 1 https://gitlab.freedesktop.org/cairo/cairo.git
RUN git clone --depth 1 --branch=5.15 git://code.qt.io/qt/qtbase.git
-ADD http://ftp.gnome.org/pub/gnome/sources/pango/1.48/pango-1.48.0.tar.xz $SRC
-RUN tar xvJf $SRC/pango-1.48.0.tar.xz
-ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.64/glib-2.64.2.tar.xz $SRC
-RUN tar xvJf $SRC/glib-2.64.2.tar.xz
+RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/pango.git
+ADD https://ftp.gnome.org/pub/gnome/sources/glib/2.70/glib-2.70.0.tar.xz $SRC
+RUN tar xvJf $SRC/glib-2.70.0.tar.xz
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.bz2
RUN git clone --depth 1 --single-branch https://gitlab.freedesktop.org/poppler/poppler.git
RUN git clone --depth 1 https://github.com/mozilla/pdf.js pdf.js && \
diff --git a/projects/poppler/build.sh b/projects/poppler/build.sh
index 23692dd5b..02915b70d 100755
--- a/projects/poppler/build.sh
+++ b/projects/poppler/build.sh
@@ -27,6 +27,14 @@ rm -rf $WORK/*
rm -rf $BUILD
mkdir -p $BUILD
+# Install Boost headers
+cd $SRC/
+tar jxf boost_1_76_0.tar.bz2
+cd boost_1_76_0/
+CFLAGS="" CXXFLAGS="" ./bootstrap.sh
+CFLAGS="" CXXFLAGS="" ./b2 headers
+cp -R boost/ /usr/include/
+
pushd $SRC/zlib
CFLAGS=-fPIC ./configure --static --prefix=$PREFIX
make install -j$(nproc)
@@ -38,7 +46,7 @@ make -j$(nproc)
make install
pushd $SRC/Little-CMS
-./configure --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+./autogen.sh --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
make -j$(nproc)
make install
@@ -59,7 +67,7 @@ if [ "$SANITIZER" != "memory" ]; then
ninja -C _builddir install
popd
- pushd $SRC/glib-2.64.2
+ pushd $SRC/glib-2.70.0
meson \
--prefix=$PREFIX \
--libdir=lib \
@@ -89,7 +97,7 @@ if [ "$SANITIZER" != "memory" ]; then
ninja -C _builddir install
popd
- pushd $SRC/pango-1.48.0
+ pushd $SRC/pango
meson \
-Ddefault_library=static \
--prefix=$PREFIX \
diff --git a/projects/poppler/project.yaml b/projects/poppler/project.yaml
index c12379633..bb1ae170c 100644
--- a/projects/poppler/project.yaml
+++ b/projects/poppler/project.yaml
@@ -3,9 +3,10 @@ language: c++
primary_contact: tsdgeos@gmail.com
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
auto_ccs:
- jonathan@titanous.com
- adam.reichold@t-online.de
-main_repo: 'https://anongit.freedesktop.org/git/poppler/poppler.git'
+main_repo: 'https://anongit.freedesktop.org/git/poppler/poppler.git' \ No newline at end of file
diff --git a/projects/postgis/Dockerfile b/projects/postgis/Dockerfile
index 67b7a6969..2c55c5497 100644
--- a/projects/postgis/Dockerfile
+++ b/projects/postgis/Dockerfile
@@ -15,8 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN echo deb http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse >> /etc/apt/sources.list
-RUN apt-get update && apt-get install -y make autoconf automake libtool g++ postgresql-server-dev-10 libgeos-dev libproj-dev libxml2-dev pkg-config libjson-c-dev
+RUN apt-get update && apt-get install -y make autoconf automake libtool g++ postgresql-server-dev-12 libgeos-dev libproj-dev libxml2-dev pkg-config libjson-c-dev
RUN git clone --depth 1 https://git.osgeo.org/gitea/postgis/postgis.git postgis
WORKDIR postgis
COPY build.sh $SRC/
diff --git a/projects/postgresql/add_fuzzers.diff b/projects/postgresql/add_fuzzers.diff
index 86b106c22..5674bc34d 100644
--- a/projects/postgresql/add_fuzzers.diff
+++ b/projects/postgresql/add_fuzzers.diff
@@ -1,25 +1,27 @@
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
-index cb5a96117f..c9b4880085 100644
+index 0775abe35d..f53b3580b3 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
-@@ -102,6 +102,9 @@ int max_stack_depth = 100;
- /* wait N seconds to allow attach from a debugger */
- int PostAuthDelay = 0;
+@@ -105,6 +105,11 @@ int PostAuthDelay = 0;
+ /* Time between checks that the client is still connected. */
+ int client_connection_check_interval = 0;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+bool fuzzer_first_run = true;
+#endif
-
-
++
++
/* ----------------
-@@ -507,10 +510,15 @@ ReadCommand(StringInfo inBuf)
+ * private typedefs etc
+ * ----------------
+@@ -471,11 +476,14 @@ static int
+ ReadCommand(StringInfo inBuf)
{
int result;
-
+-
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+ result = SocketBackend(inBuf);
++ result = SocketBackend(inBuf);
+#else
-+
if (whereToSendOutput == DestRemote)
result = SocketBackend(inBuf);
else
@@ -28,19 +30,19 @@ index cb5a96117f..c9b4880085 100644
return result;
}
-@@ -3846,6 +3854,11 @@ PostgresMain(int argc, char *argv[],
+@@ -4021,6 +4029,11 @@ PostgresMain(const char *dbname, const char *username)
bool idle_in_transaction_timeout_enabled = false;
bool idle_session_timeout_enabled = false;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+ if(fuzzer_first_run)
-+ {
++ if(fuzzer_first_run)
++ {
+#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
+
- /* Initialize startup process environment if necessary. */
- if (!IsUnderPostmaster)
- InitStandaloneProcess(argv[0]);
-@@ -4207,6 +4220,11 @@ PostgresMain(int argc, char *argv[],
+ AssertArg(dbname != NULL);
+ AssertArg(username != NULL);
+
+@@ -4312,6 +4325,11 @@ PostgresMain(const char *dbname, const char *username)
if (!ignore_till_sync)
send_ready_for_query = true; /* initially, or after error */
@@ -53,11 +55,11 @@ index cb5a96117f..c9b4880085 100644
* Non-error queries loop here.
*/
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
-index 80c2672461..c16e0423c5 100644
+index 2af87ee3bd..825bb70532 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
-@@ -600,7 +600,9 @@ errfinish(const char *filename, int lineno, const char *funcname)
- pq_endcopyout(true);
+@@ -594,7 +594,9 @@ errfinish(const char *filename, int lineno, const char *funcname)
+ }
/* Emit the message to the right places */
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
diff --git a/projects/postgresql/build.sh b/projects/postgresql/build.sh
index 12fb754a4..ee56ecdef 100644
--- a/projects/postgresql/build.sh
+++ b/projects/postgresql/build.sh
@@ -15,7 +15,7 @@
#
################################################################################
cp -r $SRC/fuzzer src/backend/
-git apply ../add_fuzzers.diff
+git apply --ignore-space-change --ignore-whitespace ../add_fuzzers.diff
useradd fuzzuser
chown -R fuzzuser .
@@ -35,5 +35,12 @@ make clean
make
cd src/backend/fuzzer
make fuzzer
+#if [ "$FUZZING_ENGINE" = "afl" ]
+#then
+rm protocol_fuzzer
+#fi
cp *_fuzzer $OUT/
cp $SRC/postgresql_fuzzer_seed_corpus.zip $OUT/
+
+# Temporary fix. Todo: David fix this.
+#rm $OUT/protocol_fuzzer
diff --git a/projects/postgresql/fuzzer/fuzzer_initialize.c b/projects/postgresql/fuzzer/fuzzer_initialize.c
index 0ab9d7dcd..33f8278b9 100644
--- a/projects/postgresql/fuzzer/fuzzer_initialize.c
+++ b/projects/postgresql/fuzzer/fuzzer_initialize.c
@@ -82,8 +82,9 @@ int FuzzerInitialize(char *dbname, char ***argv){
LocalProcessControlFile(false);
InitializeMaxBackends();
- BaseInit();
+ CreateSharedMemoryAndSemaphores();
InitProcess();
+ BaseInit();
PG_SETMASK(&UnBlockSig);
InitPostgres("dbfuzz", InvalidOid, username, InvalidOid, NULL, false);
diff --git a/projects/postgresql/fuzzer/protocol_fuzzer.c b/projects/postgresql/fuzzer/protocol_fuzzer.c
index 7621644f7..3efe8e4b2 100644
--- a/projects/postgresql/fuzzer/protocol_fuzzer.c
+++ b/projects/postgresql/fuzzer/protocol_fuzzer.c
@@ -74,7 +74,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv) {
MemoryContextInit();
if(!sigsetjmp(postgre_exit, 0)){
postgre_started = true;
- PostgresMain(5, av, "dbfuzz", "fuzzuser");
+ PostgresSingleUserMain(5, av, "fuzzuser");
}
pq_endmsgread();
return 0;
@@ -106,7 +106,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if(!sigsetjmp(postgre_exit, 0)){
postgre_started = true;
- PostgresMain(5, av, "dbfuzz", "fuzzuser");
+ PostgresSingleUserMain(5, av, "fuzzuser");
}
pq_endmsgread();
postgre_started = false;
diff --git a/projects/powerdns/Dockerfile b/projects/powerdns/Dockerfile
index db7614c37..6d02406ec 100644
--- a/projects/powerdns/Dockerfile
+++ b/projects/powerdns/Dockerfile
@@ -20,7 +20,7 @@ FROM gcr.io/oss-fuzz-base/base-builder
# maintainer for this file
# install required packages to build your project
-RUN add-apt-repository -y ppa:savoury1/boost-defaults-1.71 && apt-get update && apt-get install -y autoconf automake bison dh-autoreconf flex boost1.71-dev libluajit-5.1-dev libedit-dev libprotobuf-dev libssl-dev libtool make pkg-config protobuf-compiler ragel
+RUN apt-get update && apt-get install -y autoconf automake bison dh-autoreconf flex boost1.71-all-dev libluajit-5.1-dev libedit-dev libprotobuf-dev libssl-dev libtool make pkg-config protobuf-compiler ragel
# checkout all sources needed to build your project
RUN git clone https://github.com/PowerDNS/pdns.git pdns
diff --git a/projects/powerdns/build.sh b/projects/powerdns/build.sh
index b8922c58a..7da909ae2 100644
--- a/projects/powerdns/build.sh
+++ b/projects/powerdns/build.sh
@@ -44,7 +44,21 @@ cp fuzz_target_* "${OUT}/"
cp ../regression-tests/zones/* ../fuzzing/corpus/zones/
# generate the corpus files
-zip -j "${OUT}/fuzz_target_dnsdistcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_moadnsparser_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_packetcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
-zip -j "${OUT}/fuzz_target_zoneparsertng_seed_corpus.zip" ../fuzzing/corpus/zones/*
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+ zip -j "${OUT}/fuzz_target_dnsdistcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/txt-records/ ]; then
+ zip -j "${OUT}/fuzz_target_dnslabeltext_parseRFC1035CharString_seed_corpus.zip" ../fuzzing/corpus/txt-records/*
+fi
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+ zip -j "${OUT}/fuzz_target_moadnsparser_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/raw-dns-packets/ ]; then
+ zip -j "${OUT}/fuzz_target_packetcache_seed_corpus.zip" ../fuzzing/corpus/raw-dns-packets/*
+fi
+if [ -d ../fuzzing/corpus/proxy-protocol-raw-packets/ ]; then
+ zip -j "${OUT}/fuzz_target_proxyprotocol_seed_corpus.zip" ../fuzzing/corpus/proxy-protocol-raw-packets/*
+fi
+if [ -d ../fuzzing/corpus/zones/ ]; then
+ zip -j "${OUT}/fuzz_target_zoneparsertng_seed_corpus.zip" ../fuzzing/corpus/zones/*
+fi
diff --git a/projects/proftpd/Dockerfile b/projects/proftpd/Dockerfile
new file mode 100644
index 000000000..fe6b37f30
--- /dev/null
+++ b/projects/proftpd/Dockerfile
@@ -0,0 +1,22 @@
+# 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 make autoconf automake libtool \
+ pkg-config cmake check
+RUN git clone --depth 1 https://github.com/proftpd/proftpd
+WORKDIR proftpd
+COPY build.sh fuzzer.c $SRC/
diff --git a/projects/proftpd/build.sh b/projects/proftpd/build.sh
new file mode 100755
index 000000000..2ec6ddca6
--- /dev/null
+++ b/projects/proftpd/build.sh
@@ -0,0 +1,46 @@
+#!/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 LDFLAGS="${CFLAGS}"
+./configure --enable-ctrls
+make -j$(nproc)
+
+# We need a few declarations from main.c
+# so we rename main() to main2()
+sed 's/int main(/int main2(/g' -i $SRC/proftpd/src/main.c
+
+# Compile main.c again
+export NEW_CC_FLAG="${CC} ${CFLAGS} -DHAVE_CONFIG_H -DLINUX -I. -I./include"
+$NEW_CC_FLAG -c src/main.c -o src/main.o
+rm src/ftpdctl.o
+
+find . -name "*.o" -exec ar rcs fuzz_lib.a {} \;
+
+# Build fuzzer(s)
+$NEW_CC_FLAG -c $SRC/fuzzer.c -o fuzzer.o
+$CC $CXXFLAGS $LIB_FUZZING_ENGINE fuzzer.o -o $OUT/fuzzer \
+ src/scoreboard.o \
+ lib/prbase.a \
+ fuzz_lib.a \
+ -L/src/proftpd/lib \
+ -lcrypt -pthread
+
+# Build seed corpus
+cd $SRC
+git clone https://github.com/dvyukov/go-fuzz-corpus
+zip $OUT/fuzzer_seed_corpus.zip go-fuzz-corpus/json/corpus/*
+
diff --git a/projects/proftpd/fuzzer.c b/projects/proftpd/fuzzer.c
new file mode 100644
index 000000000..ef8606825
--- /dev/null
+++ b/projects/proftpd/fuzzer.c
@@ -0,0 +1,43 @@
+/*
+# Copyright 2021 Google LLC.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "json.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';
+
+ pool *p = make_sub_pool(NULL);
+ if (p != NULL) {
+ init_json();
+ pr_json_object_t *json = pr_json_object_from_text(p, new_str);
+ pr_json_object_free(json);
+ finish_json();
+ destroy_pool(p);
+ }
+
+ free(new_str);
+ return 0;
+}
diff --git a/projects/proftpd/project.yaml b/projects/proftpd/project.yaml
new file mode 100644
index 000000000..f3b5317f4
--- /dev/null
+++ b/projects/proftpd/project.yaml
@@ -0,0 +1,9 @@
+homepage: "http://www.proftpd.org/"
+main_repo: "https://github.com/proftpd/proftpd"
+language: c
+primary_contact: "castaglian@gmail.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
diff --git a/projects/prometheus/Dockerfile b/projects/prometheus/Dockerfile
index 7e22750f9..eb9d3bcc7 100644
--- a/projects/prometheus/Dockerfile
+++ b/projects/prometheus/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
ENV GO111MODULE=on
RUN git clone https://github.com/prometheus/prometheus $GOPATH/src/github.com/prometheus/prometheus
COPY build.sh $SRC/
diff --git a/projects/prost/Dockerfile b/projects/prost/Dockerfile
new file mode 100644
index 000000000..d340fe5fc
--- /dev/null
+++ b/projects/prost/Dockerfile
@@ -0,0 +1,20 @@
+# 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 apt-get update && apt-get install -y pkg-config libssl-dev curl libcurl4-openssl-dev ninja-build
+RUN git clone --depth 1 https://github.com/danburkert/prost
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/prost/build.sh b/projects/prost/build.sh
new file mode 100755
index 000000000..4b9c38285
--- /dev/null
+++ b/projects/prost/build.sh
@@ -0,0 +1,21 @@
+#!/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/prost
+cargo fuzz build -O
+cp fuzz/target/x86_64-unknown-linux-gnu/release/proto2 $OUT/
+cp fuzz/target/x86_64-unknown-linux-gnu/release/proto3 $OUT/
diff --git a/projects/prost/project.yaml b/projects/prost/project.yaml
new file mode 100644
index 000000000..49f69f2a7
--- /dev/null
+++ b/projects/prost/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://crates.io/crates/prost"
+main_repo: "https://github.com/danburkert/prost"
+primary_contact: "dan@danburkert.com"
+sanitizers:
+ - address
+fuzzing_engines:
+ - libfuzzer
+language: rust
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/protobuf-c/build.sh b/projects/protobuf-c/build.sh
index 8eda36a39..c84006502 100755
--- a/projects/protobuf-c/build.sh
+++ b/projects/protobuf-c/build.sh
@@ -46,6 +46,7 @@ cd $SRC/protobuf-c/
./configure --enable-static=yes --enable-shared=false PKG_CONFIG_PATH=$SRC/protobuf-install/lib/pkgconfig
make -j$(nproc)
+make install
cd $SRC/fuzzing-headers/
./install.sh
@@ -53,6 +54,6 @@ cd $SRC/fuzzing-headers/
cd $SRC/protobuf-c-fuzzers/
cp $SRC/protobuf-c/t/test-full.proto $SRC/protobuf-c-fuzzers/
export PATH=$PATH:$SRC/protobuf-c/protoc-c
-$PROTOC --c_out=. test-full.proto
+$PROTOC --c_out=. -I. -I/usr/local/include test-full.proto
$CC $CFLAGS test-full.pb-c.c -I $SRC/protobuf-install -I $SRC/protobuf-c -c -o test-full.pb-c.o
$CXX $CXXFLAGS fuzzer.cpp -I $SRC/protobuf-install -I $SRC/protobuf-c test-full.pb-c.o $SRC/protobuf-c/protobuf-c/.libs/libprotobuf-c.a $LIB_FUZZING_ENGINE -o $OUT/fuzzer
diff --git a/projects/protobuf-c/project.yaml b/projects/protobuf-c/project.yaml
index 9103f1bce..54245ffe6 100644
--- a/projects/protobuf-c/project.yaml
+++ b/projects/protobuf-c/project.yaml
@@ -5,9 +5,10 @@ auto_ccs:
- "ilya.lipnitskiy@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- i386
main_repo: 'https://github.com/protobuf-c/protobuf-c.git'
-coverage_extra_args: -ignore-filename-regex=.*/protobuf-install/.*
+coverage_extra_args: -ignore-filename-regex=.*/protobuf-install/.* \ No newline at end of file
diff --git a/projects/protobuf-java/Dockerfile b/projects/protobuf-java/Dockerfile
new file mode 100644
index 000000000..b14084f45
--- /dev/null
+++ b/projects/protobuf-java/Dockerfile
@@ -0,0 +1,34 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 pkg-config
+
+RUN curl -L https://downloads.apache.org/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 curl -L -O https://raw.githubusercontent.com/protobuf-c/protobuf-c/39cd58f5ff06048574ed5ce17ee602dc84006162/t/test-full.proto
+
+RUN git clone --depth 1 --recursive https://github.com/protocolbuffers/protobuf.git
+
+COPY build.sh $SRC
+COPY ProtobufFuzzer.java $SRC
+
+WORKDIR $SRC
diff --git a/projects/protobuf-java/ProtobufFuzzer.java b/projects/protobuf-java/ProtobufFuzzer.java
new file mode 100644
index 000000000..3e5e09a45
--- /dev/null
+++ b/projects/protobuf-java/ProtobufFuzzer.java
@@ -0,0 +1,33 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.protobuf.InvalidProtocolBufferException;
+
+import foo.TestFull;
+
+public class ProtobufFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ TestFull.TestMessSubMess.parseFrom(input);
+ } catch (InvalidProtocolBufferException ignored) { }
+ try {
+ TestFull.TestFieldFlags.parseFrom(input);
+ } catch (InvalidProtocolBufferException ignored) { }
+ try {
+ TestFull.TestMessageCheck.parseFrom(input);
+ } catch (InvalidProtocolBufferException ignored) { }
+ }
+}
diff --git a/projects/protobuf-java/build.sh b/projects/protobuf-java/build.sh
new file mode 100755
index 000000000..e5f7363d9
--- /dev/null
+++ b/projects/protobuf-java/build.sh
@@ -0,0 +1,69 @@
+#!/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 protoc with default options.
+unset CFLAGS CXXFLAGS
+mkdir $SRC/protobuf-install/
+cd $SRC/protobuf/
+./autogen.sh
+./configure --prefix=$SRC/protobuf-install
+make -j$(nproc)
+make install
+
+export PROTOC="$SRC/protobuf-install/bin/protoc"
+
+# Build protobuf-java (requires protoc in source tree).
+cd $SRC/protobuf/java/
+cp $PROTOC $SRC/protobuf/src/
+MAVEN_ARGS="-Dmaven.test.skip=true -Djavac.src.version=15 -Djavac.target.version=15"
+$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/protobuf-java-$CURRENT_VERSION.jar" $OUT/protobuf-java.jar
+
+# Compile test protos with protoc.
+cd $SRC/
+$PROTOC --java_out=. --proto_path=. test-full.proto
+jar --create --file $OUT/test-full.jar foo/*
+
+ALL_JARS="protobuf-java.jar test-full.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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\" \
+\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \
+--cp=$RUNTIME_CLASSPATH \
+--target_class=$fuzzer_basename \
+--jvm_args=\"-Xmx2048m\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
+done
+
diff --git a/projects/protobuf-java/project.yaml b/projects/protobuf-java/project.yaml
new file mode 100644
index 000000000..afb45a26f
--- /dev/null
+++ b/projects/protobuf-java/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://developers.google.com/protocol-buffers/"
+language: jvm
+primary_contact: "kfm@google.com"
+auto_ccs:
+ - "meumertzheim@code-intelligence.com"
+ - "acozzette@google.com"
+ - "elharo@google.com"
+ - "pzd@google.com"
+ - "sandyzhang@google.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://github.com/protocolbuffers/protobuf"
+sanitizers:
+ - address
diff --git a/projects/protoreflect/Dockerfile b/projects/protoreflect/Dockerfile
new file mode 100644
index 000000000..948b3a577
--- /dev/null
+++ b/projects/protoreflect/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/jhump/protoreflect
+
+COPY fuzz_protoparse.go $SRC/protoreflect/desc/protoparse/
+COPY fuzz_dynamic.go $SRC/protoreflect/proto_decoder/
+
+COPY build.sh $SRC/
+WORKDIR $SRC/protoreflect
diff --git a/projects/protoreflect/build.sh b/projects/protoreflect/build.sh
new file mode 100755
index 000000000..3511f83c0
--- /dev/null
+++ b/projects/protoreflect/build.sh
@@ -0,0 +1,20 @@
+#!/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/jhump/protoreflect/desc/protoparse FuzzProtoParse fuzz_protoparse
+# compile_go_fuzzer github.com/jhump/protoreflect/proto_decoder Fuzz fuzz_dynamic
+
diff --git a/projects/protoreflect/fuzz_dynamic.go b/projects/protoreflect/fuzz_dynamic.go
new file mode 100644
index 000000000..ba26fe298
--- /dev/null
+++ b/projects/protoreflect/fuzz_dynamic.go
@@ -0,0 +1,33 @@
+package proto_decoder
+
+import (
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes/empty"
+ "github.com/jhump/protoreflect/desc"
+ "github.com/jhump/protoreflect/desc/builder"
+ "github.com/jhump/protoreflect/dynamic"
+)
+
+func Fuzz(data []byte) int {
+ d, err := desc.LoadMessageDescriptorForMessage(&empty.Empty{})
+ if err != nil {
+ panic(err)
+ }
+ mb, err := builder.FromMessage(d)
+ if err != nil {
+ panic(err)
+ }
+
+ msg, err := mb.Build()
+ if err != nil {
+ panic(err)
+ }
+
+ decoded := dynamic.NewMessage(msg)
+ err = proto.Unmarshal(data, decoded)
+ if err != nil {
+ return 0
+ }
+
+ return 1
+}
diff --git a/projects/protoreflect/fuzz_protoparse.go b/projects/protoreflect/fuzz_protoparse.go
new file mode 100644
index 000000000..5e5b9a97e
--- /dev/null
+++ b/projects/protoreflect/fuzz_protoparse.go
@@ -0,0 +1,21 @@
+package protoparse
+
+import (
+ "bytes"
+ "io"
+ "io/ioutil"
+)
+
+func FuzzProtoParse(data []byte) int {
+ parser := &Parser{
+ Accessor: func(_ string) (closer io.ReadCloser, e error) {
+ return ioutil.NopCloser(bytes.NewReader(data)), nil
+ },
+ }
+
+ _, err := parser.ParseFiles("dummy")
+ if err != nil {
+ return 0
+ }
+ return 1
+}
diff --git a/projects/protoreflect/project.yaml b/projects/protoreflect/project.yaml
new file mode 100644
index 000000000..278f98aa5
--- /dev/null
+++ b/projects/protoreflect/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/jhump/protoreflect"
+primary_contact: "jhumphries131@gmail.com"
+auto_ccs:
+ - "p.antoine@catenacyber.fr"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+main_repo: 'https://github.com/jhump/protoreflect'
diff --git a/projects/proxygen/Dockerfile b/projects/proxygen/Dockerfile
index 7899ed2a6..859b60caf 100644
--- a/projects/proxygen/Dockerfile
+++ b/projects/proxygen/Dockerfile
@@ -28,7 +28,9 @@ RUN apt-get update && \
gcc \
g++ \
python \
- python-dev
+ python-dev \
+ cmake \
+ ninja-build
# Install and build boost from source so we can have it use libc++
RUN wget https://sourceforge.net/projects/boost/files/boost/1.70.0/boost_1_70_0.tar.gz && \
@@ -96,6 +98,13 @@ RUN wget https://github.com/facebook/zstd/releases/download/v1.4.2/zstd-1.4.2.ta
cd .. && \
rm -rf zstd-1.4.2
+# Get double conversion
+RUN git clone --single-branch https://github.com/google/double-conversion.git double-conversion && \
+ cd double-conversion/double-conversion && \
+ cmake -GNinja ../ && \
+ ninja && \
+ ninja install
+
# Build and install `fmt` needed by folly
RUN wget https://github.com/fmtlib/fmt/archive/6.0.0.tar.gz && \
tar xzf 6.0.0.tar.gz && \
@@ -149,7 +158,6 @@ RUN apt-get install -y \
zlib1g-dev \
binutils-dev \
libsodium-dev \
- libdouble-conversion-dev \
libunwind8-dev
# Install patchelf so we can fix path to libunwind
diff --git a/projects/proxygen/build.sh b/projects/proxygen/build.sh
index dd3729f7d..dfa5ef921 100755
--- a/projects/proxygen/build.sh
+++ b/projects/proxygen/build.sh
@@ -15,6 +15,15 @@
#
################################################################################
+# Dont build tests we do not care about
+echo "" > ./proxygen/httpclient/samples/CMakeLists.txt
+echo "" > ./proxygen/httpserver/tests/CMakeLists.txt
+echo "" > ./proxygen/lib/http/structuredheaders/test/CMakeLists.txt
+echo "" > ./proxygen/httpserver/filters/tests/CMakeLists.txt
+echo "" > ./proxygen/lib/http/session/test/CMakeLists.txt
+echo "" > ./proxygen/lib/http/codec/compress/test/CMakeLists.txt
+echo "" > ./proxygen/lib/services/test/CMakeLists.txt
+
cd proxygen
# Link to, and copy over, libunwind
diff --git a/projects/pulumi/Dockerfile b/projects/pulumi/Dockerfile
new file mode 100644
index 000000000..3b12b3c7f
--- /dev/null
+++ b/projects/pulumi/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/pulumi/pulumi
+COPY build.sh \
+ config_fuzzer.go \
+ schema_fuzzer.go \
+ $SRC/
+WORKDIR $SRC/pulumi
diff --git a/projects/pulumi/build.sh b/projects/pulumi/build.sh
new file mode 100644
index 000000000..9671dcae8
--- /dev/null
+++ b/projects/pulumi/build.sh
@@ -0,0 +1,26 @@
+#!/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 pkg
+#go mod download
+
+cp $SRC/schema_fuzzer.go $SRC/pulumi/pkg/codegen/schema/
+compile_go_fuzzer github.com/pulumi/pulumi/pkg/v3/codegen/schema SchemaFuzzer schema_fuzzer
+
+cp $SRC/config_fuzzer.go $SRC/pulumi/sdk/go/common/resource/config/
+compile_go_fuzzer github.com/pulumi/pulumi/sdk/v3/go/common/resource/config FuzzConfig fuzz
+compile_go_fuzzer github.com/pulumi/pulumi/sdk/v3/go/common/resource/config FuzzParseKey fuzz_parse_key
diff --git a/projects/pulumi/config_fuzzer.go b/projects/pulumi/config_fuzzer.go
new file mode 100644
index 000000000..18c3bc07a
--- /dev/null
+++ b/projects/pulumi/config_fuzzer.go
@@ -0,0 +1,51 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 config
+
+import (
+ "encoding/json"
+)
+
+func FuzzConfig(data []byte) int {
+ if len(data) != 32 {
+ return -1
+ }
+ crypter := NewSymmetricCrypter(make([]byte, 32))
+ _, _ = crypter.EncryptValue(string(data))
+ _, _ = crypter.DecryptValue(string(data))
+ return 1
+}
+
+func fuuzRoundtripKey(m Key, marshal func(v interface{}) ([]byte, error),
+ unmarshal func([]byte, interface{}) error) (Key, error) {
+ b, err := marshal(m)
+ if err != nil {
+ return Key{}, err
+ }
+
+ var newM Key
+ err = unmarshal(b, &newM)
+ return newM, err
+}
+
+func FuzzParseKey(data []byte) int {
+ k, err := ParseKey(string(data))
+ if err != nil {
+ return 0
+ }
+ fuuzRoundtripKey(k, json.Marshal, json.Unmarshal)
+ return 1
+}
diff --git a/projects/pulumi/project.yaml b/projects/pulumi/project.yaml
new file mode 100644
index 000000000..60803647c
--- /dev/null
+++ b/projects/pulumi/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://www.pulumi.com/"
+main_repo: "https://github.com/pulumi/pulumi"
+primary_contact: "anton@pulumi.com"
+auto_ccs :
+ - "adam@adalogics.com"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/pulumi/schema_fuzzer.go b/projects/pulumi/schema_fuzzer.go
new file mode 100644
index 000000000..38ac5c9ec
--- /dev/null
+++ b/projects/pulumi/schema_fuzzer.go
@@ -0,0 +1,31 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 schema
+
+import (
+ fuzz "github.com/AdaLogics/go-fuzz-headers"
+)
+
+func SchemaFuzzer(data []byte) int {
+ pkgSpec := PackageSpec{}
+ f := fuzz.NewConsumer(data)
+ err := f.GenerateStruct(&pkgSpec)
+ if err != nil {
+ return 0
+ }
+ _, _ = ImportSpec(pkgSpec, nil)
+ return 1
+}
diff --git a/projects/pygments/Dockerfile b/projects/pygments/Dockerfile
index b23fc1b6d..9b544249d 100644
--- a/projects/pygments/Dockerfile
+++ b/projects/pygments/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone \
--depth 1 \
@@ -58,4 +58,4 @@ RUN cat fuzzing/dictionaries/aff.dict \
fuzzing/dictionaries/yara.dict \
> $OUT/pygments_fuzzer.dict
-COPY build.sh pygments_fuzzer.py $SRC/
+COPY build.sh fuzz_guesser.py fuzz_lexers.py $SRC/
diff --git a/projects/pygments/build.sh b/projects/pygments/build.sh
index 01924b50d..b76e29aa9 100644
--- a/projects/pygments/build.sh
+++ b/projects/pygments/build.sh
@@ -19,7 +19,7 @@
pip3 install .
# Build fuzzers in $OUT.
-for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
+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 $fuzzer
@@ -30,7 +30,7 @@ for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
this_dir=\$(dirname \"\$0\")
ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
zip -j $OUT/files_fuzzer_seed_corpus.zip tests/examplefiles/*
diff --git a/projects/pygments/pygments_fuzzer.py b/projects/pygments/fuzz_guesser.py
index 9d21ba320..ecc2411cf 100644
--- a/projects/pygments/pygments_fuzzer.py
+++ b/projects/pygments/fuzz_guesser.py
@@ -14,22 +14,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import sys
import atheris
-import pygments
-import pygments.formatters
-import pygments.lexers
-
-
-def TestOneInput(input_bytes):
- fdp = atheris.FuzzedDataProvider(input_bytes)
- data = fdp.ConsumeUnicode(atheris.ALL_REMAINING)
+with atheris.instrument_imports():
+ import sys
+ import pygments
+ import pygments.lexers
+@atheris.instrument_func
+def TestOneInput(data: bytes) -> int:
try:
- lexer = pygments.lexers.guess_lexer(data)
+ lexer = pygments.lexers.guess_lexer(str(data))
except ValueError:
- return
- pygments.highlight(data, lexer, pygments.formatters.HtmlFormatter())
+ return 0
+ return 0
def main():
diff --git a/projects/pygments/fuzz_lexers.py b/projects/pygments/fuzz_lexers.py
new file mode 100644
index 000000000..0d610c103
--- /dev/null
+++ b/projects/pygments/fuzz_lexers.py
@@ -0,0 +1,40 @@
+#!/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 atheris
+with atheris.instrument_imports():
+ import sys
+ import pygments
+ import pygments.formatters.html
+ import pygments.lexers
+
+formatter = pygments.formatters.html.HtmlFormatter()
+# pygments.LEXERS.values() is a list of tuples like this, with some of then empty:
+# (textual class name, longname, tuple of aliases, tuple of filename patterns, tuple of mimetypes)
+LEXERS = [l[2][0] for l in pygments.lexers.LEXERS.values() if l[2]]
+
+
+def TestOneInput(data: bytes) -> int:
+ fdp = atheris.FuzzedDataProvider(data)
+ random_lexer = pygments.lexers.get_lexer_by_name(fdp.PickValueInList(LEXERS))
+ str_data = fdp.ConsumeUnicode(atheris.ALL_REMAINING)
+
+ pygments.highlight(str_data, random_lexer, formatter)
+ return 0
+
+
+atheris.Setup(sys.argv, TestOneInput)
+atheris.Fuzz()
diff --git a/projects/python-lz4/Dockerfile b/projects/python-lz4/Dockerfile
index 8598ed33d..2ce705b4c 100644
--- a/projects/python-lz4/Dockerfile
+++ b/projects/python-lz4/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone --depth 1 https://github.com/python-lz4/python-lz4
COPY build.sh $SRC/
diff --git a/projects/python-lz4/build.sh b/projects/python-lz4/build.sh
index 66f6419ac..6eaf4d518 100644
--- a/projects/python-lz4/build.sh
+++ b/projects/python-lz4/build.sh
@@ -30,5 +30,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/python-lz4/fuzz_lz4.py b/projects/python-lz4/fuzz_lz4.py
index ff6787d1b..6a7e21d22 100644
--- a/projects/python-lz4/fuzz_lz4.py
+++ b/projects/python-lz4/fuzz_lz4.py
@@ -15,7 +15,8 @@
import sys
import atheris
-import lz4.frame
+with atheris.instrument_imports():
+ import lz4.frame
def TestOneInput(data):
c =lz4.frame.compress(data)
diff --git a/projects/python3-libraries/Dockerfile b/projects/python3-libraries/Dockerfile
index 3da576e95..37f6706ec 100644
--- a/projects/python3-libraries/Dockerfile
+++ b/projects/python3-libraries/Dockerfile
@@ -15,7 +15,8 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN 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 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 cpython
RUN git clone --depth 1 https://github.com/guidovranken/python-library-fuzzers.git
COPY build.sh $SRC/
diff --git a/projects/pyyaml/Dockerfile b/projects/pyyaml/Dockerfile
index 3d5bc541c..d555b402a 100644
--- a/projects/pyyaml/Dockerfile
+++ b/projects/pyyaml/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone https://github.com/yaml/pyyaml
WORKDIR $SRC
COPY build.sh $SRC/
diff --git a/projects/pyyaml/build.sh b/projects/pyyaml/build.sh
index de7d84c2c..504adcbaa 100644
--- a/projects/pyyaml/build.sh
+++ b/projects/pyyaml/build.sh
@@ -30,5 +30,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/pyyaml/fuzz_loader.py b/projects/pyyaml/fuzz_loader.py
index 6600d842b..40c9fcc56 100644
--- a/projects/pyyaml/fuzz_loader.py
+++ b/projects/pyyaml/fuzz_loader.py
@@ -14,11 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import sys
+
import atheris
-import yaml
+with atheris.instrument_imports():
+ import yaml
+@atheris.instrument_func
def TestOneInput(input_bytes):
try:
context = yaml.load(input_bytes, Loader=yaml.FullLoader)
diff --git a/projects/pyyaml/fuzz_reader.py b/projects/pyyaml/fuzz_reader.py
index d7a0e2cb2..5cd0d1e86 100644
--- a/projects/pyyaml/fuzz_reader.py
+++ b/projects/pyyaml/fuzz_reader.py
@@ -15,8 +15,10 @@
# limitations under the License.
import sys
import atheris
-import yaml.reader
+with atheris.instrument_imports():
+ import yaml.reader
+@atheris.instrument_func
def TestOneInput(data):
if len(data) < 1:
return
@@ -30,7 +32,7 @@ def TestOneInput(data):
return
def main():
- atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+ atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
if __name__ == "__main__":
diff --git a/projects/qcms/Dockerfile b/projects/qcms/Dockerfile
index c124a14a2..922eac69a 100644
--- a/projects/qcms/Dockerfile
+++ b/projects/qcms/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN apt-get update && apt-get install -y mercurial
RUN hg clone --uncompressed https://hg.mozilla.org/mozilla-central/
COPY build.sh $SRC/
diff --git a/projects/qemu/Dockerfile b/projects/qemu/Dockerfile
index 779fc39a4..bf780b8b4 100644
--- a/projects/qemu/Dockerfile
+++ b/projects/qemu/Dockerfile
@@ -15,14 +15,9 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make autoconf automake libtool \
- libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev patchelf wget \
- libattr1 libattr1-dev libcap-ng-dev
-# Ninja in the apt repos is too old. Get it directly from github
-RUN wget https://github.com/ninja-build/ninja/releases/latest/download/ninja-linux.zip \
- && unzip ninja-linux.zip \
- && rm ninja-linux.zip \
- && mv ninja /usr/bin/ninja
+RUN apt-get update && apt-get install -y make autoconf automake libtool ninja-build libglib2.0-dev \
+ libfdt-dev libpixman-1-dev zlib1g-dev patchelf wget \
+ libattr1 libattr1-dev libcap-ng-dev pkg-config
RUN git clone --depth 1 https://git.qemu.org/git/qemu.git qemu
WORKDIR qemu
-RUN cp scripts/oss-fuzz/build.sh $SRC
+COPY build.sh $SRC/
diff --git a/projects/qemu/build.sh b/projects/qemu/build.sh
new file mode 100755
index 000000000..94c71431a
--- /dev/null
+++ b/projects/qemu/build.sh
@@ -0,0 +1,20 @@
+#!/bin/sh -e
+# 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.
+#
+################################################################################
+
+pip3 install meson
+
+./scripts/oss-fuzz/build.sh
diff --git a/projects/qemu/default.options b/projects/qemu/default.options
new file mode 100644
index 000000000..08e7afb7e
--- /dev/null
+++ b/projects/qemu/default.options
@@ -0,0 +1,3 @@
+[libfuzzer]
+close_fd_mask=3
+detect_leaks=0
diff --git a/projects/qemu/project.yaml b/projects/qemu/project.yaml
index 09748302c..db9d1dfc0 100644
--- a/projects/qemu/project.yaml
+++ b/projects/qemu/project.yaml
@@ -3,6 +3,7 @@ language: c
primary_contact: "alxndr@bu.edu"
auto_ccs:
- "bsd@redhat.com"
+ - "mcascell@redhat.com"
- "pbonzini@redhat.com"
- "stefanha@redhat.com"
- "darren.kenny@oracle.com"
diff --git a/projects/qpdf/project.yaml b/projects/qpdf/project.yaml
index 441505203..41a4be8d4 100644
--- a/projects/qpdf/project.yaml
+++ b/projects/qpdf/project.yaml
@@ -4,5 +4,6 @@ primary_contact: "qberkenbilt@gmail.com"
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
main_repo: 'https://github.com/qpdf/qpdf.git'
diff --git a/projects/qt/project.yaml b/projects/qt/project.yaml
index 941006709..6e6a84494 100644
--- a/projects/qt/project.yaml
+++ b/projects/qt/project.yaml
@@ -2,8 +2,10 @@ homepage: "http://qt-project.org"
language: c++
primary_contact: "rlohningqt@gmail.com"
auto_ccs:
+ - "sgaist.qt@gmail.com"
- "shawn.t.rutledge@gmail.com"
+main_repo: 'git://code.qt.io/qt/qt5.git'
architectures:
- x86_64
- i386
-main_repo: 'git://code.qt.io/qt/qt5.git'
+help_url: "https://code.qt.io/cgit/qt/qtbase.git/plain/tests/libfuzzer/README"
diff --git a/projects/quic-go/Dockerfile b/projects/quic-go/Dockerfile
index 9ee792c23..5719c0d0f 100644
--- a/projects/quic-go/Dockerfile
+++ b/projects/quic-go/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/marten-seemann/qpack/ && \
cd qpack && \
diff --git a/projects/quick-xml/Dockerfile b/projects/quick-xml/Dockerfile
new file mode 100644
index 000000000..43995b86c
--- /dev/null
+++ b/projects/quick-xml/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/tafia/quick-xml
+COPY fuzz_target_1.rs $SRC/quick-xml/fuzz/fuzz_targets/fuzz_target_1.rs
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/quick-xml/build.sh b/projects/quick-xml/build.sh
new file mode 100755
index 000000000..704c8605d
--- /dev/null
+++ b/projects/quick-xml/build.sh
@@ -0,0 +1,20 @@
+#!/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/quick-xml
+cargo fuzz build -O
+cp fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 $OUT/
diff --git a/projects/quick-xml/fuzz_target_1.rs b/projects/quick-xml/fuzz_target_1.rs
new file mode 100644
index 000000000..4ce369d09
--- /dev/null
+++ b/projects/quick-xml/fuzz_target_1.rs
@@ -0,0 +1,58 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+//limitations under the License.
+//
+//###################
+#![no_main]
+#[macro_use] extern crate libfuzzer_sys;
+extern crate quick_xml;
+
+use quick_xml::Reader;
+use quick_xml::events::Event;
+use std::io::Cursor;
+
+fuzz_target!(|data: &[u8]| {
+ // fuzzed code goes here
+ let cursor = Cursor::new(data);
+ let mut reader = Reader::from_reader(cursor);
+ let mut buf = vec![];
+ loop {
+ match reader.read_event(&mut buf) {
+ Ok(Event::Start(ref e)) | Ok(Event::Empty(ref e))=> {
+ if e.unescaped().is_err() {
+ break;
+ }
+ for a in e.attributes() {
+ if a.ok().map_or(false, |a| a.unescaped_value().is_err()) {
+ break;
+ }
+ }
+ }
+ Ok(Event::Text(ref e)) | Ok(Event::Comment(ref e))
+ | Ok(Event::CData(ref e)) | Ok(Event::PI(ref e))
+ | Ok(Event::DocType(ref e)) => {
+ if e.unescaped().is_err() {
+ break;
+ }
+ }
+ Ok(Event::Decl(ref e)) => {
+ let _ = e.version();
+ let _ = e.encoding();
+ let _ = e.standalone();
+ }
+ Ok(Event::End(_)) => (),
+ Ok(Event::Eof) | Err(..) => break,
+ }
+ buf.clear();
+ }
+});
diff --git a/projects/quick-xml/project.yaml b/projects/quick-xml/project.yaml
new file mode 100644
index 000000000..98af2f967
--- /dev/null
+++ b/projects/quick-xml/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/tafia/quick-xml"
+main_repo: "https://github.com/tafia/quick-xml"
+primary_contact: "tafia973@gmail.com"
+sanitizers:
+ - address
+fuzzing_engines:
+ - libfuzzer
+language: rust
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/quickjs/project.yaml b/projects/quickjs/project.yaml
index 7bc6d0988..a2e3ce733 100644
--- a/projects/quickjs/project.yaml
+++ b/projects/quickjs/project.yaml
@@ -10,4 +10,4 @@ sanitizers:
- address
blackbox: true # also use a blackbox fuzzer for this project.
-main_repo: 'https://github.com/horhof/quickjs'
+main_repo: 'https://github.com/bellard/quickjs'
diff --git a/projects/radare2/Dockerfile b/projects/radare2/Dockerfile
index b0140e064..5b2f403b1 100644
--- a/projects/radare2/Dockerfile
+++ b/projects/radare2/Dockerfile
@@ -1,7 +1,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update
-RUN git clone https://github.com/radare/radare2 radare2
-RUN git clone https://github.com/radare/radare2-regressions radare2-regressions
+RUN git clone https://github.com/radareorg/radare2 radare2
+RUN git clone https://github.com/radareorg/radare2-fuzz radare2-fuzz
WORKDIR radare2
COPY build.sh $SRC/
COPY *.options $SRC/
diff --git a/projects/radare2/build.sh b/projects/radare2/build.sh
index c04240a67..94f72f106 100755
--- a/projects/radare2/build.sh
+++ b/projects/radare2/build.sh
@@ -6,7 +6,7 @@ export HOST_CC=$CC
sys/static.sh
cp -r r2-static $OUT/
-cp -r ../radare2-regressions/fuzz/targets .
+cp -r ../radare2-fuzz/targets .
export RADARE2_STATIC_BUILD=$OUT/r2-static
cd targets
diff --git a/projects/radare2/project.yaml b/projects/radare2/project.yaml
index 9434e1817..f1b5ee965 100644
--- a/projects/radare2/project.yaml
+++ b/projects/radare2/project.yaml
@@ -1,4 +1,4 @@
-homepage: "https://github.com/radare/radare2"
+homepage: "https://github.com/radareorg/radare2"
language: c++
primary_contact: "pancake@nopcode.org"
auto_ccs:
@@ -6,4 +6,4 @@ auto_ccs:
sanitizers:
- address
run_tests: False
-main_repo: 'https://github.com/radare/radare2'
+main_repo: 'https://github.com/radareorg/radare2'
diff --git a/projects/radon/Dockerfile b/projects/radon/Dockerfile
index fe4c6ca5d..0c6ac1b89 100644
--- a/projects/radon/Dockerfile
+++ b/projects/radon/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/radondb/radon
COPY build.sh $SRC/
WORKDIR $SRC/radon
diff --git a/projects/rdkit/Dockerfile b/projects/rdkit/Dockerfile
index 1dad793c5..e072c2d23 100644
--- a/projects/rdkit/Dockerfile
+++ b/projects/rdkit/Dockerfile
@@ -15,7 +15,13 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y wget libeigen3-dev
+RUN apt-get update && apt-get install -y wget
+
+RUN git clone https://gitlab.com/libeigen/eigen && \
+ mkdir eigen_build && \
+ cd eigen_build && \
+ cmake ../eigen && \
+ make install
RUN git clone --depth 1 https://github.com/rdkit/rdkit.git $SRC/rdkit
WORKDIR $SRC/rdkit
diff --git a/projects/re2/project.yaml b/projects/re2/project.yaml
index 0fc1f837b..28f9c4bd2 100644
--- a/projects/re2/project.yaml
+++ b/projects/re2/project.yaml
@@ -3,9 +3,10 @@ language: c++
primary_contact: "junyer@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- x86_64
- i386
-main_repo: 'https://code.googlesource.com/re2'
+main_repo: 'https://code.googlesource.com/re2' \ No newline at end of file
diff --git a/projects/relic/Dockerfile b/projects/relic/Dockerfile
index 23b426b6f..20213173d 100644
--- a/projects/relic/Dockerfile
+++ b/projects/relic/Dockerfile
@@ -19,5 +19,5 @@ RUN apt-get update && apt-get install -y make autoconf automake libtool wget pyt
RUN git clone --depth 1 https://github.com/relic-toolkit/relic.git
RUN git clone --depth 1 https://github.com/randombit/botan.git
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
COPY build.sh $SRC/
diff --git a/projects/relic/build.sh b/projects/relic/build.sh
index 552b14fc6..d2c31dd26 100755
--- a/projects/relic/build.sh
+++ b/projects/relic/build.sh
@@ -26,9 +26,6 @@ CFLAGS="" CXXFLAGS="" ./bootstrap.sh
CFLAGS="" CXXFLAGS="" ./b2 headers
cp -R boost/ /usr/include/
-# Prevent Boost compilation error with -std=c++17
-export CXXFLAGS="$CXXFLAGS -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR"
-
# Build Relic
cd $SRC/relic/
mkdir build/
@@ -65,9 +62,10 @@ python gen_repository.py
rm extra_options.h
echo -n '"' >>extra_options.h
echo -n '--force-module=relic ' >>extra_options.h
-echo -n '--operations=BignumCalc,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,Digest,HMAC,KDF_X963 ' >>extra_options.h
+echo -n '--operations=BignumCalc,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Sign,ECDSA_Verify,Digest,HMAC,KDF_X963,SymmetricEncrypt,SymmetricDecrypt,ECC_Point_Add,ECC_Point_Mul ' >>extra_options.h
echo -n '--curves=secp256k1,secp256r1 ' >>extra_options.h
echo -n '--digests=NULL,SHA224,SHA256,SHA384,SHA512,BLAKE2S160,BLAKE2S256 ' >>extra_options.h
+echo -n '--ciphers=AES_128_CBC,AES_192_CBC,AES_256_CBC ' >>extra_options.h
echo -n '--calcops=Abs,Add,Bit,ClearBit,Cmp,CmpAbs,Div,ExpMod,GCD,InvMod,IsEven,IsOdd,IsZero,Jacobi,LCM,LShift1,Mod,Mul,Neg,NumBits,RShift,SetBit,Sqr,Sqrt,Sub ' >>extra_options.h
echo -n '"' >>extra_options.h
cd modules/relic/
diff --git a/projects/relic/project.yaml b/projects/relic/project.yaml
index 98fb04fce..c3d3016a8 100644
--- a/projects/relic/project.yaml
+++ b/projects/relic/project.yaml
@@ -7,7 +7,8 @@ auto_ccs:
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
architectures:
- x86_64
- i386
diff --git a/projects/resiprocate/Dockerfile b/projects/resiprocate/Dockerfile
index 58f7a92c0..c1abd02bc 100644
--- a/projects/resiprocate/Dockerfile
+++ b/projects/resiprocate/Dockerfile
@@ -16,6 +16,13 @@
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 https://github.com/fmtlib/fmt && \
+ cd fmt && \
+ mkdir build && \
+ cd build && \
+ cmake .. && \
+ make && \
+ make install
RUN git clone --depth 1 https://github.com/resiprocate/resiprocate.git resiprocate
WORKDIR resiprocate
COPY build.sh $SRC/
diff --git a/projects/rnp/Dockerfile b/projects/rnp/Dockerfile
index c82713bef..008286078 100755
--- a/projects/rnp/Dockerfile
+++ b/projects/rnp/Dockerfile
@@ -27,7 +27,7 @@ RUN apt-get install -y \
zlib1g-dev \
libjson-c-dev \
build-essential \
- python-minimal \
+ python \
wget
RUN git clone --depth 1 https://github.com/rnpgp/rnp.git rnp
diff --git a/projects/rnp/build.sh b/projects/rnp/build.sh
index 1bfd8aa5f..95439b6dc 100755
--- a/projects/rnp/build.sh
+++ b/projects/rnp/build.sh
@@ -62,4 +62,4 @@ done
mkdir -p "${OUT}/lib"
cp src/lib/librnp.so.0 "${OUT}/lib/"
cp /usr/lib/libbotan-2.so.16 "${OUT}/lib/"
-cp /lib/x86_64-linux-gnu/libjson-c.so.2 "${OUT}/lib/"
+cp /lib/x86_64-linux-gnu/libjson-c.so.* "${OUT}/lib/"
diff --git a/projects/rocksdb/build.sh b/projects/rocksdb/build.sh
index af784a2b1..e336559bd 100755
--- a/projects/rocksdb/build.sh
+++ b/projects/rocksdb/build.sh
@@ -21,6 +21,7 @@ export PATH=$PWD/external.protobuf/bin:$PATH
cd $SRC/rocksdb
export FUZZ_ENV=ossfuzz
export CC=$CXX
+export DISABLE_WARNING_AS_ERROR=1
make static_lib
cd fuzz
diff --git a/projects/runc/Dockerfile b/projects/runc/Dockerfile
index 78616e91e..ccef86642 100644
--- a/projects/runc/Dockerfile
+++ b/projects/runc/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/opencontainers/runc
COPY build.sh $SRC/
WORKDIR $SRC/runc
diff --git a/projects/rust-regex/Dockerfile b/projects/rust-regex/Dockerfile
index c64a6a1e6..e1b5b40da 100644
--- a/projects/rust-regex/Dockerfile
+++ b/projects/rust-regex/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone --depth 1 https://github.com/rust-lang/regex regex
WORKDIR $SRC
diff --git a/projects/rustls/Dockerfile b/projects/rustls/Dockerfile
index 7406a474b..361e30a3d 100644
--- a/projects/rustls/Dockerfile
+++ b/projects/rustls/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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/ctz/rustls
@@ -22,4 +22,3 @@ RUN git clone https://github.com/ctz/rustls
WORKDIR $SRC
COPY build.sh $SRC/
-COPY persist.rs $SRC/rustls/fuzz/fuzzers/persist.rs
diff --git a/projects/rustls/build.sh b/projects/rustls/build.sh
index d00359e98..1f16177d2 100755
--- a/projects/rustls/build.sh
+++ b/projects/rustls/build.sh
@@ -22,4 +22,8 @@ cp fuzz/target/x86_64-unknown-linux-gnu/release/deframer $OUT/
cp fuzz/target/x86_64-unknown-linux-gnu/release/fragment $OUT/
cp fuzz/target/x86_64-unknown-linux-gnu/release/hsjoiner $OUT/
cp fuzz/target/x86_64-unknown-linux-gnu/release/message $OUT/
-cp fuzz/target/x86_64-unknown-linux-gnu/release/server $OUT/
+if [ "$SANITIZER" != "coverage" ]
+then
+ cp fuzz/target/x86_64-unknown-linux-gnu/release/server $OUT/
+ cp fuzz/target/x86_64-unknown-linux-gnu/release/persist $OUT/
+fi
diff --git a/projects/rustls/project.yaml b/projects/rustls/project.yaml
index 73e4f27d6..d483a379a 100644
--- a/projects/rustls/project.yaml
+++ b/projects/rustls/project.yaml
@@ -8,3 +8,5 @@ fuzzing_engines:
language: rust
auto_ccs:
- "david@adalogics.com"
+ - "dirkjan@ochtman.nl"
+ - "brian@briansmith.org"
diff --git a/projects/s2geometry/Dockerfile b/projects/s2geometry/Dockerfile
new file mode 100644
index 000000000..8f58a555a
--- /dev/null
+++ b/projects/s2geometry/Dockerfile
@@ -0,0 +1,43 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 -y install \
+ libgflags-dev \
+ libgoogle-glog-dev \
+ libgtest-dev libssl-dev \
+ make \
+ curl
+
+# OpenSSL
+ARG OPENSSL_VERSION=1.1.1g
+ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
+RUN set -ex \
+ && curl -s -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 --static "$CFLAGS" \
+ && make build_generated \
+ && make libcrypto.a \
+ && make install
+
+RUN git clone https://github.com/google/s2geometry
+WORKDIR $SRC/s2geometry
+COPY build.sh \
+ s2_fuzzer.cc \
+ $SRC/
diff --git a/projects/s2geometry/build.sh b/projects/s2geometry/build.sh
new file mode 100755
index 000000000..1b7cd97e7
--- /dev/null
+++ b/projects/s2geometry/build.sh
@@ -0,0 +1,34 @@
+#!/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_SHARED_LIBS=OFF \
+ -DABSL_MIN_LOG_LEVEL=4 \
+ -DGTEST_ROOT=/usr/src/gtest ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DABSL_MIN_LOG_LEVEL=4 \
+ -I/src/s2geometry/src \
+ -I/usr/src/gtest/include -std=c++11 \
+ -c $SRC/s2_fuzzer.cc \
+ -o s2_fuzzer.o
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+ s2_fuzzer.o -o $OUT/s2_fuzzer \
+ /src/s2geometry/build/libs2.a \
+ /src/openssl-1.1.1g/libssl.a \
+ /src/openssl-1.1.1g/libcrypto.a
diff --git a/projects/s2geometry/project.yaml b/projects/s2geometry/project.yaml
new file mode 100644
index 000000000..8f53bde78
--- /dev/null
+++ b/projects/s2geometry/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/google/s2geometry"
+language: c++
+primary_contact: "jmr@google.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+main_repo: "https://github.com/google/s2geometry"
diff --git a/projects/s2geometry/s2_fuzzer.cc b/projects/s2geometry/s2_fuzzer.cc
new file mode 100644
index 000000000..62050a0dc
--- /dev/null
+++ b/projects/s2geometry/s2_fuzzer.cc
@@ -0,0 +1,99 @@
+/*
+# 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "s2/s2shapeutil_range_iterator.h"
+#include "s2/third_party/absl/strings/str_split.h"
+#include "s2/third_party/absl/strings/string_view.h"
+
+#include "s2/mutable_s2shape_index.h"
+#include "s2/s2text_format.h"
+
+// A string-splitter used to help validate the string
+// passed to s2
+static std::vector<absl::string_view> SplitString(absl::string_view str,
+ char separator) {
+ std::vector<absl::string_view> result =
+ absl::StrSplit(str, separator, absl::SkipWhitespace());
+ for (auto &e : result) {
+ e = absl::StripAsciiWhitespace(e);
+ }
+ return result;
+}
+
+// Null-terminates the fuzzers input test case
+char *null_terminated(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';
+ return new_str;
+}
+
+// Do a bit of validation that is also done by s2
+// We do them here since s2 would terminate if they
+// would return false inside s2.
+bool isValidFormat(char *nt_string, size_t size) {
+ int hash_count = 0;
+ for (int i = 0; i < size; i++) {
+ if (nt_string[i] == 35) {
+ hash_count++;
+ }
+ }
+ if (hash_count != 2) {
+ return false;
+ }
+
+ std::vector<absl::string_view> strs = SplitString(nt_string, '#');
+ size_t strs_size = strs.size();
+ if (strs.size() != 3) {
+ return false;
+ }
+
+ auto index1 = absl::make_unique<MutableS2ShapeIndex>();
+ if (s2textformat::MakeIndex(nt_string, &index1) == false) {
+ return false;
+ }
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+
+ if (size < 5) {
+ return 0;
+ }
+
+ char *nt_string = null_terminated(data, size);
+ if (nt_string == NULL) {
+ return 0;
+ }
+ if (isValidFormat(nt_string, size)) {
+ auto index = s2textformat::MakeIndex(nt_string);
+ s2shapeutil::RangeIterator it(*index);
+ if (!it.done()) {
+ it.Next();
+ }
+ }
+ free(nt_string);
+ return 0;
+}
diff --git a/projects/samba/project.yaml b/projects/samba/project.yaml
index 6f7ea359e..7e7cdc57d 100644
--- a/projects/samba/project.yaml
+++ b/projects/samba/project.yaml
@@ -1,4 +1,5 @@
homepage: "https://samba.org"
+main_repo: "https://git.samba.org/samba.git"
language: c
primary_contact: "douglas.bagnall@catalyst.net.nz"
auto_ccs:
@@ -9,6 +10,7 @@ auto_ccs:
- "sloowfranklin@gmail.com"
- "gdeschner@gmail.com"
- "volker.lendecke@gmail.com"
+ - "davidmmulder@gmail.com"
fuzzing_engines:
- libfuzzer
- honggfuzz
diff --git a/projects/scapy/Dockerfile b/projects/scapy/Dockerfile
index 6631b327e..08806d9fc 100644
--- a/projects/scapy/Dockerfile
+++ b/projects/scapy/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone \
--depth 1 \
diff --git a/projects/scapy/build.sh b/projects/scapy/build.sh
index b3270da76..223ffa36d 100644
--- a/projects/scapy/build.sh
+++ b/projects/scapy/build.sh
@@ -30,7 +30,7 @@ for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
this_dir=\$(dirname \"\$0\")
ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
- chmod u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
zip -j $OUT/pcap_fuzzer_seed_corpus.zip test/pcaps/*
diff --git a/projects/scapy/pcap_fuzzer.py b/projects/scapy/pcap_fuzzer.py
index aaf1f5ffb..0b72f0abb 100644
--- a/projects/scapy/pcap_fuzzer.py
+++ b/projects/scapy/pcap_fuzzer.py
@@ -14,13 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import io
import sys
import atheris
-import scapy
-import scapy.error
-import scapy.utils
+with atheris.instrument_imports():
+ import io
+ import scapy
+ import scapy.error
+ import scapy.utils
def TestOneInput(input_bytes):
@@ -31,7 +32,7 @@ def TestOneInput(input_bytes):
def main():
- atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+ atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
diff --git a/projects/selinux/Dockerfile b/projects/selinux/Dockerfile
index b62b4aeb9..1c278d7c6 100644
--- a/projects/selinux/Dockerfile
+++ b/projects/selinux/Dockerfile
@@ -30,4 +30,4 @@ RUN apt-get update && \
xmlto
RUN git clone --depth 1 https://github.com/SELinuxProject/selinux
WORKDIR selinux
-COPY build.sh *.c $SRC/
+COPY build.sh $SRC/
diff --git a/projects/selinux/build.sh b/projects/selinux/build.sh
index e2979ad79..0661536fc 100755
--- a/projects/selinux/build.sh
+++ b/projects/selinux/build.sh
@@ -14,13 +14,4 @@
# limitations under the License.
#
################################################################################
-
-export DESTDIR=$(pwd)/DESTDIR
-export LDFLAGS="${LDFLAGS:-} $CFLAGS"
-
-find -name Makefile | xargs sed -i 's/,-z,defs//'
-make V=1 -j$(nproc) install
-
-$CC $CFLAGS -I$DESTDIR/usr/include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -c -o secilc-fuzzer.o $SRC/secilc-fuzzer.c
-$CXX $CXXFLAGS $LIB_FUZZING_ENGINE secilc-fuzzer.o $DESTDIR/usr/lib/libsepol.a -o $OUT/secilc-fuzzer
-zip -r $OUT/secilc-fuzzer_seed_corpus.zip secilc/test
+./scripts/oss-fuzz.sh
diff --git a/projects/selinux/secilc-fuzzer.c b/projects/selinux/secilc-fuzzer.c
deleted file mode 100644
index c99df95a1..000000000
--- a/projects/selinux/secilc-fuzzer.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-# 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 <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <getopt.h>
-#include <sys/stat.h>
-
-#include <sepol/cil/cil.h>
-#include <sepol/policydb.h>
-
-int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- enum cil_log_level log_level = CIL_ERR;
- struct sepol_policy_file *pf = NULL;
- FILE *dev_null = NULL;
- int target = SEPOL_TARGET_SELINUX;
- int disable_dontaudit = 0;
- int multiple_decls = 0;
- int disable_neverallow = 0;
- int preserve_tunables = 0;
- int policyvers = POLICYDB_VERSION_MAX;
- int mls = -1;
- int attrs_expand_generated = 0;
- struct cil_db *db = NULL;
- sepol_policydb_t *pdb = NULL;
-
- cil_set_log_level(log_level);
-
- cil_db_init(&db);
- cil_set_disable_dontaudit(db, disable_dontaudit);
- cil_set_multiple_decls(db, multiple_decls);
- cil_set_disable_neverallow(db, disable_neverallow);
- cil_set_preserve_tunables(db, preserve_tunables);
- cil_set_mls(db, mls);
- cil_set_target_platform(db, target);
- cil_set_policy_version(db, policyvers);
- cil_set_attrs_expand_generated(db, attrs_expand_generated);
-
- if (cil_add_file(db, "fuzz", data, size) != SEPOL_OK)
- goto exit;
-
- if (cil_compile(db) != SEPOL_OK)
- goto exit;
-
- if (cil_build_policydb(db, &pdb) != SEPOL_OK)
- goto exit;
-
- if (sepol_policydb_optimize(pdb) != SEPOL_OK)
- goto exit;
-
- dev_null = fopen("/dev/null", "w");
- if (dev_null == NULL)
- goto exit;
-
- if (sepol_policy_file_create(&pf) != 0)
- goto exit;
-
- sepol_policy_file_set_fp(pf, dev_null);
-
- if (sepol_policydb_write(pdb, pf) != 0)
- goto exit;
-exit:
- if (dev_null != NULL)
- fclose(dev_null);
-
- cil_db_destroy(&db);
- sepol_policydb_free(pdb);
- sepol_policy_file_free(pf);
- return 0;
-}
diff --git a/projects/sentencepiece/project.yaml b/projects/sentencepiece/project.yaml
index 579c70320..2668dd021 100644
--- a/projects/sentencepiece/project.yaml
+++ b/projects/sentencepiece/project.yaml
@@ -3,8 +3,9 @@ language: c++
primary_contact: "taku@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- x86_64
-main_repo: 'https://github.com/google/sentencepiece.git'
+main_repo: 'https://github.com/google/sentencepiece.git' \ No newline at end of file
diff --git a/projects/serde-yaml/Dockerfile b/projects/serde-yaml/Dockerfile
index 42b1ce384..216394c77 100644
--- a/projects/serde-yaml/Dockerfile
+++ b/projects/serde-yaml/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone --depth 1 https://github.com/dtolnay/serde-yaml serde-yaml
WORKDIR $SRC
diff --git a/projects/serde_json/Dockerfile b/projects/serde_json/Dockerfile
index d27ebda2d..395b89715 100644
--- a/projects/serde_json/Dockerfile
+++ b/projects/serde_json/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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 --depth 1 https://github.com/serde-rs/json json
diff --git a/projects/servo/Dockerfile b/projects/servo/Dockerfile
index a0e081d0c..6fbeef8a2 100644
--- a/projects/servo/Dockerfile
+++ b/projects/servo/Dockerfile
@@ -13,7 +13,7 @@
# limitations under the License.
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-rust
RUN git clone --depth 1 https://github.com/servo/html5ever
RUN git clone --depth 1 https://github.com/servo/rust-url
diff --git a/projects/simd/Dockerfile b/projects/simd/Dockerfile
new file mode 100644
index 000000000..5c030e0df
--- /dev/null
+++ b/projects/simd/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/ermig1979/Simd
+WORKDIR Simd
+COPY build.sh simd_load_fuzzer.cpp $SRC/
diff --git a/projects/simd/build.sh b/projects/simd/build.sh
new file mode 100755
index 000000000..8f0c3e76e
--- /dev/null
+++ b/projects/simd/build.sh
@@ -0,0 +1,30 @@
+#!/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 ../prj/cmake \
+ -DCMAKE_BUILD_TYPE="Release"
+make -j$(nproc)
+
+$CXX $CXXFLAGS -I/src/Simd/src -O3 -DNDEBUG -fPIC \
+ -c $SRC/simd_load_fuzzer.cpp -o simd_load_fuzzer.o \
+ -std=c++11 -ferror-limit=5 -m64 -mtune=native
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE simd_load_fuzzer.o \
+ -o $OUT/simd_load_fuzzer \
+ $(find $SRC -name "libSimd.a")
diff --git a/projects/simd/project.yaml b/projects/simd/project.yaml
new file mode 100644
index 000000000..07eaebd3c
--- /dev/null
+++ b/projects/simd/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://ermig1979.github.io/Simd"
+language: c++
+primary_contact: "ermig@tut.by"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+main_repo: 'https://github.com/ermig1979/Simd'
diff --git a/projects/simd/simd_load_fuzzer.cpp b/projects/simd/simd_load_fuzzer.cpp
new file mode 100644
index 000000000..e93d1b874
--- /dev/null
+++ b/projects/simd/simd_load_fuzzer.cpp
@@ -0,0 +1,32 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include "Test/TestUtils.h"
+
+extern "C"
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ if (size<5) {
+ return 0;
+ }
+ Test::View::Format formats[4] = {Test::View::Gray8,
+ Test::View::Bgr24,
+ Test::View::Bgra32,
+ Test::View::Rgb24};
+ for(int i=0; i<4; i++) {
+ Test::View dst1;
+ dst1.Load(data, size, formats[i]);
+ }
+ return 0;
+}
diff --git a/projects/simdjson/project.yaml b/projects/simdjson/project.yaml
index 33b298a61..538892ddd 100644
--- a/projects/simdjson/project.yaml
+++ b/projects/simdjson/project.yaml
@@ -1,7 +1,10 @@
-homepage: "https://github.com/simdjson/simdjson"
+homepage: "https://simdjson.org/"
language: c++
primary_contact: "pauldreikossfuzz@gmail.com"
auto_ccs:
- "lemire@gmail.com"
-
+sanitizers:
+- address
+- undefined
+- memory
main_repo: 'https://github.com/simdjson/simdjson.git'
diff --git a/projects/skia/Dockerfile b/projects/skia/Dockerfile
index e42908840..4af5722aa 100644
--- a/projects/skia/Dockerfile
+++ b/projects/skia/Dockerfile
@@ -17,7 +17,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
# Mesa and libz/zlib needed to build swiftshader
-RUN apt-get update && apt-get install -y python wget libglu1-mesa-dev cmake lib32z1-dev zlib1g-dev
+RUN apt-get update && apt-get install -y python wget libglu1-mesa-dev cmake lib32z1-dev zlib1g-dev libxext-dev
RUN git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' --depth 1
ENV PATH="${SRC}/depot_tools:${PATH}"
diff --git a/projects/skia/build.sh b/projects/skia/build.sh
index 0f6d73fb4..d4a2b6a18 100644
--- a/projects/skia/build.sh
+++ b/projects/skia/build.sh
@@ -43,10 +43,17 @@ elif [ $SANITIZER == "thread" ]; then
else
exit 1
fi
-CFLAGS= CXXFLAGS="-stdlib=libc++" cmake .. -GNinja -DCMAKE_MAKE_PROGRAM="$SRC/depot_tools/ninja" -D$CMAKE_SANITIZER=1
-
-$SRC/depot_tools/ninja libGLESv2 libEGL
-mv libGLESv2.so libEGL.so $OUT
+# These deprecated warnings get quite noisy and mask other issues.
+CFLAGS= CXXFLAGS="-stdlib=libc++ -Wno-deprecated-declarations" cmake .. -GNinja \
+ -DCMAKE_MAKE_PROGRAM="$SRC/depot_tools/ninja" -D$CMAKE_SANITIZER=1
+
+$SRC/depot_tools/ninja libGLESv2_deprecated libEGL_deprecated
+# Skia is looking for the names w/o the _deprecated tag. The libraries themselves
+# are looking for the _deprecated suffix, so we copy them both ways into the out
+# directory.
+cp libEGL_deprecated.so $OUT/libEGL.so
+cp libGLESv2_deprecated.so $OUT/libGLESv2.so
+mv libGLESv2_deprecated.so libEGL_deprecated.so $OUT
export SWIFTSHADER_LIB_PATH=$OUT
popd
@@ -54,8 +61,10 @@ popd
DISABLE="-Wno-zero-as-null-pointer-constant -Wno-unused-template
-Wno-cast-qual"
# Disable UBSan vptr since target built with -fno-rtti.
-export CFLAGS="$CFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2 -fno-sanitize=vptr"
-export CXXFLAGS="$CXXFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2 -fno-sanitize=vptr"
+export CFLAGS="$CFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2\
+ -fno-sanitize=vptr -DSK_BUILD_FOR_LIBFUZZER"
+export CXXFLAGS="$CXXFLAGS $DISABLE -I$SWIFTSHADER_INCLUDE_PATH -DGR_EGL_TRY_GLES3_THEN_GLES2\
+ -fno-sanitize=vptr -DSK_BUILD_FOR_LIBFUZZER"
export LDFLAGS="$LIB_FUZZING_ENGINE $CXXFLAGS -L$SWIFTSHADER_LIB_PATH"
# This splits a space separated list into a quoted, comma separated list for gn.
@@ -73,28 +82,43 @@ if [ "$CIFUZZ" = "true" ]; then
fi
set -u
+SKIA_ARGS="skia_build_fuzzers=true
+ skia_enable_fontmgr_custom_directory=false
+ skia_enable_fontmgr_custom_embedded=false
+ skia_enable_fontmgr_custom_empty=true
+ skia_enable_gpu=true
+ skia_enable_skottie=true
+ skia_use_egl=true
+ skia_use_fontconfig=false
+ skia_use_freetype=true
+ skia_use_system_freetype2=false
+ skia_use_wuffs=true
+ skia_use_libfuzzer_defaults=false"
+
# Even though GPU is "enabled" for all these builds, none really
-# uses the gpu except for api_mock_gpu_canvas
+# uses the gpu except for api_mock_gpu_canvas.
$SRC/skia/bin/gn gen out/Fuzz\
--args='cc="'$CC'"
cxx="'$CXX'"
- '$LIMITED_LINK_POOL'
+ '"$LIMITED_LINK_POOL"'
+ '"${SKIA_ARGS[*]}"'
is_debug=false
extra_cflags_c=["'"$CFLAGS_ARR"'"]
extra_cflags_cc=["'"$CXXFLAGS_ARR"'"]
- extra_ldflags=["'"$LDFLAGS_ARR"'"]
- skia_build_fuzzers=true
- skia_enable_fontmgr_custom_directory=false
- skia_enable_fontmgr_custom_embedded=false
- skia_enable_fontmgr_custom_empty=true
- skia_enable_gpu=true
- skia_enable_skottie=true
- skia_use_egl=true
- skia_use_fontconfig=false
- skia_use_freetype=true
- skia_use_system_freetype2=false
- skia_use_wuffs=true
- skia_use_libfuzzer_defaults=false'
+ extra_ldflags=["'"$LDFLAGS_ARR"'"]'
+
+# Some fuzz targets benefit from assertions so we enable SK_DEBUG to allow SkASSERT
+# and SkDEBUGCODE to run. We still enable optimization (via is_debug=false) because
+# faster code means more fuzz tests and deeper coverage.
+$SRC/skia/bin/gn gen out/FuzzDebug\
+ --args='cc="'$CC'"
+ cxx="'$CXX'"
+ '"$LIMITED_LINK_POOL"'
+ '"${SKIA_ARGS[*]}"'
+ is_debug=false
+ extra_cflags_c=["-DSK_DEBUG","'"$CFLAGS_ARR"'"]
+ extra_cflags_cc=["-DSK_DEBUG","'"$CXXFLAGS_ARR"'"]
+ extra_ldflags=["'"$LDFLAGS_ARR"'"]'
$SRC/depot_tools/ninja -C out/Fuzz \
android_codec \
@@ -113,6 +137,7 @@ $SRC/depot_tools/ninja -C out/Fuzz \
api_regionop \
api_skparagraph \
api_svg_canvas \
+ api_triangulation \
image_decode \
image_decode_incremental \
image_filter_deserialize \
@@ -125,14 +150,16 @@ $SRC/depot_tools/ninja -C out/Fuzz \
skjson \
skottie_json \
skp \
+ svg_dom \
+ textblob_deserialize \
+ webp_encoder
+
+$SRC/depot_tools/ninja -C out/FuzzDebug \
skruntimeeffect \
sksl2glsl \
sksl2metal \
sksl2pipeline \
sksl2spirv \
- svg_dom \
- textblob_deserialize \
- webp_encoder
rm -rf $OUT/data
mkdir $OUT/data
@@ -224,16 +251,16 @@ mv out/Fuzz/image_decode_incremental $OUT/image_decode_incremental
mv ../skia_data/image_decode_seed_corpus.zip $OUT/image_decode_incremental_seed_corpus.zip
# These 4 use the same sksl_seed_corpus.
-mv out/Fuzz/sksl2glsl $OUT/sksl2glsl
+mv out/FuzzDebug/sksl2glsl $OUT/sksl2glsl
cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2glsl_seed_corpus.zip
-mv out/Fuzz/sksl2spirv $OUT/sksl2spirv
+mv out/FuzzDebug/sksl2spirv $OUT/sksl2spirv
cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2spirv_seed_corpus.zip
-mv out/Fuzz/sksl2metal $OUT/sksl2metal
+mv out/FuzzDebug/sksl2metal $OUT/sksl2metal
cp ../skia_data/sksl_seed_corpus.zip $OUT/sksl2metal_seed_corpus.zip
-mv out/Fuzz/sksl2pipeline $OUT/sksl2pipeline
+mv out/FuzzDebug/sksl2pipeline $OUT/sksl2pipeline
mv ../skia_data/sksl_seed_corpus.zip $OUT/sksl2pipeline_seed_corpus.zip
mv out/Fuzz/skdescriptor_deserialize $OUT/skdescriptor_deserialize
@@ -242,7 +269,7 @@ mv out/Fuzz/svg_dom $OUT/svg_dom
mv ../skia_data/svg_dom_seed_corpus.zip $OUT/svg_dom_seed_corpus.zip
-mv out/Fuzz/skruntimeeffect $OUT/skruntimeeffect
+mv out/FuzzDebug/skruntimeeffect $OUT/skruntimeeffect
mv ../skia_data/sksl_with_256_padding_seed_corpus.zip $OUT/skruntimeeffect_seed_corpus.zip
mv out/Fuzz/api_create_ddl $OUT/api_create_ddl
@@ -255,3 +282,5 @@ mv ../skia_data/skp_seed_corpus.zip $OUT/skp_seed_corpus.zip
mv out/Fuzz/api_skparagraph $OUT/api_skparagraph
mv out/Fuzz/api_regionop $OUT/api_regionop
+
+mv out/Fuzz/api_triangulation $OUT/api_triangulation
diff --git a/projects/skia/project.yaml b/projects/skia/project.yaml
index 824ac2117..4cbfa2c36 100644
--- a/projects/skia/project.yaml
+++ b/projects/skia/project.yaml
@@ -3,20 +3,19 @@ language: c++
primary_contact: "kjlubick@chromium.org"
auto_ccs:
- "hcm@google.com"
- - "mtklein@google.com"
- "reed@google.com"
- "bsalomon@google.com"
- "brianosman@google.com"
- "johnstiles@google.com"
- "ethannicholas@google.com"
- - "westont@google.com"
vendor_ccs:
- "lsalzman@mozilla.com"
- "twsmith@mozilla.com"
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
help_url: "https://skia.org/dev/testing/fuzz"
builds_per_day: 4
main_repo: 'https://skia.googlesource.com/skia.git'
diff --git a/projects/sleuthkit/Dockerfile b/projects/sleuthkit/Dockerfile
index cf04b56ab..a13087ffe 100644
--- a/projects/sleuthkit/Dockerfile
+++ b/projects/sleuthkit/Dockerfile
@@ -18,4 +18,4 @@ 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/sleuthkit/sleuthkit sleuthkit
WORKDIR sleuthkit
-COPY build.sh sleuthkit_mem_img.h *_fuzzer.cc $SRC/
+COPY build.sh buildcorpus.sh sleuthkit_mem_img.h *_fuzzer.cc $SRC/
diff --git a/projects/sleuthkit/build.sh b/projects/sleuthkit/build.sh
index 7ed222a73..2443ffaab 100755
--- a/projects/sleuthkit/build.sh
+++ b/projects/sleuthkit/build.sh
@@ -18,8 +18,10 @@
export CFLAGS="$CFLAGS -Wno-error=non-c-typedef-for-linkage"
export CXXFLAGS="$CXXFLAGS -Wno-error=non-c-typedef-for-linkage"
+${SRC}/buildcorpus.sh
+
./bootstrap
-./configure --enable-static --disable-shared --disable-java
+./configure --enable-static --disable-shared --disable-java --without-afflib --without-libewf --without-libvhdi --without-libvmdk
make -j$(nproc)
declare -A TSK_FS_TYPES=(
@@ -37,14 +39,20 @@ declare -A TSK_VS_TYPES=(
["sun"]="TSK_VS_TYPE_SUN"
)
+# The fls APFS fuzz target has a seperate source file since it uses the libtsk
+# pool layer.
+$CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk \
+ $SRC/sleuthkit_fls_apfs_fuzzer.cc -o $OUT/sleuthkit_fls_apfs_fuzzer \
+ $LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
+
for type in ${!TSK_FS_TYPES[@]}; do
- $CXX $CXXFLAGS -std=c++11 -I.. -I. -Itsk -DFSTYPE=${TSK_FS_TYPES[$type]} \
+ $CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk -DFSTYPE=${TSK_FS_TYPES[$type]} \
$SRC/sleuthkit_fls_fuzzer.cc -o $OUT/sleuthkit_fls_${type}_fuzzer \
$LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
done
for type in ${!TSK_VS_TYPES[@]}; do
- $CXX $CXXFLAGS -std=c++11 -I.. -I. -Itsk -DVSTYPE=${TSK_VS_TYPES[$type]} \
+ $CXX $CXXFLAGS -std=c++14 -I.. -I. -Itsk -DVSTYPE=${TSK_VS_TYPES[$type]} \
$SRC/sleuthkit_mmls_fuzzer.cc -o $OUT/sleuthkit_mmls_${type}_fuzzer \
$LIB_FUZZING_ENGINE $SRC/sleuthkit/tsk/.libs/libtsk.a
done
diff --git a/projects/sleuthkit/buildcorpus.sh b/projects/sleuthkit/buildcorpus.sh
new file mode 100755
index 000000000..435f475f1
--- /dev/null
+++ b/projects/sleuthkit/buildcorpus.sh
@@ -0,0 +1,77 @@
+#!/bin/bash -eu
+#
+# Script to downloads test data and build the corpus
+#
+# 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.
+#
+################################################################################
+
+# Test data provided by:
+#
+# The Fuzzing Project: https://fuzzing-project.org/resources.html
+# As CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
+# https://creativecommons.org/publicdomain/zero/1.0/
+#
+# The dfVFS project: https://github.com/log2timeline/dfvfs
+# As Apache 2 https://github.com/log2timeline/dfvfs/blob/main/LICENSE
+
+# Files to use for fls fuzz targets
+declare -A FLS_TEST_FILES=(
+ ["apfs"]="https://github.com/log2timeline/dfvfs/blob/main/test_data/apfs.raw?raw=true"
+ ["ext"]="https://files.fuzzing-project.org/filesystems/ext2.img"
+ ["fat"]="https://files.fuzzing-project.org/filesystems/exfat.img https://files.fuzzing-project.org/filesystems/fat12.img https://files.fuzzing-project.org/filesystems/fat16.img https://files.fuzzing-project.org/filesystems/fat32.img"
+ ["hfs"]="https://files.fuzzing-project.org/filesystems/hfsplus.img"
+ ["iso9660"]="https://files.fuzzing-project.org/discimages/iso9660.iso"
+ ["ntfs"]="https://files.fuzzing-project.org/filesystems/ntfs.img"
+)
+
+# Files to use for mmls fuzz targets
+declare -A MMLS_TEST_FILES=(
+ ["dos"]="https://files.fuzzing-project.org/discimages/partition-dos"
+ ["gpt"]="https://files.fuzzing-project.org/discimages/partition-gpt"
+ ["mac"]="https://files.fuzzing-project.org/discimages/partition-mac"
+)
+
+
+for type in ${!FLS_TEST_FILES[@]}; do
+ fuzz_target="sleuthkit_fls_${type}_fuzzer"
+
+ mkdir -p "test_data/${fuzz_target}"
+
+ IFS=" "; for url in ${FLS_TEST_FILES[$type]}; do
+ filename=$( echo ${url} | sed 's/?[^?]*$//' )
+ filename=$( basename ${filename} )
+
+ curl -L -o "test_data/${fuzz_target}/${filename}" "${url}"
+ done
+
+ (cd "test_data/${fuzz_target}" && zip ${OUT}/${fuzz_target}_seed_corpus.zip *)
+done
+
+
+for type in ${!MMLS_TEST_FILES[@]}; do
+ fuzz_target="sleuthkit_mmls_${type}_fuzzer"
+
+ mkdir -p "test_data/${fuzz_target}"
+
+ IFS=" "; for url in ${MMLS_TEST_FILES[$type]}; do
+ filename=$( echo ${url} | sed 's/?[^?]*$//' )
+ filename=$( basename ${filename} )
+
+ curl -L -o "test_data/${fuzz_target}/${filename}" "${url}"
+ done
+
+ (cd "test_data/${fuzz_target}" && zip ${OUT}/${fuzz_target}_seed_corpus.zip *)
+done
diff --git a/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc b/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc
new file mode 100644
index 000000000..5c0f40272
--- /dev/null
+++ b/projects/sleuthkit/sleuthkit_fls_apfs_fuzzer.cc
@@ -0,0 +1,60 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 <stddef.h>
+#include <stdint.h>
+
+#include "sleuthkit/tsk/tsk_tools_i.h"
+#include "sleuthkit/tsk/fs/tsk_fs.h"
+#include "sleuthkit/tsk/pool/tsk_pool.h"
+#include "sleuthkit_mem_img.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ TSK_IMG_INFO* img;
+ TSK_IMG_INFO* pool_img;
+ TSK_FS_INFO* fs;
+ const TSK_POOL_INFO* pool;
+
+ img = mem_open(data, size);
+ if (img == nullptr) {
+ return 0;
+ }
+ pool = tsk_pool_open_img_sing(img, 0, TSK_POOL_TYPE_APFS);
+
+ if (pool == nullptr) {
+ goto out_img;
+ }
+ // Pool start block is APFS container specific and is hard coded for now
+ pool_img = pool->get_img_info(pool, (TSK_DADDR_T) 106);
+
+ if (pool_img == nullptr) {
+ goto out_pool;
+ }
+ fs = tsk_fs_open_img_decrypt(pool_img, 0, TSK_FS_TYPE_APFS_DETECT, "");
+
+ if (fs != nullptr) {
+ tsk_fs_fls(fs, TSK_FS_FLS_FULL, fs->root_inum, TSK_FS_DIR_WALK_FLAG_RECURSE, nullptr, 0);
+
+ fs->close(fs);
+ }
+ tsk_img_close(pool_img);
+
+out_pool:
+ tsk_pool_close(pool);
+
+out_img:
+ tsk_img_close(img);
+
+ return 0;
+}
diff --git a/projects/smt/Dockerfile b/projects/smt/Dockerfile
new file mode 100644
index 000000000..536986d23
--- /dev/null
+++ b/projects/smt/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/celestiaorg/smt
+
+COPY build.sh $SRC
+WORKDIR $SRC/smt
diff --git a/projects/smt/build.sh b/projects/smt/build.sh
new file mode 100755
index 000000000..48547497b
--- /dev/null
+++ b/projects/smt/build.sh
@@ -0,0 +1,18 @@
+#!/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 ./oss-fuzz-build.sh
diff --git a/projects/smt/project.yaml b/projects/smt/project.yaml
new file mode 100644
index 000000000..471479e5e
--- /dev/null
+++ b/projects/smt/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://github.com/celestiaorg/smt"
+primary_contact: "ismail@celestia.org"
+auto_ccs:
+ - fuzzing@orijtech.com
+ - emmanuel@orijtech.com
+ - cuong@orijtech.com
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+main_repo: "https://github.com/celestiaorg/smt"
diff --git a/projects/solidity/Dockerfile b/projects/solidity/Dockerfile
index c59136c8f..4272be5ca 100644
--- a/projects/solidity/Dockerfile
+++ b/projects/solidity/Dockerfile
@@ -19,16 +19,17 @@ RUN apt-get update && apt-get install -y make autoconf automake libtool \
build-essential libbz2-dev ninja-build zlib1g-dev wget python python-dev \
liblzma-dev uuid-dev pkg-config openjdk-8-jdk unzip mlton
-RUN git clone --recursive -b breaking https://github.com/ethereum/solidity.git solidity
+RUN git clone --recursive -b develop https://github.com/ethereum/solidity.git solidity
RUN git clone --depth 1 https://github.com/ethereum/solidity-fuzzing-corpus.git
RUN git clone --depth 1 https://github.com/google/libprotobuf-mutator.git
-RUN git clone --branch="v0.4.0" --recurse-submodules \
+# evmone v0.8.2 fixes: https://github.com/ethereum/evmone/issues/373
+RUN git clone --branch="v0.8.2" --recurse-submodules \
https://github.com/ethereum/evmone.git
# Install statically built dependencies in "/usr" directory
# Install boost
RUN cd $SRC; \
- wget -q 'https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.bz2' -O boost.tar.bz2; \
+ wget -q 'https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2' -O boost.tar.bz2; \
test "$(sha256sum boost.tar.bz2)" = "4eb3b8d442b426dc35346235c8733b5ae35ba431690e38c6a8263dce9fcbb402 boost.tar.bz2"; \
tar -xf boost.tar.bz2; \
rm boost.tar.bz2; \
diff --git a/projects/solidity/build.sh b/projects/solidity/build.sh
index ae5844c74..9f9668b97 100755
--- a/projects/solidity/build.sh
+++ b/projects/solidity/build.sh
@@ -20,18 +20,7 @@ set -ex
ROOTDIR="${SRC}/solidity"
BUILDDIR="${ROOTDIR}/build"
-mkdir -p "${BUILDDIR}" && mkdir -p "$BUILDDIR/deps"
-
-ANTLRJAR="${BUILDDIR}/deps/antlr4.8.jar"
-ANTLRJAR_URI="https://www.antlr.org/download/antlr-4.8-complete.jar"
-
-download_antlr4()
-{
- if [[ ! -e "${ANTLRJAR}" ]]
- then
- wget -O "${ANTLRJAR}" "${ANTLRJAR_URI}"
- fi
-}
+mkdir -p "${BUILDDIR}"
generate_protobuf_bindings()
{
@@ -43,21 +32,6 @@ generate_protobuf_bindings()
done
}
-generate_antlr4_bindings()
-{
- cd "${ROOTDIR}"
- # Replace boolean with bool to suit c++ syntax
- sed -i 's/boolean /bool /g' docs/grammar/Solidity.g4
- # Generate antlr4 visitor/parser/lexer c++ bindings
- java -jar "${ANTLRJAR}" -Dlanguage=Cpp \
- -Xexact-output-dir -package solidity::test::fuzzer -o test/tools/ossfuzz \
- -no-listener -visitor docs/grammar/SolidityLexer.g4 docs/grammar/Solidity.g4
- # Delete unnecessary autogen files
- rm -f "${ROOTDIR}"/test/tools/ossfuzz/Solidity*Visitor.cpp \
- "${ROOTDIR}"/test/tools/ossfuzz/Solidity*.interp \
- "${ROOTDIR}"/test/tools/ossfuzz/Solidity*.tokens
-}
-
build_fuzzers()
{
cd "${BUILDDIR}"
@@ -87,9 +61,7 @@ update_corpus()
done
}
-download_antlr4
generate_protobuf_bindings
-generate_antlr4_bindings
build_fuzzers
copy_fuzzers_and_config
-update_corpus \ No newline at end of file
+update_corpus
diff --git a/projects/sound-open-firmware/project.yaml b/projects/sound-open-firmware/project.yaml
index 4065def34..5f8f889f0 100644
--- a/projects/sound-open-firmware/project.yaml
+++ b/projects/sound-open-firmware/project.yaml
@@ -3,4 +3,9 @@ primary_contact: "cujomalainey@chromium.org"
language: c
auto_ccs:
- "ranjani.sridharan@intel.corp-partner.google.com"
+ - "lgirdwood@gmail.com"
+ - "harsha.p.n@intel.corp-partner.google.com"
+ - "sathyanarayana.nujella@intel.corp-partner.google.com"
+ - "adrian.bonislawski@intel.com"
+ - "michal.wasko@intel.com"
main_repo: "https://github.com/thesofproject/sof"
diff --git a/projects/spdk/Dockerfile b/projects/spdk/Dockerfile
new file mode 100644
index 000000000..9ac85748e
--- /dev/null
+++ b/projects/spdk/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 curl yasm autoconf libtool meson nasm
+RUN git clone --depth 1 https://github.com/spdk/spdk && \
+ cd spdk && \
+ git submodule update --init
+WORKDIR $SRC/spdk
+COPY build.sh parse_json_fuzzer.cc $SRC/
diff --git a/projects/spdk/build.sh b/projects/spdk/build.sh
new file mode 100755
index 000000000..8cf7d6f0e
--- /dev/null
+++ b/projects/spdk/build.sh
@@ -0,0 +1,32 @@
+#!/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 spdk
+export LDFLAGS="${CFLAGS}"
+./scripts/pkgdep.sh
+./configure --without-shared --without-isal
+make -j$(nproc)
+
+# Build fuzzers
+$CXX $CXXFLAGS -I/src/spdk -I/src/spdk/include \
+ -fPIC -c $SRC/parse_json_fuzzer.cc \
+ -o parse_json_fuzzer.o
+
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+ parse_json_fuzzer.o -o $OUT/parse_json_fuzzer \
+ /src/spdk/build/lib/libspdk_env_dpdk.a \
+ /src/spdk/build/lib/libspdk_json.a
diff --git a/infra/base-images/base-sanitizer-libs-builder/Dockerfile b/projects/spdk/parse_json_fuzzer.cc
index b1a17b96c..94304ba66 100644
--- a/infra/base-images/base-sanitizer-libs-builder/Dockerfile
+++ b/projects/spdk/parse_json_fuzzer.cc
@@ -1,4 +1,5 @@
-# Copyright 2017 Google Inc.
+/*
+# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,10 +14,21 @@
# limitations under the License.
#
################################################################################
+*/
-FROM gcr.io/oss-fuzz-base/base-clang
-RUN sed -i -r 's/#\s*deb-src/deb-src/g' /etc/apt/sources.list
-RUN apt-get update && apt-get install -y python dpkg-dev patchelf python-apt zip
+#include <stdlib.h>
+#include "spdk/json.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ char *buf = (char *)malloc(size);
+ if (buf == NULL) {
+ return 0;
+ }
+ memcpy(buf, data, size);
+ ssize_t rc = spdk_json_parse(buf, size, NULL, 0, NULL, 0);
+
+ free(buf);
+ return 0;
+}
-COPY compiler_wrapper.py msan_build.py patch_build.py wrapper_utils.py /usr/local/bin/
-COPY packages /usr/local/bin/packages
diff --git a/projects/spdk/project.yaml b/projects/spdk/project.yaml
new file mode 100644
index 000000000..d326726eb
--- /dev/null
+++ b/projects/spdk/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/spdk/spdk"
+main_repo: "https://github.com/spdk/spdk"
+language: c
+primary_contact: "james.r.harris@intel.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
diff --git a/projects/spdlog/project.yaml b/projects/spdlog/project.yaml
index b2a7b59b3..afea591d9 100644
--- a/projects/spdlog/project.yaml
+++ b/projects/spdlog/project.yaml
@@ -1,10 +1,9 @@
homepage: "https://github.com/gabime/spdlog"
language: c++
primary_contact: "gmelman1@gmail.com"
-auto_ccs:
- - "ouyangyunshu@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
main_repo: 'https://github.com/gabime/spdlog.git'
diff --git a/projects/spice-usbredir/Dockerfile b/projects/spice-usbredir/Dockerfile
new file mode 100644
index 000000000..6a1059f88
--- /dev/null
+++ b/projects/spice-usbredir/Dockerfile
@@ -0,0 +1,31 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libtool libusb-1.0-0-dev pkg-config libglib2.0-dev && \
+ apt-get clean
+
+# Ubuntu 16.04 ships Meson 0.29 which doesn't support the "feature" option type.
+#
+# https://mesonbuild.com/Build-options.html#features
+RUN python3 -m pip install --no-user --no-cache meson ninja
+
+RUN git clone --depth 1 https://gitlab.freedesktop.org/spice/usbredir.git $SRC/spice-usbredir
+
+WORKDIR $SRC/spice-usbredir
+COPY build.sh $SRC/
diff --git a/projects/spice-usbredir/build.sh b/projects/spice-usbredir/build.sh
new file mode 100755
index 000000000..ffe02a7c1
--- /dev/null
+++ b/projects/spice-usbredir/build.sh
@@ -0,0 +1,18 @@
+#!/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.
+#
+################################################################################
+
+exec ./build-aux/oss-fuzz.sh
diff --git a/projects/spice-usbredir/project.yaml b/projects/spice-usbredir/project.yaml
new file mode 100644
index 000000000..391eea346
--- /dev/null
+++ b/projects/spice-usbredir/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.spice-space.org/usbredir.html"
+language: c++
+primary_contact: "freddy77@gmail.com"
+auto_ccs:
+ - "imsnah@gmail.com"
+sanitizers:
+ - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+ - undefined
+main_repo: "https://gitlab.freedesktop.org/spice/usbredir.git" \ No newline at end of file
diff --git a/projects/spidermonkey/Dockerfile b/projects/spidermonkey/Dockerfile
index 9c74dce54..226091bcc 100644
--- a/projects/spidermonkey/Dockerfile
+++ b/projects/spidermonkey/Dockerfile
@@ -21,7 +21,8 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \
libc++abi1 \
m4 \
yasm \
- python
+ python \
+ patchelf
# This wrapper of cargo seems to interfere with our build system.
RUN rm -f /usr/local/bin/cargo
diff --git a/projects/spidermonkey/build.sh b/projects/spidermonkey/build.sh
index bf2e03bfc..ddee98df1 100755
--- a/projects/spidermonkey/build.sh
+++ b/projects/spidermonkey/build.sh
@@ -41,3 +41,6 @@ cp dist/bin/js $OUT
mkdir -p $OUT/lib
cp -L /usr/lib/x86_64-linux-gnu/libc++.so.1 $OUT/lib
cp -L /usr/lib/x86_64-linux-gnu/libc++abi.so.1 $OUT/lib
+
+# Make sure libs are resolved properly
+patchelf --set-rpath '$ORIGIN/lib' $OUT/js
diff --git a/projects/spirv-tools/Dockerfile b/projects/spirv-tools/Dockerfile
new file mode 100644
index 000000000..9ef1e805e
--- /dev/null
+++ b/projects/spirv-tools/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 ninja-build
+RUN git clone --depth 1 https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools
+WORKDIR spirv-tools
+COPY build.sh $SRC/
diff --git a/projects/spirv-tools/build.sh b/projects/spirv-tools/build.sh
new file mode 100755
index 000000000..707c9d6ab
--- /dev/null
+++ b/projects/spirv-tools/build.sh
@@ -0,0 +1,107 @@
+#!/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.
+#
+################################################################################
+
+git clone https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers --depth=1
+git clone https://github.com/protocolbuffers/protobuf external/protobuf --branch v3.13.0.1
+git clone https://dawn.googlesource.com/tint --depth=1
+
+mkdir build
+pushd build
+
+CMAKE_ARGS="-DSPIRV_BUILD_LIBFUZZER_TARGETS=ON -DSPIRV_LIB_FUZZING_ENGINE_LINK_OPTIONS=$LIB_FUZZING_ENGINE"
+
+# With ubsan, RTTI must be enabled due to certain checks (vptr) requiring it.
+if [ $SANITIZER == "undefined" ];
+then
+ CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_RTTI=ON"
+fi
+cmake -G Ninja .. ${CMAKE_ARGS}
+ninja
+
+SPIRV_BINARY_FUZZERS="spvtools_binary_parser_fuzzer\
+ spvtools_dis_fuzzer\
+ spvtools_opt_legalization_fuzzer\
+ spvtools_opt_performance_fuzzer\
+ spvtools_opt_size_fuzzer\
+ spvtools_val_fuzzer"
+
+SPIRV_ASSEMBLY_FUZZERS="spvtools_as_fuzzer"
+
+for fuzzer in $SPIRV_BINARY_FUZZERS $SPIRV_ASSEMBLY_FUZZERS
+do
+ cp test/fuzzers/$fuzzer $OUT
+done
+
+popd
+
+# An un-instrumented build of spirv-as is used to generate a corpus of SPIR-V binaries.
+mkdir standard-build
+pushd standard-build
+
+# Back-up instrumentation options
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+export AFL_NOOPT=1
+
+cmake -G Ninja .. ${CMAKE_ARGS}
+ninja spirv-as
+
+# Restore instrumentation options
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+unset AFL_NOOPT
+
+popd
+
+
+# Generate a corpus of SPIR-V binaries from the SPIR-V assembly files in the
+# SPIRV-Tools and tint repositories.
+mkdir $WORK/tint-binary-corpus
+python3 tint/fuzzers/generate_spirv_corpus.py tint/test $WORK/tint-binary-corpus standard-build/tools/spirv-as
+mkdir $WORK/spirv-binary-corpus-hashed-names
+tint_test_cases=`ls $WORK/tint-binary-corpus/*.spv`
+spirv_tools_test_cases=`find test/fuzzers/corpora -name "*.spv"`
+for f in $tint_test_cases $spirv_tools_test_cases
+do
+ hashed_name=$(sha1sum "$f" | awk '{print $1}')
+ cp $f $WORK/spirv-binary-corpus-hashed-names/$hashed_name
+done
+zip -j "$WORK/spirv_binary_seed_corpus.zip" "$WORK/spirv-binary-corpus-hashed-names"/*
+
+# Supply each of the binary fuzzers with this seed corpus.
+for fuzzer in $SPIRV_BINARY_FUZZERS
+do
+ cp "$WORK/spirv_binary_seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
+
+# Generate a corpus of SPIR-V assembly files from the tint repository.
+mkdir $WORK/spirv-assembly-corpus-hashed-names
+for f in `find tint/test -name "*.spvasm"`
+do
+ hashed_name=$(sha1sum "$f" | awk '{print $1}')
+ cp $f $WORK/spirv-assembly-corpus-hashed-names/$hashed_name
+done
+
+zip -j "$WORK/spirv_assembly_seed_corpus.zip" "$WORK/spirv-assembly-corpus-hashed-names"/*
+
+# Supply each of the assembly fuzzers with this seed corpus.
+for fuzzer in $SPIRV_ASSEMBLY_FUZZERS
+do
+ cp "$WORK/spirv_assembly_seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
diff --git a/projects/spirv-tools/project.yaml b/projects/spirv-tools/project.yaml
new file mode 100644
index 000000000..2f02d02bc
--- /dev/null
+++ b/projects/spirv-tools/project.yaml
@@ -0,0 +1,15 @@
+homepage: https://github.com/KhronosGroup/SPIRV-Tools
+language: c++
+primary_contact: rharrison@google.com
+auto_ccs:
+ - "afdx@google.com"
+ - "alanbaker@google.com"
+ - "stevenperron@google.com"
+sanitizers:
+ - address
+ - memory
+ - undefined
+main_repo: 'https://github.com/KhronosGroup/SPIRV-Tools.git'
+architectures:
+ - x86_64
+ - i386
diff --git a/projects/sql-parser/Dockerfile b/projects/sql-parser/Dockerfile
new file mode 100755
index 000000000..b68268bfb
--- /dev/null
+++ b/projects/sql-parser/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/hyrise/sql-parser
+
+WORKDIR $SRC
+COPY build.sh $SRC/
+COPY fuzz_sql_parse.cpp $SRC/sql-parser/fuzz_sql_parse.cpp
diff --git a/projects/sql-parser/build.sh b/projects/sql-parser/build.sh
new file mode 100755
index 000000000..c795dd517
--- /dev/null
+++ b/projects/sql-parser/build.sh
@@ -0,0 +1,22 @@
+#!/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 sql-parser
+sed 's/static ?= no/LIB_CFLAGS += ${CXXFLAGS}\nstatic ?= no/g' -i Makefile
+make static=yes
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+ fuzz_sql_parse.cpp libsqlparser.a -I./src -o $OUT/fuzz_sql_parse
diff --git a/projects/sql-parser/fuzz_sql_parse.cpp b/projects/sql-parser/fuzz_sql_parse.cpp
new file mode 100644
index 000000000..1fb59c92a
--- /dev/null
+++ b/projects/sql-parser/fuzz_sql_parse.cpp
@@ -0,0 +1,26 @@
+/* Copyright 2021 Google LLC
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <string>
+#include "SQLParser.h"
+
+using namespace hsql;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ std::string input(reinterpret_cast<const char*>(data), size);
+ SQLParserResult res;
+ SQLParser::parse(input, &res);
+ return 0;
+}
diff --git a/projects/sql-parser/project.yaml b/projects/sql-parser/project.yaml
new file mode 100755
index 000000000..40a73dbd2
--- /dev/null
+++ b/projects/sql-parser/project.yaml
@@ -0,0 +1,7 @@
+homepage: "https://github.com/hyrise/sql-parser"
+main_repo: "https://github.com/hyrise/sql-parser"
+primary_contact: "marcel.weisgut@hpi.de"
+language: c++
+auto_ccs:
+ - "klauck2@gmail.com"
+ - "david@adalogics.com"
diff --git a/projects/sqlalchemy/Dockerfile b/projects/sqlalchemy/Dockerfile
new file mode 100644
index 000000000..80c314a54
--- /dev/null
+++ b/projects/sqlalchemy/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 rel_1_3 https://github.com/sqlalchemy/sqlalchemy
+WORKDIR $SRC/sqlalchemy
+COPY build.sh sqlalchemy_fuzzer.py $SRC/
diff --git a/projects/sqlalchemy/build.sh b/projects/sqlalchemy/build.sh
new file mode 100644
index 000000000..8f4bee46e
--- /dev/null
+++ b/projects/sqlalchemy/build.sh
@@ -0,0 +1,31 @@
+#!/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 install
+for fuzzer in $(find $SRC -name '*_fuzzer.py'); do
+ fuzzer_basename=$(basename -s .py $fuzzer)
+ fuzzer_package=${fuzzer_basename}.pkg
+ pyinstaller --distpath $OUT --onefile --name $fuzzer_package $fuzzer
+
+ # Create execution wrapper.
+ echo "#!/bin/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+this_dir=\$(dirname \"\$0\")
+ASAN_OPTIONS=\$ASAN_OPTIONS:symbolize=1:external_symbolizer_path=\$this_dir/llvm-symbolizer:detect_leaks=0 \
+\$this_dir/$fuzzer_package \$@" > $OUT/$fuzzer_basename
+ chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/sqlalchemy/project.yaml b/projects/sqlalchemy/project.yaml
new file mode 100644
index 000000000..2fe9bf515
--- /dev/null
+++ b/projects/sqlalchemy/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://www.sqlalchemy.org"
+language: python
+primary_contact: "mike_mp@zzzcomputing.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+ - undefined
+main_repo: "ihttps://github.com/sqlalchemy/sqlalchemy"
diff --git a/projects/sqlalchemy/sqlalchemy_fuzzer.py b/projects/sqlalchemy/sqlalchemy_fuzzer.py
new file mode 100644
index 000000000..d3ae577ba
--- /dev/null
+++ b/projects/sqlalchemy/sqlalchemy_fuzzer.py
@@ -0,0 +1,52 @@
+#!/usr/bin/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.
+
+import sys
+import atheris
+
+with atheris.instrument_imports():
+ import sqlalchemy
+ from sqlalchemy import create_engine
+ from sqlalchemy import Table, Column, Integer, String, MetaData
+ from sqlalchemy.sql import text
+
+@atheris.instrument_func
+def TestOneInput(input_bytes):
+ try:
+ sql_string = input_bytes.decode("utf-8")
+ metadata = MetaData()
+ fuzz_table = Table('fuzz_table', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('column1', String),
+ Column('column2', String),
+ )
+
+ engine = create_engine('sqlite:///fuzz.db')
+ metadata.create_all(engine)
+ statement = text(sql_string)
+ with engine.connect() as conn:
+ conn.execute(statement)
+ except Exception as e:
+ pass
+
+
+def main():
+ atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/stb/Dockerfile b/projects/stb/Dockerfile
index d9449ea9a..6b89306c2 100644
--- a/projects/stb/Dockerfile
+++ b/projects/stb/Dockerfile
@@ -22,12 +22,17 @@ RUN apt-get update && \
RUN git clone --depth 1 https://github.com/nothings/stb.git
-RUN wget -O $SRC/stb/gif.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-gif-1.00.tar.gz
-RUN wget -O $SRC/stb/jpg.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-jpg-1.00.tar.gz
-RUN wget -O $SRC/stb/bmp.zip http://entropymine.com/jason/bmpsuite/releases/bmpsuite-2.6.zip
-RUN wget -O $SRC/stb/tga.zip https://github.com/richgel999/tga_test_files/archive/master.zip
+RUN mkdir $SRC/stbi # CIFuzz workaround
-RUN wget -O $SRC/stb/tests/gif.dict https://raw.githubusercontent.com/mirrorer/afl/master/dictionaries/gif.dict &> /dev/null
+RUN wget -O $SRC/stbi/gif.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-gif-1.00.tar.gz
+RUN wget -O $SRC/stbi/jpg.tar.gz https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/imagetestsuite/imagetestsuite-jpg-1.00.tar.gz
+RUN wget -O $SRC/stbi/bmp.zip http://entropymine.com/jason/bmpsuite/releases/bmpsuite-2.6.zip
+RUN wget -O $SRC/stbi/tga.zip https://github.com/richgel999/tga_test_files/archive/master.zip
+
+RUN wget -O $SRC/stbi/gif.dict https://raw.githubusercontent.com/mirrorer/afl/master/dictionaries/gif.dict
+
+# Maintain compatibility with master branch until a new release
+RUN cp $SRC/stbi/gif.tar.gz $SRC/stbi/jpg.tar.gz $SRC/stbi/bmp.zip $SRC/stbi/gif.dict $SRC/stb
WORKDIR stb
COPY build.sh $SRC/
diff --git a/projects/sudoers/build.sh b/projects/sudoers/build.sh
index 905450cb4..d157c9a63 100755
--- a/projects/sudoers/build.sh
+++ b/projects/sudoers/build.sh
@@ -28,7 +28,11 @@ else
sanitizer_opts="$SANITIZER_FLAGS"
fi
# This is already added by --enable-fuzzer
-CFLAGS="`echo \"$CFLAGS\" | sed \"s/ -fsanitize=fuzzer-no-link//\"`"
+CFLAGS="`echo \"$CFLAGS\" | sed 's/ -fsanitize=fuzzer-no-link//'`"
+
+# Copy optimization flag to LDFLAGS for UBSan object-size check.
+OPTFLAG="`echo \"$CFLAGS\" | sed 's/^.*\(-O[^ ]\).*$/\1/'`"
+export LDFLAGS="${LDFLAGS:-}${LDFLAGS:+ }$OPTFLAG"
# Build sudo with static libs and enable fuzzing targets.
# All fuzz targets are integrated into the build process.
diff --git a/projects/sudoers/project.yaml b/projects/sudoers/project.yaml
index 309a3eb3a..3b3a660f1 100755
--- a/projects/sudoers/project.yaml
+++ b/projects/sudoers/project.yaml
@@ -4,7 +4,6 @@ language: c
fuzzing_engines:
- libfuzzer
- honggfuzz
- - dataflow
-auto_ccs :
+auto_ccs:
- "david@adalogics.com"
main_repo: 'https://github.com/sudo-project/sudo'
diff --git a/projects/suricata/Dockerfile b/projects/suricata/Dockerfile
index 257e7fb04..964c39498 100644
--- a/projects/suricata/Dockerfile
+++ b/projects/suricata/Dockerfile
@@ -14,10 +14,11 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y build-essential autoconf automake libtool make pkg-config python flex bison zlib1g-dev libpcre3-dev libpcre2-dev cmake tshark
+FROM gcr.io/oss-fuzz-base/base-builder-rust
+RUN apt-get update && apt-get install -y build-essential autoconf automake libtool make pkg-config python flex bison zlib1g-dev libpcre3-dev cmake tshark
-#TODO libmagic, liblzma, pcre and other optional libraries
+# TODO libmagic, liblzma and other optional libraries
+ADD https://ftp.pcre.org/pub/pcre/pcre2-10.36.tar.gz pcre2-10.36.tar.gz
ADD https://www.tcpdump.org/release/libpcap-1.9.1.tar.gz libpcap-1.9.1.tar.gz
ADD http://www.digip.org/jansson/releases/jansson-2.12.tar.gz jansson-2.12.tar.gz
RUN git clone --depth=1 https://github.com/yaml/libyaml
diff --git a/projects/suricata/build.sh b/projects/suricata/build.sh
index 18f228047..d825b9eb6 100755
--- a/projects/suricata/build.sh
+++ b/projects/suricata/build.sh
@@ -16,6 +16,15 @@
################################################################################
# build dependencies statically
+(
+tar -xvzf pcre2-10.36.tar.gz
+cd pcre2-10.36
+./configure --disable-shared
+make -j$(nproc) clean
+make -j$(nproc) all
+make -j$(nproc) install
+)
+
tar -xvzf lz4-1.9.2.tar.gz
cd lz4-1.9.2
make liblz4.a
@@ -52,6 +61,8 @@ make install
cd ..
export CARGO_BUILD_TARGET="x86_64-unknown-linux-gnu"
+# cf https://github.com/google/sanitizers/issues/1389
+export MSAN_OPTIONS=strict_memcmp=false
#we did not put libhtp there before so that cifuzz does not remove it
mv libhtp suricata/
@@ -61,22 +72,27 @@ sh autogen.sh
#run configure with right options
if [ "$SANITIZER" = "address" ]
then
- export RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-trace-geps -Cllvm-args=-sanitizer-coverage-prune-blocks=0 -Cllvm-args=-sanitizer-coverage-pc-table -Clink-dead-code -Cllvm-args=-sanitizer-coverage-stack-depth"
+ export RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov-module -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-pc-table -Clink-dead-code -Cllvm-args=-sanitizer-coverage-stack-depth -Ccodegen-units=1"
fi
./src/tests/fuzz/oss-fuzz-configure.sh
make -j$(nproc)
+./src/suricata --list-app-layer-protos | tail -n +2 | while read i; do cp src/fuzz_applayerparserparse $OUT/fuzz_applayerparserparse_$i; done
+
cp src/fuzz_* $OUT/
# dictionaries
./src/suricata --list-keywords | grep "\- " | sed 's/- //' | awk '{print "\""$0"\""}' > $OUT/fuzz_siginit.dict
+echo \"SMB\" > $OUT/fuzz_applayerparserparse_smb.dict
+
# build corpuses
# default configuration file
zip -r $OUT/fuzz_confyamlloadstring_seed_corpus.zip suricata.yaml
# rebuilds rules corpus with only one rule by file
unzip ../emerging.rules.zip
cd rules
+cat *.rules > $OUT/fuzz.rules
i=0
mkdir corpus
# quiet output for commands
@@ -105,9 +121,19 @@ rm -Rf corpus
mkdir corpus
set +x
ls | grep -v corpus | while read t; do
-cat $t/*.rules > corpus/$i || true; echo -ne '\0' >> corpus/$i; fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+grep -v "#" $t/*.rules | head -1 | cut -d "(" -f2 | cut -d ")" -f1 > corpus/$i || true; echo -ne '\0' >> corpus/$i; fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
echo -ne '\0' >> corpus/$i; python3 $SRC/fuzzpcap/tcptofpc.py $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
done
set -x
zip -q -r $OUT/fuzz_sigpcap_aware_seed_corpus.zip corpus
echo "\"FPC0\"" > $OUT/fuzz_sigpcap_aware.dict
+rm -Rf corpus
+mkdir corpus
+set +x
+ls | grep -v corpus | while read t; do
+fpc_bin $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+python3 $SRC/fuzzpcap/tcptofpc.py $t/*.pcap >> corpus/$i || rm corpus/$i; i=$((i+1));
+done
+set -x
+zip -q -r $OUT/fuzz_predefpcap_aware_seed_corpus.zip corpus
+echo "\"FPC0\"" > $OUT/fuzz_predefpcap_aware.dict
diff --git a/projects/suricata/project.yaml b/projects/suricata/project.yaml
index 3babd8f61..1db82dff3 100644
--- a/projects/suricata/project.yaml
+++ b/projects/suricata/project.yaml
@@ -1,11 +1,12 @@
homepage: "https://suricata-ids.org"
-language: c++
+language: rust
primary_contact: "vjulien@openinfosecfoundation.org"
auto_ccs:
- "jish@openinfosecfoundation.org"
- "p.antoine@catenacyber.fr"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
main_repo: 'https://github.com/OISF/suricata.git'
diff --git a/projects/swift-nio/Dockerfile b/projects/swift-nio/Dockerfile
new file mode 100644
index 000000000..1e47174c0
--- /dev/null
+++ b/projects/swift-nio/Dockerfile
@@ -0,0 +1,24 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 swift-nio
+RUN git clone --depth 1 https://github.com/google/fuzzing
+RUN git clone --depth 1 https://github.com/apple/swift-nio.git
+COPY build.sh $SRC
+COPY *.swift $SRC/
+WORKDIR $SRC/swift-nio
diff --git a/projects/swift-nio/Package.swift b/projects/swift-nio/Package.swift
new file mode 100644
index 000000000..98ab5dc43
--- /dev/null
+++ b/projects/swift-nio/Package.swift
@@ -0,0 +1,19 @@
+// swift-tools-version:5.3
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "swift-nio-fuzz",
+ dependencies: [
+ // Dependencies declare other packages that this package depends on.
+ .package(name: "swift-nio", path: ".."),
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+ // Targets can depend on other targets in this package, and on products in packages this package depends on.
+ .target(
+ name: "swift-nio-http1-fuzz",
+ dependencies: [.product(name: "NIOHTTP1", package: "swift-nio")]),
+ ]
+)
diff --git a/projects/swift-nio/build.sh b/projects/swift-nio/build.sh
new file mode 100755
index 000000000..1544e2b66
--- /dev/null
+++ b/projects/swift-nio/build.sh
@@ -0,0 +1,40 @@
+#!/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 swift-nio-fuzz
+cd swift-nio-fuzz
+swift package init --type=executable
+rm -Rf Sources/swift-nio-fuzz
+mkdir Sources/swift-nio-http1-fuzz
+cp $SRC/fuzz_http1.swift Sources/swift-nio-http1-fuzz/main.swift
+cp $SRC/Package.swift Package.swift
+
+. precompile_swift
+swift build -c debug $SWIFTFLAGS
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "*fuzz" -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 "*fuzz" -executable | while read i; do cp $i $OUT/"$i"-release; done
+)
+
+cp $SRC/fuzzing/dictionaries/http.dict $OUT/swift-nio-http1-fuzz-debug.dict
+cp $SRC/fuzzing/dictionaries/http.dict $OUT/swift-nio-http1-fuzz-release.dict
diff --git a/projects/swift-nio/fuzz_http1.swift b/projects/swift-nio/fuzz_http1.swift
new file mode 100644
index 000000000..065471a9a
--- /dev/null
+++ b/projects/swift-nio/fuzz_http1.swift
@@ -0,0 +1,21 @@
+import NIOHTTP1
+import NIO
+
+@_cdecl("LLVMFuzzerTestOneInput")
+public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
+ let bytes = UnsafeRawBufferPointer(start: start, count: count)
+ let channel = EmbeddedChannel()
+ var buffer = channel.allocator.buffer(capacity: count)
+ buffer.writeBytes(bytes)
+ do {
+ try channel.pipeline.addHandler(ByteToMessageHandler(HTTPRequestDecoder())).wait()
+ try channel.writeInbound(buffer)
+ channel.embeddedEventLoop.run()
+ } catch {
+ }
+ do {
+ try channel.finish(acceptAlreadyClosed: true)
+ } catch {
+ }
+ return 0
+}
diff --git a/projects/swift-nio/project.yaml b/projects/swift-nio/project.yaml
new file mode 100644
index 000000000..6c9a01ddc
--- /dev/null
+++ b/projects/swift-nio/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/apple/swift-nio"
+language: swift
+primary_contact: "lukasa@apple.com"
+auto_ccs :
+- "johannesweiss@apple.com"
+- "pp_adams@apple.com"
+- "p.antoine@catenacyber.fr"
+
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+- thread
+main_repo: 'https://github.com/apple/swift-nio.git'
diff --git a/projects/swift-protobuf/Dockerfile b/projects/swift-protobuf/Dockerfile
new file mode 100644
index 000000000..d8be91344
--- /dev/null
+++ b/projects/swift-protobuf/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+
+RUN git clone --depth 1 https://github.com/apple/swift-protobuf.git
+COPY build.sh $SRC
+WORKDIR $SRC/swift-protobuf
diff --git a/projects/swift-protobuf/build.sh b/projects/swift-protobuf/build.sh
new file mode 100755
index 000000000..4c30102bb
--- /dev/null
+++ b/projects/swift-protobuf/build.sh
@@ -0,0 +1,41 @@
+#!/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
+cd FuzzTesting
+
+# debug build
+swift build -c debug $SWIFTFLAGS
+(
+cd .build/debug/
+find . -maxdepth 1 -type f -name "Fuzz*" -executable | while read i; do cp $i $OUT/"$i"_debug; done
+)
+
+# release build
+swift build -c release $SWIFTFLAGS
+(
+cd .build/release/
+find . -maxdepth 1 -type f -name "Fuzz*" -executable | while read i; do cp $i $OUT/"$i"_release; done
+)
+
+# Copy any dictionaries over.
+for fuzz_dict in Fuzz*.dict ; do
+ fuzzer_name=$(basename $fuzz_dict .dict)
+ cp $fuzz_dict $OUT/${fuzzer_name}_debug.dict
+ cp $fuzz_dict $OUT/${fuzzer_name}_release.dict
+done
diff --git a/projects/swift-protobuf/project.yaml b/projects/swift-protobuf/project.yaml
new file mode 100644
index 000000000..002ee8726
--- /dev/null
+++ b/projects/swift-protobuf/project.yaml
@@ -0,0 +1,13 @@
+homepage: "https://github.com/apple/swift-protobuf"
+language: swift
+primary_contact: "tkientzle@apple.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+- "thomasvl@google.com"
+
+fuzzing_engines:
+- libfuzzer
+sanitizers:
+- address
+- thread
+main_repo: 'https://github.com/apple/swift-protobuf.git'
diff --git a/projects/systemd/Dockerfile b/projects/systemd/Dockerfile
index 0705c568a..09369d2ba 100644
--- a/projects/systemd/Dockerfile
+++ b/projects/systemd/Dockerfile
@@ -19,7 +19,7 @@ RUN apt-get update &&\
apt-get install -y gperf m4 gettext python3-pip \
libcap-dev libmount-dev libkmod-dev \
pkg-config wget &&\
- pip3 install meson==0.56.2 ninja
+ pip3 install meson ninja jinja2
RUN git clone --depth 1 https://github.com/systemd/systemd systemd
WORKDIR systemd
COPY build.sh $SRC/
diff --git a/projects/syzkaller/Dockerfile b/projects/syzkaller/Dockerfile
index fdef5b4be..a5803a803 100644
--- a/projects/syzkaller/Dockerfile
+++ b/projects/syzkaller/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/google/syzkaller/
diff --git a/projects/syzkaller/project.yaml b/projects/syzkaller/project.yaml
index 1442c047f..ed2b5b67d 100644
--- a/projects/syzkaller/project.yaml
+++ b/projects/syzkaller/project.yaml
@@ -2,7 +2,6 @@ homepage: "https://github.com/google/syzkaller.git"
primary_contact: "dvyukov@google.com"
auto_ccs:
- "andreyknvl@google.com"
- - "mmoroz@chromium.org"
- "syzkaller@googlegroups.com"
language: go
fuzzing_engines:
diff --git a/projects/tailscale/Dockerfile b/projects/tailscale/Dockerfile
new file mode 100644
index 000000000..9aaaba541
--- /dev/null
+++ b/projects/tailscale/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/tailscale/tailscale
+COPY build.sh $SRC/
+WORKDIR $SRC/tailscale
diff --git a/projects/tailscale/build.sh b/projects/tailscale/build.sh
new file mode 100644
index 000000000..47f281ad7
--- /dev/null
+++ b/projects/tailscale/build.sh
@@ -0,0 +1,18 @@
+#!/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 tailscale.com/net/stun FuzzStunParser stun_parser_fuzzer
diff --git a/projects/tailscale/project.yaml b/projects/tailscale/project.yaml
new file mode 100644
index 000000000..06698fd79
--- /dev/null
+++ b/projects/tailscale/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://tailscale.com/"
+main_repo: "https://github.com/tailscale/tailscale"
+primary_contact: "Adam@adalogics.com"
+auto_ccs :
+ - "josh@tailscale.com"
+ - "danderson@tailscale.com"
+ - "bradfitz@tailscale.com"
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
diff --git a/projects/tcmalloc/Dockerfile b/projects/tcmalloc/Dockerfile
new file mode 100644
index 000000000..18b8abdc5
--- /dev/null
+++ b/projects/tcmalloc/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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
+RUN git clone --depth 1 https://github.com/google/tcmalloc tcmalloc
+WORKDIR tcmalloc
+COPY build.sh $SRC/
diff --git a/projects/tcmalloc/build.sh b/projects/tcmalloc/build.sh
new file mode 100755
index 000000000..b204d1cb6
--- /dev/null
+++ b/projects/tcmalloc/build.sh
@@ -0,0 +1,18 @@
+#!/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_build_fuzz_tests
diff --git a/projects/tcmalloc/project.yaml b/projects/tcmalloc/project.yaml
new file mode 100644
index 000000000..19ce8c051
--- /dev/null
+++ b/projects/tcmalloc/project.yaml
@@ -0,0 +1,10 @@
+homepage: "tcmalloc"
+language: c++
+primary_contact: "ckennelly@google.com"
+main_repo: "https://github.com/google/tcmalloc"
+auto_ccs:
+ - "david@adalogics.com"
+sanitizers:
+ - address
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
diff --git a/projects/tdengine/Dockerfile b/projects/tdengine/Dockerfile
new file mode 100644
index 000000000..aa78f11f5
--- /dev/null
+++ b/projects/tdengine/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libtool build-essential
+RUN git clone --depth 1 https://github.com/taosdata/TDengine tdengine
+WORKDIR tdengine
+COPY build.sh $SRC/
+COPY *.options $SRC/
diff --git a/projects/tdengine/build.sh b/projects/tdengine/build.sh
new file mode 100755
index 000000000..539915c5d
--- /dev/null
+++ b/projects/tdengine/build.sh
@@ -0,0 +1,47 @@
+#!/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/git@/https:\/\//g' .gitmodules
+sed -i 's/:taos/\/taos/g' .gitmodules
+sed -i 's/\.git//g' .gitmodules
+
+git submodule update --init --recursive
+sed -i 's/-Werror//g' ./cmake/define.inc
+mkdir debug && cd debug
+cmake .. && cmake --build .
+
+cd build/bin
+
+# Now let's build the fuzzer.
+$CC $CFLAGS -DLINUX -DUSE_LIBICONV -D_LINUX -D_M_X64 \
+ -D_TD_LINUX -D_TD_LINUX_64 \
+ -I/src/tdengine/src/inc -I/src/tdengine/src/os/inc \
+ -I/src/tdengine/src/util/inc -I/src/tdengine/src/common/inc \
+ -I/src/tdengine/src/tsdb/inc -I/src/tdengine/src/query/inc \
+ -o sql-fuzzer.o -c $SRC/tdengine/tests/fuzz//sql-fuzzer.c
+
+$CC $CFLAGS $LIB_FUZZING_ENGINE sql-fuzzer.o -o $OUT/sql-fuzzer \
+ ../../../debug/src/common/CMakeFiles/common.dir/src/tglobal.c.o \
+ -Wl,--start-group \
+ ../lib/libtaos_static.a ../lib/libtrpc.a ../lib/libtutil.a \
+ ../lib/libquery.a ../lib/libtsdb.a ../lib/libcommon.a \
+ ../lib/libtfs.a ../lib/liblz4.a ../lib/libos.a \
+ ../lib/liboslinux.a ../lib/libz.a ../lib/librmonotonic.a \
+ ../lib/liblua.a \
+ -Wl,--end-group -lpthread -ldl
+
+cp $SRC/*.options $OUT/
diff --git a/projects/tdengine/project.yaml b/projects/tdengine/project.yaml
new file mode 100644
index 000000000..63236eed9
--- /dev/null
+++ b/projects/tdengine/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://www.taosdata.com/en/documentation/"
+language: c
+primary_contact: "sangshuduo@gmail.com"
+main_repo: "https://github.com/taosdata/TDengine"
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/tdengine/sql-fuzzer.options b/projects/tdengine/sql-fuzzer.options
new file mode 100644
index 000000000..f9d09656c
--- /dev/null
+++ b/projects/tdengine/sql-fuzzer.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/teleport/Dockerfile b/projects/teleport/Dockerfile
index 8ffafb3a0..c3e3beb55 100644
--- a/projects/teleport/Dockerfile
+++ b/projects/teleport/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/gravitational/teleport.git
COPY build.sh $SRC/
WORKDIR $SRC/teleport
diff --git a/projects/tendermint/Dockerfile b/projects/tendermint/Dockerfile
new file mode 100644
index 000000000..58899ef16
--- /dev/null
+++ b/projects/tendermint/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/tendermint/tendermint
+
+COPY build.sh $SRC
+WORKDIR $SRC/tendermint
diff --git a/projects/tendermint/build.sh b/projects/tendermint/build.sh
new file mode 100755
index 000000000..8981352c7
--- /dev/null
+++ b/projects/tendermint/build.sh
@@ -0,0 +1,18 @@
+#!/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 ./test/fuzz/oss-fuzz-build.sh
diff --git a/projects/tendermint/project.yaml b/projects/tendermint/project.yaml
new file mode 100644
index 000000000..67d02d5f0
--- /dev/null
+++ b/projects/tendermint/project.yaml
@@ -0,0 +1,15 @@
+homepage: "https://github.com/tendermint/tendermint"
+primary_contact: "security@interchain.io"
+auto_ccs:
+ - fuzzing@orijtech.com
+ - emmanuel@orijtech.com
+ - cuong@orijtech.com
+ - callum@interchain.io
+ - tychoish@interchain.io
+ - william@interchain.io
+language: go
+fuzzing_engines:
+ - libfuzzer
+sanitizers:
+ - address
+main_repo: "https://github.com/tendermint/tendermint"
diff --git a/projects/tensorflow-py/Dockerfile b/projects/tensorflow-py/Dockerfile
index dea03cb2f..e5e2a66ae 100644
--- a/projects/tensorflow-py/Dockerfile
+++ b/projects/tensorflow-py/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
diff --git a/projects/tensorflow-py/build.sh b/projects/tensorflow-py/build.sh
index afd501b62..8e12b3d9b 100644
--- a/projects/tensorflow-py/build.sh
+++ b/projects/tensorflow-py/build.sh
@@ -39,7 +39,7 @@ this_dir=\$(dirname \"\$0\")
LD_PRELOAD=\"\$this_dir/sanitizer_with_fuzzer.so \$this_dir/libz-eb09ad1d.so.1.2.3 \$this_dir/libquadmath-2d0c479f.so.0.0.0 \$this_dir/libgfortran-2e0d59d6.so.5.0.0 \$this_dir/libopenblasp-r0-09e95953.3.13.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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
mv $SRC/tensorflow/tensorflow_src $SRC/tensorflow/tensorflow
diff --git a/projects/tensorflow-py/project.yaml b/projects/tensorflow-py/project.yaml
index 64c5eba43..cac4a1a17 100644
--- a/projects/tensorflow-py/project.yaml
+++ b/projects/tensorflow-py/project.yaml
@@ -3,6 +3,7 @@ language: python
primary_contact: "amitpatankar@google.com"
auto_ccs:
- "mihaimaruseac@google.com"
+ - "lpak@google.com"
fuzzing_engines:
- libfuzzer
sanitizers:
diff --git a/projects/tesseract-ocr/Dockerfile b/projects/tesseract-ocr/Dockerfile
index 20094e7bb..3e02c5ea1 100644
--- a/projects/tesseract-ocr/Dockerfile
+++ b/projects/tesseract-ocr/Dockerfile
@@ -15,8 +15,24 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake libtool pkg-config libpng-dev libjpeg8-dev libtiff5-dev zlib1g-dev
+RUN apt-get update && apt-get install -y autoconf automake libtool pkg-config libpng-dev libjpeg8-dev liblzma-dev
+
+RUN git clone https://www.cl.cam.ac.uk/~mgk25/git/jbigkit jbigkit && \
+ cd jbigkit && \
+ make clean && \
+ make -j$(nproc) lib && \
+ cp libjbig/libjbig.a /usr/lib/x86_64-linux-gnu/libjbig.a
+
+RUN git clone --depth 1 https://gitlab.com/libtiff/libtiff libtiff && \
+ cd libtiff && \
+ cmake . -DBUILD_SHARED_LIBS=off && \
+ make clean && \
+ make -j$(nproc) && \
+ make install && \
+ cp libtiff/libtiff.a /usr/lib/x86_64-linux-gnu/libtiff.a
+
RUN git clone --depth 1 https://github.com/danbloomberg/leptonica
RUN git clone --depth 1 https://github.com/tesseract-ocr/tesseract
RUN git clone --depth 1 https://github.com/tesseract-ocr/tessdata
+
COPY build.sh $SRC/
diff --git a/projects/thrift/Dockerfile b/projects/thrift/Dockerfile
index 040188316..f66941700 100644
--- a/projects/thrift/Dockerfile
+++ b/projects/thrift/Dockerfile
@@ -15,7 +15,30 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y libssl-dev pkg-config autoconf automake libtool bison flex libboost-all-dev
+
+# We use compile_go_fuzzer in this set up and also go itself
+FROM gcr.io/oss-fuzz-base/base-builder-go
+
+RUN apt-get update && apt-get install -y libssl-dev pkg-config autoconf automake libtool bison flex wget make \
+ autoconf \
+ automake \
+ sudo \
+ gcc \
+ g++ \
+ python-dev \
+ cmake \
+ ninja-build
+
+RUN wget https://sourceforge.net/projects/boost/files/boost/1.70.0/boost_1_70_0.tar.gz && \
+ tar xzf boost_1_70_0.tar.gz && \
+ cd boost_1_70_0 && \
+ ./bootstrap.sh --with-toolset=clang && \
+ ./b2 clean && \
+ ./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -j$(nproc) install && \
+ cd .. && \
+ rm -rf boost_1_70_0
+
+#libboost-all-dev
RUN git clone --depth 1 https://github.com/apache/thrift
WORKDIR $SRC/thrift
COPY build.sh $SRC/
diff --git a/projects/thrift/build.sh b/projects/thrift/build.sh
index 8194063b6..ffbd115d9 100755
--- a/projects/thrift/build.sh
+++ b/projects/thrift/build.sh
@@ -18,6 +18,10 @@
# build project
export ASAN_OPTIONS=detect_leaks=0
+if [ "$SANITIZER" = "coverage" ]
+then
+ cp /usr/bin/ld.gold /usr/bin/ld
+fi
./bootstrap.sh
# rust fails compilation with clippy warnings
./configure --with-rs=no
diff --git a/projects/tidb/Dockerfile b/projects/tidb/Dockerfile
index 5c7d0fd3b..17091a6bd 100644
--- a/projects/tidb/Dockerfile
+++ b/projects/tidb/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/pingcap/tidb
COPY build.sh $SRC/
WORKDIR $SRC/tidb
diff --git a/projects/tidb/build.sh b/projects/tidb/build.sh
index c11028f24..da5fd1c43 100755
--- a/projects/tidb/build.sh
+++ b/projects/tidb/build.sh
@@ -15,10 +15,6 @@
#
################################################################################
-# Insert empty main function
-sed -i '23 i\func main(){}'\\n $SRC/tidb/plugin/conn_ip_example/conn_ip_example.go
-
-go get ./...
compile_go_fuzzer github.com/pingcap/tidb/types FuzzMarshalJSON fuzzMarshalJSON
compile_go_fuzzer github.com/pingcap/tidb/types FuzzNewBitLiteral fuzzNewBitLiteral
diff --git a/projects/tidy-html5/build.sh b/projects/tidy-html5/build.sh
index d10c505a8..7b75ab68e 100644
--- a/projects/tidy-html5/build.sh
+++ b/projects/tidy-html5/build.sh
@@ -22,12 +22,12 @@ cd ${WORK}/tidy-html5
cmake -GNinja ${SRC}/tidy-html5/
ninja
-for fuzzer in tidy_config_fuzzer tidy_fuzzer; do
+for fuzzer in tidy_config_fuzzer tidy_fuzzer tidy_xml_fuzzer tidy_parse_string_fuzzer tidy_parse_file_fuzzer tidy_general_fuzzer; do
${CC} ${CFLAGS} -c -I${SRC}/tidy-html5/include \
$SRC/${fuzzer}.c -o ${fuzzer}.o
${CXX} ${CXXFLAGS} -std=c++11 ${fuzzer}.o \
-o $OUT/${fuzzer} \
- $LIB_FUZZING_ENGINE libtidys.a
+ $LIB_FUZZING_ENGINE libtidy.a
done
cp ${SRC}/*.options ${OUT}/
diff --git a/projects/tidy-html5/project.yaml b/projects/tidy-html5/project.yaml
index d62facb4d..086f83ba4 100644
--- a/projects/tidy-html5/project.yaml
+++ b/projects/tidy-html5/project.yaml
@@ -1,6 +1,6 @@
homepage: "http://www.html-tidy.org/"
language: c++
-primary_contact: "sbucur@google.com"
+primary_contact: "balthisar@gmail.com"
auto_ccs:
- "nmarrow@google.com"
- "pmokati@google.com"
diff --git a/projects/tidy-html5/tidy_general_fuzzer.c b/projects/tidy-html5/tidy_general_fuzzer.c
new file mode 100644
index 000000000..67a064c7f
--- /dev/null
+++ b/projects/tidy-html5/tidy_general_fuzzer.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+// All boolean options. These will be set randomly
+// based on the fuzzer data.
+TidyOptionId bool_options[] = {
+ TidyJoinClasses,
+ TidyJoinStyles,
+ TidyKeepFileTimes,
+ TidyKeepTabs,
+ TidyLiteralAttribs,
+ TidyLogicalEmphasis,
+ TidyLowerLiterals,
+ TidyMakeBare,
+ TidyFixUri,
+ TidyForceOutput,
+ TidyGDocClean,
+ TidyHideComments,
+ TidyMark,
+ TidyXmlTags,
+ TidyMakeClean,
+ TidyAnchorAsName,
+ TidyMergeEmphasis,
+ TidyMakeBare,
+ TidyMetaCharset,
+ TidyMuteShow,
+ TidyNCR,
+ TidyNumEntities,
+ TidyOmitOptionalTags,
+ TidyPunctWrap,
+ TidyQuiet,
+ TidyQuoteAmpersand,
+ TidyQuoteMarks,
+ TidyQuoteNbsp,
+ TidyReplaceColor,
+ TidyShowFilename,
+ TidyShowInfo,
+ TidyShowMarkup,
+ TidyShowMetaChange,
+ TidyShowWarnings,
+ TidySkipNested,
+ TidyUpperCaseTags,
+ TidyWarnPropAttrs,
+ TidyWord2000,
+ TidyWrapAsp,
+ TidyWrapAttVals,
+ TidyWrapJste,
+ TidyWrapPhp,
+ TidyWrapScriptlets,
+ TidyWrapSection,
+ TidyWriteBack,
+};
+
+void set_option(const uint8_t** data, size_t *size, TidyDoc *tdoc, TidyOptionId tboolID) {
+ uint8_t decider;
+ decider = **data;
+ *data += 1;
+ *size -= 1;
+ if (decider % 2 == 0) tidyOptSetBool( *tdoc, tboolID, yes );
+ else { tidyOptSetBool( *tdoc, tboolID, no ); }
+}
+
+int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
+ uint8_t decider;
+
+ // We need enough data for picking all of the options. One byte per option.
+ if (size < 5+(sizeof(bool_options)/sizeof(bool_options[0]))) {
+ return 0;
+ }
+
+ TidyDoc tdoc = tidyCreate();
+
+ // Decide output format
+ decider = *data;
+ data++; size--;
+ if (decider % 3 == 0) tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+ else { tidyOptSetBool( tdoc, TidyXhtmlOut, no ); }
+
+ if (decider % 3 == 1) tidyOptSetBool( tdoc, TidyHtmlOut, yes );
+ else { tidyOptSetBool( tdoc, TidyHtmlOut, no ); }
+
+ if (decider % 3 == 2) tidyOptSetBool( tdoc, TidyXmlOut, yes );
+ else { tidyOptSetBool( tdoc, TidyXmlOut, no ); }
+
+ // Set options
+ for (int i=0; i < sizeof(bool_options)/sizeof(TidyOptionId); i++) {
+ set_option(&data, &size, &tdoc, bool_options[i]);
+ }
+
+ // Set an error buffer.
+ tidySetErrorBuffer(tdoc, errbuf);
+
+ // Parse the data
+ decider = *data;
+ data++; size--;
+ switch (decider % 2) {
+ case 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);
+
+ tidyParseFile(tdoc, filename);
+ unlink(filename);
+ }
+ break;
+ case 1: {
+ char *inp = malloc(size+1);
+ inp[size] = '\0';
+ memcpy(inp, data, size);
+ tidyParseString(tdoc, inp);
+ free(inp);
+ }
+ }
+
+ // Cleanup
+ tidyRelease( tdoc );
+
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ TidyBuffer fuzz_toutput;
+ TidyBuffer fuzz_terror;
+
+ tidyBufInit(&fuzz_toutput);
+ tidyBufInit(&fuzz_terror);
+
+ TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
+
+ tidyBufFree(&fuzz_toutput);
+ tidyBufFree(&fuzz_terror);
+
+ return 0;
+}
diff --git a/projects/tidy-html5/tidy_parse_file_fuzzer.c b/projects/tidy-html5/tidy_parse_file_fuzzer.c
new file mode 100644
index 000000000..febeaa6ca
--- /dev/null
+++ b/projects/tidy-html5/tidy_parse_file_fuzzer.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+
+int TidyXhtml(const uint8_t* data, size_t size, TidyBuffer* output, TidyBuffer* errbuf) {
+ Bool ok;
+
+ TidyDoc tdoc = tidyCreate();
+
+ ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+ if (ok) tidySetErrorBuffer(tdoc, errbuf);
+
+ 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);
+
+ tidyParseFile(tdoc, filename);
+
+ tidyRelease( tdoc );
+ unlink(filename);
+
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ TidyBuffer fuzz_toutput;
+ TidyBuffer fuzz_terror;
+
+ tidyBufInit(&fuzz_toutput);
+ tidyBufInit(&fuzz_terror);
+
+ TidyXhtml(data, size, &fuzz_toutput, &fuzz_terror);
+
+ tidyBufFree(&fuzz_toutput);
+ tidyBufFree(&fuzz_terror);
+ return 0;
+}
+
diff --git a/projects/tidy-html5/tidy_parse_string_fuzzer.c b/projects/tidy-html5/tidy_parse_string_fuzzer.c
new file mode 100644
index 000000000..3d1f7e27d
--- /dev/null
+++ b/projects/tidy-html5/tidy_parse_string_fuzzer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "tidybuffio.h"
+#include "tidy.h"
+
+
+int TidyXhtml(const char* input, TidyBuffer* output, TidyBuffer* errbuf) {
+ TidyDoc tdoc = tidyCreate();
+ tidyOptSetBool( tdoc, TidyXhtmlOut, yes );
+ tidySetErrorBuffer(tdoc, errbuf);
+
+ tidyParseString(tdoc, input);
+
+ tidyCleanAndRepair(tdoc);
+ tidyRunDiagnostics(tdoc);
+ tidyOptSetBool(tdoc, TidyForceOutput, yes);
+ tidySaveBuffer(tdoc, output);
+ tidyRelease( tdoc );
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ char *fuzz_inp = malloc(size+1);
+ memcpy(fuzz_inp, data, size);
+ fuzz_inp[size] = '\0';
+
+ TidyBuffer fuzz_toutput;
+ TidyBuffer fuzz_terror;
+
+ tidyBufInit(&fuzz_toutput);
+ tidyBufInit(&fuzz_terror);
+
+ TidyXhtml(fuzz_inp, &fuzz_toutput, &fuzz_terror);
+
+ tidyBufFree(&fuzz_toutput);
+ tidyBufFree(&fuzz_terror);
+ free(fuzz_inp);
+ return 0;
+}
+
diff --git a/projects/tidy-html5/tidy_xml_fuzzer.c b/projects/tidy-html5/tidy_xml_fuzzer.c
new file mode 100644
index 000000000..c40551193
--- /dev/null
+++ b/projects/tidy-html5/tidy_xml_fuzzer.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "tidy.h"
+#include "tidybuffio.h"
+#include "tidyenum.h"
+#include "tidyplatform.h"
+
+void TidyXml(char *fuzz_inp, TidyBuffer *toutput,
+ TidyBuffer *terror) {
+ TidyDoc tdoc = tidyCreate();
+ tidyBufClear(toutput);
+ tidyBufClear(terror);
+ if (tidyOptSetBool(tdoc, TidyXmlOut, yes)) {
+ tidySetCharEncoding(tdoc, "utf8");
+ tidySetErrorBuffer(tdoc, terror);
+ tidyOptSetInt(tdoc, TidyWrapLen, 0);
+ tidyOptSetBool(tdoc, TidyXmlTags, yes);
+ tidyOptSetBool(tdoc, TidyQuoteNbsp, no);
+ tidyOptSetBool(tdoc, TidyNumEntities, yes);
+ tidyOptSetBool(tdoc, TidyQuiet, yes);
+ tidyOptSetBool(tdoc, TidyMark, no);
+ tidyOptSetBool(tdoc, TidyShowWarnings, no);
+ tidyParseString(tdoc, fuzz_inp);
+ tidyCleanAndRepair(tdoc);
+ tidyRunDiagnostics(tdoc);
+ tidySaveBuffer(tdoc, toutput);
+ }
+
+ tidyRelease(tdoc);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ char *fuzz_inp = malloc(size+1);
+ memcpy(fuzz_inp, data, size);
+ fuzz_inp[size] = '\0';
+
+ TidyBuffer fuzz_toutput;
+ TidyBuffer fuzz_terror;
+
+ tidyBufInit(&fuzz_toutput);
+ tidyBufInit(&fuzz_terror);
+
+ TidyXml(fuzz_inp, &fuzz_toutput, &fuzz_terror);
+
+ free(fuzz_inp);
+ tidyBufFree(&fuzz_toutput);
+ tidyBufFree(&fuzz_terror);
+ return 0;
+}
diff --git a/projects/tint/Dockerfile b/projects/tint/Dockerfile
new file mode 100644
index 000000000..dc293e905
--- /dev/null
+++ b/projects/tint/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 ninja-build
+RUN git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' --depth 1
+ENV PATH="${SRC}/depot_tools:${PATH}"
+RUN git clone --depth 1 https://dawn.googlesource.com/tint tint
+WORKDIR tint
+COPY build.sh $SRC/
diff --git a/projects/tint/build.sh b/projects/tint/build.sh
new file mode 100755
index 000000000..68b682b91
--- /dev/null
+++ b/projects/tint/build.sh
@@ -0,0 +1,106 @@
+#!/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 standalone.gclient .gclient
+gclient sync
+
+mkdir -p out/Debug
+pushd out/Debug
+
+# ubsan's vptr sanitization is desabled as it requires RTTI, which is disabled
+# when building tint.
+CFLAGS="$CFLAGS -fno-sanitize=vptr" \
+CXXFLAGS="$CXXFLAGS -fno-sanitize=vptr" \
+cmake -GNinja ../.. -DCMAKE_BUILD_TYPE=Release -DTINT_BUILD_FUZZERS=ON -DTINT_BUILD_SPIRV_TOOLS_FUZZER=ON -DTINT_BUILD_TESTS=OFF -DTINT_LIB_FUZZING_ENGINE_LINK_OPTIONS=$LIB_FUZZING_ENGINE
+
+if [ -n "${OSS_FUZZ_CI-}" ]
+then
+ # When running in the CI, restrict to a small number of fuzz targets to save
+ # time and disk space. A SPIR-V Tools-based fuzzer that uses the HLSL
+ # back-end, and a regular fuzzer that uses the MSL back-end, are selected.
+ SPIRV_TOOLS_FUZZERS="tint_spirv_tools_hlsl_writer_fuzzer"
+ SPIRV_FUZZERS="tint_spv_reader_msl_writer_fuzzer\
+ ${SPIRV_TOOLS_FUZZERS}"
+else
+ SPIRV_TOOLS_FUZZERS="tint_spirv_tools_hlsl_writer_fuzzer\
+ tint_spirv_tools_msl_writer_fuzzer\
+ tint_spirv_tools_spv_writer_fuzzer\
+ tint_spirv_tools_wgsl_writer_fuzzer"
+ SPIRV_FUZZERS="tint_spv_reader_hlsl_writer_fuzzer\
+ tint_spv_reader_msl_writer_fuzzer\
+ tint_spv_reader_spv_writer_fuzzer\
+ tint_spv_reader_wgsl_writer_fuzzer\
+ ${SPIRV_TOOLS_FUZZERS}"
+fi
+
+# The spirv-as tool is used to build seed corpora
+ninja ${SPIRV_FUZZERS}
+
+cp ${SPIRV_FUZZERS} $OUT
+
+popd
+
+# An un-instrumented build of spirv-as is used to generate a corpus of SPIR-V binaries.
+mkdir -p out/Standard
+pushd out/Standard
+
+# Back-up instrumentation options
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+export AFL_NOOPT=1
+
+cmake -GNinja ../.. -DCMAKE_BUILD_TYPE=Release
+ninja spirv-as
+
+# Restore instrumentation options
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+unset AFL_NOOPT
+
+popd
+
+# Generate a corpus of SPIR-V binaries from the SPIR-V assembly files in the
+# tint repository.
+mkdir $WORK/spirv-corpus
+python3 fuzzers/generate_spirv_corpus.py test $WORK/spirv-corpus out/Standard/spirv-as
+
+mkdir $WORK/spirv-corpus-hashed-names
+for f in `ls $WORK/spirv-corpus/*.spv`
+do
+ hashed_name=$(sha1sum "$f" | awk '{print $1}')
+ cp $f $WORK/spirv-corpus-hashed-names/$hashed_name
+done
+
+zip -j "$WORK/seed_corpus.zip" "$WORK"/spirv-corpus-hashed-names/*
+
+for fuzzer in $SPIRV_FUZZERS
+do
+ cp "$WORK/seed_corpus.zip" "$OUT/${fuzzer}_seed_corpus.zip"
+done
+
+for fuzzer in $SPIRV_TOOLS_FUZZERS
+do
+ echo "[libfuzzer]
+max_len = 10000
+cross_over = 0
+mutate_depth = 1
+tint_enable_all_mutations = false
+tint_mutation_batch_size = 5
+" > "$OUT/${fuzzer}.options"
+done
diff --git a/projects/tint/project.yaml b/projects/tint/project.yaml
new file mode 100644
index 000000000..46fec183e
--- /dev/null
+++ b/projects/tint/project.yaml
@@ -0,0 +1,13 @@
+homepage: https://dawn.googlesource.com/tint
+language: c++
+primary_contact: bclayton@google.com
+auto_ccs:
+ - "afdx@google.com"
+sanitizers:
+ - address
+ - memory
+ - undefined
+main_repo: 'https://dawn.googlesource.com/tint.git'
+architectures:
+ - x86_64
+ - i386
diff --git a/projects/tinyobjloader/Dockerfile b/projects/tinyobjloader/Dockerfile
new file mode 100644
index 000000000..72ad9eaba
--- /dev/null
+++ b/projects/tinyobjloader/Dockerfile
@@ -0,0 +1,20 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/tinyobjloader/tinyobjloader
+COPY build.sh $SRC
+WORKDIR $SRC/tinyobjloader
diff --git a/projects/tinyobjloader/build.sh b/projects/tinyobjloader/build.sh
new file mode 100755
index 000000000..e80301bfe
--- /dev/null
+++ b/projects/tinyobjloader/build.sh
@@ -0,0 +1,23 @@
+#!/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 fuzz* $OUT/
diff --git a/projects/tinyobjloader/project.yaml b/projects/tinyobjloader/project.yaml
new file mode 100644
index 000000000..467e88905
--- /dev/null
+++ b/projects/tinyobjloader/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/tinyobjloader/tinyobjloader"
+language: c++
+primary_contact: "syoyo@lighttransport.com"
+auto_ccs :
+- "p.antoine@catenacyber.fr"
+
+sanitizers:
+- address
+- undefined
+main_repo: 'https://github.com/tinyobjloader/tinyobjloader'
diff --git a/projects/tmux/build.sh b/projects/tmux/build.sh
index 53de126ac..f4fe555e5 100644
--- a/projects/tmux/build.sh
+++ b/projects/tmux/build.sh
@@ -44,3 +44,8 @@ cat "${SRC}/tmux-fuzzing-corpus/iterm2"/* | \
split -a5 -db$MAXLEN - iterm2.
zip -q -j -r "${OUT}/input-fuzzer_seed_corpus.zip" \
"${WORK}/fuzzing_corpus/"
+
+# Handle libevent not existing on runner.
+mkdir $OUT/lib
+cp /lib/x86_64-linux-gnu/libevent_core* $OUT/lib
+patchelf --set-rpath '$ORIGIN/lib' $OUT/input-fuzzer
diff --git a/projects/tor/Dockerfile b/projects/tor/Dockerfile
index 37d9753e0..3211c40be 100644
--- a/projects/tor/Dockerfile
+++ b/projects/tor/Dockerfile
@@ -15,7 +15,7 @@
##############################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y autoconf automake make libtool
+RUN apt-get update && apt-get install -y autoconf automake make libtool pkg-config
RUN git clone --depth 1 https://git.torproject.org/tor.git
RUN git clone --depth 1 https://git.torproject.org/fuzzing-corpora.git tor-fuzz-corpora
RUN git clone --depth 1 https://github.com/madler/zlib.git
diff --git a/projects/tor/build.sh b/projects/tor/build.sh
index 1c5154a91..8f4d029bc 100644
--- a/projects/tor/build.sh
+++ b/projects/tor/build.sh
@@ -63,13 +63,15 @@ export ASAN_OPTIONS=detect_leaks=0
--with-libevent-dir=${SRC}/deps \
--with-openssl-dir=${SRC}/deps \
--with-zlib-dir=${SRC}/deps \
- --disable-gcc-hardening
+ --disable-gcc-hardening \
+ LDFLAGS="-L${TOR_DEPS}/lib64"
make clean
+make micro-revision.i # Workaround from https://gitlab.torproject.org/tpo/core/tor/-/issues/29520#note_2749427
make -j$(nproc) oss-fuzz-fuzzers
TORLIBS="`make show-testing-libs`"
-TORLIBS="$TORLIBS -lm -Wl,-Bstatic -lssl -lcrypto -levent -lz -L${TOR_DEPS}/lib"
+TORLIBS="$TORLIBS -lm -Wl,-Bstatic -lssl -lcrypto -levent -lz -L${TOR_DEPS}/lib -L${TOR_DEPS}/lib64"
TORLIBS="$TORLIBS -Wl,-Bdynamic"
for fuzzer in src/test/fuzz/*.a; do
diff --git a/projects/tpm2-tss/Dockerfile b/projects/tpm2-tss/Dockerfile
index 9f74c7a14..f2dbae6f2 100644
--- a/projects/tpm2-tss/Dockerfile
+++ b/projects/tpm2-tss/Dockerfile
@@ -68,10 +68,10 @@ RUN wget --quiet --show-progress --progress=dot:giga "http://mirror.kumi.systems
&& make -j $(nproc) && make install
RUN rm -fr $autoconf_archive.tar.xz
-ARG ibmtpm_name=ibmtpm1119
+ARG ibmtpm_name=ibmtpm1661
WORKDIR /tmp
RUN wget --quiet --show-progress --progress=dot:giga "https://downloads.sourceforge.net/project/ibmswtpm2/$ibmtpm_name.tar.gz" \
- && sha256sum $ibmtpm_name.tar.gz | grep ^b9eef79904e276aeaed2a6b9e4021442ef4d7dfae4adde2473bef1a6a4cd10fb \
+ && sha256sum $ibmtpm_name.tar.gz | grep ^55145928ad2b24f34be6a0eacf9fb492e10e0ea919b8428c721fa970e85d6147 \
&& mkdir -p $ibmtpm_name \
&& tar xvf $ibmtpm_name.tar.gz -C $ibmtpm_name \
&& rm $ibmtpm_name.tar.gz
diff --git a/projects/tpm2-tss/project.yaml b/projects/tpm2-tss/project.yaml
index 04af6fe9d..7ac01a967 100644
--- a/projects/tpm2-tss/project.yaml
+++ b/projects/tpm2-tss/project.yaml
@@ -1,12 +1,12 @@
homepage: "https://github.com/tpm2-software/tpm2-tss"
language: c++
-primary_contact: "tadeusz.struk@intel.com"
+primary_contact: "william.c.roberts@intel.com"
auto_ccs:
- "andreas.fuchs@sit.fraunhofer.de"
- - "john.s.andersen@intel.com"
- - "william.c.roberts@intel.com"
- "tstruk@gmail.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
+main_repo: 'https://github.com/tstruk/tpm2-tss.git' \ No newline at end of file
diff --git a/projects/tpm2/Dockerfile b/projects/tpm2/Dockerfile
index 3cd80b8ed..f008ce398 100644
--- a/projects/tpm2/Dockerfile
+++ b/projects/tpm2/Dockerfile
@@ -5,7 +5,7 @@
# Defines a docker image that can build fuzzers.
#
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make libssl-dev binutils libgcc-5-dev
+RUN apt-get update && apt-get install -y make libssl-dev binutils libgcc-9-dev
RUN git clone --depth 1 https://chromium.googlesource.com/chromiumos/third_party/tpm2
WORKDIR tpm2
RUN cp /src/tpm2/fuzz/build.sh /src/
diff --git a/projects/ujson/Dockerfile b/projects/ujson/Dockerfile
index 81550c687..9b43468da 100644
--- a/projects/ujson/Dockerfile
+++ b/projects/ujson/Dockerfile
@@ -14,13 +14,13 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN pip3 install hypothesis
RUN git clone \
--depth 1 \
- --branch master \
+ --branch main \
https://github.com/ultrajson/ultrajson.git
WORKDIR ultrajson
diff --git a/projects/ujson/build.sh b/projects/ujson/build.sh
index fd339d57e..094d851a2 100755
--- a/projects/ujson/build.sh
+++ b/projects/ujson/build.sh
@@ -31,5 +31,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/ujson/hypothesis_structured_fuzzer.py b/projects/ujson/hypothesis_structured_fuzzer.py
index c07a2cf5f..ef43c263d 100644
--- a/projects/ujson/hypothesis_structured_fuzzer.py
+++ b/projects/ujson/hypothesis_structured_fuzzer.py
@@ -58,6 +58,7 @@ UJSON_ENCODE_KWARGS = {
@given(obj=JSON_OBJECTS, kwargs=st.fixed_dictionaries(UJSON_ENCODE_KWARGS))
+@atheris.instrument_func
def test_ujson_roundtrip(obj, kwargs):
"""Check that all JSON objects round-trip regardless of other options."""
assert obj == ujson.decode(ujson.encode(obj, **kwargs))
@@ -68,5 +69,5 @@ if __name__ == "__main__":
# and minimize any failures discovered by earlier runs or by OSS-Fuzz, or
# briefly search for new failures if none are known.
# Or, when running via OSS-Fuzz, we'll execute it via the fuzzing hook:
- atheris.Setup(sys.argv, test_ujson_roundtrip.hypothesis.fuzz_one_input)
+ atheris.Setup(sys.argv, atheris.instrument_func(test_ujson_roundtrip.hypothesis.fuzz_one_input))
atheris.Fuzz()
diff --git a/projects/ujson/json_differential_fuzzer.py b/projects/ujson/json_differential_fuzzer.py
index fd26de18f..4ab012c54 100755
--- a/projects/ujson/json_differential_fuzzer.py
+++ b/projects/ujson/json_differential_fuzzer.py
@@ -37,12 +37,15 @@ values that are too big or too small is techincally fine; however,
misinterpreting them is not.
"""
-import atheris_no_libfuzzer as atheris
-import json
-import ujson
+import atheris
import sys
+with atheris.instrument_imports():
+ import json
+ import ujson
+
+@atheris.instrument_func
def ClearAllIntegers(data):
"""Used to prevent known bug; sets all integers in data recursively to 0."""
if type(data) == int:
@@ -56,6 +59,7 @@ def ClearAllIntegers(data):
return data
+@atheris.instrument_func
def TestOneInput(input_bytes):
fdp = atheris.FuzzedDataProvider(input_bytes)
original = fdp.ConsumeUnicode(sys.maxsize)
diff --git a/projects/ujson/ujson_fuzzer.py b/projects/ujson/ujson_fuzzer.py
index c785ec6ce..51b33a9ff 100755
--- a/projects/ujson/ujson_fuzzer.py
+++ b/projects/ujson/ujson_fuzzer.py
@@ -29,7 +29,7 @@ coverage.
"""
import sys
-import atheris_no_libfuzzer as atheris
+import atheris
import ujson
diff --git a/projects/unicode-rs/Dockerfile b/projects/unicode-rs/Dockerfile
new file mode 100644
index 000000000..9d9cc4767
--- /dev/null
+++ b/projects/unicode-rs/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/unicode-rs/unicode-normalization
+RUN git clone --depth 1 https://github.com/unicode-rs/unicode-segmentation
+
+WORKDIR $SRC
+
+COPY build.sh $SRC/
diff --git a/projects/unicode-rs/build.sh b/projects/unicode-rs/build.sh
new file mode 100755
index 000000000..9db130ebe
--- /dev/null
+++ b/projects/unicode-rs/build.sh
@@ -0,0 +1,29 @@
+#!/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.
+#
+################################################################################
+
+if [ $SANITIZER != "coverage" ]
+then
+ cd $SRC/unicode-normalization
+ cargo fuzz build -O
+ cp fuzz/target/x86_64-unknown-linux-gnu/release/unicode-normalization $OUT/unicode-normalization-normalization
+ cp fuzz/target/x86_64-unknown-linux-gnu/release/streaming $OUT/unicode-normalization-streaming
+fi
+
+cd $SRC/unicode-segmentation/
+cargo fuzz build -O
+cp ./fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 $OUT/unicode-segmentation-fuzzer
+
diff --git a/projects/unicode-rs/project.yaml b/projects/unicode-rs/project.yaml
new file mode 100644
index 000000000..914c14551
--- /dev/null
+++ b/projects/unicode-rs/project.yaml
@@ -0,0 +1,10 @@
+homepage: "http://unicode-rs.github.io/"
+main_repo: "https://github.com/unicode-rs"
+primary_contact: "manishsmail@gmail.com"
+sanitizers:
+ - address
+fuzzing_engines:
+ - libfuzzer
+language: rust
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/unrar/project.yaml b/projects/unrar/project.yaml
index 242c91f1e..2fa4c872b 100644
--- a/projects/unrar/project.yaml
+++ b/projects/unrar/project.yaml
@@ -5,6 +5,7 @@ auto_ccs:
- "vakh@chromium.org"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/aawc/unrar.git'
+main_repo: 'https://github.com/aawc/unrar.git' \ No newline at end of file
diff --git a/projects/upb/Dockerfile b/projects/upb/Dockerfile
index 7e157a15f..c97eaf05d 100644
--- a/projects/upb/Dockerfile
+++ b/projects/upb/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y cmake
+RUN apt-get update && apt-get install python -y
RUN git clone --depth 1 https://github.com/protocolbuffers/upb.git upb
-WORKDIR $SRC
+WORKDIR upb
COPY build.sh $SRC/
diff --git a/projects/upb/build.sh b/projects/upb/build.sh
index 3f5bebf75..f93779561 100755
--- a/projects/upb/build.sh
+++ b/projects/upb/build.sh
@@ -15,16 +15,4 @@
#
################################################################################
-# build project
-cd upb/cmake
-cmake .
-make -j$(nproc)
-
-# use bazel to build instead ?
-$CC $CFLAGS -I. -I.. -o descriptor.upb.o -c google/protobuf/descriptor.upb.c
-$CXX $CXXFLAGS -DHAVE_FUZZER=1 -std=c++11 -I. -I.. -o fuzz_parsenew.o -c ../tests/file_descriptor_parsenew_fuzzer.cc
-$CXX $CXXFLAGS fuzz_parsenew.o descriptor.upb.o -o $OUT/fuzz_parsenew *.a $LIB_FUZZING_ENGINE
-
-# builds corpus
-cd ..
-find . -name "*.proto" | xargs zip -r $OUT/fuzz_parsenew_seed_corpus.zip
+bazel_build_fuzz_tests
diff --git a/projects/upb/project.yaml b/projects/upb/project.yaml
index b67152df3..eb3c62e78 100644
--- a/projects/upb/project.yaml
+++ b/projects/upb/project.yaml
@@ -1,8 +1,6 @@
homepage: "https://github.com/protocolbuffers/upb"
language: c++
primary_contact: "haberman@google.com"
-auto_ccs :
-- "p.antoine@catenacyber.fr"
sanitizers:
- address
diff --git a/projects/uriparser/project.yaml b/projects/uriparser/project.yaml
index 9ca257378..ec64c6468 100644
--- a/projects/uriparser/project.yaml
+++ b/projects/uriparser/project.yaml
@@ -3,9 +3,10 @@ language: c++
primary_contact: "webmaster@hartwork.org"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
architectures:
- x86_64
- i386
-main_repo: 'https://github.com/uriparser/uriparser'
+main_repo: 'https://github.com/uriparser/uriparser' \ No newline at end of file
diff --git a/projects/urllib3/Dockerfile b/projects/urllib3/Dockerfile
index 799b8b957..a6cf8d6a5 100644
--- a/projects/urllib3/Dockerfile
+++ b/projects/urllib3/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-python
RUN git clone --depth 1 https://github.com/urllib3/urllib3
COPY build.sh $SRC/
diff --git a/projects/urllib3/build.sh b/projects/urllib3/build.sh
index 66f6419ac..6eaf4d518 100644
--- a/projects/urllib3/build.sh
+++ b/projects/urllib3/build.sh
@@ -30,5 +30,5 @@ 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 u+x $OUT/$fuzzer_basename
+ chmod +x $OUT/$fuzzer_basename
done
diff --git a/projects/urllib3/fuzz_urlparse.py b/projects/urllib3/fuzz_urlparse.py
index f2fcd9bbd..81c016453 100644
--- a/projects/urllib3/fuzz_urlparse.py
+++ b/projects/urllib3/fuzz_urlparse.py
@@ -33,5 +33,6 @@ def main():
atheris.Fuzz()
if __name__ == "__main__":
+ atheris.instrument_all()
main()
diff --git a/projects/usbguard/build.sh b/projects/usbguard/build.sh
index 5c7daf68e..1504da82f 100644
--- a/projects/usbguard/build.sh
+++ b/projects/usbguard/build.sh
@@ -81,3 +81,10 @@ if [[ ! -d "$SRC/usbguard/src/Tests/Fuzzers/$corpus_dir" ]] ; then
cp -R "$SRC/usbguard/src/Tests/USB/data" "${corpus_dir}"
zip -r "${zip_name}" "${corpus_dir}"
fi
+
+# Ubuntu 20.04 doesn't have a static libqb.
+mkdir -p $OUT/lib
+cp /lib/x86_64-linux-gnu/libqb* $OUT/lib
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-uevent
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-usb-descriptor
+patchelf --set-rpath '$ORIGIN/lib' $OUT/fuzzer-rules
diff --git a/projects/usbguard/project.yaml b/projects/usbguard/project.yaml
index a372cd3a6..a220a6532 100644
--- a/projects/usbguard/project.yaml
+++ b/projects/usbguard/project.yaml
@@ -4,7 +4,8 @@ primary_contact: "rsroka@redhat.com"
sanitizers:
- address
- undefined
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
auto_ccs:
- "alakatos@redhat.com"
- "allenwebb@google.com"
diff --git a/projects/usrsctp/project.yaml b/projects/usrsctp/project.yaml
index 54fb49449..b2c310cf0 100644
--- a/projects/usrsctp/project.yaml
+++ b/projects/usrsctp/project.yaml
@@ -5,12 +5,12 @@ auto_ccs:
- "t00fcxen@googlemail.com"
- "markwo@google.com"
- "natashenka@google.com"
- - "yuquanw@google.com"
+ - "orphis@google.com"
+ - "mbonadei@google.com"
fuzzing_engines:
- libfuzzer
- afl
- honggfuzz
- - dataflow
sanitizers:
- address
- undefined
diff --git a/projects/uwebsockets/project.yaml b/projects/uwebsockets/project.yaml
index e46ea9a2a..47536fa4e 100644
--- a/projects/uwebsockets/project.yaml
+++ b/projects/uwebsockets/project.yaml
@@ -4,6 +4,7 @@ primary_contact: "alexhultman@gmail.com"
builds_per_day: 4
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/uNetworking/uWebSockets.git'
+main_repo: 'https://github.com/uNetworking/uWebSockets.git' \ No newline at end of file
diff --git a/projects/varnish/Dockerfile b/projects/varnish/Dockerfile
new file mode 100644
index 000000000..5fd0fb49c
--- /dev/null
+++ b/projects/varnish/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 automake autoconf libtool pkg-config python3-docutils python3-sphinx libedit-dev libpcre2-dev libncurses-dev
+RUN git clone --depth 1 https://github.com/varnishcache/varnish-cache
+COPY build.sh $SRC
+WORKDIR $SRC/varnish-cache
diff --git a/projects/varnish/build.sh b/projects/varnish/build.sh
new file mode 100755
index 000000000..3a7f24836
--- /dev/null
+++ b/projects/varnish/build.sh
@@ -0,0 +1,27 @@
+#!/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
+./autogen.sh
+./configure --enable-oss-fuzz PCRE2_LIBS=-l:libpcre2-8.a
+make -j2 -C include/
+make -j2 -C lib/libvarnish/
+make -j2 -C lib/libvgz/
+make -j2 -C lib/libvsc/
+make -j2 -C bin/varnishd/ esi_parse_fuzzer
+cp bin/varnishd/*_fuzzer $OUT/
diff --git a/projects/varnish/project.yaml b/projects/varnish/project.yaml
index 836179045..d25135569 100644
--- a/projects/varnish/project.yaml
+++ b/projects/varnish/project.yaml
@@ -1,7 +1,8 @@
homepage: "https://varnish-cache.org/"
-primary_contact: "federico.schwindt@gmail.com"
+language: c
+primary_contact: "phk@varnish.org"
auto_ccs:
- - "phk@varnish.org"
-sanitizers:
- - address
- - undefined
+ - "bsdphk@gmail.com"
+ - "nils.goroll@uplex.de"
+ - "martin@varnish-software.com"
+main_repo: 'https://github.com/varnishcache/varnish-cache'
diff --git a/projects/vitess/Dockerfile b/projects/vitess/Dockerfile
index 8f066c8ba..9eda3560d 100644
--- a/projects/vitess/Dockerfile
+++ b/projects/vitess/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/vitessio/vitess
COPY build.sh $SRC/
WORKDIR $SRC/vitess
diff --git a/projects/vlc/Dockerfile b/projects/vlc/Dockerfile
new file mode 100644
index 000000000..6d24f0254
--- /dev/null
+++ b/projects/vlc/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 flex bison gettext libglu1-mesa-dev
+RUN git clone --depth 1 https://github.com/videolan/vlc vlc
+WORKDIR vlc
+COPY build.sh $SRC/
diff --git a/projects/vlc/build.sh b/projects/vlc/build.sh
new file mode 100755
index 000000000..8eb7053a1
--- /dev/null
+++ b/projects/vlc/build.sh
@@ -0,0 +1,53 @@
+#!/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.
+#
+################################################################################
+
+# Use OSS-Fuzz environment rather than hardcoded setup.
+sed -i 's/-fsanitize-coverage=trace-pc-guard//g' ./configure.ac
+sed -i 's/-fsanitize-coverage=trace-cmp//g' ./configure.ac
+sed -i 's/-fsanitize-coverage=trace-pc//g' ./configure.ac
+sed -i 's/-lFuzzer//g' ./configure.ac
+
+# In order to build statically we avoid libxml and ogg plugins.
+sed -i 's/..\/..\/lib\/libvlc_internal.h/lib\/libvlc_internal.h/g' ./test/src/input/decoder.c
+sed -i 's/..\/modules\/libxml_plugin.la//g' ./test/Makefile.am
+sed -i 's/..\/modules\/libogg_plugin.la//g' ./test/Makefile.am
+sed -i 's/f(misc_xml_xml)//g' ./test/src/input/demux-run.c
+sed -i 's/f(demux_ogg)//g' ./test/src/input/demux-run.c
+
+# Ensure that we compile with the correct link flags.
+RULE="vlc_demux_libfuzzer_LDADD"
+FUZZ_LDFLAGS="vlc_demux_libfuzzer_LDFLAGS=\${LIB_FUZZING_ENGINE}"
+sed -i "s/${RULE}/${FUZZ_LDFLAGS}\n${RULE}/g" ./test/Makefile.am
+
+RULE="vlc_demux_dec_libfuzzer_LDADD"
+FUZZ_LDFLAGS="vlc_demux_dec_libfuzzer_LDFLAGS=\${LIB_FUZZING_ENGINE}"
+sed -i "s/${RULE}/${FUZZ_LDFLAGS}\n${RULE}/g" ./test/Makefile.am
+
+./bootstrap
+./configure --disable-ogg --disable-oggspots --disable-libxml2 --disable-lua \
+ --disable-shared \
+ --enable-static \
+ --enable-vlc=no \
+ --disable-avcodec \
+ --disable-swscale \
+ --disable-a52 \
+ --disable-xcb \
+ --disable-alsa \
+ --with-libfuzzer
+make V=1 -j$(nproc)
+cp ./test/vlc-demux-dec-libfuzzer $OUT/
+cp ./test/vlc-demux-libfuzzer $OUT/
diff --git a/projects/vlc/project.yaml b/projects/vlc/project.yaml
new file mode 100644
index 000000000..1006c84e7
--- /dev/null
+++ b/projects/vlc/project.yaml
@@ -0,0 +1,10 @@
+homepage: "https://github.com/videolan/vlc"
+language: c
+primary_contact: "ossfuzz@videolan.org"
+auto_ccs:
+ - "adam@adalogics.com"
+ - "david@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+main_repo: 'https://github.com/videolan/vlc'
diff --git a/projects/wasm3/Dockerfile b/projects/wasm3/Dockerfile
new file mode 100644
index 000000000..1d123adb2
--- /dev/null
+++ b/projects/wasm3/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/wasm3/wasm3
+WORKDIR wasm3
+COPY build.sh $SRC/
diff --git a/projects/wasm3/build.sh b/projects/wasm3/build.sh
new file mode 100755
index 000000000..1ef87c03a
--- /dev/null
+++ b/projects/wasm3/build.sh
@@ -0,0 +1,21 @@
+#!/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_WASI=none ..
+make -j$(nproc)
+$CC $CFLAGS -c $SRC/wasm3/platforms/app_fuzz/fuzzer.c -o fuzzer.o -I/src/wasm3/source
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE -o $OUT/fuzzer fuzzer.o /src/wasm3/build/source/libm3.a
diff --git a/projects/wasm3/project.yaml b/projects/wasm3/project.yaml
new file mode 100644
index 000000000..41c18cae7
--- /dev/null
+++ b/projects/wasm3/project.yaml
@@ -0,0 +1,14 @@
+homepage: "https://github.com/wasm3/wasm3"
+main_repo: "https://github.com/wasm3/wasm3"
+language: c
+primary_contact: "vshymanskyi@gmail.com"
+auto_ccs:
+ - "Adam@adalogics.com"
+sanitizers:
+ - address
+ - undefined
+ - memory
+fuzzing_engines:
+ - libfuzzer
+ - afl
+ - honggfuzz
diff --git a/projects/wasmtime/Dockerfile b/projects/wasmtime/Dockerfile
index e310b360a..fe6c8dd3e 100644
--- a/projects/wasmtime/Dockerfile
+++ b/projects/wasmtime/Dockerfile
@@ -14,9 +14,15 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+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
+# Install a newer version of OCaml than provided by Ubuntu 16.04 (base version for this image)
+RUN curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh -o install.sh && \
+ echo | sh install.sh && \
+ opam init --disable-sandboxing --yes && \
+ opam install ocamlbuild --yes
+
RUN git clone --depth 1 https://github.com/bytecodealliance/wasm-tools wasm-tools
RUN git clone --depth 1 https://github.com/bytecodealliance/regalloc.rs regalloc.rs
diff --git a/projects/wasmtime/build.sh b/projects/wasmtime/build.sh
index 80423e376..b22a11be4 100755
--- a/projects/wasmtime/build.sh
+++ b/projects/wasmtime/build.sh
@@ -56,6 +56,9 @@ build() {
done
}
+# Ensure OCaml environment is set up prior to Wasmtime build.
+eval $(opam env)
+
# Build with peepmatic in order to enable the related fuzz targets.
build wasmtime "" "" --features "peepmatic-fuzzing experimental_x64"
diff --git a/projects/wavpack/Dockerfile b/projects/wavpack/Dockerfile
index 2cee9fd97..8c5a96a64 100644
--- a/projects/wavpack/Dockerfile
+++ b/projects/wavpack/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
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 make autoconf automake libtool gettext
RUN git clone --depth 1 https://github.com/dbry/WavPack.git wavpack
RUN cp wavpack/fuzzing/build.sh $SRC
WORKDIR wavpack
diff --git a/projects/wazuh/Dockerfile b/projects/wazuh/Dockerfile
new file mode 100755
index 000000000..cf231652e
--- /dev/null
+++ b/projects/wazuh/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 libpcre2-dev libssl-dev libsystemd-dev autoconf libtool
+RUN git clone https://github.com/wazuh/wazuh
+
+WORKDIR $SRC/wazuh
+COPY build.sh $SRC/
+COPY fuzz_xml.c $SRC/fuzz_xml.c
diff --git a/projects/wazuh/build.sh b/projects/wazuh/build.sh
new file mode 100755
index 000000000..984da47f6
--- /dev/null
+++ b/projects/wazuh/build.sh
@@ -0,0 +1,25 @@
+#!/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
+export LDFLAGS="$CFLAGS"
+
+make deps
+make TARGET=local
+$CC $CFLAGS $LIB_FUZZING_ENGINE $SRC/fuzz_xml.c -o $OUT/fuzz_xml -I./ -I./os_xml \
+ ./libwazuh.a ./external/sqlite/libsqlite3.a ./external/cJSON/libcjson.a \
+ ./external/zlib/libz.a ./external/bzip2/libbz2.a
diff --git a/projects/wazuh/fuzz_xml.c b/projects/wazuh/fuzz_xml.c
new file mode 100644
index 000000000..c889bccd1
--- /dev/null
+++ b/projects/wazuh/fuzz_xml.c
@@ -0,0 +1,72 @@
+/* Copyright 2021 Google LLC
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT 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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "./os_xml/os_xml.h"
+#include "./os_xml/os_xml_internal.h"
+
+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);
+
+ OS_XML xml;
+ if (OS_ReadXML(filename, &xml) < 0) {
+ unlink(filename);
+ return 0;
+ }
+ XML_NODE node = NULL;
+ node = OS_GetElementsbyNode(&xml, NULL);
+ if (node == NULL) {
+ OS_ClearXML(&xml);
+ return 0;
+ }
+ int i = 0;
+
+ while (node[i]) {
+ int j = 0;
+ XML_NODE cnode;
+ cnode = OS_GetElementsbyNode(&xml, node[i]);
+ if (cnode == NULL) {
+ i++;
+ continue;
+ }
+
+ while (cnode[j]) {
+ if (cnode[j]->attributes && cnode[j]->values) {
+ int k = 0;
+ while (cnode[j]->attributes[k]) {
+ k++;
+ }
+ }
+ j++;
+ }
+
+ OS_ClearNode(cnode);
+ i++;
+ }
+
+ OS_ClearNode(node);
+ OS_ClearXML(&xml);
+ unlink(filename);
+ return 0;
+}
+
diff --git a/projects/wazuh/fuzz_xml.options b/projects/wazuh/fuzz_xml.options
new file mode 100644
index 000000000..f9d09656c
--- /dev/null
+++ b/projects/wazuh/fuzz_xml.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+detect_leaks=0
diff --git a/projects/wazuh/project.yaml b/projects/wazuh/project.yaml
new file mode 100755
index 000000000..04d791d2a
--- /dev/null
+++ b/projects/wazuh/project.yaml
@@ -0,0 +1,6 @@
+homepage: "https://wazuh.com/"
+main_repo: 'https://github.com/wazuh/wazuh'
+primary_contact: "devel@wazuh.com"
+language: c
+auto_ccs:
+ - "david@adalogics.com"
diff --git a/projects/wget/Dockerfile b/projects/wget/Dockerfile
index ec20c7ca9..2382da6ec 100644
--- a/projects/wget/Dockerfile
+++ b/projects/wget/Dockerfile
@@ -22,6 +22,7 @@ RUN apt-get update && apt-get install -y \
autogen \
autopoint \
autoconf \
+ autoconf-archive \
automake \
libtool \
texinfo \
diff --git a/projects/wget/build.sh b/projects/wget/build.sh
index 840977d73..b52580137 100755
--- a/projects/wget/build.sh
+++ b/projects/wget/build.sh
@@ -16,7 +16,7 @@
################################################################################
export WGET_DEPS_PATH=$SRC/wget_deps
-export PKG_CONFIG_PATH=$WGET_DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$WGET_DEPS_PATH/lib64/pkgconfig:$WGET_DEPS_PATH/lib/pkgconfig
export CPPFLAGS="-I$WGET_DEPS_PATH/include"
export LDFLAGS="-L$WGET_DEPS_PATH/lib"
export GNULIB_SRCDIR=$SRC/gnulib
@@ -76,19 +76,31 @@ make install
# avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
export ASAN_OPTIONS=detect_leaks=0
+# Ensure our libraries can be found
+ln -s $WGET_DEPS_PATH/lib64/libhogweed.a $WGET_DEPS_PATH/lib/libhogweed.a
+ln -s $WGET_DEPS_PATH/lib64/libnettle.a $WGET_DEPS_PATH/lib/libnettle.a
+
cd $SRC/wget
./bootstrap
+autoreconf -fi
+
+export CFLAGS="$CFLAGS -I$WGET_DEPS_PATH/include"
+export CXXFLAGS="$CXXFLAGS -I$WGET_DEPS_PATH/include"
# build and run non-networking tests
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
- ./configure -C
+GNUTLS_CFLAGS="-lgnutls" \
+GNUTLS_LIBS="-lgnutls" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
+./configure -C
make clean
make -j$(nproc)
make -j$(nproc) -C fuzz check
# build for fuzzing
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
- ./configure --enable-fuzzing -C
+GNUTLS_CFLAGS="-lgnutls" \
+GNUTLS_LIBS="-lgnutls" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
+./configure --enable-fuzzing -C
make clean
make -j$(nproc) -C lib
make -j$(nproc) -C src
diff --git a/projects/wget2/Dockerfile b/projects/wget2/Dockerfile
index bc2451ea5..8513d586d 100644
--- a/projects/wget2/Dockerfile
+++ b/projects/wget2/Dockerfile
@@ -34,7 +34,8 @@ RUN apt-get update && apt-get install -y \
wget \
python \
lzip \
- rsync
+ rsync \
+ libmicrohttpd-dev
ENV GNULIB_TOOL $SRC/gnulib/gnulib-tool
RUN git clone git://git.savannah.gnu.org/gnulib.git
diff --git a/projects/wget2/build.sh b/projects/wget2/build.sh
index 3ad4e04bd..866a4259f 100755
--- a/projects/wget2/build.sh
+++ b/projects/wget2/build.sh
@@ -16,7 +16,7 @@
################################################################################
export WGET2_DEPS_PATH=$SRC/wget2_deps
-export PKG_CONFIG_PATH=$WGET2_DEPS_PATH/lib/pkgconfig
+export PKG_CONFIG_PATH=$WGET2_DEPS_PATH/lib64/pkgconfig:$WGET2_DEPS_PATH/lib/pkgconfig
export CPPFLAGS="-I$WGET2_DEPS_PATH/include"
export LDFLAGS="-L$WGET2_DEPS_PATH/lib"
export GNULIB_SRCDIR=$SRC/gnulib
@@ -72,29 +72,20 @@ CFLAGS="$GNUTLS_CFLAGS" \
make -j$(nproc)
make install
-cd $SRC/libmicrohttpd-*
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
-./configure --prefix=$WGET2_DEPS_PATH --disable-doc --disable-examples --disable-shared --enable-static
-make -j$(nproc)
-make install
-
-
# avoid iconv() memleak on Ubuntu 16.04 image (breaks test suite)
export ASAN_OPTIONS=detect_leaks=0
cd $SRC/wget2
./bootstrap
-# build and run non-networking tests
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
./configure -C --enable-static --disable-shared --disable-doc --without-plugin-support
make clean
make -j$(nproc)
make -j$(nproc) -C unit-tests check
make -j$(nproc) -C fuzz check
-# build for fuzzing
-LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring" \
+LIBS="-lgnutls -lhogweed -lnettle -lidn2 -lunistring -lpsl" \
./configure -C --enable-fuzzing --enable-static --disable-shared --disable-doc --without-plugin-support
make clean
make -j$(nproc) -C lib
@@ -102,8 +93,13 @@ make -j$(nproc) -C include
make -j$(nproc) -C libwget
make -j$(nproc) -C src
+# Ensure our libraries can be found
+ln -s $WGET2_DEPS_PATH/lib64/libhogweed.a $WGET2_DEPS_PATH/lib/libhogweed.a
+ln -s $WGET2_DEPS_PATH/lib64/libnettle.a $WGET2_DEPS_PATH/lib/libnettle.a
+
# build fuzzers
cd fuzz
+
CXXFLAGS="$CXXFLAGS -L$WGET2_DEPS_PATH/lib/" make oss-fuzz
find . -name '*_fuzzer' -exec cp -v '{}' $OUT ';'
diff --git a/projects/wolfssl/Dockerfile b/projects/wolfssl/Dockerfile
index 963f5e0e3..83cbdf460 100644
--- a/projects/wolfssl/Dockerfile
+++ b/projects/wolfssl/Dockerfile
@@ -24,9 +24,29 @@ RUN git clone --depth 1 https://github.com/guidovranken/wolf-ssl-ssh-fuzzers
RUN git clone --depth 1 https://github.com/guidovranken/cryptofuzz
RUN git clone --depth 1 https://github.com/randombit/botan.git
RUN git clone --depth 1 https://github.com/google/wycheproof.git
-RUN wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.bz2
+RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.74.0/source/boost_1_74_0.tar.bz2
RUN git clone https://github.com/wolfssl/oss-fuzz-targets --depth 1 $SRC/fuzz-targets
+# Retrieve corpora from other projects
+RUN wget https://storage.googleapis.com/pub/gsutil.tar.gz -O $SRC/gsutil.tar.gz
+RUN tar zxf $SRC/gsutil.tar.gz
+ENV PATH="${PATH}:$SRC/gsutil"
+RUN gsutil cp gs://bearssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/bearssl_cryptofuzz-bearssl/public.zip $SRC/corpus_bearssl.zip
+RUN gsutil cp gs://nettle-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/nettle_cryptofuzz-nettle-with-mini-gmp/public.zip $SRC/corpus_nettle.zip
+RUN gsutil cp gs://libecc-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/libecc_cryptofuzz-libecc/public.zip $SRC/corpus_libecc.zip
+RUN gsutil cp gs://relic-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/relic_cryptofuzz-relic/public.zip $SRC/corpus_relic.zip
+RUN gsutil cp gs://cryptofuzz-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/cryptofuzz_cryptofuzz-openssl/public.zip $SRC/corpus_cryptofuzz.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math-all/public.zip $SRC/corpus_wolfssl_sp-math-all.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math-all-8bit/public.zip $SRC/corpus_wolfssl_sp-math-all-8bit.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-sp-math/public.zip $SRC/corpus_wolfssl_sp-math.zip
+RUN gsutil cp gs://wolfssl-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/wolfssl_cryptofuzz-disable-fastmath/public.zip $SRC/corpus_wolfssl_disable-fastmath.zip
+
+# Botan corpora, which require a special import procedure
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p256/public.zip $SRC/corpus_botan_ecc_p256.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p384/public.zip $SRC/corpus_botan_ecc_p384.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_p521/public.zip $SRC/corpus_botan_ecc_p521.zip
+RUN gsutil cp gs://botan-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/botan_ecc_bp256/public.zip $SRC/corpus_botan_ecc_bp256.zip
+
WORKDIR wolfssl
COPY build.sh $SRC/
diff --git a/projects/wolfssl/build.sh b/projects/wolfssl/build.sh
index 70db45387..2e6e5c673 100755
--- a/projects/wolfssl/build.sh
+++ b/projects/wolfssl/build.sh
@@ -17,7 +17,7 @@
if [[ $CFLAGS != *sanitize=dataflow* ]]
then
- 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-rabbit --enable-aesccm --enable-aesctr --enable-hc128 --enable-xts --enable-des3 --enable-idea --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --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"
+ 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-rabbit --enable-aesccm --enable-aesctr --enable-hc128 --enable-xts --enable-des3 --enable-idea --enable-x963kdf --enable-harden --enable-aescfb --enable-aesofb --enable-aeskeywrap --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-aesgcm-stream --enable-smallstack --enable-ed25519-stream --enable-ed448-stream"
if [[ $CFLAGS = *sanitize=memory* ]]
then
WOLFCRYPT_CONFIGURE_PARAMS="$WOLFCRYPT_CONFIGURE_PARAMS --disable-asm"
@@ -31,10 +31,14 @@ then
CFLAGS="" CXXFLAGS="" ./b2 headers
cp -R boost/ /usr/include/
+ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
+
OLD_CFLAGS="$CFLAGS"
OLD_CXXFLAGS="$CXXFLAGS"
# Configure Cryptofuzz
+ cd $SRC/cryptofuzz
+ sed -i 's/kNegativeIntegers = false/kNegativeIntegers = true/g' config.h
cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-openssl-api/
cd $SRC/cryptofuzz-openssl-api/
python gen_repository.py
@@ -75,11 +79,23 @@ then
echo -n '"' >>extra_options.h
echo -n '--force-module=wolfCrypt ' >>extra_options.h
echo -n '--digests=NULL ' >>extra_options.h
- echo -n '--operations=BignumCalc,DH_GenerateKeyPair,DH_Derive,ECC_GenerateKeyPair,ECC_PrivateToPublic,ECC_ValidatePubkey,ECDSA_Verify,ECDSA_Sign' >>extra_options.h
+ echo -n '--operations=' >>extra_options.h
+ echo -n 'BignumCalc,' >>extra_options.h
+ echo -n 'DH_GenerateKeyPair,' >>extra_options.h
+ echo -n 'DH_Derive,' >>extra_options.h
+ echo -n 'ECC_GenerateKeyPair,' >>extra_options.h
+ echo -n 'ECC_PrivateToPublic,' >>extra_options.h
+ echo -n 'ECC_ValidatePubkey,' >>extra_options.h
+ echo -n 'ECDSA_Verify,' >>extra_options.h
+ echo -n 'ECDSA_Sign,' >>extra_options.h
+ echo -n 'ECIES_Encrypt,' >>extra_options.h
+ echo -n 'ECIES_Decrypt,' >>extra_options.h
+ echo -n 'ECC_Point_Add,' >>extra_options.h
+ echo -n 'ECC_Point_Mul,' >>extra_options.h
+ echo -n 'ECDH_Derive ' >>extra_options.h
echo -n '"' >>extra_options.h
# Build Botan
- export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_BOTAN_IS_ORACLE"
cd $SRC/botan
if [[ $CFLAGS != *-m32* ]]
then
@@ -91,12 +107,44 @@ then
export LIBBOTAN_A_PATH="$SRC/botan/libbotan-3.a"
export BOTAN_INCLUDE_PATH="$SRC/botan/build/include"
+ # Build normal math fuzzer
+ cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-normal-math/
+ cp -R $SRC/wolfssl/ $SRC/wolfssl-normal-math/
+ cd $SRC/wolfssl-normal-math/
+ autoreconf -ivf
+ 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"
+ if [[ $CFLAGS != *-m32* ]]
+ then
+ ./configure $WOLFCRYPT_CONFIGURE_PARAMS
+ else
+ # Compiling instrumented 32 bit normal math with asm is currently
+ # not possible because it results in Clang error messages such as:
+ #
+ # wolfcrypt/src/tfm.c:3154:11: error: inline assembly requires more registers than available
+ ./configure $WOLFCRYPT_CONFIGURE_PARAMS --disable-asm
+ fi
+ make -j$(nproc)
+ export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
+ export WOLFCRYPT_LIBWOLFSSL_A_PATH="$SRC/wolfssl-normal-math/src/.libs/libwolfssl.a"
+ export WOLFCRYPT_INCLUDE_PATH="$SRC/wolfssl-normal-math/"
+ cd $SRC/cryptofuzz-normal-math/modules/wolfcrypt
+ make -j$(nproc)
+ cd $SRC/cryptofuzz-normal-math/modules/botan
+ make -j$(nproc)
+ cd $SRC/cryptofuzz-normal-math/
+ LIBFUZZER_LINK="$LIB_FUZZING_ENGINE" make -B -j$(nproc)
+ cp cryptofuzz $OUT/cryptofuzz-normal-math
+ CFLAGS="$OLD_CFLAGS"
+ CXXFLAGS="$OLD_CXXFLAGS"
+ unset WOLFCRYPT_LIBWOLFSSL_A_PATH
+ unset WOLFCRYPT_INCLUDE_PATH
+
# Build sp-math-all fuzzer
cp -R $SRC/cryptofuzz/ $SRC/cryptofuzz-sp-math-all/
cp -R $SRC/wolfssl/ $SRC/wolfssl-sp-math-all/
cd $SRC/wolfssl-sp-math-all/
autoreconf -ivf
- 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"
+ 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"
./configure $WOLFCRYPT_CONFIGURE_PARAMS --enable-sp-math-all
make -j$(nproc)
export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
@@ -119,7 +167,7 @@ then
cp -R $SRC/wolfssl/ $SRC/wolfssl-sp-math-all-8bit/
cd $SRC/wolfssl-sp-math-all-8bit/
autoreconf -ivf
- 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 -DSP_WORD_SIZE=8"
+ 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 -DSP_WORD_SIZE=8 -DWOLFSSL_SP_INT_NEGATIVE"
./configure $WOLFCRYPT_CONFIGURE_PARAMS --enable-sp-math-all
make -j$(nproc)
export CXXFLAGS="$CXXFLAGS -DCRYPTOFUZZ_NO_OPENSSL -DCRYPTOFUZZ_WOLFCRYPT -DCRYPTOFUZZ_BOTAN"
@@ -143,7 +191,7 @@ then
cd $SRC/wolfssl-sp-math/
autoreconf -ivf
# -DHAVE_ECC_BRAINPOOL and -DHAVE_ECC_KOBLITZ are lacking from the CFLAGS; these are not supported by SP math
- CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP"
+ CFLAGS="$CFLAGS -DHAVE_AES_ECB -DWOLFSSL_DES_ECB -DHAVE_ECC_SECPR2 -DHAVE_ECC_SECPR3 -DWOLFSSL_ECDSA_SET_K -DWOLFSSL_ECDSA_SET_K_ONE_LOOP -DWOLFSSL_PUBLIC_ECC_ADD_DBL"
# SP math does not support custom curves, so remove that flag
export WOLFCRYPT_CONFIGURE_PARAMS_SP_MATH=${WOLFCRYPT_CONFIGURE_PARAMS//"--enable-ecccustcurves"/}
./configure $WOLFCRYPT_CONFIGURE_PARAMS_SP_MATH --enable-sp --enable-sp-math
@@ -186,16 +234,57 @@ then
unset WOLFCRYPT_LIBWOLFSSL_A_PATH
unset WOLFCRYPT_INCLUDE_PATH
+ mkdir $SRC/cryptofuzz-seed-corpus/
+
# Convert Wycheproof test vectors to Cryptofuzz corpus format
- mkdir $SRC/corpus-cryptofuzz-wycheproof/
- find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_*' -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-wycheproof={},$SRC/corpus-cryptofuzz-wycheproof/ \;
+ find $SRC/wycheproof/testvectors/ -type f -name 'ecdsa_*' -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-wycheproof={},$SRC/cryptofuzz-seed-corpus/ \;
+
+ # Unpack corpora from other projects
+ unzip -n $SRC/corpus_bearssl.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_nettle.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_libecc.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_relic.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_cryptofuzz.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_wolfssl_sp-math-all.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_wolfssl_sp-math-all-8bit.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_wolfssl_sp-math.zip -d $SRC/cryptofuzz_seed_corpus/
+ unzip -n $SRC/corpus_wolfssl_disable-fastmath.zip -d $SRC/cryptofuzz_seed_corpus/
+
+ # Import Botan corpora
+ mkdir $SRC/botan-p256-corpus/
+ unzip $SRC/corpus_botan_ecc_p256.zip -d $SRC/botan-p256-corpus/
+ find $SRC/botan-p256-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp256r1 \;
+
+ mkdir $SRC/botan-p384-corpus/
+ unzip $SRC/corpus_botan_ecc_p384.zip -d $SRC/botan-p384-corpus/
+ find $SRC/botan-p384-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp384r1 \;
+
+ mkdir $SRC/botan-p521-corpus/
+ unzip $SRC/corpus_botan_ecc_p521.zip -d $SRC/botan-p521-corpus/
+ find $SRC/botan-p521-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,secp521r1 \;
+
+ mkdir $SRC/botan-bp256-corpus/
+ unzip $SRC/corpus_botan_ecc_bp256.zip -d $SRC/botan-bp256-corpus/
+ find $SRC/botan-bp256-corpus/ -type f -exec $SRC/cryptofuzz-disable-fastmath/cryptofuzz --from-botan={},$SRC/cryptofuzz-seed-corpus/,brainpool256r1 \;
+
# Pack it
- zip -j $SRC/cryptofuzz_wycheproof_seed_corpus.zip $SRC/corpus-cryptofuzz-wycheproof/*
+ cd $SRC/cryptofuzz_seed_corpus
+ zip -r $SRC/cryptofuzz_seed_corpus.zip .
+
# Use it as the seed corpus for each Cryptofuzz-based fuzzer
- cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math-all_seed_corpus.zip
- cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math-all-8bit_seed_corpus.zip
- cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-sp-math_seed_corpus.zip
- cp $SRC/cryptofuzz_wycheproof_seed_corpus.zip $OUT/cryptofuzz-disable-fastmath_seed_corpus.zip
+ cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-normal-math_seed_corpus.zip
+ cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math-all_seed_corpus.zip
+ cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math-all-8bit_seed_corpus.zip
+ cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-sp-math_seed_corpus.zip
+ cp $SRC/cryptofuzz_seed_corpus.zip $OUT/cryptofuzz-disable-fastmath_seed_corpus.zip
+
+ # Remove files that are no longer needed to prevent running out of disk space
+ rm -rf $SRC/botan-p256-corpus/
+ rm -rf $SRC/botan-p384-corpus/
+ rm -rf $SRC/botan-p521-corpus/
+ rm -rf $SRC/botan-bp256-corpus/
+ rm -rf $SRC/cryptofuzz_seed_corpus/
+ rm -rf $SRC/cryptofuzz_seed_corpus.zip
# Build SSL/SSH fuzzers
NEW_SRC=$SRC/wolf-ssl-ssh-fuzzers/oss-fuzz/projects/wolf-ssl-ssh/
diff --git a/projects/wolfssl/project.yaml b/projects/wolfssl/project.yaml
index a6a31a18d..fdd186bb6 100644
--- a/projects/wolfssl/project.yaml
+++ b/projects/wolfssl/project.yaml
@@ -10,10 +10,11 @@ auto_ccs:
- "levi@wolfssl.com"
- "testing@wolfssl.com"
- "dgarske80@gmail.com"
+ - "jeffelms.wolfssl@gmail.com"
+ - "douzzer@mega.nu"
- "guidovranken@gmail.com"
fuzzing_engines:
- libfuzzer
- - afl
- honggfuzz
- dataflow
sanitizers:
diff --git a/projects/wuffs/build.sh b/projects/wuffs/build.sh
index b8d4f5366..17c4fc888 100755
--- a/projects/wuffs/build.sh
+++ b/projects/wuffs/build.sh
@@ -19,14 +19,34 @@
# Wuffs' generated C files are "drop-in libraries" a la
# http://gpfault.net/posts/drop-in-libraries.txt.html
-for f in fuzz/c/std/*_fuzzer.c; do
- # Extract the format name, such as "gzip", from the C file name,
- # "fuzz/c/std/gzip_fuzzer.c".
- b=$(basename $f _fuzzer.c)
+for f in fuzz/c/std/*_fuzzer.c*; do
+ # Extract the format name (such as "gzip", from the C or C++ file name,
+ # "fuzz/c/std/gzip_fuzzer.c") and make the "gzip_fuzzer" binary. First
+ # compile the (C or C++) Wuffs code...
+ extension="${f##*.}"
+ if [ "$extension" = "c" ]; then
+ echo "Building (C) $f"
+ b=$(basename $f _fuzzer.c)
+ $CC $CFLAGS -c $f -o $WORK/${b}_fuzzer.o
+ elif [ "$extension" = "cc" ]; then
+ if [[ $LIB_FUZZING_ENGINE == *"DataFlow"* ]]; then
+ # Linking (below) with "--engine dataflow" works with the C fuzzers but
+ # not the C++ ones. With C++, we get errors like `undefined reference to
+ # `dfs$_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev'`
+ #
+ # This is possibly "DFsan instrumented dependencies"
+ # https://github.com/google/oss-fuzz/issues/3388
+ echo "Skipping (C++) $f"
+ continue
+ fi
+ echo "Building (C++) $f"
+ b=$(basename $f _fuzzer.cc)
+ $CXX $CXXFLAGS -c $f -o $WORK/${b}_fuzzer.o
+ else
+ continue
+ fi
- # Make the "gzip_fuzzer" binary. First compile the (C) Wuffs code, then link
- # the (C++) fuzzing library.
- $CC $CFLAGS -c $f -o $WORK/${b}_fuzzer.o
+ # ...then link the (C++) fuzzing library.
$CXX $CXXFLAGS $WORK/${b}_fuzzer.o -o $OUT/${b}_fuzzer $LIB_FUZZING_ENGINE
# Make the optional "gzip_fuzzer_seed_corpus.zip" archive. This means
diff --git a/projects/xmlsec/Dockerfile b/projects/xmlsec/Dockerfile
index 75814fcc1..013c53078 100644
--- a/projects/xmlsec/Dockerfile
+++ b/projects/xmlsec/Dockerfile
@@ -16,7 +16,7 @@
FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config \
- libssl-dev libxslt-dev wget liblzma-dev
+ libssl-dev wget liblzma-dev python-dev python3-dev
RUN git clone --depth 1 https://github.com/lsh123/xmlsec
RUN git clone --depth 1 https://gitlab.gnome.org/GNOME/libxml2.git
diff --git a/projects/xmlsec/build.sh b/projects/xmlsec/build.sh
index b2976c3d9..bb601a79c 100755
--- a/projects/xmlsec/build.sh
+++ b/projects/xmlsec/build.sh
@@ -28,7 +28,7 @@ make -j$(nproc) all
make install
cd $SRC/libxslt
-./autogen.sh --prefix="$XMLSEC_DEPS_PATH"
+./autogen.sh --prefix="$XMLSEC_DEPS_PATH" --with-libxml-src=${SRC}/libxml2
make -j$(nproc)
make install
@@ -40,7 +40,8 @@ make -j$(nproc) all
for file in $SRC/xmlsec/tests/oss-fuzz/*_target.c; do
b=$(basename $file _target.c)
- $CC $CFLAGS -c $file -I /usr/include/libxml2 -I ./include/ \
+ echo -e "#include <stdint.h>\n$(cat $file)" > $file
+ $CC $CFLAGS -c $file -I${XMLSEC_DEPS_PATH=}/include/libxml2 -I${XMLSEC_DEPS_PATH=}/include/ -I ./include/ \
-o $OUT/${b}_target.o
$CXX $CXXFLAGS $OUT/${b}_target.o ./src/.libs/libxmlsec1.a \
./src/openssl/.libs/libxmlsec1-openssl.a $LIB_FUZZING_ENGINE \
diff --git a/projects/xnu/Dockerfile b/projects/xnu/Dockerfile
new file mode 100644
index 000000000..ab69648a6
--- /dev/null
+++ b/projects/xnu/Dockerfile
@@ -0,0 +1,37 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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 \
+ ninja-build
+
+# Install Protobuf for C++ as the version in the base-builder repos may
+# be outdated.
+RUN curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.18.1/protobuf-cpp-3.18.1.tar.gz
+RUN tar xf protobuf-cpp-3.18.1.tar.gz
+WORKDIR $SRC/protobuf-3.18.1
+# Build statically
+RUN ./configure --disable-shared
+RUN make -j $(nproc)
+RUN make install
+
+WORKDIR $SRC
+RUN git clone --depth 1 https://github.com/googleprojectzero/SockFuzzer.git
+COPY build.sh $SRC
diff --git a/projects/xnu/build.sh b/projects/xnu/build.sh
new file mode 100755
index 000000000..715e32bd2
--- /dev/null
+++ b/projects/xnu/build.sh
@@ -0,0 +1,24 @@
+#!/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 -GNinja $SRC/SockFuzzer
+ninja
+
+cp $SRC/build/net_fuzzer $OUT
diff --git a/projects/xnu/project.yaml b/projects/xnu/project.yaml
new file mode 100644
index 000000000..e0d883189
--- /dev/null
+++ b/projects/xnu/project.yaml
@@ -0,0 +1,9 @@
+homepage: "https://opensource.apple.com/"
+language: "c"
+primary_contact: "nedwill@google.com"
+main_repo: "https://github.com/googleprojectzero/SockFuzzer"
+fuzzing_engines:
+ - libfuzzer
+ - honggfuzz
+sanitizers:
+ - address
diff --git a/projects/xpdf/Dockerfile b/projects/xpdf/Dockerfile
index a3090f06b..5c43ae74a 100755
--- a/projects/xpdf/Dockerfile
+++ b/projects/xpdf/Dockerfile
@@ -15,7 +15,7 @@
################################################################################
FROM gcr.io/oss-fuzz-base/base-builder
-RUN apt-get update && apt-get install -y make wget cmake libqt4-dev
+RUN apt-get update && apt-get install software-properties-common -y && apt-get update && apt-add-repository ppa:rock-core/qt4 && apt-get install -y make wget cmake libqt4-dev
RUN wget --no-check-certificate https://dl.xpdfreader.com/xpdf-latest.tar.gz
WORKDIR $SRC
diff --git a/projects/yajl-ruby/project.yaml b/projects/yajl-ruby/project.yaml
index d1da04dac..11edfb944 100644
--- a/projects/yajl-ruby/project.yaml
+++ b/projects/yajl-ruby/project.yaml
@@ -5,12 +5,10 @@ fuzzing_engines:
- libfuzzer
- afl
- honggfuzz
- - dataflow
sanitizers:
- address
- undefined
- memory
- - dataflow
auto_ccs:
- aaron.patterson@gmail.com
- jonathan@titanous.com
diff --git a/projects/ygot/Dockerfile b/projects/ygot/Dockerfile
index b592c307b..c8f0a419f 100644
--- a/projects/ygot/Dockerfile
+++ b/projects/ygot/Dockerfile
@@ -14,7 +14,7 @@
#
################################################################################
-FROM gcr.io/oss-fuzz-base/base-builder
+FROM gcr.io/oss-fuzz-base/base-builder-go
RUN git clone --depth 1 https://github.com/openconfig/ygot
COPY build.sh $SRC/
diff --git a/projects/zeek/build.sh b/projects/zeek/build.sh
index 996fe9c12..bd6c57031 100644
--- a/projects/zeek/build.sh
+++ b/projects/zeek/build.sh
@@ -20,12 +20,12 @@ CFLAGS="${CFLAGS} -pthread" CXXFLAGS="${CXXFLAGS} -pthread" \
--build-type=debug \
--generator=Ninja \
--enable-fuzzers \
+ --enable-mobile-ipv6 \
--disable-python \
--disable-zeekctl \
--disable-auxtools \
--disable-broker-tests
-
cd build
ninja install
diff --git a/projects/zeek/project.yaml b/projects/zeek/project.yaml
index b0239dab7..5d1b068ad 100644
--- a/projects/zeek/project.yaml
+++ b/projects/zeek/project.yaml
@@ -11,6 +11,9 @@ auto_ccs:
- "vern@corelight.com"
- "vlad@es.net"
- "dominik.charousset@corelight.com"
+fuzzing_engines:
+ - libfuzzer
+ - honggfuzz
sanitizers:
- address
main_repo: 'https://github.com/zeek/zeek'
diff --git a/projects/znc/Dockerfile b/projects/znc/Dockerfile
new file mode 100644
index 000000000..923e01556
--- /dev/null
+++ b/projects/znc/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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/znc/znc
+WORKDIR $SRC/znc
+COPY build.sh msg_parse_fuzzer.cpp $SRC/
diff --git a/projects/znc/build.sh b/projects/znc/build.sh
new file mode 100755
index 000000000..7472ad8b5
--- /dev/null
+++ b/projects/znc/build.sh
@@ -0,0 +1,33 @@
+#!/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.
+#
+################################################################################
+
+git submodule update --init --recursive
+mkdir build && cd build
+cmake -DBUILD_SHARED_LIBS=OFF \
+ -DWANT_ICU=OFF \
+ -DWANT_OPENSSL=OFF \
+ -DWANT_ZLIB=OFF \
+ -DWANT_IPV6=OFF ..
+make -j$(nproc)
+
+$CXX $CXXFLAGS -DGTEST_HAS_POSIX_RE=0 \
+ -I/src/znc/include -I/src/znc/build/include \
+ -fPIE -include znc/zncconfig.h -std=c++11 \
+ -c $SRC/msg_parse_fuzzer.cpp -o msg_parse_fuzzer.o
+$CXX $CXXFLAGS $LIB_FUZZING_ENGINE \
+ msg_parse_fuzzer.o -o $OUT/msg_parse_fuzzer \
+ /src/znc/build/src/libznc.a
diff --git a/projects/znc/msg_parse_fuzzer.cpp b/projects/znc/msg_parse_fuzzer.cpp
new file mode 100644
index 000000000..73389459e
--- /dev/null
+++ b/projects/znc/msg_parse_fuzzer.cpp
@@ -0,0 +1,30 @@
+/*
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 <stdint.h>
+#include <znc/Message.h>
+
+extern "C"
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ std::string input(reinterpret_cast<const char*>(data), size);
+ CMessage msg;
+ msg.Parse(input);
+ msg.SetParam(1, input);
+ msg.GetParams();
+ return 0;
+}
diff --git a/projects/znc/project.yaml b/projects/znc/project.yaml
new file mode 100644
index 000000000..984e04087
--- /dev/null
+++ b/projects/znc/project.yaml
@@ -0,0 +1,12 @@
+homepage: "https://znc.in"
+language: c++
+primary_contact: "alexey+znc@asokolov.org"
+auto_ccs:
+ - "Adam@adalogics.com"
+ - "ktonibud@gmail.com"
+sanitizers:
+ - address
+ - undefined
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
+main_repo: "https://github.com/znc/znc" \ No newline at end of file
diff --git a/projects/zopfli/project.yaml b/projects/zopfli/project.yaml
index 33c9f3104..ba175ad8d 100644
--- a/projects/zopfli/project.yaml
+++ b/projects/zopfli/project.yaml
@@ -3,6 +3,7 @@ language: c++
primary_contact: "lode@google.com"
sanitizers:
- address
- - memory
+# Disabled MSAN because of https://github.com/google/oss-fuzz/issues/6294
+# - memory
- undefined
-main_repo: 'https://github.com/google/zopfli'
+main_repo: 'https://github.com/google/zopfli' \ No newline at end of file
diff --git a/projects/zxing/Dockerfile b/projects/zxing/Dockerfile
new file mode 100644
index 000000000..389b7c0ee
--- /dev/null
+++ b/projects/zxing/Dockerfile
@@ -0,0 +1,29 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 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://downloads.apache.org/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/zxing/zxing
+
+COPY build.sh $SRC/
+COPY MultiFormatDecodeFuzzer.java MultiFormatEncodeFuzzer.java $SRC/
+WORKDIR $SRC/zxing
diff --git a/projects/zxing/MultiFormatDecodeFuzzer.java b/projects/zxing/MultiFormatDecodeFuzzer.java
new file mode 100644
index 000000000..991428dfb
--- /dev/null
+++ b/projects/zxing/MultiFormatDecodeFuzzer.java
@@ -0,0 +1,56 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.zxing.BinaryBitmap;
+import com.google.zxing.BufferedImageLuminanceSource;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.ReaderException;
+import com.google.zxing.Result;
+import com.google.zxing.common.HybridBinarizer;
+
+import javax.imageio.ImageIO;
+import java.io.IOException;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+
+public final class MultiFormatDecodeFuzzer {
+ private static MultiFormatReader barcodeReader = new MultiFormatReader();
+
+ public static void fuzzerInitialize() {
+ }
+
+ public static void fuzzerTestOneInput(byte[] input) {
+ BufferedImage image;
+ try {
+ image = ImageIO.read(new ByteArrayInputStream(input));
+ } catch (IOException e) {
+ return;
+ }
+ if (image == null)
+ return;
+ if ((long) image.getHeight() * (long) image.getWidth() > 10000000)
+ return;
+
+ BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
+ BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
+ try {
+ Result result = barcodeReader.decode(bitmap);
+ result.getText();
+ result.getResultMetadata();
+ } catch (ReaderException ignored) {
+ }
+ }
+}
diff --git a/projects/zxing/MultiFormatEncodeFuzzer.java b/projects/zxing/MultiFormatEncodeFuzzer.java
new file mode 100644
index 000000000..46a9e80e1
--- /dev/null
+++ b/projects/zxing/MultiFormatEncodeFuzzer.java
@@ -0,0 +1,187 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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.zxing.BarcodeFormat;
+import com.google.zxing.MultiFormatWriter;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.aztec.encoder.AztecCode;
+import com.google.zxing.aztec.AztecReader;
+import com.google.zxing.datamatrix.DataMatrixReader;
+import com.google.zxing.maxicode.MaxiCodeReader;
+import com.google.zxing.oned.MultiFormatOneDReader;
+import com.google.zxing.pdf417.PDF417Reader;
+import com.google.zxing.qrcode.QRCodeReader;
+import com.google.zxing.oned.CodaBarReader;
+import com.google.zxing.oned.Code128Reader;
+import com.google.zxing.oned.Code39Reader;
+import com.google.zxing.oned.Code93Reader;
+import com.google.zxing.oned.EAN13Reader;
+import com.google.zxing.oned.EAN8Reader;
+import com.google.zxing.oned.ITFReader;
+import com.google.zxing.oned.UPCAReader;
+import com.google.zxing.oned.UPCEReader;
+import com.google.zxing.pdf417.PDF417Reader;
+import com.google.zxing.qrcode.QRCodeReader;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import javax.naming.NameNotFoundException;
+
+import com.google.zxing.Reader;
+import com.google.zxing.Binarizer;
+import com.google.zxing.BinaryBitmap;
+import com.google.zxing.WriterException;
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.common.BitArray;
+import com.google.zxing.NotFoundException;
+import com.google.zxing.FormatException;
+import com.google.zxing.ChecksumException;
+import com.google.zxing.LuminanceSource;
+import com.google.zxing.Result;
+import com.google.zxing.pdf417.PDF417Writer;
+
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+import com.google.zxing.qrcode.decoder.Mode;
+import com.google.zxing.qrcode.encoder.QRCode;
+
+import com.google.zxing.datamatrix.encoder.HighLevelEncoder;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+public final class MultiFormatEncodeFuzzer {
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ int width = data.consumeInt(100, 200);
+ int height = data.consumeInt(100, 200);
+ BarcodeFormat format = data.pickValue(BarcodeFormat.values());
+ String originalData = data.consumeRemainingAsAsciiString();
+
+ BitMatrix matrix;
+ try {
+ matrix = new MultiFormatWriter().encode(originalData, format, width, height);
+ } catch (WriterException | IllegalArgumentException e) {
+ return;
+ }
+
+ BinaryBitmap bitmap = null;
+ Result result;
+ try {
+ bitmap = new BinaryBitmap(new TrivialBinarizer(matrix));
+ result = getReader(format).decode(bitmap);
+ } catch (NotFoundException | ChecksumException | FormatException e) {
+ throw new IllegalStateException("Failed to recover\n" + originalData + "\nencoded with " + format + " in "
+ + width + "x" + height + "\n\n" + matrix.toString() + "\n\n" + bitmap.toString(), e);
+ }
+ String decodedData = result.getText();
+ if (!decodedData.equals(originalData)) {
+ throw new IllegalStateException(
+ "Failed to recover\n" + originalData + "\nencoded with " + format + " in " + width + "x" + height
+ + ", got:\n" + decodedData + "\n\n" + matrix.toString() + "\n\n" + bitmap.toString());
+ }
+ }
+
+ private static Reader getReader(BarcodeFormat format) {
+ switch (format) {
+ case EAN_8:
+ return new EAN8Reader();
+ case UPC_E:
+ return new UPCEReader();
+ case EAN_13:
+ return new EAN13Reader();
+ case UPC_A:
+ return new UPCAReader();
+ case QR_CODE:
+ return new QRCodeReader();
+ case CODE_39:
+ return new Code39Reader();
+ case CODE_93:
+ return new Code93Reader();
+ case CODE_128:
+ return new Code128Reader();
+ case ITF:
+ return new ITFReader();
+ case PDF_417:
+ return new PDF417Reader();
+ case CODABAR:
+ return new CodaBarReader();
+ case DATA_MATRIX:
+ return new DataMatrixReader();
+ case AZTEC:
+ return new AztecReader();
+ default:
+ throw new IllegalArgumentException("No encoder available for format " + format);
+ }
+ }
+
+ private static final class TrivialBinarizer extends Binarizer {
+ private final BitMatrix matrix;
+
+ public TrivialBinarizer(BitMatrix matrix) {
+ super(new TrivialLuminanceSource(matrix));
+ this.matrix = matrix;
+ }
+
+ public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
+ return matrix.getRow(y, row);
+ }
+
+ public BitMatrix getBlackMatrix() throws NotFoundException {
+ return matrix;
+ }
+
+ public Binarizer createBinarizer(LuminanceSource source) {
+ return new TrivialBinarizer(matrix);
+ }
+ }
+
+ private static final class TrivialLuminanceSource extends LuminanceSource {
+ private final BitMatrix matrix;
+
+ public TrivialLuminanceSource(BitMatrix matrix) {
+ super(matrix.getWidth(), matrix.getHeight());
+ this.matrix = matrix;
+ }
+
+ public byte[] getRow(int y, byte[] row) {
+ if (row.length != matrix.getWidth()) {
+ row = new byte[matrix.getWidth()];
+ }
+ BitArray bitRow = matrix.getRow(y, null);
+ for (int i = 0; i < matrix.getWidth(); i++) {
+ if (bitRow.get(i)) {
+ row[i] = 0;
+ } else {
+ row[i] = (byte) 255;
+ }
+ }
+ return row;
+ }
+
+ public byte[] getMatrix() {
+ byte[] bytes = new byte[matrix.getWidth() * matrix.getHeight()];
+ for (int x = 0; x < matrix.getWidth(); x++) {
+ for (int y = 0; y < matrix.getHeight(); y++) {
+ if (!matrix.get(x, y))
+ bytes[x + y * matrix.getWidth()] = (byte) 255;
+ }
+ }
+ return bytes;
+ }
+ }
+}
diff --git a/projects/zxing/build.sh b/projects/zxing/build.sh
new file mode 100644
index 000000000..70f15c0a6
--- /dev/null
+++ b/projects/zxing/build.sh
@@ -0,0 +1,53 @@
+#!/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.
+#
+################################################################################
+
+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 "core/target/core-$CURRENT_VERSION.jar" $OUT/zxing.jar
+
+mkdir -p $OUT/com/google/zxing
+cp core/target/test-classes/com/google/zxing/BufferedImageLuminanceSource.class $OUT/com/google/zxing
+
+ALL_JARS="zxing.jar"
+
+# The classpath at build-time includes the project jars in $OUT as well as the
+# Jazzer API. Additionally, include $OUT itself to pick up
+# BufferedImageLuminanceSource.
+BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH:$OUT
+
+# 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/sh
+# LLVMFuzzerTestOneInput for fuzzer detection.
+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_basename \
+--jvm_args=\"-Xmx2048m;-Djava.awt.headless=true\" \
+\$@" > $OUT/$fuzzer_basename
+ chmod u+x $OUT/$fuzzer_basename
+done
diff --git a/projects/zxing/project.yaml b/projects/zxing/project.yaml
new file mode 100644
index 000000000..ceab3c387
--- /dev/null
+++ b/projects/zxing/project.yaml
@@ -0,0 +1,11 @@
+homepage: "https://github.com/zxing/zxing"
+language: jvm
+primary_contact: "srowen@gmail.com"
+auto_ccs:
+ - "wagner@code-intelligence.com"
+ - "meumertzheim@code-intelligence.com"
+fuzzing_engines:
+ - libfuzzer
+main_repo: "https://github.com/zxing/zxing.git"
+sanitizers:
+ - address
diff --git a/projects/zydis/build.sh b/projects/zydis/build.sh
index b38ce5b2c..98103a4f4 100755
--- a/projects/zydis/build.sh
+++ b/projects/zydis/build.sh
@@ -20,6 +20,7 @@ mv $SRC/ZydisFuzz_seed_corpus.zip $OUT/ZydisFuzz_seed_corpus.zip
mkdir build && cd build
cmake \
+ -DZYAN_FORCE_ASSERTS=ON \
-DZYDIS_BUILD_EXAMPLES=OFF \
-DZYDIS_BUILD_TOOLS=OFF \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
@@ -29,7 +30,7 @@ cmake \
-DCMAKE_CXX_FLAGS="$CXXFLAGS" \
..
-make -j8
+make -j$(nproc) VERBOSE=1
$CXX \
$CXXFLAGS \