diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile index fbc79305..6a734a08 100644 --- a/.clusterfuzzlite/Dockerfile +++ b/.clusterfuzzlite/Dockerfile @@ -1,4 +1,4 @@ -FROM gcr.io/oss-fuzz-base/base-builder +FROM gcr.io/oss-fuzz-base/base-builder:ubuntu-24-04 RUN apt-get update && apt-get install -y \ build-essential \ diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh index f638031d..bc48bde3 100755 --- a/.clusterfuzzlite/build.sh +++ b/.clusterfuzzlite/build.sh @@ -89,6 +89,9 @@ if [ ${#FUZZ_TARGETS[@]} -eq 0 ]; then exit 1 fi +# Expose the discovered targets to the run-fuzzers container. +cp "$WORK/fuzz_targets.txt" "$OUT/fuzz_targets.txt" + # Must match FuzzTargetPlaceholder in src/test/fuzz/fuzz.cpp so the python # patching below can locate the placeholder string. MAGIC_STR="d6f1a2b39c4e5d7a8b9c0d1e2f30415263748596a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff00fedcba9876543210a0b1c2d3" diff --git a/.clusterfuzzlite/run-cfl-helper.sh b/.clusterfuzzlite/run-cfl-helper.sh index d1ec63c8..f675c422 100755 --- a/.clusterfuzzlite/run-cfl-helper.sh +++ b/.clusterfuzzlite/run-cfl-helper.sh @@ -48,7 +48,7 @@ ensure_image_cached() { case "${operation}" in detect-symbolizer) - image='ghcr.io/sjors/clusterfuzzlite-run-fuzzers:llvm-22-debug' + image='gcr.io/oss-fuzz-base/clusterfuzzlite-run-fuzzers:ubuntu-24-04-v1' ensure_image_cached "$image" docker run \ "${docker_common[@]}" \ diff --git a/.github/workflows/clusterfuzzlite-shared.yml b/.github/workflows/clusterfuzzlite-shared.yml index 088de2fe..dd996f0e 100644 --- a/.github/workflows/clusterfuzzlite-shared.yml +++ b/.github/workflows/clusterfuzzlite-shared.yml @@ -49,7 +49,9 @@ jobs: fetch-depth: 0 - name: Build fuzzers (${{ matrix.sanitizer }}) - uses: Sjors/clusterfuzzlite/actions/build_fuzzers@2026/02/clang-22-v2 + # Pin to a SHA on google/clusterfuzzlite#146 so the branch can rebase + # without breaking us; revert to a tagged release once the PR lands. + uses: google/clusterfuzzlite/actions/build_fuzzers@d2c7d068aab9081cbbc57825ad0d5d6ca6674f95 # migrate-to-ubuntu-24-04 with: language: c++ sanitizer: ${{ matrix.sanitizer }} @@ -83,7 +85,9 @@ jobs: - name: Run fuzzers (${{ matrix.sanitizer }}) if: ${{ inputs.run_fuzzers }} - uses: Sjors/clusterfuzzlite/actions/run_fuzzers@2026/02/clang-22-v2 + # Pin to a SHA on google/clusterfuzzlite#146 so the branch can rebase + # without breaking us; revert to a tagged release once the PR lands. + uses: google/clusterfuzzlite/actions/run_fuzzers@d2c7d068aab9081cbbc57825ad0d5d6ca6674f95 # migrate-to-ubuntu-24-04 with: github-token: ${{ secrets.GITHUB_TOKEN }} sanitizer: ${{ matrix.sanitizer }} diff --git a/src/test/fuzz/fuzz.cpp b/src/test/fuzz/fuzz.cpp index 671cd246..358e75f0 100644 --- a/src/test/fuzz/fuzz.cpp +++ b/src/test/fuzz/fuzz.cpp @@ -36,6 +36,13 @@ __AFL_FUZZ_INIT(); #endif +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# define SV2_MSAN_ENABLED 1 +# endif +#endif + extern const std::function G_TEST_LOG_FUN{}; const TranslateFn G_TRANSLATION_FUN{nullptr}; @@ -234,6 +241,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) // This function is used by libFuzzer extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) { +#ifdef SV2_MSAN_ENABLED + // libFuzzer forwards argc/argv from glibc's __libc_start_main. On + // glibc >= 2.39 MSan does not unpoison them, so SetArgs would trip + // use-of-uninitialized-value on the first deref. Unpoison the shadow + // at both addresses first, then dereference and unpoison the strings. + __msan_unpoison(argc, sizeof(*argc)); + __msan_unpoison(argv, sizeof(*argv)); + const int ac{*argc}; + char** const av{*argv}; + __msan_unpoison(av, sizeof(*av) * (ac + 1)); + for (int i = 0; i < ac; ++i) { + if (av[i] != nullptr) { + __msan_unpoison(av[i], std::strlen(av[i]) + 1); + } + } +#endif SetArgs(*argc, *argv); initialize(); return 0;