Skip to content

docs: record the environment an ASan build needs - #12736

Open
jvepsalainen-nv wants to merge 1 commit into
shader-slang:masterfrom
jvepsalainen-nv:docs/asan-build-requirements
Open

docs: record the environment an ASan build needs#12736
jvepsalainen-nv wants to merge 1 commit into
shader-slang:masterfrom
jvepsalainen-nv:docs/asan-build-requirements

Conversation

@jvepsalainen-nv

Copy link
Copy Markdown
Contributor

1. Motivation

-DSLANG_ENABLE_ASAN=ON does not build out of the box, and neither failure mentions the sanitizer,
so the cause is not obvious. Both were hit on a plain Ubuntu 24.04 host with clang-18:

slang-embed: error while loading shared libraries: libclang_rt.asan-x86_64.so:
cannot open shared object file: No such file or directory
==54966==ERROR: LeakSanitizer: detected memory leaks
SUMMARY: AddressSanitizer: 828842 byte(s) leaked in 3661 allocation(s).
ninja: build stopped: subcommand failed.

The build compiles its own generators (slang-embed, slang-fiddle) and then runs them. Under
ASan they are instrumented and link the runtime dynamically, so they cannot start unless it is
locatable; and they leak, so LeakSanitizer's non-zero exit fails the build. Both are already handled
in CI (ci-slang-sanitizer.yml:134 and :144), but nothing in the docs says so, so anyone
reproducing a sanitizer finding locally rediscovers them.

The first of these is recorded in issue #12707 as a container-specific gotcha. It is not
container-specific — it reproduced on an ordinary host at the identical runtime path. The
LeakSanitizer one is not recorded anywhere.

2. Proposed solution

Add a short "Building with AddressSanitizer" section to docs/building.md giving the two exports
and the error each one prevents, and point at the CI workflow as the authoritative copy.

It also documents a third, run-time requirement that is more insidious than either build failure:
the build's lib/ directory must be on LD_LIBRARY_PATH when running the binaries. slang-test
dlopens its tools, and when that fails the affected tests are reported ignored, not failed —
so the run appears to succeed while silently testing nothing. I hit exactly this and briefly
concluded that ASan was incompatible with Vulkan before finding the real cause.

The section explains why this is specific to sanitizer builds, which is the part that makes it
memorable rather than a rule to copy: normally that dlopen resolves through the executable's
$ORIGIN/../lib runpath unaided, but under a sanitizer the call is intercepted and issued from the
sanitizer runtime's own object, which has no runpath — so $ORIGIN/../lib is never searched. Setting
LD_LIBRARY_PATH to the runtime directory alone is therefore not sufficient, which is the trap,
since that is exactly what the first build-time fix tells you to do.

A closing note covers -DSLANG_ENABLE_TSAN=ON, where the same two LD_LIBRARY_PATH requirements
apply with the TSan runtime, and ASAN_OPTIONS=detect_leaks=0 is unnecessary because
ThreadSanitizer has no leak checker. I re-encountered the trap on a TSan build after it had already
been diagnosed on ASan, which is the reason for making the generality explicit.

clang -print-runtime-dir is used rather than a hardcoded path so the snippet does not rot across
clang versions.

3. Change summary

File What changed
docs/building.md New "Building with AddressSanitizer" section before "Notes": the two build-time exports with the error each prevents, the run-time lib/ requirement with its silent-ignore failure mode and the runpath reason it is sanitizer-specific, and a note carrying all of it over to SLANG_ENABLE_TSAN

4. Concepts and vocabulary

  • slang-embed / slang-fiddle — host tools the build compiles and then executes to generate
    sources. Being instrumented themselves is what makes them sensitive to the ASan runtime.
  • ignored vs failed — slang-test reports a test whose tool could not be loaded, or whose device
    is unavailable, as ignored. Ignored tests do not fail a run, which is why a missing
    LD_LIBRARY_PATH entry removes coverage silently.

5. Process report

Documentation only; no behaviour change and nothing to root-cause. The values are not invented —
each is copied from what ci-slang-sanitizer.yml already does, so the docs and CI agree, and the
section says so to keep CI as the single source of truth.

Whether the leaks in slang-fiddle should be fixed rather than suppressed is a separate question,
deliberately not addressed here: detect_leaks=0 is already CI's chosen behaviour for the build
step, and changing it is not a documentation matter.

6. Verification

Both exports were required, in sequence, to get a working ASan build on this host — the build failed
at object 511/1188 without the first and at 516/1188 without the second, and completed with both.
The run-time lib/ requirement was confirmed by observing Check vk,vulkan: Not Supported and 0
tests executing without it, versus vk tests passing with it.

Configuring with SLANG_ENABLE_ASAN=ON fails partway through a build unless the
ASan runtime is on LD_LIBRARY_PATH and leak detection is disabled: the build
runs its own instrumented generators (slang-embed, slang-fiddle), which cannot
start without the runtime and whose leaks make LeakSanitizer fail the build.
Neither failure mentions the sanitizer, so the cause is not obvious.

Also note that the build's lib/ directory must be on LD_LIBRARY_PATH when
running the binaries, since slang-test dlopen()s its tools and reports the
affected tests as ignored -- not failed -- when that lookup fails.
@jvepsalainen-nv
jvepsalainen-nv requested a review from a team as a code owner August 25, 2026 13:08
@jvepsalainen-nv
jvepsalainen-nv requested review from bmillsNV and removed request for a team August 25, 2026 13:08
@jvepsalainen-nv jvepsalainen-nv added the pr: non-breaking PRs without breaking changes label Aug 25, 2026
@jhelferty-nv
jhelferty-nv removed the request for review from bmillsNV August 25, 2026 13:08
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The build documentation now describes AddressSanitizer and ThreadSanitizer builds, runtime-library paths, LeakSanitizer settings, dynamic tool loading, and the related CI configuration.

Sanitizer Documentation

Layer / File(s) Summary
AddressSanitizer build and runtime setup
docs/building.md
Adds AddressSanitizer build commands, runtime-library configuration, LeakSanitizer settings, and LD_LIBRARY_PATH requirements for dynamically loaded test tools.
ThreadSanitizer configuration
docs/building.md
Documents ThreadSanitizer runtime handling and links the corresponding sanitizer CI configuration. It clarifies that leak detection disabling applies only to AddressSanitizer.

Suggested reviewers: bmillsnv, jkwak-work, pdeayton-nv

Merge Risk: 🟡 Moderate · up to 31033

The new sanitizer guidance can suppress leak reports in later tests, mislead users on unsupported platforms or architectures, and create an unsafe empty library-search-path entry. These documentation errors can cause misleading test results or invalid runtime setup, so the PR is not ready to merge without correction or explicit owner acceptance.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the documentation change and its primary focus on the environment required for ASan builds.
Description check ✅ Passed The description directly explains the ASan and TSan build requirements, runtime-library configuration, CI alignment, and verification results.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2c7510e4-37b7-482b-a474-4d8053073386

📥 Commits

Reviewing files that changed from the base of the PR and between eb20c14 and 3103397.

📒 Files selected for processing (1)
  • docs/building.md

Included review availability: Your plan provides up to 8 included reviews per hour; 5 remain after this review.

Comment thread docs/building.md
Comment on lines +613 to +622
Configuring with `-DSLANG_ENABLE_ASAN=ON` needs two environment settings that are easy to miss,
because without them the build fails partway through for reasons that do not mention the sanitizer.

```bash
# 1. The build compiles and then *runs* its own generators (slang-embed, slang-fiddle). Under
# SLANG_ENABLE_ASAN they are instrumented and link the ASan runtime dynamically, so the runtime
# must be locatable or they fail to start:
# slang-embed: error while loading shared libraries: libclang_rt.asan-x86_64.so:
# cannot open shared object file: No such file or directory
export LD_LIBRARY_PATH="$(clang -print-runtime-dir):$LD_LIBRARY_PATH"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'SLANG_ENABLE_(ASAN|TSAN)|shared-libsan|CMAKE_(C|CXX)_COMPILER_ID' \
  cmake/CompilerFlags.cmake .github/workflows/ci-slang-sanitizer.yml docs/building.md

Repository: shader-slang/slang

Length of output: 26757


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- docs/building.md ---'
sed -n '611,652p' docs/building.md

printf '%s\n' '--- sanitizer option definitions and compiler branches ---'
rg -n -C 5 \
  'SLANG_ENABLE_(ASAN|TSAN)|shared-libsan|fsanitize=(address|thread)|/fsanitize=address|CMAKE_CXX_COMPILER_ID' \
  CMakeLists.txt cmake docs/building.md .github/workflows/ci-slang-sanitizer.yml

Repository: shader-slang/slang

Length of output: 24874


Limit the sanitizer instructions to Linux Clang builds.

The CMake implementation uses -shared-libsan only for non-Apple Clang builds. GNU and MSVC use different sanitizer runtime handling, while Apple Clang already uses a dynamic runtime. The TSan example also names the x86_64-specific libclang_rt.tsan-x86_64.so. Scope these instructions to Linux Clang builds, or document the platform- and architecture-specific equivalents.

Comment thread docs/building.md
# must be locatable or they fail to start:
# slang-embed: error while loading shared libraries: libclang_rt.asan-x86_64.so:
# cannot open shared object file: No such file or directory
export LD_LIBRARY_PATH="$(clang -print-runtime-dir):$LD_LIBRARY_PATH"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
set -euo pipefail

unset LD_LIBRARY_PATH
unsafe="runtime:${LD_LIBRARY_PATH-}"
safe="runtime${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"

test "$unsafe" = "runtime:"
test "$safe" = "runtime"

Repository: shader-slang/slang

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- docs/building.md ---'
sed -n '600,655p' docs/building.md

printf '%s\n' '--- relevant loader-path references ---'
rg -n -C 3 'LD_LIBRARY_PATH|clang -print-runtime-dir' docs cmake

Repository: shader-slang/slang

Length of output: 6096


🌐 Web query:

Linux ld.so LD_LIBRARY_PATH empty path element current working directory man page

💡 Result:

In the Linux dynamic linker (ld.so), an empty path element within the LD_LIBRARY_PATH environment variable is interpreted as the current working directory [1][2][3]. According to the official ld.so(8) manual page, LD_LIBRARY_PATH is defined as a list of directories separated by colons or semicolons, and a zero-length directory name (e.g., resulting from a leading colon, trailing colon, or consecutive colons like::) explicitly indicates that the dynamic linker should search the current working directory [1][4][3]. This behavior is a legacy feature consistent with the treatment of the PATH environment variable in POSIX systems [5][6]. Because this behavior can cause the linker to load arbitrary libraries from the current directory—potentially leading to security vulnerabilities if an attacker introduces malicious shared objects into that directory—it is generally recommended to avoid empty elements in LD_LIBRARY_PATH [7]. This variable is also ignored entirely when the program is executed in secure-execution mode (such as for set-user-ID or set-group-ID binaries) to mitigate such risks [1][3].

Citations:


Avoid empty entries in LD_LIBRARY_PATH.

When LD_LIBRARY_PATH is unset, both commands create a trailing :. Linux treats the empty entry as the current directory, which can load unintended libraries. Use a conditional separator.

Comment thread docs/building.md
Comment on lines +624 to +628
# 2. Those same generators leak, and LeakSanitizer's non-zero exit status fails the build:
# ERROR: LeakSanitizer: detected memory leaks
# SUMMARY: AddressSanitizer: 828842 byte(s) leaked in 3661 allocation(s)
# They are short-lived build tools, so leak detection is not meaningful for them.
export ASAN_OPTIONS=detect_leaks=0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope ASAN_OPTIONS to the build commands.

The exported variable remains active after cmake --build completes. If the user runs slang-test in the same shell, ASan tests inherit detect_leaks=0, so leak reports are suppressed. Apply the variable only to the configure and build commands, or instruct users to unset it before running tests.

Proposed documentation change
-export ASAN_OPTIONS=detect_leaks=0
-
-cmake --preset default -DSLANG_ENABLE_ASAN=ON
-cmake --build --preset release
+ASAN_OPTIONS=detect_leaks=0 cmake --preset default -DSLANG_ENABLE_ASAN=ON
+ASAN_OPTIONS=detect_leaks=0 cmake --build --preset release

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: 🟡 Has issues — 1 gap

This PR adds a "Building with AddressSanitizer" section to docs/building.md documenting the two environment settings (LD_LIBRARY_PATH for the ASan runtime + build lib/, ASAN_OPTIONS=detect_leaks=0) an ASan build/test run needs. The ASan-specific claims all check out against .github/workflows/ci-slang-sanitizer.yml and CMakeLists.txt; one factual error remains: it documents a -DSLANG_ENABLE_TSAN=ON option that the build system does not define.

Changes Overview

ASan/sanitizer build docs (docs/building.md)

  • What changed: Adds a new section explaining that under -DSLANG_ENABLE_ASAN=ON the build-time generators (slang-embed, slang-fiddle) need the ASan runtime on LD_LIBRARY_PATH and ASAN_OPTIONS=detect_leaks=0, and that running the binaries additionally needs the build's lib/ on LD_LIBRARY_PATH because the sanitizer-intercepted dlopen loses the $ORIGIN/../lib runpath. Points at ci-slang-sanitizer.yml for the CI equivalent.
Findings (1 total)
Severity Location Finding
🟡 Gap docs/building.md:647 Documents -DSLANG_ENABLE_TSAN=ON, a build option that does not exist (only SLANG_ENABLE_ASAN is defined)

Note: the "affected tests are reported as ignored rather than failed" claim was verified accurate — a failed dlopen of the render-test tool makes the -only-startup device probe fail, leaving the render API out of availableRenderApiFlags, so _canIgnore reports dependent tests as TestResult::Ignored (slang-test-main.cpp:1961→1104→5267→5564). The --preset release vs CI's releaseWithDebugInfo and bare clang vs clang-18 differences are acceptable local-dev generality (build/Release/lib is internally consistent with --preset release).

reviewed: 3103397 · diff sha256 d7a5758a1b41

Comment thread docs/building.md

```bash
export LD_LIBRARY_PATH="$PWD/build/Release/lib:$(clang -print-runtime-dir):$LD_LIBRARY_PATH"
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Gap: -DSLANG_ENABLE_TSAN=ON documents a build option that does not exist

This paragraph tells the reader that the same setup applies to a ThreadSanitizer build enabled via -DSLANG_ENABLE_TSAN=ON, but no such option exists in the build system. The only sanitizer option is SLANG_ENABLE_ASAN (CMakeLists.txt:162, "Enable AddressSanitizer (ASan), and UndefinedBehaviorSanitizer (UBSan) if available as well"), and cmake/CompilerFlags.cmake only implements -fsanitize=address/-fsanitize=undefined under that option — there is no -fsanitize=thread path. A grep of CMakeLists.txt, cmake/, and CMakePresets.json for TSAN/ThreadSanitizer returns zero build-configuration matches, and ci-slang-sanitizer.yml configures ASan only.

Example: A reader following this line runs cmake --preset default -DSLANG_ENABLE_TSAN=ON. CMake emits a "Manually-specified variables were not used by the project" warning and produces an ordinary, non-instrumented build — not a ThreadSanitizer build — so the described libclang_rt.tsan-x86_64.so setup never applies. Since the PR's purpose is to "record the environment an ASan build needs," documenting a toggle the build does not honor is actively misleading.

Suggested fix: Drop the TSAN paragraph (lines 647–648), or gate it as aspirational (e.g. "if a SLANG_ENABLE_TSAN option is added…"), or add the actual CMake option before documenting it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: non-breaking PRs without breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants