Skip to main content

wasmtime_provider/
lib.rs

1#![deny(
2  clippy::expect_used,
3  clippy::explicit_deref_methods,
4  clippy::option_if_let_else,
5  clippy::await_holding_lock,
6  clippy::cloned_instead_of_copied,
7  clippy::explicit_into_iter_loop,
8  clippy::flat_map_option,
9  clippy::fn_params_excessive_bools,
10  clippy::implicit_clone,
11  clippy::inefficient_to_string,
12  clippy::large_types_passed_by_value,
13  clippy::manual_ok_or,
14  clippy::map_flatten,
15  clippy::map_unwrap_or,
16  clippy::must_use_candidate,
17  clippy::needless_for_each,
18  clippy::needless_pass_by_value,
19  clippy::option_option,
20  clippy::redundant_else,
21  clippy::semicolon_if_nothing_returned,
22  clippy::too_many_lines,
23  clippy::trivially_copy_pass_by_ref,
24  clippy::unnested_or_patterns,
25  clippy::future_not_send,
26  clippy::useless_let_if_seq,
27  clippy::str_to_string,
28  clippy::inherent_to_string,
29  clippy::let_and_return,
30  clippy::try_err,
31  clippy::unused_async,
32  clippy::missing_enforced_import_renames,
33  clippy::nonstandard_macro_braces,
34  clippy::rc_mutex,
35  clippy::unwrap_or_default,
36  clippy::manual_split_once,
37  clippy::derivable_impls,
38  clippy::needless_option_as_deref,
39  clippy::iter_not_returning_iterator,
40  clippy::same_name_method,
41  clippy::manual_assert,
42  clippy::non_send_fields_in_send_ty,
43  clippy::equatable_if_let,
44  bad_style,
45  clashing_extern_declarations,
46  dead_code,
47  deprecated,
48  explicit_outlives_requirements,
49  improper_ctypes,
50  invalid_value,
51  missing_copy_implementations,
52  missing_debug_implementations,
53  mutable_transmutes,
54  no_mangle_generic_items,
55  non_shorthand_field_patterns,
56  overflowing_literals,
57  path_statements,
58  patterns_in_fns_without_body,
59  private_interfaces,
60  private_bounds,
61  renamed_and_removed_lints,
62  trivial_bounds,
63  trivial_casts,
64  trivial_numeric_casts,
65  type_alias_bounds,
66  unconditional_recursion,
67  unreachable_pub,
68  unsafe_code,
69  unstable_features,
70  unused,
71  unused_allocation,
72  unused_comparisons,
73  unused_import_braces,
74  unused_parens,
75  unused_qualifications,
76  while_true,
77  missing_docs
78)]
79#![doc = include_str!("../README.md")]
80#![cfg_attr(docsrs, feature(doc_cfg))]
81
82mod callbacks;
83#[cfg(feature = "async")]
84mod callbacks_async;
85#[cfg(feature = "wasi")]
86mod wasi;
87
88mod provider;
89pub use provider::{WasmtimeEngineProvider, WasmtimeEngineProviderPre};
90
91#[cfg(feature = "async")]
92mod provider_async;
93#[cfg(feature = "async")]
94#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
95pub use provider_async::{WasmtimeEngineProviderAsync, WasmtimeEngineProviderAsyncPre};
96
97mod store;
98
99#[cfg(feature = "async")]
100mod store_async;
101
102pub mod errors;
103
104mod builder;
105pub use builder::WasmtimeEngineProviderBuilder;
106// export wasmtime and wasmtime_wasi, so that consumers of this crate can use
107// the very same version
108pub use wasmtime;
109#[cfg(feature = "wasi")]
110#[cfg_attr(docsrs, doc(cfg(feature = "wasi")))]
111pub use wasmtime_wasi;
112
113/// Configure behavior of wasmtime [epoch-based interruptions](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.epoch_interruption)
114///
115/// There are two kind of deadlines that apply to waPC modules:
116///
117/// * waPC initialization code: this is the code defined by the module inside
118///   of the `wapc_init` or the `_start` functions
119/// * user function: the actual waPC guest function written by an user
120///
121/// Both these limits are expressed using the number of ticks that are allowed before the
122/// WebAssembly execution is interrupted.
123/// It's up to the embedder of waPC to define how much time a single tick is granted. This could
124/// be 1 second, 10 nanoseconds, or whatever the user prefers.
125#[derive(Clone, Copy, Debug)]
126pub struct EpochDeadlines {
127  /// Deadline for waPC initialization code. Expressed in number of epoch ticks
128  pub wapc_init: u64,
129
130  /// Deadline for user-defined waPC function computation. Expressed in number of epoch ticks
131  pub wapc_func: u64,
132}
133
134/// Configure limits on the resources a single waPC WebAssembly instance is
135/// allowed to consume, leveraging wasmtime's
136/// [`ResourceLimiter`](https://docs.rs/wasmtime/latest/wasmtime/trait.ResourceLimiter.html)
137/// facility (via [`wasmtime::StoreLimits`]).
138///
139/// This can be used to prevent a malicious, or misbehaving, WebAssembly
140/// module from exhausting the host's memory, for example by growing its
141/// linear memory in an unbounded loop.
142///
143/// When a limit is exceeded, the corresponding `memory.grow`/`table.grow`
144/// wasm instruction fails and returns `-1` to the guest, following the
145/// WebAssembly specification. Most language toolchains (Rust, TinyGo,
146/// AssemblyScript, ...) treat a failed growth as a fatal allocation failure
147/// and abort the guest, which is reported back to the host as a trap. The
148/// memory/table cap itself is always enforced by the host regardless of how
149/// the guest reacts to the failed growth.
150#[derive(Clone, Copy, Debug, Default)]
151pub struct ResourceLimits {
152  /// Maximum size, in bytes, that each of the module's linear memories is
153  /// allowed to grow to. This limit is applied to each linear memory
154  /// individually.
155  ///
156  /// `None` (the default) means no limit is enforced.
157  pub max_memory_size: Option<usize>,
158
159  /// Maximum number of elements each of the module's tables is allowed to
160  /// grow to. This limit is applied to each table individually.
161  ///
162  /// WebAssembly tables are used to hold indirect function references (e.g.
163  /// Rust trait objects, Go interfaces, C function pointers) and each
164  /// element costs roughly the size of a pointer of host memory. Most
165  /// modules never grow their tables at runtime, so this is a secondary,
166  /// defense-in-depth limit compared to [`ResourceLimits::max_memory_size`].
167  /// A generous value such as `100_000` (~0.8 MB on a 64-bit host) is
168  /// unlikely to affect legitimate modules.
169  ///
170  /// `None` (the default) means no limit is enforced.
171  pub max_table_elements: Option<usize>,
172}
173
174// Builds a `wasmtime::StoreLimits` out of the (optional) `ResourceLimits`
175// configuration. When `None` is provided, the resulting limits are
176// effectively unlimited (i.e. wasmtime's defaults).
177fn store_limits(resource_limits: Option<ResourceLimits>) -> wasmtime::StoreLimits {
178  let mut builder = wasmtime::StoreLimitsBuilder::new();
179  if let Some(limits) = resource_limits {
180    if let Some(max_memory_size) = limits.max_memory_size {
181      builder = builder.memory_size(max_memory_size);
182    }
183    if let Some(max_table_elements) = limits.max_table_elements {
184      builder = builder.table_elements(max_table_elements);
185    }
186  }
187  builder.build()
188}