When we compute the amount of space that we need in a stack frame for
the stack limit check, we were only counting spill-slots and explicit
stack-slots. However, we need to account for all uses of the stack which
occur before the next stack limit check. That includes clobbers and any
stack arguments we want to pass to callees.
The maximum amount that we could have missed by is essentially bounded
by the number of arguments which could be passed to a function. In
Wasmtime, that is limited by `MAX_WASM_FUNCTION_PARAMS` in
`wasmparser::limits`, which is set to 1,000, and the largest arguments
are 16-byte vectors, so this could undercount by about 16kB.
This is not a security issue according to Wasmtime's security policy
(https://docs.wasmtime.dev/security-what-is-considered-a-security-vulnerability.html)
because it's the embedder's responsibility to ensure that the stack
where Wasmtime is running has enough extra space on top of the
configured `max_wasm_stack` size, and getting within 16kB of the host
stack size is too small to be safe even with this fixed.
However, this was definitely not the intended behavior when stack limit
checks or stack probes are enabled, and anyone with non-default
configurations or non-Wasmtime uses of Cranelift should evaluate whether
this bug impacts your use case.
(For reference: When Wasmtime is used in async mode or on Linux, the
default stack size is 1.5MB larger than the default WebAssembly stack
limit, so such configurations are typically safe regardless. On the
other hand, on macOS the default non-async stack size for threads other
than the main thread is the same size as the default for
`max_wasm_stack`, so that is too small with or without this bug fix.)
Co-authored-by: Jamey Sharp <jsharp@fastly.com>
This commit fixes an accidental issue introduced in #8018 where using an
element segment which had been dropped with an `externref` table would
cause a panic. The panic happened due to an assertion that tables are
being used with the right type of item and that was being mismatched.
The underlying issue was that dropped element segments are modeled as an
empty element segment but the empty element segment was using the
"functions" encoding as opposed to the "expressions" encoding. This
meant that code later assumed that due to the use of functions the table
must be a table-of-functions, but this was not correct for
externref-based tables.
The fix in this commit is to instead model the encoding as an
"expressions" list which means that the table type is dispatched on to
call the appropriate initializer.
There is no memory safety issue with this mistake as the assertion was
specifically targetted at preventing memory safety. This does, however,
enable any WebAssembly module to panic a host.
Closes#8281
* Fix `wasmtime settings` command.
Currently the `settings` command panics because the tunables are not set in the
compiler builder.
This commit creates a default tunables based on either the target triple passed
on the command line or uses the default for the host.
Fixes#8058.
* Additional clean up.
Co-authored-by: Peter Huene <peter@huene.dev>
* wasmtime-wasi: introduce WasiP1Ctx, re-jigger p0 & p1 linkers to take closure (#8053)
and add a few missing bits of functionality for use in the c-api
* wasmtime c-api: warn that wasi_config_preopen_socket is deprecated in next release (#8064)
this PR will be backported to the release-19.0.0 branch prior to the 19
release.
* Add release notes
---------
Co-authored-by: Pat Hickey <phickey@fastly.com>
* Add commentary on advantages/disadvantages of the pooling allocator
Inspired by discussion on #8034
* Add `memory_init_cow` commentary on disadvantages
* Fix doc link
* Show true error reason in `wasmtime serve`
The `wasmtime serve` command prints failed HTTP handling to `stderr`
but, when the reason was due to failure inside the HTTP handler itself,
the printed error message is not descriptive enough. After looking at
long dumps of `guest never invoked `response-outparam::set` method`, I
realized that errors inside the Tokio `task` are never propagated
outwards. This change captures those errors and appends them to the
printed error message.
* review: remove TODO comment
* review: improve doc comment
Co-authored-by: Trevor Elliott <telliott@fastly.com>
* review: add comment about immediate resolution
---------
Co-authored-by: Trevor Elliott <telliott@fastly.com>
* Add CLI flags for instance limits
While experimenting with `wasmtime serve`, I found it helpful to be able
to configure some of the maximum limits of the various objects stored in
the pooling allocator. This change surfaces some new `-O total-*` flags
for controlling these limits from the command line.
* review: prepend flags with `pooling_*`
* update capstone dependency to 0.12.0
this is only used for benchmarking, so the cargo vet is just an exemption which I updated to the latest version.
* winch filetests: fix capstone changes
* Add WinML backend for wasi-nn.
* Log execution time.
* WinML backend supports execution target selection.
ExecutionTarget::Gpu is mapped to LearningModelDeviceKind::DirectX.
* Limit WinML backend on Windows only.
* Move wasi-nn WinML example to new test infra.
* Scale tensor data in test app.
App knows input and target data range, so it's better to let app to
handle scaling.
* Remove old example for wasi-nn WinML backend.
* Update image2tensor link.
* Format code.
* Upgrade image2tensor to 0.3.1.
* Upgrade windows to 0.52.0
* Use tensor data as input for wasi-nn WinML backend test.
To avoid involving too many external dependencies, input image is
converted to tensor data offline.
* Restore trailing new line for Cargo.toml.
* Remove unnecessary features for windows crate.
* Check input tensor types.
Only FP32 is supported right now. Reject other tensor types.
* Rename default model name to model.onnx.
It aligns with openvino backend.
prtest:full
* Run nn_image_classification_winml only when winml is enabled.
* vet: add trusted `windows` crate to lockfile
* Fix wasi-nn tests when both openvino and winml are enabled.
* Add check for WinML availability.
* vet: reapply vet lock
---------
Co-authored-by: Andrew Brown <andrew.brown@intel.com>
This commit fixes an issue when inspecting the types of a component
where if a resource type wasn't substituted through an import it would
end up panicking. The fix here is to add a third kind of resource type
which represents an uninstantiated component as opposed to an
instantiated component or host type.
Closes#8003
When native unwinding information is enabled Wasmtime will use the
`__register_frame` API on Unix platforms to inform the runtime of the
unwinding information generated for wasm modules. This function,
however, has a different interface in libgcc vs libunwind. This means
that we need to detect which is being used and adapt our calls to it
appropriately.
Previously this decision was static. FreeBSD and Linux glibc would
assume libgcc and everything else was assumed to be libunwind. It's
possible to use libgcc on other platforms, however, such as with musl.
The goal of this PR is to make the detection here more robust.
Specifically this PR now probes for a symbol at runtime rather than
relying on a compile-time decision. That way we can see what we got at
runtime and make the decision then.
Closes#7997
* Add a "custom" platform configuration for Wasmtime
This commit leverages adds a new "platform" to Wasmtime to be supported
in the `crates/runtime/src/sys` folder. This joins preexisting platforms
such as Unix and Windows. The goal of this platform is to be an opt-in
way to build Wasmtime for targets that don't have a predefined way to
run.
The new "custom" platform requires `--cfg wasmtime_custom_platform` to
be passed to the Rust compiler, for example by using `RUSTFLAGS`. This
new platform bottoms out in a C API that is intended to be small and
Linux-like. The C API is effectively the interface to virtual memory
that Wasmtime requires. This C API is also available as a header file at
`examples/min-platform/embedding/wasmtime-platform.h` (generated by
`cbindgen`).
The main purpose of this is to make it easier to experiment with porting
Wasmtime to new platforms. By decoupling a platform implementation from
Wasmtime itself it should be possible to run these experiments
out-of-tree. An example of this I've been working on is getting
Wasmtime running on bare-metal with a custom kernel. This support
enables defining the platform interface of the custom kernel's syscalls
outside of Wasmtime.
* Exclude wasmtime-platform.h from formatting
* Include build-wasmtime-target-wasm32 in final job
* Don't force any single toolchain
* Add notes to no_std docs
* Add rust-src to CI
* Review comments
* Change APIs to be fallible
* Only compile the min-platform example on Linux
* Fix compile of min-platform example
* Fix another compile error in the example
This commit is an attempt to make the mistake fixed in #8016 harder to
happen again. This removes the `set_raw` helper entirely from tables and
instead forces all callers to view the table as either a table of
funcrefs or a table of externefs. By forcing that choice outwards
instead of handling it inwards it enables dealing with a typed table in
more contexts which should help naturally do the right thing.
While debugging #7999, we learned of a possible, extremely subtle,
interaction between the design of our ISLE mid-end prelude and matching
rules with a certain structure. Because a `Value` represents an entire
eclass, separate left-hand sides (as in helper rules or if-let clauses)
that match on the value may match against different enodes returned by
the multi-match extractor's iterator. We then may infer some property of
one enode, another property of another enode, and perform a rewrite that
is only valid if both of those matches are on the same enode.
The precise distinction is whether it is a property of the *value* -- e.g.,
nonzero, or even, or within a range -- or a property of the *operation*
and matched subpieces. The former is fine, the latter runs into
trouble. We found that #7719 added a helper that determined whether a
value "was a certain operator" -- actually, had any enode of a certain
operator -- and separately, matched "the operator" and extracted its
opcode and parameters (actually, *any* binary operator). The first half
can match an opcode we support simplifying, and the second half can get
the arguments and `op` and blindly use them in the rewrite.
This PR adds new guidance to avoid complex helpers and be aware of
multi-matching behavior, preferring to write patterns directly (as the
fix in #8005 does) instead. Longer-term, we also have other ideas, e.g.
@jameysharp's suggestion to disallow at-patterns on multi-extractors in
left hand sides to reduce the chance of hitting this footgun.
This logs the resulting values of a call into ISLE's `simplify` constructor, not
just the input value, so we can better debug in the future by tracing how a value
was produced and which value it is a rewrite of.
New output:
Calling into ISLE with original value v2
-> returned from ISLE: v2 -> [v3, v4, v5]
Old output:
Calling into ISLE with original value v2
-> returned from ISLE, generated 3 optimized values
We had two optimization rules which started off like this:
(rule (simplify (ireduce smallty val@(binary_op _ op x y)))
(if-let _ (reducible_modular_op val))
...)
This was intended to check that `x` and `y` came from an instruction
which not only was a binary op but also matched `reducible_modular_op`.
Unfortunately, both `binary_op` and `reducible_modular_op` were
multi-terms.
- So `binary_op` would search the eclass rooted at `val` to find each
instruction that uses a binary operator.
- Then `reducible_modular_op` would search the entire eclass again to
find an instruction which matched its criteria.
Nothing ensured that both searches would find the same instruction.
The reason these rules were written this way was because they had
additional guards (`will_simplify_with_ireduce`) which made them fairly
complex, and it seemed desirable to not have to copy those guards for
every operator where we wanted to apply this optimization.
However, we've decided that checking whether the rule is actually an
improvement is not desirable. In general, that should be the job of the
cost function. Blindly adding equivalent expressions gives us more
opportunities for other rules to fire, and we have global recursion and
growth limits to keep the process from going too wild.
As a result, we can just delete those guards. That allows us to write
the rules in a more straightforward way.
Fixes#7999.
Co-authored-by: Trevor Elliott <telliott@fastly.com>
Co-authored-by: L Pereira <l.pereira@fastly.com>
Co-authored-by: Chris Fallin <chris@cfallin.org>
This commit is an implementation of #7860 for Wasmtime where
`wasmtime::component::Linker` is now "semver aware". This means that it
assumes that hosts are always managing WIT interfaces in a
semver-aare fashion meaning that semver-compatible upgrade exclusively
adds functionality. This neatly fits into the idea of subtyping at the
instance-level where if a binary built against 0.2.0 only requests a
subset of functionality from a runtime that provides 0.2.1, that should
work just fine.
Specifically what this change does is:
* For all names inserted into a `Linker` there might also be a "semver
compatible name" which is registered as well. For example `..@1.0.0`
is also registered as `..@1`.
* Semver-compatible names are only provided for versions without a
prerelease and with either a nonzero major or minor version number.
* When looking up an item in the linker if no exact match is found then
if a semver-compatible-name is available for the lookup key then
that's consulted as well.
This semantically means that if a components imports WASI 0.2.0 then a
runtime which only provides WASI 0.2.1 will be able to instantiate the
component. Furthermore if a component imports WASI 0.2.1 but only
imports the subset of WASI that was available in 0.2.0 then it will be
instantiable in a runtime that only supports 0.2.0.
This implementation is intended to be a crucial part of the evolution to
WASI to make it more seamless to upgrade WASI from both a host and guest
perspective. This no longer requires everyone to upgrade to the same
version all at the same time but instead decouples the upgrade
schedules.
Closes#7860
* winch: Fix bounds checks for dynamic heaps
This commit fixes a fuzz bug in which the current implementation was incorrectly cloberring the index register of a memory access (for addition overflow check) and then using that same clobbered register to perform the memory access. The clobbered register contained the value: `index + offset + access_size`, which resulting in an incorrect access and consequently in an incorrect `HeapOutOfBounds` trap.
This bug is only reproducible when modifying Wasmtime's memory settings, forcing the heap to be treated as `Dynamic`.
Currently in Winch there's no easy way to have specific Wasmtime configurations, so having a filetests for this case is not straightforward. I've opted to add an integration test, in which it's easier to configure Wasmtime.
Note that the `tests/all/winch.rs` file is temporary, and the plan is to execute all the other integration tests with Winch at some point. In the case of `memory.rs`, that will be once Winch supports `memory64` hoping to reduce the amount of code needed in order to integrate Winch.
* Remove unused variable in integration tests
This commit updates Wasmtime to support `global.get` in constant
expressions when located in table initializers and element segments.
Pre-reference-types this never came up because there was no valid
`global.get` that would typecheck. After the reference-types proposal
landed however this became possible but Wasmtime did not support it.
This was surfaced in #6705 when the spec test suite was updated and has
a new test that exercises this functionality.
This commit both updates the spec test suite and additionally adds
support for this new form of element segment and table initialization
expression.
The fact that Wasmtime hasn't supported this until now also means that
we have a gap in our fuzz-testing infrastructure. The `wasm-smith`
generator is being updated in bytecodealliance/wasm-tools#1426 to
generate modules with this particular feature and I've tested that with
that PR fuzzing here eventually generates an error before this PR.
Closes#6705
* Wasmtime: Add a `gc` cargo feature
This controls whether support for `ExternRef` and its associated deferred,
reference-counting garbage collector is enabled at compile time or not. It will
also be used for similarly for Wasmtime's full Wasm GC support as that gets
added.
* Add CI for `gc` Cargo feature
* Cut down on the number of `#[cfg(feature = "gc")]`s outside the implementation of `[VM]ExternRef`
* Fix wasmparser reference types configuration with GC disabled/enabled
* More config fix
* doc cfg
* Make the dummy `VMExternRefActivationsTable` inhabited
* Fix winch tests
* final review bits
* Enable wasmtime's gc cargo feature for the C API
* Enable wasmtime's gc cargo feature from wasmtime-cli-flags
* enable gc cargo feature in a couple other crates
This commit fixes an accidental regression from #7766 where
`infer_native_flags` is called even if a target is explicitly specified
to a `Config`. Now inference only happens if a target isn't specified
meaning that the host is selected.
First of all, it is just a nice separation of concerns.
Second of all, as I design the GC rooting APIs for Wasmtime's upcoming Wasm GC
support, I want this same thing and I'd rather not open code it multiple times.
* Enable compiling the Wasmtime CLI to Wasm
While not the most useful thing to do in the world it's kind of neat to
play around with. This builds on the previous work to exclude the
runtime from the `wasmtime` crate so it's now possible to compile the
Wasmtime CLI's `compile` command, and only the `compile` command, to
wasm itself. This means you can run Wasmtime in Wasmtime!
* Fix warning on wasm
* Fix some feature combos
* Update some CI dependencies
* Update to the latest nightly toolchain
* Update mdbook
* Update QEMU for cross-compiled testing
* Update `cargo nextest` for usage with MIRI
prtest:full
* Remove lots of unnecessary imports
* Downgrade qemu as 8.2.1 seems to segfault
* Remove more imports
* Remove unused winch trait method
* Fix warnings about unused trait methods
* More unused imports
* More unused imports
This is true for anything I've ever encountered historically so I'm not
sure if it's worth having an explicit `compile_error!` here for all
non-enumerated platforms.
* Refactor the prologue and epilogue interface in winch
* Remove the locals reservation from the MacroAssembler's prologue/epilogue
* Update winch tests