Skip to content

fix(wit): export module functions through interfaces so write cannot shadow libc - #20

Merged
DenhamPreen merged 2 commits into
mainfrom
fix/namespace-wit-exports
Sep 7, 2026
Merged

DenhamPreen merged 2 commits into
mainfrom
fix/namespace-wit-exports

Conversation

@DenhamPreen

@DenhamPreen DenhamPreen commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Found while getting CI green: decoder_then_stdout_roundtrip and stdout_and_blackhole_sinks_accept_writes_and_flushes fail on main, locally and on the Linux runner, with a trap in stdout_sink.wasm!dlfree.

Cause. The sink world exported write at world level, so the core module carries a symbol literally named write. wasm-ld resolves wasi-libc's write(2) to it instead of pulling libc's own. Current stable Rust routes wasip2 stdout/stderr through libc write, so the moment a guest prints (the stdout sink, or any module's panic message) it calls its own write export with libc's arguments and corrupts its heap. The backtrace shows exactly that chain: Stderr::write_all → write → _export_write_cabi → dlfree trap.

Fix. Exports move into processor-impl and sink-impl interfaces (wit/hyperpipe.wit, mirrored in examples/wit and the ARCHITECTURE excerpt). Core symbols become envio:hyperpipe/sink-impl#write and cannot collide with anything. Host side calls bindings.envio_hyperpipe_sink_impl().call_write(..); the SDK export macros implement the interface Guest; the raw-bindgen blackhole-sink imports it. Modules written against the SDK need no source change, just a rebuild.

This is a WIT change, so existing compiled .wasm artifacts must be rebuilt (./scripts/build-modules.sh, just build-example-module).

Test plan

  • cargo test -p hp-wasm-host: lib 44/44, integration 32/32 (was 30/32)
  • cargo test -p hp-cli, cd modules && cargo test
  • All guest modules and examples/modules/enrich build for wasm32-wasip2

Touches crates/wasm-host/src/lib.rs near the same lines as #19 (wasmtime bump); whichever merges second gets a trivial conflict.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tj76igEYjgdV7iZ7kaMxN8

Summary by CodeRabbit

  • Improvements
    • Processor and sink operations are now grouped under dedicated interfaces, providing clearer namespacing and avoiding conflicts with standard symbols.
    • Updated component integrations and examples to use the new processor and sink interfaces.
    • Existing processing, writing, flushing, error handling, and pooling behavior remains unchanged.
  • Documentation
    • Added guidance explaining the interface organization and symbol-collision considerations.

…t shadow libc

A world-level `export write` becomes a core-module symbol named `write`,
which the linker resolves in place of wasi-libc's `write(2)`. With the
current stable Rust, std's wasip2 stdout/stderr go through libc `write`,
so any guest that prints (the stdout sink, or a panic message from any
module) calls its own export with garbage arguments and corrupts its
heap. Symptom: `stdout_sink.wasm!dlfree` trap, reproduced locally and in
CI on Linux.

Move the exports into `processor-impl` / `sink-impl` interfaces. Core
symbols are now `envio:hyperpipe/sink-impl#write` etc. and cannot
collide with anything. The host calls
`bindings.envio_hyperpipe_sink_impl().call_write(..)`; the SDK macros
implement the interface `Guest` trait; the raw-bindgen blackhole sink
imports it. Module authors using the SDK see no change.

`cargo test -p hp-wasm-host --test integration`: 32/32 (was 30/32).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tj76igEYjgdV7iZ7kaMxN8
@coderabbitai

coderabbitai Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 665a93ae-0480-4ece-9d24-9965092d3a89

📥 Commits

Reviewing files that changed from the base of the PR and between fda25af and 45ba8e5.

📒 Files selected for processing (6)
  • ARCHITECTURE.md
  • crates/wasm-host/src/lib.rs
  • examples/wit/hyperpipe.wit
  • modules/blackhole-sink/src/lib.rs
  • modules/sdk/src/lib.rs
  • wit/hyperpipe.wit

Included review availability: 2 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


📝 Walkthrough

Walkthrough

The WIT contracts now export processor and sink operations through named implementation interfaces. SDK Guest implementations and wasm-host calls use the generated interface-specific bindings.

Changes

Interface namespacing

Layer / File(s) Summary
WIT interface contracts
ARCHITECTURE.md, wit/hyperpipe.wit, examples/wit/hyperpipe.wit
Adds processor-impl and sink-impl interfaces and exports them from the corresponding worlds.
Component binding updates
modules/sdk/src/lib.rs, modules/blackhole-sink/src/lib.rs
Updates shared type re-exports and Guest implementations to use the generated implementation interfaces.
Host interface calls
crates/wasm-host/src/lib.rs
Routes processor initialization, processing, sink initialization, writing, and flushing through the new interface bindings.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 45ba8

The processor and sink exports are consistently namespaced to prevent the libc write-symbol collision. Modules must be rebuilt, but no actionable merge-blocking issue remains.

Suggested reviewers: nikbhintade

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. (3 skipped: 3… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: moving module function exports into interfaces to prevent the write symbol from shadowing libc.
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

Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Warning

Some tools did not complete. Review the errors below.

🔧 Clippy (1.97.1)

Clippy execution failed


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

…orts

# Conflicts:
#	crates/wasm-host/src/lib.rs
@DenhamPreen
DenhamPreen merged commit 69dfd54 into main Sep 7, 2026
3 checks passed
@DenhamPreen
DenhamPreen deleted the fix/namespace-wit-exports branch September 7, 2026 14:13
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.

1 participant