Skip to content

Dockerfile.windows: enable assertions and disable /GF for the sanitizer build#298

Merged
Jarred-Sumner merged 2 commits into
mainfrom
robobun/windows-asan-assertions
Jul 16, 2026
Merged

Dockerfile.windows: enable assertions and disable /GF for the sanitizer build#298
Jarred-Sumner merged 2 commits into
mainfrom
robobun/windows-asan-assertions

Conversation

@robobun

@robobun robobun commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Matches the Linux/macOS Dockerfiles, which set ENABLE_ASSERTS=ON whenever ENABLE_SANITIZERS is non-empty, and additionally disables /GF string pooling (which /O2 turns on implicitly) for the sanitizer leg.

ENABLE_ASSERTS

Without this, bun-webkit-windows-amd64-asan ships with ASSERT_ENABLED=0, so ASSERT_ENABLED-gated symbols that the JSC headers reference from inline code (ObjectInitializationScope, DoesGCCheck::verifyCanGC, StrongRefTracker, Structure::checkConsistency, MarkedBlock::assertMarksNotStale, ...) are absent from the .lib. A consumer compiling with ASSERT_ENABLED=1 to match the other -asan prebuilts then fails to link, and a consumer compiling with ASSERT_ENABLED=0 gets a different WTF struct layout than the Linux/macOS asan artifacts (ASSERT_ENABLED gates fields like RefCountedBase::m_deletionHasBegun).

/GF-

clang-cl /O2 implies /GF, which emits each string literal as a SELECT_ANY COMDAT sized to the original string (e.g. 1 byte for ""). The ASAN descriptor for that literal still records size_with_redzone (32 bytes for "", larger for longer strings), so at runtime __asan_register_globals poisons past the end of the COMDAT section into whatever the linker placed next. It additionally lets an uninstrumented literal (from ICU, which the sanitizer leg does not instrument) win COMDAT selection over an instrumented one of the same content, with the instrumented descriptor still registered.

jsc.exe from the current tarball avoids this by luck of .rdata layout. In bun's larger link it surfaces as a deterministic global-buffer-overflow in icu_73::StringPiece::StringPiece via u_getTimeZoneFilesDirectory on first JSC::VM construction, with the report pointing at an instrumented WTF/JSC literal whose redzone covers an adjacent global.

With /GF-, string literals are private unnamed constants; the ASAN padding is part of the section and cannot merge with ICU's uninstrumented literals.

Non-sanitizer Windows legs are unchanged (ENABLE_ASSERTS=AUTO is the existing cmake default; SAN_FLAGS stays empty).

Matches the Linux/macOS Dockerfiles, which set ENABLE_ASSERTS=ON whenever
ENABLE_SANITIZERS is non-empty. Without this, bun-webkit-windows-amd64-asan
ships with ASSERT_ENABLED=0, so ASSERT_ENABLED-gated symbols that the JSC
headers reference from inline code (ObjectInitializationScope,
DoesGCCheck::verifyCanGC, StrongRefTracker, Structure::checkConsistency,
MarkedBlock::assertMarksNotStale, ...) are absent from the .lib. Consumers
that compile with ASSERT_ENABLED=1 then fail to link, and consumers that
compile with ASSERT_ENABLED=0 get a different WTF struct layout than the
Linux/macOS asan artifacts (ASSERT_ENABLED gates fields like
RefCountedBase::m_deletionHasBegun).
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8dbe1044-f16e-4ef0-be40-a7f206c4f1a9

📥 Commits

Reviewing files that changed from the base of the PR and between e5f7fc2 and 5b80fd1.

📒 Files selected for processing (1)
  • Dockerfile.windows

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

@claude claude 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.

LGTM — brings the Windows sanitizer leg into parity with Dockerfile / Dockerfile.macos.

What was reviewed:

  • Confirmed Dockerfile and Dockerfile.macos use the identical ENABLE_ASSERTS=AUTOON-when-sanitizers pattern.
  • Confirmed ENABLE_ASSERTS accepts AUTO/ON/OFF in Source/cmake/OptionsCommon.cmake, so the non-sanitizer path (AUTO) is a no-op vs. the prior implicit default.
  • Checked shell chaining: the new ; \ continuation between the two assignment lines is fine (assignments can't fail; matches the existing SAN_FLAGS=""; if ... idiom on the same line).
Extended reasoning...

Overview

Two-line change to Dockerfile.windows in the WebKit cmake configure step: introduce a shell-local ENABLE_ASSERTS variable defaulting to AUTO, flip it to ON inside the existing if [ -n "${ENABLE_SANITIZERS}" ] branch, and pass it through as -DENABLE_ASSERTS=.... This mirrors the exact pattern already present in Dockerfile (lines 263-266, 290) and Dockerfile.macos (lines 187-188, 214).

Security risks

None. This is a CI/build-artifact configuration flag that toggles ASSERT_ENABLED in the produced sanitizer prebuilt. No auth, crypto, permissions, or runtime-input handling is touched.

Level of scrutiny

Low. It's a mechanical parity fix for a build matrix leg (bun-webkit-windows-amd64-asan) and only affects the sanitizer variant — the non-sanitizer path now passes -DENABLE_ASSERTS=AUTO explicitly, which OptionsCommon.cmake:293 shows is the existing cache default, so behavior there is unchanged. Any regression would surface immediately as a CI build failure rather than a runtime bug.

Other factors

  • The shell edit keeps the surrounding &&-chain intact: the split into SAN_FLAGS=""; ENABLE_ASSERTS="AUTO"; \ followed by if ... fi && \ is equivalent to the previous single line since variable assignments always succeed and the if still terminates with &&.
  • OptionsCommon.cmake confirms ENABLE_ASSERTS is a tri-state (AUTO/ON/OFF) and that ON prepends -DASSERT_ENABLED=1, which is exactly what the PR description says is needed for the ASSERT-gated symbols to be present in the .lib.
  • No prior reviewer comments to address; coderabbit was rate-limited and left no substantive feedback.

clang-cl /O2 implies /GF, which emits each string literal as a SELECT_ANY
COMDAT sized to the original string. The ASAN descriptor for that literal
records size_with_redzone, so at runtime __asan_register_globals poisons
past the end of the COMDAT section into whatever the linker placed next.
In the bun link (larger .rdata than jsc.exe) that manifests as a
global-buffer-overflow on first VM init when ICU reads its own empty
string literal (merged with an instrumented WTF/JSC literal by the
linker). With /GF-, string literals are private unnamed constants and the
ASAN padding is part of the section.
@robobun robobun changed the title Dockerfile.windows: enable assertions for the sanitizer build Dockerfile.windows: enable assertions and disable /GF for the sanitizer build Jul 16, 2026

@claude claude 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.

LGTM — small, self-contained build-config change bringing the Windows sanitizer leg into parity with the Linux/macOS Dockerfiles.

What was reviewed:

  • Confirmed Dockerfile and Dockerfile.macos already set ENABLE_ASSERTS=ON under ENABLE_SANITIZERS; this mirrors that pattern.
  • Confirmed ENABLE_ASSERTS is a valid cache var in OptionsCommon.cmake with AUTO as the default, so non-sanitizer legs are unchanged.
  • Checked whether /GF- in CMAKE_C(XX)_FLAGS could be overridden by a later /GF on the compile line — ruled out.
Extended reasoning...

Overview

This PR touches a single file, Dockerfile.windows, and changes three lines in the WebKit cmake configure step: it initializes ENABLE_ASSERTS="AUTO", and inside the existing if [ -n "${ENABLE_SANITIZERS}" ] branch it (a) prepends /GF- to SAN_FLAGS and (b) sets ENABLE_ASSERTS="ON". It then passes -DENABLE_ASSERTS="${ENABLE_ASSERTS}" to cmake. No source code, no runtime logic, no other build legs are touched.

Security risks

None. This is a Docker build recipe for a CI artifact. No new inputs are introduced, no network endpoints, no auth/crypto/permissions. The added flags are compiler/cmake options that only affect the -asan Windows tarball.

Level of scrutiny

Low. The change is:

  • Mechanical parity: Dockerfile (line 263-266, 290) and Dockerfile.macos (line 187-188, 214) already do exactly this ENABLE_ASSERTS=AUTOON-under-sanitizers dance and pass it to cmake. This PR copies that pattern verbatim.
  • Scoped to a debug/CI artifact: only the ENABLE_SANITIZERS-gated leg changes. The non-sanitizer Windows builds get SAN_FLAGS="" and ENABLE_ASSERTS="AUTO", which OptionsCommon.cmake:293 confirms is the existing cmake default — a no-op for those legs.
  • Well-motivated: the PR description gives a concrete, reproducible failure (global-buffer-overflow in icu_73::StringPiece::StringPiece on first VM construction in bun's link) that /GF- addresses, and a concrete link/ABI-layout mismatch that ENABLE_ASSERTS=ON addresses. The author has clearly exercised the resulting artifact.

Other factors

  • The bug hunting system found no issues. One finder raised the possibility that /GF- (placed in CMAKE_C(XX)_FLAGS) is overridden by a later /GF on the compile line (from /O2 in CMAKE_CXX_FLAGS_RELEASE or add_compile_options(/Oy- /Gw /Gy /GF) in OptionsMSVC.cmake:98); the verifier examined this and refuted it.
  • Shell syntax is correct: the new ENABLE_ASSERTS="AUTO"; assignment is chained with the surrounding && via the following if ...; fi &&, matching the existing SAN_FLAGS/EXE_LD_FLAGS idiom in the same RUN block.
  • No prior reviews from me on this PR; the only timeline entry is a coderabbit rate-limit notice.

Given the tiny scope, the established pattern being copied, and the fact that only a sanitizer CI artifact is affected, this is safe to approve without human review.

@github-actions

Copy link
Copy Markdown

Preview Builds

Commit Release Date
5b80fd1b autobuild-preview-pr-298-5b80fd1b 2026-07-16 10:21:15 UTC

@Jarred-Sumner
Jarred-Sumner merged commit 365cb02 into main Jul 16, 2026
49 checks passed
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