maxdeviant added the bug label to Issue #10415.
maxdeviant opened issue #10415:
We use Wasm and Wasmtime to power the extension system in Zed and are seeing some undesired behavior with
std::env::current_dir
when executing Wasm on Windows.I have created a minimized test case that I believe showcases the issue. The repo can be found at maxdeviant/wasmtime-current-dir-repro. It contains CI set up to run the reproduction case on Windows, as well as on macOS and Linux to contrast the behaviors.
If the Wasmtime repo isn't the right place for this issue, let me know where I can redirect it.
Test Case
In the reproduction repo above, I have the following Rust program:
fn main() { let pwd = std::env::var("PWD").expect("failed to get PWD"); println!("PWD: {pwd:?}"); println!( "Before: {:?}", std::env::current_dir().expect("failed to get current_dir") ); std::env::set_current_dir(pwd).expect("failed to set current_dir"); println!( "After: {:?}", std::env::current_dir().expect("failed to get current_dir") ); }
When run on Windows with the
PWD
environment variable set toD:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
this is the output of the program:PWD: "D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro" Before: "/" After: "/D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro"
Steps to Reproduce
- Compile the above program with
cargo build --target wasm32-wasip1
- Run the Wasm program on Windows with
wasmtime run --dir=$PWD --env PWD ./target/wasm32-wasip1/debug/wasm-current-dir-repro.wasm
- Observe that the
std::env::current_dir
path in theAfter:
line contains a leading slashExpected Results
std::env::current_dir
returnsD:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
as the path.Actual Results
std::env::current_dir
returns/D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
as the path (note the leading slash).Versions and Environment
Wasmtime version or commit:
wasmtime 30.0.2 (398694a59 2025-02-25)
Operating system: Windows
Architecture: x64
Extra Info
I also tried testing this with
--target wasm32-wasip2
to see if it would make a difference, and it did not: the output remained the same on Windows (containing a leading slash).
maxdeviant edited issue #10415:
We use Wasm and Wasmtime to power the extension system in Zed and are seeing some undesired behavior with
std::env::current_dir
when executing Wasm on Windows.I have created a minimized test case that I believe showcases the issue. The repo can be found at maxdeviant/wasmtime-current-dir-repro. It contains CI set up to run the reproduction case on Windows, as well as on macOS and Linux to contrast the behaviors.
If the Wasmtime repo isn't the right place for this issue, let me know where I can redirect it.
Test Case
In the reproduction repo above, I have the following Rust program:
fn main() { let pwd = std::env::var("PWD").expect("failed to get PWD"); println!("PWD: {pwd:?}"); println!( "Before: {:?}", std::env::current_dir().expect("failed to get current_dir") ); std::env::set_current_dir(pwd).expect("failed to set current_dir"); println!( "After: {:?}", std::env::current_dir().expect("failed to get current_dir") ); }
When run on Windows with the
PWD
environment variable set toD:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
this is the output of the program:PWD: "D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro" Before: "/" After: "/D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro"
Steps to Reproduce
- Compile the above program with
cargo build --target wasm32-wasip1
- Run the Wasm program on Windows with
wasmtime run --dir=$PWD --env PWD ./target/wasm32-wasip1/debug/wasm-current-dir-repro.wasm
- Observe that the
std::env::current_dir
path in theAfter:
line contains a leading slashExpected Results
std::env::current_dir
returnsD:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
as the path.Actual Results
std::env::current_dir
returns/D:/a/wasmtime-current-dir-repro/wasmtime-current-dir-repro
as the path (note the leading slash).Versions and Environment
Wasmtime version or commit:
wasmtime 30.0.2 (398694a59 2025-02-25)
Operating system: Windows 10
Architecture: x64
Extra Info
I also tried testing this with
--target wasm32-wasip2
to see if it would make a difference, and it did not: the output remained the same on Windows (containing a leading slash).
alexcrichton commented on issue #10415:
Thanks for the report, and thank you for minimizing this as well, it's much appreciated! I fear though that I may not have great news for you as this is not going to be an easy bug to fix.
Unfortunately this has nothing to do with Wasmtime, it's got everything to do with the guest program itself. However it's also not entirely fair (IMO) to "point the finger of blame" at the guest program. In the end this is basically a situation that's not super well supported today.
To elaborate on that, what's happening here is, as you've seen, a clash of Windows an Unix paths. Windows understands that the leading
D:/
is a drive prefix but to a unix path system (which WASI targets use currently) there's no knowledge of theD:/
prefix so it looks like a folder name, meaning"/".join("D:/")
produces"/D:/"
. The default current directory is set in wasi-libc itself which is/
by default (as you've seen), so changing the current directory toD:/...
is interpreted in a similar manner toset_current_dir("foo")
which would change to/foo
. Effectively WASI and wasi-libc are using a unix-like filesystem format and there's nothing on Windows to do any sort of translation between the two.The question is then somewhat: "who should do this translation?" A reasonable answer is "wasmtime!" but unfortunately the tools aren't in place for that right now. For example to Wasmtime this is "just another env var" being passed to the program and it has no idea that
PWD
is in fact a path. Wasmtime would then additionally need to have some sort of translation understanding that when mounting the root path there's some sort of understanding/translation to access the various drives. This is all theoretically possible but not set up today.So in essence the problem you're running into is that when giving access to the whole filesystem to windows guest someone or something will have to do translation of windows paths. As-is today something would have to translate
D:/...
to something unix-like (like/d/...
) and would need to translate both ways (e.g. passing paths to the guest and processing paths received from the guest as well). My gut is that something inwasmtime-wasi
probably wants to do this as opposed to guest programs and/or changes to wasi-libc, but I'm not actually sure what that would look like. Overall I don't think we've sufficiently filled out functionality in "give the guest access to the entire host drive" in Wasmtime, which is where this is all stemming from.cc @sunfishcode this seems like the kind of bug/issue you might be interested in being aware of
maxdeviant commented on issue #10415:
Thank you for the reply, @alexcrichton!
Unfortunately this has nothing to do with Wasmtime, it's got everything to do with the guest program itself. However it's also not entirely fair (IMO) to "point the finger of blame" at the guest program. In the end this is basically a situation that's not super well supported today.
This is pretty much what I expected, but wanted to make get confirmation by opening this issue rather than simply assuming :smile:
Last updated: Apr 18 2025 at 09:03 UTC