Is it a deliberate decision to pass functions like path_open
a GuestPtr<'_, str>
rather than resolving that to a &str
in the wrapper?
Currently yes, since obtaining &str
is unsafe and requires manually tracking borrows. That's why whenever you want to obtain a &str
, you'required to invoke
let mut bc = GuestBorrows::new(); unsafe { &*ptr.as_raw(&mut bc) }
This way we're trying to avoid any overlapping borrows that may occur.
Now, I'm not sure how valid or difficult it would be to push the resolution to the layer above the trait method such as path_open
I'm worried it might become quite tricky to properly track borrows then, although in case of strings, they are meant to be immutable (for now at least) and we create a new borrow checker instance per each resolution of &str
Would it help if we could assume that no witx API will have aliasing of any mutable references?
It probably would in part, but what about reentrancy e.g., recursive calls, etc?
Ah, interesting. So nothing in WASI currently is recursive, but in the general case, witx APIs could be.
Yep, that was the motivating factor behind the current design.
Hmm, but even with recursive functions, how could you get aliasing between a mutable buffer and another pointer in the same scope?
Hmm, so assuming you could get &str
to some region in guest's memory, and then from WASI's host function you'd want to call back in guest's memory again, that would potentially require some intricate mechanism for tracking borrows, wouldn't it? At least that's how I understood it when chatting with @Alex Crichton about it.
yes this is protections in general against bugs in wasmtime
even without recursion once you have &str
you can't modify the contents, but using the APIs of Memory
it's very easy to modify the contents with an accidentally aliasing guest mutable pointer
acquisition of &str
is a pretty unsafe operation (basically just runs into these examples)
We could however copy out the contents of that region into a String
and pass that around, but I'm worried this might be somewhat heavy and unnecessary at times?
it's true that is almost always safe, yeah
@Dan Gohman do you think passing paths as String
would be something we could consider?
I wouldn't rule it out, but it doesn't seem like something we need to do right now.
I'd like to think a bit and see what other ideas we can come up with.
Such as, what if we added a parameter to from_witx
which could say "I promise that none of my implementations will re-enter (on penalty of undefined behavior)"
"or call memory.grow
or equivalent"
Last updated: Nov 22 2024 at 16:03 UTC