|
1 | 1 | use crate::error::{Error, OomOrDynError}; |
2 | 2 | use core::{fmt, mem, ptr::NonNull}; |
3 | 3 |
|
4 | | -/// Out-of-memory error. |
| 4 | +/// An out-of-memory (OOM) error. |
5 | 5 | /// |
6 | 6 | /// This error is the sentinel for allocation failure due to memory exhaustion. |
7 | 7 | /// |
8 | | -/// Constructing an [`Error`] from an `OutOfMemory` does not |
9 | | -/// allocate. |
| 8 | +/// Constructing an [`Error`] from an `OutOfMemory` does not allocate. |
10 | 9 | /// |
11 | 10 | /// Allocation failure inside any `Error` method that must allocate |
12 | 11 | /// (e.g. [`Error::context`]) will propagate an `OutOfMemory` error. |
| 12 | +/// |
| 13 | +/// # Out-of-Memory Handling in Wasmtime |
| 14 | +/// |
| 15 | +/// Wasmtime performs out-of-memory (OOM) error handling on a **best-effort |
| 16 | +/// basis**. OOM handling does not have [tier 1 |
| 17 | +/// support](https://docs.wasmtime.dev/stability-tiers.html) at this time and, |
| 18 | +/// therefore, while failure to handle OOM at some allocation site may be |
| 19 | +/// considered a bug, and might be a potential denial-of-service vector, it |
| 20 | +/// would not be considered a security vulnerability.[^limits] |
| 21 | +/// |
| 22 | +/// [^limits]: Note that unconstrained guest-controlled resource usage is still |
| 23 | +/// considered a vulnerability. Wasmtime has tier 1 support for limiting guest |
| 24 | +/// resources, but not for handling OOMs within those limits. |
| 25 | +/// |
| 26 | +/// ## Where Wasmtime Attempts to Handle OOM |
| 27 | +/// |
| 28 | +/// It is important to note that **not all portions of Wasmtime attempt to |
| 29 | +/// handle out-of-memory errors**. Notably, Wasmtime only ever attempts to |
| 30 | +/// handle OOM in the core *runtime* and never in the *compiler*. No attempt is |
| 31 | +/// made to handle allocation failure in the middle of compiling new `Module`s |
| 32 | +/// or `Component`s from Wasm to machine code (or Pulley bytecode). However, |
| 33 | +/// Wasmtime will attempt to handle OOM when running *pre-compiled* Wasm code |
| 34 | +/// (loaded via `Module::deserialize` or `Component::deserialize`). |
| 35 | +/// |
| 36 | +/// Wasmtime's interfaces allow *you* to handle OOM in your own embedding's WASI |
| 37 | +/// implementations and host APIs, but Wasmtime's provided WASI implementations |
| 38 | +/// (e.g. `wasmtime_wasi_http`) will generally not attempt to handle OOM (as |
| 39 | +/// they often depend on third-party crates that do not attempt to handle OOM). |
| 40 | +/// |
| 41 | +/// The API documentation for individual functions and methods that handle OOM |
| 42 | +/// should generally document this fact by listing `OutOfMemory` as one of the |
| 43 | +/// potential errors returned. |
| 44 | +/// |
| 45 | +/// | **Where** | **Handles OOM?** | |
| 46 | +/// |-------------------------------------------------|---------------------------------| |
| 47 | +/// | **Compiler** | **No** | |
| 48 | +/// |  `wasmtime::Module::new` | No | |
| 49 | +/// |  `wasmtime::Component::new` | No | |
| 50 | +/// |  `wasmtime::CodeBuilder` | No | |
| 51 | +/// |  Other compilation APIs... | No | |
| 52 | +/// | **Runtime** | **Yes** | |
| 53 | +/// |  `wasmtime::Store` | Yes | |
| 54 | +/// |  `wasmtime::Linker` | Yes | |
| 55 | +/// |  `wasmtime::Module::deserialize` | Yes | |
| 56 | +/// |  `wasmtime::Instance` | Yes | |
| 57 | +/// |  `wasmtime::Func::call` | Yes | |
| 58 | +/// |  Component Model concurrency/async APIs | Not yet | |
| 59 | +/// |  Other instantiation and execution APIs... | Yes | |
| 60 | +/// | **WASI Implementations and Host APIs** | **Depends** | |
| 61 | +/// |  `wasmtime_wasi` | No | |
| 62 | +/// |  `wasmtime_wasi_http` | No | |
| 63 | +/// |  `wasmtime_wasi_*` | No | |
| 64 | +/// |  Your embedding's APIs | If *you* implement OOM handling | |
| 65 | +/// |
| 66 | +/// If you encounter an unhandled OOM inside Wasmtime, and it is within a |
| 67 | +/// portion of code where it should be handled, then please [file an |
| 68 | +/// issue](https://github.com/bytecodealliance/wasmtime/issues/new/choose). |
| 69 | +/// |
| 70 | +/// ## Handling More OOMs with Rust Nightly APIs |
| 71 | +/// |
| 72 | +/// Rust's standard library provides fallible allocation APIs, or the necessary |
| 73 | +/// building blocks for making our own fallible allocation APIs, for some of its |
| 74 | +/// types and collections. For example, it provides `Vec::try_reserve` which can |
| 75 | +/// be used to build a fallible version of `Vec::push` and fallible `Box` |
| 76 | +/// allocation can be built upon raw allocations from the global allocator and |
| 77 | +/// `Box::from_raw`. |
| 78 | +/// |
| 79 | +/// However, the standard library does not provide these things for all the |
| 80 | +/// types and collections that Wasmtime uses. Some of these APIs are completely |
| 81 | +/// missing (such as a fallible version of |
| 82 | +/// `std::collections::hash_map::VacantEntry::insert`) and some APIs exist but |
| 83 | +/// are feature-gated on unstable, nightly-only Rust features. The most relevant |
| 84 | +/// API from this latter category is |
| 85 | +/// [`Arc::try_new`](https://doc.rust-lang.org/nightly/std/sync/struct.Arc.html#method.try_new), |
| 86 | +/// as Wasmtime's runtime uses a number of `Arc`s under the covers. |
| 87 | +/// |
| 88 | +/// If handling OOMs is important for your Wasmtime embedding, then you should |
| 89 | +/// compile Wasmtime from source using a Nightly Rust toolchain and with the |
| 90 | +/// `RUSTFLAGS="--cfg arc_try_new"` environment variable set. This unlocks |
| 91 | +/// Wasmtime's internal usage of `Arc::try_new`, making more OOM handling at |
| 92 | +/// more allocation sites possible. |
13 | 93 | #[derive(Clone, Copy)] |
14 | 94 | // NB: `OutOfMemory`'s representation must be the same as `OomOrDynError` |
15 | 95 | // (and therefore also `Error`). |
|
0 commit comments