Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move precompiled module detection into wasmtime #5342

Merged
merged 10 commits into from
Dec 1, 2022

Conversation

cr0sh
Copy link
Contributor

@cr0sh cr0sh commented Nov 29, 2022

Previously, wasmtime-cli checked the module to be loaded is
precompiled or not, by pre-opening the given file path to
check if the "\x7FELF" header exists.
This commit moves this branch into the Module::from_trusted_file,
which is only invoked with --allow-precompiled flag on CLI.

The initial motivation of the commit is, feeding a module to wasmtime
from piped inputs, is blocked by the pre-opening of the module.
The Module::from_trusted_file, assumes the --allow-precompiled flag
so there is no piped inputs, happily mmap-ing the module to test
if the header exists.
If --allow-precompiled is not supplied, the existing Module::from_file
will be used, without the additional header check as the precompiled
modules are intentionally not allowed on piped inputs for security measures.

One caveat of this approach is that the user may be confused if
he or she tries to execute a precompiled module without
--allow-precompiled, as wasmtime shows an 'input bytes aren't valid
utf-8' error, not directly getting what's going wrong.
So this commit includes a hack-ish workaround for this: If the error
on Module::new ends with "input bytes aren't valid utf-8" strings,
show a simple note to the standard error stream.

This might be a small hiccup on preparing i18n or changing error
format on the wat crate, but I feel comfortable (yet) this strategy
because the wat crate includes tests for the error messages, so one
would notice the breakage if the error message have changed.

Thanks to @jameysharp for suggesting this idea with a detailed guidance.

Note: this supercedes #5035.

This applies to unix targets only,
as Windows does not have an appropriate alternative.
@github-actions github-actions bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label Nov 29, 2022
@github-actions
Copy link

Subscribe to Label Action

cc @peterhuene

This issue or pull request has been labeled: "wasmtime:api"

Thus the following users have been cc'd because of the following labels:

  • peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

Copy link
Contributor

@jameysharp jameysharp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks like exactly what I hoped for! There are a couple issues—most notably, this doesn't compile due to some other changes that happened while you were working on it. I hope the fixes will be straightforward, but do let me know if you run into any trouble!

@@ -241,6 +241,10 @@ impl Module {
if #[cfg(feature = "wat")] {
let mut e = e.downcast::<wat::Error>()?;
e.set_path(file);
if e.to_string().ends_with("input bytes aren't valid utf-8") {
eprintln!("note: wasmtime might be trying to load a precompiled binary without --allow-compiled.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant --allow-precompiled here:

Suggested change
eprintln!("note: wasmtime might be trying to load a precompiled binary without --allow-compiled.");
eprintln!("note: wasmtime might be trying to load a precompiled binary without --allow-precompiled.");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the wasmtime library should print to stderr. There is no way for a binary to suppress this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, wasmtime is a library so eprintln should be avoided if possible. How about deferring this eprintln to the wasmtime-cli? This would make wasmtime-cli add wat dependency to downcast error.
Also the #[cfg(feature = "wat")] branch condition cannot be used on wasmtime-cli, so this eprintln would be fired unconditionally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just suggested a different way to report this error, so let's delete this eprintln in favor of that alternative.

crates/wasmtime/src/module.rs Outdated Show resolved Hide resolved
Comment on lines 352 to 353
return SerializedModule::from_mmap(mmap, &engine.config().module_version)?
.into_module(engine);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, things changed underneath you (in #5153), so SerializedModule doesn't exist any more. Fortunately, I think this is an easy fix. In crates/wasmtime/src/engine.rs, make fn load_code be pub(crate). Then here you can call engine.load_code(mmap, ObjectKind::Module). See deserialize and deserialize_file for examples of the current pattern.

Copy link
Contributor Author

@cr0sh cr0sh Nov 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I forgot to cargo check again after rebasing. I'll fix at the eod today

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done and I found a small typo near load_code so fixed it too ;)

.into_module(engine);
}

Module::new(engine, &*mmap)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, is the * necessary here? I think if you write &mmap, Rust will still figure out that you want the dereferenced type. But I think the & is necessary either way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs a type implementing AsRef<[u8]> as argument. &MmapVec doesn't implement this. MmapVec only implements Deref and DerefMut.

cr0sh and others added 7 commits November 30, 2022 21:19
This applies to unix targets only,
as Windows does not have an appropriate alternative.
Previously, wasmtime-cli checked the module to be loaded is
precompiled or not, by pre-opening the given file path to
check if the "\x7FELF" header exists.
This commit moves this branch into the `Module::from_trusted_file`,
which is only invoked with `--allow-precompiled` flag on CLI.

The initial motivation of the commit is, feeding a module to wasmtime
from piped inputs, is blocked by the pre-opening of the module.
The `Module::from_trusted_file`, assumes the --allow-precompiled flag
so there is no piped inputs, happily mmap-ing the module to test
if the header exists.
If --allow-precompiled is not supplied, the existing `Module::from_file`
will be used, without the additional header check as the precompiled
modules are intentionally not allowed on piped inputs for security measures.

One caveat of this approach is that the user may be confused if
he or she tries to execute a precompiled module without
--allow-precompiled, as wasmtime shows an 'input bytes aren't valid
utf-8' error, not directly getting what's going wrong.
So this commit includes a hack-ish workaround for this: If the error
on `Module::new` ends with "input bytes aren't valid utf-8" strings,
show a simple note to the standard error stream.

This might be a small hiccup on preparing i18n or changing error
format on the `wat` crate, but I feel comfortable (yet) this strategy
because the `wat` crate includes tests for the error messages, so one
would notice the breakage if the error message have changed.

Thanks to @jameysharp for suggesting this idea with a detailed guidance.
Co-authored-by: Jamey Sharp <jamey@minilop.net>
@cr0sh cr0sh force-pushed the run-piped-modules branch from 9fab923 to b30937e Compare November 30, 2022 12:20
cr0sh and others added 2 commits December 1, 2022 13:57
Copy link
Contributor

@jameysharp jameysharp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. Thank you for putting this together! You put a lot of work into this and I think it's turned out great.

@jameysharp jameysharp merged commit ebb693a into bytecodealliance:main Dec 1, 2022
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Dec 1, 2022
This commit addresses a few items I saw after reading bytecodealliance#5342 such as:

* `Module::from_trusted_file` no longer panics if the file length is
  less than 4
* `Module::from_trusted_file` with an empty file now returns a syntax
  error for `*.wat` instead of a "failed to map" error.
* Usage of `-` for stdin no works on Windows instead of just Unix.
* The filename for `-` reported to the executable is `<stdin>` rather
  than `stdin`.
@cr0sh cr0sh deleted the run-piped-modules branch December 1, 2022 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasmtime:api Related to the API of the `wasmtime` crate itself
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants