Struct OutOfMemory
pub struct OutOfMemory { /* private fields */ }Expand description
An out-of-memory (OOM) error.
This error is the sentinel for allocation failure due to memory exhaustion.
Constructing an Error from an OutOfMemory does not allocate.
Allocation failure inside any Error method that must allocate
(e.g. Error::context) will propagate an OutOfMemory error.
§Out-of-Memory Handling in Wasmtime
Wasmtime performs out-of-memory (OOM) error handling on a best-effort basis. OOM handling does not have tier 1 support at this time and, therefore, while failure to handle OOM at some allocation site may be considered a bug, and might be a potential denial-of-service vector, it would not be considered a security vulnerability.1
§Where Wasmtime Attempts to Handle OOM
It is important to note that not all portions of Wasmtime attempt to
handle out-of-memory errors. Notably, Wasmtime only ever attempts to
handle OOM in the core runtime and never in the compiler. No attempt is
made to handle allocation failure in the middle of compiling new Modules
or Components from Wasm to machine code (or Pulley bytecode). However,
Wasmtime will attempt to handle OOM when running pre-compiled Wasm code
(loaded via Module::deserialize or Component::deserialize).
Wasmtime’s interfaces allow you to handle OOM in your own embedding’s WASI
implementations and host APIs, but Wasmtime’s provided WASI implementations
(e.g. wasmtime_wasi_http) will generally not attempt to handle OOM (as
they often depend on third-party crates that do not attempt to handle OOM).
The API documentation for individual functions and methods that handle OOM
should generally document this fact by listing OutOfMemory as one of the
potential errors returned.
| Where | Handles OOM? |
|---|---|
| Compiler | No |
wasmtime::Module::new | No |
wasmtime::Component::new | No |
wasmtime::CodeBuilder | No |
| Other compilation APIs… | No |
| Runtime | Yes |
wasmtime::Store | Yes |
wasmtime::Linker | Yes |
wasmtime::Module::deserialize | Yes |
wasmtime::Instance | Yes |
wasmtime::Func::call | Yes |
| Component Model concurrency/async APIs | Not yet |
| Other instantiation and execution APIs… | Yes |
| WASI Implementations and Host APIs | Depends |
wasmtime_wasi | No |
wasmtime_wasi_http | No |
wasmtime_wasi_* | No |
| Your embedding’s APIs | If you implement OOM handling |
If you encounter an unhandled OOM inside Wasmtime, and it is within a portion of code where it should be handled, then please file an issue.
§Handling More OOMs with Rust Nightly APIs
Rust’s standard library provides fallible allocation APIs, or the necessary
building blocks for making our own fallible allocation APIs, for some of its
types and collections. For example, it provides Vec::try_reserve which can
be used to build a fallible version of Vec::push and fallible Box
allocation can be built upon raw allocations from the global allocator and
Box::from_raw.
However, the standard library does not provide these things for all the
types and collections that Wasmtime uses. Some of these APIs are completely
missing (such as a fallible version of
std::collections::hash_map::VacantEntry::insert) and some APIs exist but
are feature-gated on unstable, nightly-only Rust features. The most relevant
API from this latter category is
Arc::try_new,
as Wasmtime’s runtime uses a number of Arcs under the covers.
If handling OOMs is important for your Wasmtime embedding, then you should
compile Wasmtime from source using a Nightly Rust toolchain and with the
RUSTFLAGS="--cfg arc_try_new" environment variable set. This unlocks
Wasmtime’s internal usage of Arc::try_new, making more OOM handling at
more allocation sites possible.
Note that unconstrained guest-controlled resource usage is still considered a vulnerability. Wasmtime has tier 1 support for limiting guest resources, but not for handling OOMs within those limits. ↩
Implementations§
§impl OutOfMemory
impl OutOfMemory
pub const fn new(requested_allocation_size: usize) -> OutOfMemory
pub const fn new(requested_allocation_size: usize) -> OutOfMemory
Construct a new OutOfMemory error.
The requested_allocation_size argument should be the size (in bytes)
of the associated allocation that was attempted and failed.
This operation does not allocate.
§Example
use alloc::alloc::{Layout, alloc};
use core::ptr::NonNull;
/// Attempt to allocate a block of memory from the global allocator,
/// returning an `OutOfMemory` error on failure.
fn try_global_alloc(layout: Layout) -> Result<NonNull<u8>, OutOfMemory> {
if layout.size() == 0 {
return Ok(NonNull::dangling());
}
// Safety: the layout's size is non-zero.
let ptr = unsafe { alloc(layout) };
if let Some(ptr) = NonNull::new(ptr) {
Ok(ptr)
} else {
// The allocation failed, so return an `OutOfMemory` error,
// passing the attempted allocation's size into the `OutOfMemory`
// constructor.
Err(OutOfMemory::new(layout.size()))
}
}pub fn requested_allocation_size(&self) -> usize
pub fn requested_allocation_size(&self) -> usize
Get the size (in bytes) of the associated allocation that was attempted and which failed.
Very large allocation sizes (near isize::MAX and larger) may be capped
to a maximum value.
§Example
let oom = OutOfMemory::new(8192);
assert_eq!(oom.requested_allocation_size(), 8192);Trait Implementations§
§impl Clone for OutOfMemory
impl Clone for OutOfMemory
§fn clone(&self) -> OutOfMemory
fn clone(&self) -> OutOfMemory
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more§impl Debug for OutOfMemory
impl Debug for OutOfMemory
§impl Display for OutOfMemory
impl Display for OutOfMemory
§impl Error for OutOfMemory
impl Error for OutOfMemory
§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
§impl<T> TryFromIterator<T, OutOfMemory> for Box<[T]>
impl<T> TryFromIterator<T, OutOfMemory> for Box<[T]>
§fn try_from_iter<I>(iter: I) -> Result<Box<[T]>, OutOfMemory>where
I: Iterator<Item = T>,
fn try_from_iter<I>(iter: I) -> Result<Box<[T]>, OutOfMemory>where
I: Iterator<Item = T>,
iter provided. Read moreimpl Copy for OutOfMemory
impl Send for OutOfMemory
impl Sync for OutOfMemory
Auto Trait Implementations§
impl Freeze for OutOfMemory
impl RefUnwindSafe for OutOfMemory
impl Unpin for OutOfMemory
impl UnsafeUnpin for OutOfMemory
impl UnwindSafe for OutOfMemory
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more