Commit Graph

207 Commits

Author SHA1 Message Date
Alex Crichton
01e567ca05 Downgrade a cpu feature log message (#3842)
It looks like `error!` is printed by default as it's showing up in
oss-fuzz logs, so downgrade this to `warn!` to avoid printing while fuzzing.
2022-02-23 10:06:52 -08:00
Alex Crichton
bbd4a4a500 Enable copy-on-write heap initialization by default (#3825)
* Enable copy-on-write heap initialization by default

This commit enables the `Config::memfd` feature by default now that it's
been fuzzed for a few weeks on oss-fuzz, and will continue to be fuzzed
leading up to the next release of Wasmtime in early March. The
documentation of the `Config` option has been updated as well as adding
a CLI flag to disable the feature.

* Remove ubiquitous "memfd" terminology

Switch instead to forms of "memory image" or "cow" or some combination
thereof.

* Update new option names
2022-02-22 17:12:18 -06:00
Alex Crichton
593f8d96aa Update wasm-{smith,encoder} (#3835)
Ended up being a routine update but seemed good to go ahead and hook up
updates. While I was at it I went ahead and hooked up multi-value
swarm fuzzing as well now that wasm-smith implements it.
2022-02-22 13:04:13 -08:00
Alex Crichton
709f7e0c8a Enable SSE 4.2 unconditionally (#3833)
* Enable SSE 4.2 unconditionally

Fuzzing over the weekend found that `i64x2` comparison operators
require `pcmpgtq` which is an SSE 4.2 instruction. Along the lines of #3816
this commit unconditionally enables and requires SSE 4.2 for compilation
and fuzzing. It will no longer be possible to create a compiler for
x86_64 with simd enabled if SSE 4.2 is disabled.

* Update comment
2022-02-22 13:23:51 -06:00
Chris Fallin
43d31c5bf7 memfd: make "dense image" heuristic limit configurable. (#3831)
In #3820 we see an issue with the new heuristics that control use of
memfd: it's entirely possible for a reasonable Wasm module produced by a
snapshotting system to have a relatively sparse heap (less than 50%
filled). A system that avoids memfd because of this would have an
undesirable performance reduction on such modules.

Ultimately we should try to implement a hybrid scheme where we support
outlier/leftover initializers, but for now this PR makes the "always
allow dense" limit configurable. This way, embedders that want to ensure
that memfd is used can do so, if they have other knowledge about the
maximum heap size allowed in their system.

(Partially addresses #3820 but let's leave it open to track the hybrid
idea)
2022-02-22 12:40:43 -06:00
Peter Huene
084452acab Fix max memory pages for spectests fuzz target. (#3829)
This commit fixes the spectests fuzz target to set a lower bound on the
arbitrary pooling allocator configurations of 10 memory pages so that the limit
doesn't interfere with what's required in the spec tests.
2022-02-22 09:03:50 -06:00
Alex Crichton
f425eb7ea5 Limit total memory usage in instantiate-many fuzzer (#3823)
Per-`Store` allocations are already limited with the `StoreLimits`
structure while fuzzing to ensure fuzz targets don't allocate more than
1GB of memory, but the `instantiate-many` fuzzer created many separate
stores which each had their own limit, meaning that the 2GB limit of
fuzzing could be pretty easily reached.

This commit fixes the issue by making `StoreLimits` a shareable type via
`Rc` to ensure the same limits can be applied to all stores created
within a fuzz run, globally limiting the memory even across stores to 1GB.
2022-02-17 10:26:23 -08:00
Alex Crichton
37b0fd482d Improve platform compatibility of fuzz test cases (#3824)
In #3800 I added support to consume fuzz input as selection of whether
or not target features should be enabled. This was done in a
platform-specific manner, however, which means that I can no longer
reliably take the fuzz reproducer cases from oss-fuzz and reproduce them
locally on an aarch64 machine. This commit fixes this problem by
unconditionally pulling bytes from the input for fuzz features,
irrespective of the host platform. Features are then discarded if
they're not applicable.
2022-02-17 12:07:02 -06:00
Alex Crichton
498c592b19 Unconditionally enable sse3, ssse3, and sse4.1 when fuzzing (#3814)
* Unconditionally enable sse3, ssse3, and sse4.1 when fuzzing

This commit unconditionally enables some x86_64 instructions when
fuzzing because the cranelift backend is known to not work if these
features are disabled. From discussion on the wasm simd proposal the
assumed general baseline for running simd code is SSE4.1 anyway.

At this time I haven't added any sort of checks in Wasmtime itself.
Wasmtime by default uses the native architecture and when explicitly
enabling features this still needs to be explicitly specified.

Closes #3809

* Update crates/fuzzing/src/generators.rs

Co-authored-by: Andrew Brown <andrew.brown@intel.com>

Co-authored-by: Andrew Brown <andrew.brown@intel.com>
2022-02-16 14:53:52 -06:00
Peter Huene
6ffcd4ead9 Improve stability for fuzz targets. (#3804)
This commit improves the stability of the fuzz targets by ensuring the
generated configs and modules are congruent, especially when the pooling
allocator is being used.

For the `differential` target, this means both configurations must use the same
allocation strategy for now as one side generates the module that might not be
compatible with another arbitrary config now that we fuzz the pooling
allocator.

These changes also ensure that constraints put on the config are more
consistently applied, especially when using a fuel-based timeout.
2022-02-15 12:59:04 -08:00
Alex Crichton
0b4263333b Fuzz cranelift cpu flag settings with Wasmtime (#3800)
* Fuzz cranelift cpu flag settings with Wasmtime

This commit updates the `Config` fuzz-generator to consume some of the
input as configuration settings for codegen flags we pass to cranelift.
This should allow for ideally some more coverage where settings are
disabled or enabled, ideally finding possible bugs in feature-specific
implementations or generic implementations that are rarely used if the
feature-specific ones almost always take precedent.

The technique used in this commit is to weight selection of codegen
settings less frequently than using the native settings. Afterwards each
listed feature is individually enabled or disabled depending on the
input fuzz data, and if a feature is enabled but the host doesn't
actually support it then the fuzz input is rejected with a log message.
The goal here is to still have many fuzz inputs accepted but also ensure
determinism across hosts. If there's a bug specifically related to
enabling a flag then running it on a host without the flag should
indicate that the flag isn't supported rather than silently leaving it
disabled and reporting the fuzz case a success.

* Use built-in `Unstructured::ratio` method

* Tweak macro

* Bump arbitrary dep version
2022-02-15 14:27:55 -06:00
Peter Huene
da539255a5 Use a much lower memory page limit for pooling allocator fuzzing. (#3795)
This commit makes it such that the pooling allocator will be configured with a
much lower upper bound for memory pages, which will greatly reduce the
likelihood that the fuzzer memory limits will be hit from having too many
memories from too many instances committed.
2022-02-14 10:18:29 -06:00
Peter Huene
41eb225765 Add the instance allocation strategy to generated fuzzing configs. (#3780)
* Add the instance allocation strategy to generated fuzzing configs.

This commit adds support for generating configs with arbitrary instance
allocation strategies.

With this, the pooling allocator will be fuzzed as part of the existing fuzz
targets.

* Refine maximum constants for arbitrary module limits.

* Add an `instantiate-many` fuzz target.

This commit adds a new `instantiate-many` fuzz target that will attempt to
instantiate and terminate modules in an arbitrary order.

It generates up to 5 modules, from which a random sequence of instances will be
created.

The primary benefactor of this fuzz target is the pooling instance allocator.

* Allow no aliasing in generated modules when using the pooling allocator.

This commit prevents aliases in the generated modules as they might count
against the configured import limits of the pooling allocator.

As the existing module linking proposal implementation will eventually be
deprecated in favor of the component model proposal, it isn't very important
that we test aliases in generated modules with the pooling allocator.

* Improve distribution of memory config in fuzzing.

The previous commit attempted to provide a 32-bit upper bound to 64-bit
arbitrary values, which skewed the distribution heavily in favor of the upper
bound.

This commit removes the constraint and instead uses arbitrary 32-bit values
that are converted to 64-bit values in the `Arbitrary` implementation.
2022-02-10 11:55:44 -08:00
Alex Crichton
027dea549a Fuzz using precompiled modules on CI (#3788)
In working on #3787 I see now that our coverage of loading precompiled
files specifically is somewhat lacking, so this adds a config option to
the fuzzers where, if enabled, will round-trip all compiled modules
through the filesystem to test out the mmapped-file case.
2022-02-10 11:55:18 -06:00
Alex Crichton
5cd97c054d Update memfd support with a runtime toggle (#3778)
This commit updates the `memfd` support in Wasmtime to have a runtime
toggle as to whether it's used or not. The compile-time feature gating
`memfd` support is now also re-enabled by default, but the new runtime
switch is still disabled-by-default.

Additionally this commit updates our fuzz oracle to turn on/off the
memfd flag to re-enable fuzzing with memfd on oss-fuzz.
2022-02-08 15:47:13 -06:00
Nick Fitzgerald
605c79fd05 Merge pull request #3756 from alexcrichton/update-wasm-tools
Update wasm-tools crates
2022-02-03 11:19:55 -08:00
Alex Crichton
4ba3404ca3 Fix MemFd's allocated memory for dynamic memories (#3763)
This fixes a bug in the memfd-related management of a linear memory
where for dynamic memories memfd wasn't informed of the extra room that
the dynamic memory could grow into, only the actual size of linear
memory, which ended up tripping an assert once the memory was grown. The
fix here is pretty simple which is to factor in this extra space when
passing the allocation size to the creation of the `MemFdSlot`.
2022-02-03 11:56:16 -06:00
Alex Crichton
3f5cbddab5 Fix a text format test expectation 2022-02-02 10:17:18 -08:00
Alex Crichton
9d1e517615 Update some more version reqs 2022-02-02 09:51:27 -08:00
Alex Crichton
65486a0680 Update wasm-tools crates
Nothing major here, just a routine update with a few extra things to
handle here-and-there.
2022-02-02 09:50:08 -08:00
Nick Fitzgerald
f292ff55cf Do another GC after running Wasm in the table_ops test oracle 2022-01-27 16:53:10 -08:00
Nick Fitzgerald
cc8d7778e2 Make the table_ops test case generator use globals as well
This will make it generate `table.set`s that come from `global.get`s and
`global.get`s that come from `table.set`s. Ultimately, it should give us much
more fuzzing coverage of `externref` globals, their barriers, and passing
`externref`s into and out of Wasm to get or set globals.
2022-01-27 16:53:10 -08:00
Alex Crichton
2459776424 fuzz: Fix infinite loops in table_ops fuzzers
I forgot in the recent refactoring to add back in fuel support to the
`table_ops` fuzzer. This commit re-adds the previously existent logic to
always use fuel to cancel execution of the table_ops fuzzer.
2022-01-08 17:19:00 -08:00
Alex Crichton
ab1d845ac1 Refactor fuzzing configuration and sometimes disable debug verifier. (#3664)
* fuzz: Refactor Wasmtime's fuzz targets

A recent fuzz bug found is related to timing out when compiling a
module. This timeout, however, is predominately because Cranelift's
debug verifier is enabled and taking up over half the compilation time.
I wanted to fix this by disabling the verifier when input modules might
have a lot of functions, but this was pretty difficult to implement.

Over time we've grown a number of various fuzzers. Most are
`wasm-smith`-based at this point but there's various entry points for
configuring the wasm-smith module, the wasmtime configuration, etc. I've
historically gotten quite lost in trying to change defaults and feeling
like I have to touch a lot of different places. This is the motivation
for this commit, simplifying fuzzer default configuration.

This commit removes the ability to create a default `Config` for
fuzzing, instead only supporting generating a configuration via
`Arbitrary`. This then involved refactoring all targets and fuzzers to
ensure that configuration is generated through `Arbitrary`. This should
actually expand the coverage of some existing fuzz targets since
`Arbitrary for Config` will tweak options that don't affect runtime,
such as memory configuration or jump veneers.

All existing fuzz targets are refactored to use this new method of
configuration. Some fuzz targets were also shuffled around or
reimplemented:

* `compile` - this now directly calls `Module::new` to skip all the
  fuzzing infrastructure. This is mostly done because this fuzz target
  isn't too interesting and is largely just seeing what happens when
  things are thrown at the wall for Wasmtime.

* `instantiate-maybe-invalid` - this fuzz target now skips instantiation
  and instead simply goes into `Module::new` like the `compile` target.
  The rationale behind this is that most modules won't instantiate
  anyway and this fuzz target is primarily fuzzing the compiler. This
  skips having to generate arbitrary configuration since
  wasm-smith-generated-modules (or valid ones at least) aren't used
  here.

* `instantiate` - this fuzz target was removed. In general this fuzz
  target isn't too interesting in isolation. Almost everything it deals
  with likely won't pass compilation and is covered by the `compile`
  fuzz target, and otherwise interesting modules being instantiated can
  all theoretically be created by `wasm-smith` anyway.

* `instantiate-wasm-smith` and `instantiate-swarm` - these were both merged
  into a new `instantiate` target (replacing the old one from above).
  There wasn't really much need to keep these separate since they really
  only differed at this point in methods of timeout. Otherwise we much
  more heavily use `SwarmConfig` than wasm-smith's built-in options.

The intention is that we should still have basically the same coverage
of fuzzing as before, if not better because configuration is now
possible on some targets. Additionally there is one centralized point of
configuration for fuzzing for wasmtime, `Arbitrary for ModuleConfig`.
This internally creates an arbitrary `SwarmConfig` from `wasm-smith` and
then further tweaks it for Wasmtime's needs, such as enabling various
wasm proposals by default. In the future enabling a wasm proposal on
fuzzing should largely just be modifying this one trait implementation.

* fuzz: Sometimes disable the cranelift debug verifier

This commit disables the cranelift debug verifier if the input wasm
module might be "large" for the definition of "more than 10 functions".
While fuzzing we disable threads (set them to 1) and enable the
cranelift debug verifier. Coupled with a 20-30x slowdown this means that
a module with the maximum number of functions, 100, gives:

    60x / 100 functions / 30x slowdown = 20ms

With only 20 milliseconds per function this is even further halved by
the `differential` fuzz target compiling a module twice, which means
that, when compiling with a normal release mode Wasmtime, if any
function takes more than 10ms to compile then it's a candidate for
timing out while fuzzing. Given that the cranelift debug verifier can
more than double compilation time in fuzzing mode this actually means
that the real time budget for function compilation is more like 4ms.

The `wasm-smith` crate can pretty easily generate a large function that
takes 4ms to compile, and then when that function is multiplied 100x in
the `differential` fuzz target we trivially time out the fuzz target.

The hope of this commit is to buy back half our budget by disabling the
debug verifier for modules that may have many functions. Further
refinements can be implemented in the future such as limiting functions
for just the differential target as well.

* Fix the single-function-module fuzz configuration

* Tweak how features work in differential fuzzing

* Disable everything for baseline differential fuzzing
* Enable selectively for each engine afterwards
* Also forcibly enable reference types and bulk memory for spec tests

* Log wasms when compiling

* Add reference types support to v8 fuzzer

* Fix timeouts via fuel

The default store has "infinite" fuel so that needs to be consumed
before fuel is added back in.

* Remove fuzzing-specific tests

These no longer compile and also haven't been added to in a long time.
Most of the time a reduced form of original the fuzz test case is added
when a fuzz bug is fixed.
2022-01-07 15:12:25 -06:00
Alex Crichton
ec43254292 Enable nan canonicalization in differential fuzzing (#3557)
This fixes a fuzz issue discovered over the weekend where stores with
different values for nan canonicalization may produce different results.
This is expected, however, so the fix for differential execution is to
always enable nan canonicalization.
2021-11-22 12:21:26 -06:00
Alex Crichton
e08bcd6aad Revert "Temporarily disable SIMD fuzzing on CI" (#3555)
This reverts commit 95e8723d0767556f0ddbc9151bce269464852bb1.
2021-11-19 14:33:11 -06:00
Alex Crichton
ff1af20479 Add a fuzz mode to stress unaligned wasm addresses (#3516)
Alignment on all memory instructions in wasm is currently best-effort
and not actually required, meaning that whatever wasm actually uses as
an address should work regardless of whether the address is aligned or
not. This is theoretically tested in the fuzzers via
wasm-smith-generated code, but wasm-smith doesn't today have too too
high of a chance of generating an actual successful load/store.

This commit adds a new configuration option to the `Config` generator
for fuzzing which forces usage of a custom linear memory implementation
which is backed by Rust's `Vec<u8>` and forces the base address of
linear memory to be off-by-one relative to the base address of the
`Vec<u8>` itself. This should theoretically force host addresses to
almost always be unaligned, even if wasm addresses are otherwise
aligned.

The main interesting fuzz coverage here is likely to be in the existing
`differential` target which compares running the same module in wasmtime
with two different `Config` values to ensure the same results are
produced. This probably won't increase coverage all that much in the
near future due to wasm-smith rarely generating successful loads/stores,
but in the meantime by hooking this up into `Config` it also means that
we'll be running in comparison against v8 and also ensuring that all
spec tests succeed if misalignment is forced at the hardware level.

As a side effect this commit also cleans up the fuzzers slightly:

* The `DifferentialConfig` struct is removed and folded into `Config`
* The `init_hang_limit` processing is removed since we don't use
  `-ttf`-generated modules from binaryen any more.
* Traps are now asserted to have the same trap code, otherwise
  differential fuzzing fails.
* Some more debug logging was added to the differential fuzzer
2021-11-15 08:24:23 -06:00
Alex Crichton
9a27fdad86 Update v8 used during fuzzing (#3493)
This commit updates the crate name from `rusty_v8` to `v8` as well since
the upstream bindings have sinced moved. I originally wanted to do this
to see if a fix for one of our fuzz bugs was pulled in but I don't think
the fix has been pulled in yet. Despite that it seems reasonable to go
ahead and update.
2021-11-01 09:18:11 -05:00
Alex Crichton
1a5fa3ed3f Enable stable wasm features for spectest fuzzing (#3454)
These are now required for the general suite of spec tests we're running
by default.
2021-10-15 10:40:42 -05:00
Alex Crichton
9c6884e28d Update the spec reference testsuite submodule (#3450)
* Update the spec reference testsuite submodule

This commit brings in recent updates to the spec test suite. Most of the
changes here were already fixed in `wasmparser` with some tweaks to
esoteric modules, but Wasmtime also gets a bug fix where where import
matching for the size of tables/memories is based on the current runtime
size of the table/memory rather than the original type of the
table/memory. This means that during type matching the actual value is
consulted for its size rather than using the minimum size listed in its
type.

* Fix now-missing directories in build script
2021-10-13 16:14:12 -05:00
Alex Crichton
91482f39d0 Disable module linking in compilation fuzzer (#3416)
Module linking is otherwise covered by other fuzzers and by enabling
module linking it rejects more modules than necessary due to
restrictions on import strings.
2021-10-05 09:12:11 -05:00
Alex Crichton
25d3fa4d7b Remove spec interpreter fuzz target temporarily (#3399)
This commit removes the `differential_spec` fuzz target for now,
although this removal is intended to be temporary. We have #3251 to
track re-enabling the spec interpreter in a way that it won't time out,
and additionally the spec interpreter is also failing to build with
ocaml on oss-fuzz so that will also need to be investigated when
re-enabling.
2021-09-30 13:09:19 -05:00
Alex Crichton
1ee2af0098 Remove the lightbeam backend (#3390)
This commit removes the Lightbeam backend from Wasmtime as per [RFC 14].
This backend hasn't received maintenance in quite some time, and as [RFC
14] indicates this doesn't meet the threshold for keeping the code
in-tree, so this commit removes it.

A fast "baseline" compiler may still be added in the future. The
addition of such a backend should be in line with [RFC 14], though, with
the principles we now have for stable releases of Wasmtime. I'll close
out Lightbeam-related issues once this is merged.

[RFC 14]: https://github.com/bytecodealliance/rfcs/pull/14
2021-09-27 12:27:19 -05:00
Alex Crichton
476d0bee96 Allow another trap mismatch with v8
If Wasmtime thinks a module stack-overflows and v8 says that it does
something else that's ok. This means that the limits on v8 and Wasmtime
are different which is expected and not something we want fuzz-bugs
about.
2021-09-23 08:48:11 -07:00
Alex Crichton
bcf3544924 Optimize Func::call and its C API (#3319)
* Optimize `Func::call` and its C API

This commit is an alternative to #3298 which achieves effectively the
same goal of optimizing the `Func::call` API as well as its C API
sibling of `wasmtime_func_call`. The strategy taken here is different
than #3298 though where a new API isn't created, rather a small tweak to
an existing API is done. Specifically this commit handles the major
sources of slowness with `Func::call` with:

* Looking up the type of a function, to typecheck the arguments with and
  use to guide how the results should be loaded, no longer hits the
  rwlock in the `Engine` but instead each `Func` contains its own
  `FuncType`. This can be an unnecessary allocation for funcs not used
  with `Func::call`, so this is a downside of this implementation
  relative to #3298. A mitigating factor, though, is that instance
  exports are loaded lazily into the `Store` and in theory not too many
  funcs are active in the store as `Func` objects.

* Temporary storage is amortized with a long-lived `Vec` in the `Store`
  rather than allocating a new vector on each call. This is basically
  the same strategy as #3294 only applied to different types in
  different places. Specifically `wasmtime::Store` now retains a
  `Vec<u128>` for `Func::call`, and the C API retains a `Vec<Val>` for
  calling `Func::call`.

* Finally, an API breaking change is made to `Func::call` and its type
  signature (as well as `Func::call_async`). Instead of returning
  `Box<[Val]>` as it did before this function now takes a
  `results: &mut [Val]` parameter. This allows the caller to manage the
  allocation and we can amortize-remove it in `wasmtime_func_call` by
  using space after the parameters in the `Vec<Val>` we're passing in.
  This change is naturally a breaking change and we'll want to consider
  it carefully, but mitigating factors are that most embeddings are
  likely using `TypedFunc::call` instead and this signature taking a
  mutable slice better aligns with `Func::new` which receives a mutable
  slice for the results.

Overall this change, in the benchmark of "call a nop function from the C
API" is not quite as good as #3298. It's still a bit slower, on the
order of 15ns, because there's lots of capacity checks around vectors
and the type checks are slightly less optimized than before. Overall
though this is still significantly better than today because allocations
and the rwlock to acquire the type information are both avoided. I
personally feel that this change is the best to do because it has less
of an API impact than #3298.

* Rebase issues
2021-09-21 14:07:05 -05:00
Alex Crichton
fc6328ae06 Temporarily disable SIMD fuzzing on CI (#3376)
We've got a large crop of fuzz-bugs from fuzzing with enabled-with-SIMD
on oss-fuzz but at this point the fuzz stats from oss-fuzz say that the
fuzzers like v8 are spending less than 50% of its time actually fuzzing
and presumably mostly hitting crashes and such. While we fix the other
issues this disables simd for fuzzing with v8 so we can try to see if we
can weed out other issues.
2021-09-20 14:17:19 -05:00
Ulrich Weigand
51131a3acc Fix s390x regressions (#3330)
- Add relocation handling needed after PR #3275
- Fix incorrect handling of signed constants detected by PR #3056 test
- Fix LabelUse max pos/neg ranges; fix overflow in buffers.rs
- Disable fuzzing tests that require pre-built v8 binaries
- Disable cranelift test that depends on i128
- Temporarily disable memory64 tests
2021-09-20 09:12:36 -05:00
Nick Fitzgerald
b32130d0aa Fix table_ops fuzz generator test's expected results 2021-09-17 11:07:56 -07:00
Nick Fitzgerald
101998733b Merge pull request from GHSA-v4cp-h94r-m7xf
Fix a use-after-free bug when passing `ExternRef`s to Wasm
2021-09-17 10:27:29 -07:00
Nick Fitzgerald
d2ce1ac753 Fix a use-after-free bug when passing ExternRefs to Wasm
We _must not_ trigger a GC when moving refs from host code into
Wasm (e.g. returned from a host function or passed as arguments to a Wasm
function). After insertion into the table, this reference is no longer
rooted. If multiple references are being sent from the host into Wasm and we
allowed GCs during insertion, then the following events could happen:

* Reference A is inserted into the activations table. This does not trigger a
  GC, but does fill the table to capacity.

* The caller's reference to A is removed. Now the only reference to A is from
  the activations table.

* Reference B is inserted into the activations table. Because the table is at
  capacity, a GC is triggered.

* A is reclaimed because the only reference keeping it alive was the activation
  table's reference (it isn't inside any Wasm frames on the stack yet, so stack
  scanning and stack maps don't increment its reference count).

* We transfer control to Wasm, giving it A and B. Wasm uses A. That's a use
  after free.

To prevent uses after free, we cannot GC when moving refs into the
`VMExternRefActivationsTable` because we are passing them from the host to Wasm.

On the other hand, when we are *cloning* -- as opposed to moving -- refs from
the host to Wasm, then it is fine to GC while inserting into the activations
table, because the original referent that we are cloning from is still alive and
rooting the ref.
2021-09-14 14:23:42 -07:00
Alex Crichton
b759514124 Allow wasmtime/v8 to differ on errors slightly (#3348)
I'm not sure why when run repeatedly v8 has different limits on
call-stack-size but it's not particularly interesting to assert exact
matches here, so this should fix a fuzz-bug-failure found on oss-fuzz.
2021-09-14 10:40:24 -05:00
Alex Crichton
1532516a36 Use relative call instructions between wasm functions (#3275)
* Use relative `call` instructions between wasm functions

This commit is a relatively major change to the way that Wasmtime
generates code for Wasm modules and how functions call each other.
Prior to this commit all function calls between functions, even if they
were defined in the same module, were done indirectly through a
register. To implement this the backend would emit an absolute 8-byte
relocation near all function calls, load that address into a register,
and then call it. While this technique is simple to implement and easy
to get right, it has two primary downsides associated with it:

* Function calls are always indirect which means they are more difficult
  to predict, resulting in worse performance.

* Generating a relocation-per-function call requires expensive
  relocation resolution at module-load time, which can be a large
  contributing factor to how long it takes to load a precompiled module.

To fix these issues, while also somewhat compromising on the previously
simple implementation technique, this commit switches wasm calls within
a module to using the `colocated` flag enabled in Cranelift-speak, which
basically means that a relative call instruction is used with a
relocation that's resolved relative to the pc of the call instruction
itself.

When switching the `colocated` flag to `true` this commit is also then
able to move much of the relocation resolution from `wasmtime_jit::link`
into `wasmtime_cranelift::obj` during object-construction time. This
frontloads all relocation work which means that there's actually no
relocations related to function calls in the final image, solving both
of our points above.

The main gotcha in implementing this technique is that there are
hardware limitations to relative function calls which mean we can't
simply blindly use them. AArch64, for example, can only go +/- 64 MB
from the `bl` instruction to the target, which means that if the
function we're calling is a greater distance away then we would fail to
resolve that relocation. On x86_64 the limits are +/- 2GB which are much
larger, but theoretically still feasible to hit. Consequently the main
increase in implementation complexity is fixing this issue.

This issue is actually already present in Cranelift itself, and is
internally one of the invariants handled by the `MachBuffer` type. When
generating a function relative jumps between basic blocks have similar
restrictions. This commit adds new methods for the `MachBackend` trait
and updates the implementation of `MachBuffer` to account for all these
new branches. Specifically the changes to `MachBuffer` are:

* For AAarch64 the `LabelUse::Branch26` value now supports veneers, and
  AArch64 calls use this to resolve relocations.

* The `emit_island` function has been rewritten internally to handle
  some cases which previously didn't come up before, such as:

  * When emitting an island the deadline is now recalculated, where
    previously it was always set to infinitely in the future. This was ok
    prior since only a `Branch19` supported veneers and once it was
    promoted no veneers were supported, so without multiple layers of
    promotion the lack of a new deadline was ok.

  * When emitting an island all pending fixups had veneers forced if
    their branch target wasn't known yet. This was generally ok for
    19-bit fixups since the only kind getting a veneer was a 19-bit
    fixup, but with mixed kinds it's a bit odd to force veneers for a
    26-bit fixup just because a nearby 19-bit fixup needed a veneer.
    Instead fixups are now re-enqueued unless they're known to be
    out-of-bounds. This may run the risk of generating more islands for
    19-bit branches but it should also reduce the number of islands for
    between-function calls.

  * Otherwise the internal logic was tweaked to ideally be a bit more
    simple, but that's a pretty subjective criteria in compilers...

I've added some simple testing of this for now. A synthetic compiler
option was create to simply add padded 0s between functions and test
cases implement various forms of calls that at least need veneers. A
test is also included for x86_64, but it is unfortunately pretty slow
because it requires generating 2GB of output. I'm hoping for now it's
not too bad, but we can disable the test if it's prohibitive and
otherwise just comment the necessary portions to be sure to run the
ignored test if these parts of the code have changed.

The final end-result of this commit is that for a large module I'm
working with the number of relocations dropped to zero, meaning that
nothing actually needs to be done to the text section when it's loaded
into memory (yay!). I haven't run final benchmarks yet but this is the
last remaining source of significant slowdown when loading modules,
after I land a number of other PRs both active and ones that I only have
locally for now.

* Fix arm32

* Review comments
2021-09-01 13:27:38 -05:00
Alex Crichton
4376cf2609 Add differential fuzzing against V8 (#3264)
* Add differential fuzzing against V8

This commit adds a differential fuzzing target to Wasmtime along the
lines of the wasmi and spec interpreters we already have, but with V8
instead. The intention here is that wasmi is unlikely to receive updates
over time (e.g. for SIMD), and the spec interpreter is not suitable for
fuzzing against in general due to its performance characteristics. The
hope is that V8 is indeed appropriate to fuzz against because it's
naturally receiving updates and it also is expected to have good
performance.

Here the `rusty_v8` crate is used which provides bindings to V8 as well
as precompiled binaries by default. This matches exactly the use case we
need and at least for now I think the `rusty_v8` crate will be
maintained by the Deno folks as they continue to develop it. If it
becomes an issue though maintaining we can evaluate other options to
have differential fuzzing against.

For now this commit enables the SIMD and bulk-memory feature of
fuzz-target-generation which should enable them to get
differentially-fuzzed with V8 in addition to the compilation fuzzing
we're already getting.

* Use weak linkage for GDB jit helpers

This should help us deduplicate our symbol with other JIT runtimes, if
any. For now this leans on some C helpers to define the weak linkage
since Rust doesn't support that on stable yet.

* Don't use rusty_v8 on MinGW

They don't have precompiled libraries there.

* Fix msvc build

* Comment about execution
2021-08-31 09:34:55 -05:00
Chris Fallin
b2bcdd13ec Spec-interpreter fuzzing: check out fuzzing branch of our mirror. (#3222)
In #3186, we found an issue that requires patching the spec interpreter
for now. Our plan is to have a `fuzzing` branch in our spec-repo mirror
that lets us make these fixes locally before they are upstreamed.
This PR updates the build script for the spec-interpreter wrapper
crate to clone this particular `fuzzing` branch instead of the main
branch.
2021-08-20 12:54:52 -05:00
Alex Crichton
0642e62f16 Use wasm-smith to canonicalize NaN in differential fuzzing (#3195)
* Update wasm-smith to 0.7.0

* Canonicalize NaN with wasm-smith for differential fuzzing

This then also enables floating point executing in wasmi in addition to
the spec interpreter. With NaN canonicalization at the wasm level this
means that we should be producing deterministic results between Wasmtime
and these alternative implementations.
2021-08-17 11:42:22 -05:00
Alex Crichton
e68aa99588 Implement the memory64 proposal in Wasmtime (#3153)
* Implement the memory64 proposal in Wasmtime

This commit implements the WebAssembly [memory64 proposal][proposal] in
both Wasmtime and Cranelift. In terms of work done Cranelift ended up
needing very little work here since most of it was already prepared for
64-bit memories at one point or another. Most of the work in Wasmtime is
largely refactoring, changing a bunch of `u32` values to something else.

A number of internal and public interfaces are changing as a result of
this commit, for example:

* Acessors on `wasmtime::Memory` that work with pages now all return
  `u64` unconditionally rather than `u32`. This makes it possible to
  accommodate 64-bit memories with this API, but we may also want to
  consider `usize` here at some point since the host can't grow past
  `usize`-limited pages anyway.

* The `wasmtime::Limits` structure is removed in favor of
  minimum/maximum methods on table/memory types.

* Many libcall intrinsics called by jit code now unconditionally take
  `u64` arguments instead of `u32`. Return values are `usize`, however,
  since the return value, if successful, is always bounded by host
  memory while arguments can come from any guest.

* The `heap_addr` clif instruction now takes a 64-bit offset argument
  instead of a 32-bit one. It turns out that the legalization of
  `heap_addr` already worked with 64-bit offsets, so this change was
  fairly trivial to make.

* The runtime implementation of mmap-based linear memories has changed
  to largely work in `usize` quantities in its API and in bytes instead
  of pages. This simplifies various aspects and reflects that
  mmap-memories are always bound by `usize` since that's what the host
  is using to address things, and additionally most calculations care
  about bytes rather than pages except for the very edge where we're
  going to/from wasm.

Overall I've tried to minimize the amount of `as` casts as possible,
using checked `try_from` and checked arithemtic with either error
handling or explicit `unwrap()` calls to tell us about bugs in the
future. Most locations have relatively obvious things to do with various
implications on various hosts, and I think they should all be roughly of
the right shape but time will tell. I mostly relied on the compiler
complaining that various types weren't aligned to figure out
type-casting, and I manually audited some of the more obvious locations.
I suspect we have a number of hidden locations that will panic on 32-bit
hosts if 64-bit modules try to run there, but otherwise I think we
should be generally ok (famous last words). In any case I wouldn't want
to enable this by default naturally until we've fuzzed it for some time.

In terms of the actual underlying implementation, no one should expect
memory64 to be all that fast. Right now it's implemented with
"dynamic" heaps which have a few consequences:

* All memory accesses are bounds-checked. I'm not sure how aggressively
  Cranelift tries to optimize out bounds checks, but I suspect not a ton
  since we haven't stressed this much historically.

* Heaps are always precisely sized. This means that every call to
  `memory.grow` will incur a `memcpy` of memory from the old heap to the
  new. We probably want to at least look into `mremap` on Linux and
  otherwise try to implement schemes where dynamic heaps have some
  reserved pages to grow into to help amortize the cost of
  `memory.grow`.

The memory64 spec test suite is scheduled to now run on CI, but as with
all the other spec test suites it's really not all that comprehensive.
I've tried adding more tests for basic things as I've had to implement
guards for them, but I wouldn't really consider the testing adequate
from just this PR itself. I did try to take care in one test to actually
allocate a 4gb+ heap and then avoid running that in the pooling
allocator or in emulation because otherwise that may fail or take
excessively long.

[proposal]: https://github.com/WebAssembly/memory64/blob/master/proposals/memory64/Overview.md

* Fix some tests

* More test fixes

* Fix wasmtime tests

* Fix doctests

* Revert to 32-bit immediate offsets in `heap_addr`

This commit updates the generation of addresses in wasm code to always
use 32-bit offsets for `heap_addr`, and if the calculated offset is
bigger than 32-bits we emit a manual add with an overflow check.

* Disable memory64 for spectest fuzzing

* Fix wrong offset being added to heap addr

* More comments!

* Clarify bytes/pages
2021-08-12 09:40:20 -05:00
Andrew Brown
76a93dc112 fuzz: log Wasm contents to file when log::debug is enabled
Previously, the WAT was printed as a log message. This change
standardizes all of the oracles to use `log_wasm`, which emits a `.wasm`
and `.wat` file for each case if `log::debug` is enabled and prints a
message with the names of the created files. Closes #3140.
2021-08-11 09:10:20 -07:00
Andrew Brown
42acb72c54 fuzz: retrieve the WebAssembly spec repository in build.rs
To avoid the large download size of the spec repository mentioned
[here](https://github.com/bytecodealliance/wasmtime/pull/3124#discussion_r684605984),
this change removes it as a submodule and instead clones it shallowly
when the directory is empty (or not present) when `build.rs` is run.
2021-08-10 11:56:07 -07:00
Andrew Brown
651a321f1a fuzz: add differential_spec fuzzing target
This new target compares the outputs of executing the first exported
function of a Wasm module in Wasmtime and in the official Wasm spec
interpreter (using the `wasm-spec-interpreter` crate). This is an
initial step towards more fully-featured fuzzing (e.g. compare memories,
add `v128`, add references, add other proposals, etc.)
2021-08-10 11:56:07 -07:00
Andrew Brown
f3955fa62a refactor: rename DifferentialWasmiModuleConfig to SingleFunctionModuleConfig
Since we plan to reuse this configuration, we rename it and ensure it
has at least 1 type (this resulted in invalid modules).
2021-08-10 11:56:07 -07:00