Skip to content

build-logic: link sanitizer runtime for the fuzzer shared lib#646

Merged
rkennke merged 1 commit into
mainfrom
rkennke/fuzzer-sanitizer-runtime-link
Jul 10, 2026
Merged

build-logic: link sanitizer runtime for the fuzzer shared lib#646
rkennke merged 1 commit into
mainfrom
rkennke/fuzzer-sanitizer-runtime-link

Conversation

@rkennke

@rkennke rkennke commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

configureFuzzer now links the sanitizer runtime into the fuzzer shared library on Linux, mirroring the existing configureAsan treatment. The detected compiler is threaded through so the right runtime is chosen (clang: -lclang_rt.asan-<arch>, which also supplies UBSan symbols; gcc: -lasan + -lubsan).

Why

commonLinuxLinkerArgs() includes -Wl,-z,defs, which forbids undefined symbols in the output. The fuzzer objects are compiled with -fsanitize=address,undefined, so they reference __asan_*/__ubsan_* — but -fsanitize=address only links the sanitizer runtime into executables, not shared libraries. The fuzzer .so is therefore left with undefined __asan_*/__ubsan_* and the link fails under -z defs:

/usr/bin/ld: wallClock.o: undefined reference to `__ubsan_handle_type_mismatch_v1_abort'
/usr/bin/ld: wallClock.o: undefined reference to `__asan_report_load4'
clang++: error: linker command failed with exit code 1

The asan config already solves exactly this via locateLibasan; this change applies the same, already-proven pattern to the fuzzer config.

Why CI didn't catch it

The publish/build path passes --exclude-task compileFuzzer (.gitlab/scripts/deploy.sh) and the build job only assembles :ddprof-lib:assembleReleaseJar, so the fuzzer is never linked in CI. The bug only surfaces on a local build that links all active configs — e.g. publishToMavenLocal on a clang box where hasFuzzer() is true (non-musl, clang with libFuzzer).

Scope / risk

  • Low-risk: mirrors the existing asan linker logic; when no runtime is located the behavior is unchanged (falls back to the prior fuzzerLinkerArgs).
  • The macOS branch is untouched.
  • CI's --exclude-task compileFuzzer is left in place (it still saves build time); this change just makes the fuzzer link work when it is built.

Testing

./gradlew ddprof-lib:linkFuzzer succeeds on a clang Linux box (Successfully linked libjavaProfiler.so). Before this change it failed at link with the undefined __asan_*/__ubsan_* references above.

🤖 Generated with Claude Code

commonLinuxLinkerArgs() carries -Wl,-z,defs, which forbids undefined
symbols in the output. The fuzzer objects are instrumented with
-fsanitize=address,undefined and therefore reference __asan_*/__ubsan_*,
but -fsanitize=address only links the sanitizer runtime into
*executables*, not shared libraries. So the fuzzer .so ends up with
undefined __asan_*/__ubsan_* and the link fails under -z defs on any box
where the fuzzer config is active (clang with libFuzzer, non-musl).

The asan config already solves this by linking the matching runtime
explicitly via locateLibasan (-lclang_rt.asan-<arch> on clang, which also
provides UBSan symbols; -lasan + -lubsan on gcc). Apply the same,
already-proven treatment to configureFuzzer: thread the detected compiler
through and add the runtime to the Linux linker args.

CI never hit this because its publish/build path passes
--exclude-task compileFuzzer and only assembles the release jar, so the
fuzzer is never linked there. It only bites a local build that links all
active configs (e.g. publishToMavenLocal on a clang box). The macOS branch
is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rkennke rkennke marked this pull request as ready for review July 9, 2026 15:35
@rkennke rkennke requested a review from a team as a code owner July 9, 2026 15:35

@jbachorik jbachorik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1d186990d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +357 to +360
listOf("-L$asanLibDir", "-l$asanLibName",
"-Wl,-rpath,$asanLibDir") +
ubsanLibs +
fuzzerLinkerArgs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preload ASan for fuzzer test JVMs

When the Linux fuzzer config is used by the generated Java tasks (for example testFuzzer from ProfilerTestPlugin), these new link args add a DT_NEEDED dependency on the ASan runtime but the fuzzer testEnvironment still never sets LD_PRELOAD. An unsanitized JVM that later loads this ASan-instrumented libjavaProfiler.so aborts before tests start with the usual “ASan runtime does not come first” error; configureAsan avoids that by preloading the same libasan. Please mirror that here when libasan != null.

Useful? React with 👍 / 👎.

@dd-octo-sts

dd-octo-sts Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #29029761735 | Commit: 1b35393 | Duration: 14m 27s (longest job)

1 of 32 test jobs failed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - - -
8-ibm - - -
8-j9 - -
8-librca - -
8-orcl - - -
11 - - -
11-j9 - -
11-librca - -
17 - -
17-graal - -
17-j9 - -
17-librca - -
21 - -
21-graal - -
21-librca - -
25 - -
25-graal - -
25-librca - -

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Failed Tests

glibc-amd64/debug / 8-ibm

Job: View logs

No detailed failure information available. Check the job logs.

Summary: Total: 32 | Passed: 31 | Failed: 1


Updated: 2026-07-09 15:48:35 UTC

@rkennke

rkennke commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Re: the Codex review comment on the fuzzer test environment — confirmed and reproduced locally, and it's a real (but separate) issue.

The link fix here does let the auto-generated testFuzzer JVM task get past linking, where it then SIGABRTs:

  1. As-is (no LD_PRELOAD): ==NNNNN==ASan runtime does not come first in initial library list ... → SIGABRT.
  2. After adding LD_PRELOAD=<libasan> (mirroring configureAsan): the abort clears and tests run, but the JVM then aborts on LeakSanitizer — AddressSanitizer: 4306806 byte(s) leaked in 33812 allocation(s) → SIGABRT.

So making testFuzzer green requires asan's entire JVM test env (LD_PRELOAD + LSAN_OPTIONS=detect_leaks=0 + the tuned ASAN_OPTIONS/UBSAN_OPTIONS + the HeapBaseMinAddress/heap-sizing args) — at which point it's effectively a duplicate of testAsan (both are address+undefined instrumentation).

Important: testFuzzer was already broken before this PR — it failed earlier, at the link step — so this change doesn't regress it; it just moves the failure from link-time to test-time. The native gtestFuzzer suites and libFuzzer fuzz targets are unaffected and pass (GtestTaskBuilder already strips LD_PRELOAD for the sanitized gtest executables).

Keeping this PR scoped to the link fix and tracking the testFuzzer JVM environment separately: PROF-15369 (https://datadoghq.atlassian.net/browse/PROF-15369), which captures the two candidate fixes (mirror asan's JVM test env via a shared helper, or don't generate a JVM testFuzzer task for the fuzzer variant).

@rkennke rkennke merged commit 87ee799 into main Jul 10, 2026
105 of 106 checks passed
@rkennke rkennke deleted the rkennke/fuzzer-sanitizer-runtime-link branch July 10, 2026 07:44
@github-actions github-actions Bot added this to the 1.47.0 milestone Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants