Skip to content

Reject lossy WASI file path conversions - #1158

Open
JustYannicc wants to merge 3 commits into
servo:mainfrom
JustYannicc:fix/wasi-reject-lossy-file-paths
Open

JustYannicc wants to merge 3 commits into
servo:mainfrom
JustYannicc:fix/wasi-reject-lossy-file-paths

Conversation

@JustYannicc

Copy link
Copy Markdown

On WASI, Url::from_file_path currently returns Ok after replacing invalid UTF-8 filename bytes with U+FFFD. For example, the WASIp1 path b"/foo/ba\x80r" becomes file:///foo/ba%EF%BF%BDr, so converting it back addresses a different filename.

Reject invalid UTF-8 in the WASI encoder, consistent with the existing WASI decoder. This keeps the stable WASIp2 support from #983 and avoids a new dependency on WASIp2's unstable std::os::wasi APIs. Native platform behavior is unchanged. The regression constructs the invalid path in memory; no filesystem access is needed.

Validation with Rust 1.95.0:

  • The new WASIp1 invalid-byte test fails before the fix, then passes with it under Node 24.18.0's WASI host.
  • Both new WASIp1 tests pass, including valid Unicode U+FFFD and é round trips.
  • The existing native new_path_bad_utf8 test passes.
  • The WASIp2 unit-test binary compiles and links; WASIp2 runtime was not tested.
  • Targeted rustfmt and diff whitespace checks pass. Independent source review found no correctness findings.

Commands:

cargo +1.95.0 test -p url --test unit new_path -j 2
cargo +1.95.0 test -p url --test unit --target wasm32-wasip1 --no-run -j 2
cargo +1.95.0 test -p url --test unit --target wasm32-wasip2 --no-run -j 2

Run the WASIp1 binary with the following Node script, passing its path as the first argument:

import { WASI } from 'node:wasi';
import { readFileSync } from 'node:fs';
const binary = process.argv[2];
const wasi = new WASI({
  version: 'preview1',
  args: [binary, 'new_path_wasi', '--test-threads=1'],
  env: {},
  preopens: {},
  returnOnExit: true,
});
const instance = new WebAssembly.Instance(
  new WebAssembly.Module(readFileSync(binary)), wasi.getImportObject());
process.exitCode = wasi.start(instance);

Implemented with GPT 6.1 Sol through the Codex harness.

This branch has not been deployed

No deployments
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