substrate_wasmtime/externals.rs
1use crate::trampoline::{
2 generate_global_export, generate_memory_export, generate_table_export, StoreInstanceHandle,
3};
4use crate::values::{from_checked_anyfunc, into_checked_anyfunc, Val};
5use crate::{
6 ExternRef, ExternType, Func, GlobalType, MemoryType, Mutability, Store, TableType, Trap,
7 ValType,
8};
9use anyhow::{anyhow, bail, Result};
10use std::mem;
11use std::ptr;
12use std::slice;
13use wasmtime_environ::wasm;
14use wasmtime_runtime::{self as runtime, InstanceHandle};
15
16// Externals
17
18/// An external item to a WebAssembly module, or a list of what can possibly be
19/// exported from a wasm module.
20///
21/// This is both returned from [`Instance::exports`](crate::Instance::exports)
22/// as well as required by [`Instance::new`](crate::Instance::new). In other
23/// words, this is the type of extracted values from an instantiated module, and
24/// it's also used to provide imported values when instantiating a module.
25#[derive(Clone)]
26pub enum Extern {
27 /// A WebAssembly `func` which can be called.
28 Func(Func),
29 /// A WebAssembly `global` which acts like a `Cell<T>` of sorts, supporting
30 /// `get` and `set` operations.
31 Global(Global),
32 /// A WebAssembly `table` which is an array of `Val` types.
33 Table(Table),
34 /// A WebAssembly linear memory.
35 Memory(Memory),
36}
37
38impl Extern {
39 /// Returns the underlying `Func`, if this external is a function.
40 ///
41 /// Returns `None` if this is not a function.
42 pub fn into_func(self) -> Option<Func> {
43 match self {
44 Extern::Func(func) => Some(func),
45 _ => None,
46 }
47 }
48
49 /// Returns the underlying `Global`, if this external is a global.
50 ///
51 /// Returns `None` if this is not a global.
52 pub fn into_global(self) -> Option<Global> {
53 match self {
54 Extern::Global(global) => Some(global),
55 _ => None,
56 }
57 }
58
59 /// Returns the underlying `Table`, if this external is a table.
60 ///
61 /// Returns `None` if this is not a table.
62 pub fn into_table(self) -> Option<Table> {
63 match self {
64 Extern::Table(table) => Some(table),
65 _ => None,
66 }
67 }
68
69 /// Returns the underlying `Memory`, if this external is a memory.
70 ///
71 /// Returns `None` if this is not a memory.
72 pub fn into_memory(self) -> Option<Memory> {
73 match self {
74 Extern::Memory(memory) => Some(memory),
75 _ => None,
76 }
77 }
78
79 /// Returns the type associated with this `Extern`.
80 pub fn ty(&self) -> ExternType {
81 match self {
82 Extern::Func(ft) => ExternType::Func(ft.ty()),
83 Extern::Memory(ft) => ExternType::Memory(ft.ty()),
84 Extern::Table(tt) => ExternType::Table(tt.ty()),
85 Extern::Global(gt) => ExternType::Global(gt.ty()),
86 }
87 }
88
89 pub(crate) fn get_wasmtime_export(&self) -> wasmtime_runtime::Export {
90 match self {
91 Extern::Func(f) => f.wasmtime_function().clone().into(),
92 Extern::Global(g) => g.wasmtime_export.clone().into(),
93 Extern::Memory(m) => m.wasmtime_export.clone().into(),
94 Extern::Table(t) => t.wasmtime_export.clone().into(),
95 }
96 }
97
98 pub(crate) fn from_wasmtime_export(
99 wasmtime_export: wasmtime_runtime::Export,
100 instance: StoreInstanceHandle,
101 ) -> Extern {
102 match wasmtime_export {
103 wasmtime_runtime::Export::Function(f) => {
104 Extern::Func(Func::from_wasmtime_function(f, instance))
105 }
106 wasmtime_runtime::Export::Memory(m) => {
107 Extern::Memory(Memory::from_wasmtime_memory(m, instance))
108 }
109 wasmtime_runtime::Export::Global(g) => {
110 Extern::Global(Global::from_wasmtime_global(g, instance))
111 }
112 wasmtime_runtime::Export::Table(t) => {
113 Extern::Table(Table::from_wasmtime_table(t, instance))
114 }
115 }
116 }
117
118 pub(crate) fn comes_from_same_store(&self, store: &Store) -> bool {
119 let my_store = match self {
120 Extern::Func(f) => f.store(),
121 Extern::Global(g) => &g.instance.store,
122 Extern::Memory(m) => &m.instance.store,
123 Extern::Table(t) => &t.instance.store,
124 };
125 Store::same(my_store, store)
126 }
127}
128
129impl From<Func> for Extern {
130 fn from(r: Func) -> Self {
131 Extern::Func(r)
132 }
133}
134
135impl From<Global> for Extern {
136 fn from(r: Global) -> Self {
137 Extern::Global(r)
138 }
139}
140
141impl From<Memory> for Extern {
142 fn from(r: Memory) -> Self {
143 Extern::Memory(r)
144 }
145}
146
147impl From<Table> for Extern {
148 fn from(r: Table) -> Self {
149 Extern::Table(r)
150 }
151}
152
153/// A WebAssembly `global` value which can be read and written to.
154///
155/// A `global` in WebAssembly is sort of like a global variable within an
156/// [`Instance`](crate::Instance). The `global.get` and `global.set`
157/// instructions will modify and read global values in a wasm module. Globals
158/// can either be imported or exported from wasm modules.
159///
160/// If you're familiar with Rust already you can think of a `Global` as a sort
161/// of `Rc<Cell<Val>>`, more or less.
162///
163/// # `Global` and `Clone`
164///
165/// Globals are internally reference counted so you can `clone` a `Global`. The
166/// cloning process only performs a shallow clone, so two cloned `Global`
167/// instances are equivalent in their functionality.
168#[derive(Clone)]
169pub struct Global {
170 instance: StoreInstanceHandle,
171 wasmtime_export: wasmtime_runtime::ExportGlobal,
172}
173
174impl Global {
175 /// Creates a new WebAssembly `global` value with the provide type `ty` and
176 /// initial value `val`.
177 ///
178 /// The `store` argument provided is used as a general global cache for
179 /// information, and otherwise the `ty` and `val` arguments are used to
180 /// initialize the global.
181 ///
182 /// # Errors
183 ///
184 /// Returns an error if the `ty` provided does not match the type of the
185 /// value `val`.
186 pub fn new(store: &Store, ty: GlobalType, val: Val) -> Result<Global> {
187 if !val.comes_from_same_store(store) {
188 bail!("cross-`Store` globals are not supported");
189 }
190 if val.ty() != *ty.content() {
191 bail!("value provided does not match the type of this global");
192 }
193 let (instance, wasmtime_export) = generate_global_export(store, &ty, val)?;
194 Ok(Global {
195 instance,
196 wasmtime_export,
197 })
198 }
199
200 /// Returns the underlying type of this `global`.
201 pub fn ty(&self) -> GlobalType {
202 // The original export is coming from wasmtime_runtime itself we should
203 // support all the types coming out of it, so assert such here.
204 GlobalType::from_wasmtime_global(&self.wasmtime_export.global)
205 }
206
207 /// Returns the value type of this `global`.
208 pub fn val_type(&self) -> ValType {
209 ValType::from_wasm_type(&self.wasmtime_export.global.wasm_ty)
210 }
211
212 /// Returns the underlying mutability of this `global`.
213 pub fn mutability(&self) -> Mutability {
214 if self.wasmtime_export.global.mutability {
215 Mutability::Var
216 } else {
217 Mutability::Const
218 }
219 }
220
221 /// Returns the current [`Val`] of this global.
222 pub fn get(&self) -> Val {
223 unsafe {
224 let definition = &mut *self.wasmtime_export.definition;
225 match self.val_type() {
226 ValType::I32 => Val::from(*definition.as_i32()),
227 ValType::I64 => Val::from(*definition.as_i64()),
228 ValType::F32 => Val::F32(*definition.as_u32()),
229 ValType::F64 => Val::F64(*definition.as_u64()),
230 ValType::ExternRef => Val::ExternRef(
231 definition
232 .as_externref()
233 .clone()
234 .map(|inner| ExternRef { inner }),
235 ),
236 ValType::FuncRef => {
237 from_checked_anyfunc(definition.as_anyfunc() as *mut _, &self.instance.store)
238 }
239 ty => unimplemented!("Global::get for {:?}", ty),
240 }
241 }
242 }
243
244 /// Attempts to set the current value of this global to [`Val`].
245 ///
246 /// # Errors
247 ///
248 /// Returns an error if this global has a different type than `Val`, or if
249 /// it's not a mutable global.
250 pub fn set(&self, val: Val) -> Result<()> {
251 if self.mutability() != Mutability::Var {
252 bail!("immutable global cannot be set");
253 }
254 let ty = self.val_type();
255 if val.ty() != ty {
256 bail!("global of type {:?} cannot be set to {:?}", ty, val.ty());
257 }
258 if !val.comes_from_same_store(&self.instance.store) {
259 bail!("cross-`Store` values are not supported");
260 }
261 unsafe {
262 let definition = &mut *self.wasmtime_export.definition;
263 match val {
264 Val::I32(i) => *definition.as_i32_mut() = i,
265 Val::I64(i) => *definition.as_i64_mut() = i,
266 Val::F32(f) => *definition.as_u32_mut() = f,
267 Val::F64(f) => *definition.as_u64_mut() = f,
268 Val::FuncRef(f) => {
269 *definition.as_anyfunc_mut() = f.map_or(ptr::null(), |f| {
270 f.caller_checked_anyfunc().as_ptr() as *const _
271 });
272 }
273 Val::ExternRef(x) => {
274 // In case the old value's `Drop` implementation is
275 // re-entrant and tries to touch this global again, do a
276 // replace, and then drop. This way no one can observe a
277 // halfway-deinitialized value.
278 let old = mem::replace(definition.as_externref_mut(), x.map(|x| x.inner));
279 drop(old);
280 }
281 _ => unimplemented!("Global::set for {:?}", val.ty()),
282 }
283 }
284 Ok(())
285 }
286
287 pub(crate) fn from_wasmtime_global(
288 wasmtime_export: wasmtime_runtime::ExportGlobal,
289 instance: StoreInstanceHandle,
290 ) -> Global {
291 Global {
292 instance,
293 wasmtime_export,
294 }
295 }
296}
297
298/// A WebAssembly `table`, or an array of values.
299///
300/// Like [`Memory`] a table is an indexed array of values, but unlike [`Memory`]
301/// it's an array of WebAssembly values rather than bytes. One of the most
302/// common usages of a table is a function table for wasm modules, where each
303/// element has the `Func` type.
304///
305/// Tables, like globals, are not threadsafe and can only be used on one thread.
306/// Tables can be grown in size and each element can be read/written.
307///
308/// # `Table` and `Clone`
309///
310/// Tables are internally reference counted so you can `clone` a `Table`. The
311/// cloning process only performs a shallow clone, so two cloned `Table`
312/// instances are equivalent in their functionality.
313#[derive(Clone)]
314pub struct Table {
315 instance: StoreInstanceHandle,
316 wasmtime_export: wasmtime_runtime::ExportTable,
317}
318
319fn set_table_item(
320 instance: &InstanceHandle,
321 table_index: wasm::DefinedTableIndex,
322 item_index: u32,
323 item: runtime::TableElement,
324) -> Result<()> {
325 instance
326 .table_set(table_index, item_index, item)
327 .map_err(|()| anyhow!("table element index out of bounds"))
328}
329
330impl Table {
331 /// Creates a new `Table` with the given parameters.
332 ///
333 /// * `store` - a global cache to store information in
334 /// * `ty` - the type of this table, containing both the element type as
335 /// well as the initial size and maximum size, if any.
336 /// * `init` - the initial value to fill all table entries with, if the
337 /// table starts with an initial size.
338 ///
339 /// # Errors
340 ///
341 /// Returns an error if `init` does not match the element type of the table.
342 pub fn new(store: &Store, ty: TableType, init: Val) -> Result<Table> {
343 let (instance, wasmtime_export) = generate_table_export(store, &ty)?;
344
345 let init: runtime::TableElement = match ty.element() {
346 ValType::FuncRef => into_checked_anyfunc(init, store)?.into(),
347 ValType::ExternRef => init
348 .externref()
349 .ok_or_else(|| {
350 anyhow!("table initialization value does not have expected type `externref`")
351 })?
352 .map(|x| x.inner)
353 .into(),
354 ty => bail!("unsupported table element type: {:?}", ty),
355 };
356
357 // Initialize entries with the init value.
358 let definition = unsafe { &*wasmtime_export.definition };
359 let index = instance.table_index(definition);
360 for i in 0..definition.current_elements {
361 set_table_item(&instance, index, i, init.clone())?;
362 }
363
364 Ok(Table {
365 instance,
366 wasmtime_export,
367 })
368 }
369
370 /// Returns the underlying type of this table, including its element type as
371 /// well as the maximum/minimum lower bounds.
372 pub fn ty(&self) -> TableType {
373 TableType::from_wasmtime_table(&self.wasmtime_export.table.table)
374 }
375
376 fn wasmtime_table_index(&self) -> wasm::DefinedTableIndex {
377 unsafe { self.instance.table_index(&*self.wasmtime_export.definition) }
378 }
379
380 /// Returns the table element value at `index`.
381 ///
382 /// Returns `None` if `index` is out of bounds.
383 pub fn get(&self, index: u32) -> Option<Val> {
384 let table_index = self.wasmtime_table_index();
385 let item = self.instance.table_get(table_index, index)?;
386 match item {
387 runtime::TableElement::FuncRef(f) => {
388 Some(unsafe { from_checked_anyfunc(f, &self.instance.store) })
389 }
390 runtime::TableElement::ExternRef(None) => Some(Val::ExternRef(None)),
391 runtime::TableElement::ExternRef(Some(x)) => {
392 Some(Val::ExternRef(Some(ExternRef { inner: x })))
393 }
394 }
395 }
396
397 /// Writes the `val` provided into `index` within this table.
398 ///
399 /// # Errors
400 ///
401 /// Returns an error if `index` is out of bounds or if `val` does not have
402 /// the right type to be stored in this table.
403 pub fn set(&self, index: u32, val: Val) -> Result<()> {
404 if !val.comes_from_same_store(&self.instance.store) {
405 bail!("cross-`Store` values are not supported in tables");
406 }
407 let table_index = self.wasmtime_table_index();
408 set_table_item(
409 &self.instance,
410 table_index,
411 index,
412 val.into_table_element()?,
413 )
414 }
415
416 /// Returns the current size of this table.
417 pub fn size(&self) -> u32 {
418 unsafe { (*self.wasmtime_export.definition).current_elements }
419 }
420
421 /// Grows the size of this table by `delta` more elements, initialization
422 /// all new elements to `init`.
423 ///
424 /// Returns the previous size of this table if successful.
425 ///
426 /// # Errors
427 ///
428 /// Returns an error if the table cannot be grown by `delta`, for example
429 /// if it would cause the table to exceed its maximum size. Also returns an
430 /// error if `init` is not of the right type.
431 pub fn grow(&self, delta: u32, init: Val) -> Result<u32> {
432 let index = self.wasmtime_table_index();
433 let orig_size = match self.ty().element() {
434 ValType::FuncRef => {
435 let init = into_checked_anyfunc(init, &self.instance.store)?;
436 self.instance.defined_table_grow(index, delta, init.into())
437 }
438 ValType::ExternRef => {
439 let init = match init {
440 Val::ExternRef(Some(x)) => Some(x.inner),
441 Val::ExternRef(None) => None,
442 _ => bail!("incorrect init value for growing table"),
443 };
444 self.instance.defined_table_grow(
445 index,
446 delta,
447 runtime::TableElement::ExternRef(init),
448 )
449 }
450 _ => unreachable!("only `funcref` and `externref` tables are supported"),
451 };
452 if let Some(size) = orig_size {
453 Ok(size)
454 } else {
455 bail!("failed to grow table by `{}`", delta)
456 }
457 }
458
459 /// Copy `len` elements from `src_table[src_index..]` into
460 /// `dst_table[dst_index..]`.
461 ///
462 /// # Errors
463 ///
464 /// Returns an error if the range is out of bounds of either the source or
465 /// destination tables.
466 pub fn copy(
467 dst_table: &Table,
468 dst_index: u32,
469 src_table: &Table,
470 src_index: u32,
471 len: u32,
472 ) -> Result<()> {
473 if !Store::same(&dst_table.instance.store, &src_table.instance.store) {
474 bail!("cross-`Store` table copies are not supported");
475 }
476
477 // NB: We must use the `dst_table`'s `wasmtime_handle` for the
478 // `dst_table_index` and vice versa for `src_table` since each table can
479 // come from different modules.
480
481 let dst_table_index = dst_table.wasmtime_table_index();
482 let dst_table = dst_table.instance.get_defined_table(dst_table_index);
483
484 let src_table_index = src_table.wasmtime_table_index();
485 let src_table = src_table.instance.get_defined_table(src_table_index);
486
487 runtime::Table::copy(dst_table, src_table, dst_index, src_index, len)
488 .map_err(Trap::from_runtime)?;
489 Ok(())
490 }
491
492 /// Fill `table[dst..(dst + len)]` with the given value.
493 ///
494 /// # Errors
495 ///
496 /// Returns an error if
497 ///
498 /// * `val` is not of the same type as this table's
499 /// element type,
500 ///
501 /// * the region to be filled is out of bounds, or
502 ///
503 /// * `val` comes from a different `Store` from this table.
504 pub fn fill(&self, dst: u32, val: Val, len: u32) -> Result<()> {
505 if !val.comes_from_same_store(&self.instance.store) {
506 bail!("cross-`Store` table fills are not supported");
507 }
508
509 let table_index = self.wasmtime_table_index();
510 self.instance
511 .handle
512 .defined_table_fill(table_index, dst, val.into_table_element()?, len)
513 .map_err(Trap::from_runtime)?;
514
515 Ok(())
516 }
517
518 pub(crate) fn from_wasmtime_table(
519 wasmtime_export: wasmtime_runtime::ExportTable,
520 instance: StoreInstanceHandle,
521 ) -> Table {
522 Table {
523 instance,
524 wasmtime_export,
525 }
526 }
527}
528
529/// A WebAssembly linear memory.
530///
531/// WebAssembly memories represent a contiguous array of bytes that have a size
532/// that is always a multiple of the WebAssembly page size, currently 64
533/// kilobytes.
534///
535/// WebAssembly memory is used for global data, statics in C/C++/Rust, shadow
536/// stack memory, etc. Accessing wasm memory is generally quite fast!
537///
538/// # `Memory` and `Clone`
539///
540/// Memories are internally reference counted so you can `clone` a `Memory`. The
541/// cloning process only performs a shallow clone, so two cloned `Memory`
542/// instances are equivalent in their functionality.
543///
544/// # `Memory` and threads
545///
546/// It is intended that `Memory` is safe to share between threads. At this time
547/// this is not implemented in `wasmtime`, however. This is planned to be
548/// implemented though!
549///
550/// # `Memory` and Safety
551///
552/// Linear memory is a lynchpin of safety for WebAssembly, but it turns out
553/// there are very few ways to safely inspect the contents of a memory from the
554/// host (Rust). This is because memory safety is quite tricky when working with
555/// a `Memory` and we're still working out the best idioms to encapsulate
556/// everything safely where it's efficient and ergonomic. This section of
557/// documentation, however, is intended to help educate a bit what is and isn't
558/// safe when working with `Memory`.
559///
560/// For safety purposes you can think of a `Memory` as a glorified
561/// `Rc<UnsafeCell<Vec<u8>>>`. There are a few consequences of this
562/// interpretation:
563///
564/// * At any time someone else may have access to the memory (hence the `Rc`).
565/// This could be a wasm instance, other host code, or a set of wasm instances
566/// which all reference a `Memory`. When in doubt assume someone else has a
567/// handle to your `Memory`.
568///
569/// * At any time, memory can be read from or written to (hence the
570/// `UnsafeCell`). Anyone with a handle to a wasm memory can read/write to it.
571/// Primarily other instances can execute the `load` and `store` family of
572/// instructions, as well as any other which modifies or reads memory.
573///
574/// * At any time memory may grow (hence the `Vec<..>`). Growth may relocate the
575/// base memory pointer (similar to how `vec.push(...)` can change the result
576/// of `.as_ptr()`)
577///
578/// So given that we're working roughly with `Rc<UnsafeCell<Vec<u8>>>` that's a
579/// lot to keep in mind! It's hopefully though sort of setting the stage as to
580/// what you can safely do with memories.
581///
582/// Let's run through a few safe examples first of how you can use a `Memory`.
583///
584/// ```rust
585/// use wasmtime::Memory;
586///
587/// fn safe_examples(mem: &Memory) {
588/// // Just like wasm, it's safe to read memory almost at any time. The
589/// // gotcha here is that we need to be sure to load from the correct base
590/// // pointer and perform the bounds check correctly. So long as this is
591/// // all self contained here (e.g. not arbitrary code in the middle) we're
592/// // good to go.
593/// let byte = unsafe { mem.data_unchecked()[0x123] };
594///
595/// // Short-lived borrows of memory are safe, but they must be scoped and
596/// // not have code which modifies/etc `Memory` while the borrow is active.
597/// // For example if you want to read a string from memory it is safe to do
598/// // so:
599/// let string_base = 0xdead;
600/// let string_len = 0xbeef;
601/// let string = unsafe {
602/// let bytes = &mem.data_unchecked()[string_base..][..string_len];
603/// match std::str::from_utf8(bytes) {
604/// Ok(s) => s.to_string(), // copy out of wasm memory
605/// Err(_) => panic!("not valid utf-8"),
606/// }
607/// };
608///
609/// // Additionally like wasm you can write to memory at any point in time,
610/// // again making sure that after you get the unchecked slice you don't
611/// // execute code which could read/write/modify `Memory`:
612/// unsafe {
613/// mem.data_unchecked_mut()[0x123] = 3;
614/// }
615///
616/// // When working with *borrows* that point directly into wasm memory you
617/// // need to be extremely careful. Any functionality that operates on a
618/// // borrow into wasm memory needs to be thoroughly audited to effectively
619/// // not touch the `Memory` at all
620/// let data_base = 0xfeed;
621/// let data_len = 0xface;
622/// unsafe {
623/// let data = &mem.data_unchecked()[data_base..][..data_len];
624/// host_function_that_doesnt_touch_memory(data);
625///
626/// // effectively the same rules apply to mutable borrows
627/// let data_mut = &mut mem.data_unchecked_mut()[data_base..][..data_len];
628/// host_function_that_doesnt_touch_memory(data);
629/// }
630/// }
631/// # fn host_function_that_doesnt_touch_memory(_: &[u8]){}
632/// ```
633///
634/// It's worth also, however, covering some examples of **incorrect**,
635/// **unsafe** usages of `Memory`. Do not do these things!
636///
637/// ```rust
638/// # use anyhow::Result;
639/// use wasmtime::Memory;
640///
641/// // NOTE: All code in this function is not safe to execute and may cause
642/// // segfaults/undefined behavior at runtime. Do not copy/paste these examples
643/// // into production code!
644/// unsafe fn unsafe_examples(mem: &Memory) -> Result<()> {
645/// // First and foremost, any borrow can be invalidated at any time via the
646/// // `Memory::grow` function. This can relocate memory which causes any
647/// // previous pointer to be possibly invalid now.
648/// let pointer: &u8 = &mem.data_unchecked()[0x100];
649/// mem.grow(1)?; // invalidates `pointer`!
650/// // println!("{}", *pointer); // FATAL: use-after-free
651///
652/// // Note that the use-after-free also applies to slices, whether they're
653/// // slices of bytes or strings.
654/// let slice: &[u8] = &mem.data_unchecked()[0x100..0x102];
655/// mem.grow(1)?; // invalidates `slice`!
656/// // println!("{:?}", slice); // FATAL: use-after-free
657///
658/// // Due to the reference-counted nature of `Memory` note that literal
659/// // calls to `Memory::grow` are not sufficient to audit for. You'll need
660/// // to be careful that any mutation of `Memory` doesn't happen while
661/// // you're holding an active borrow.
662/// let slice: &[u8] = &mem.data_unchecked()[0x100..0x102];
663/// some_other_function(); // may invalidate `slice` through another `mem` reference
664/// // println!("{:?}", slice); // FATAL: maybe a use-after-free
665///
666/// // An especially subtle aspect of accessing a wasm instance's memory is
667/// // that you need to be extremely careful about aliasing. Anyone at any
668/// // time can call `data_unchecked()` or `data_unchecked_mut()`, which
669/// // means you can easily have aliasing mutable references:
670/// let ref1: &u8 = &mem.data_unchecked()[0x100];
671/// let ref2: &mut u8 = &mut mem.data_unchecked_mut()[0x100];
672/// // *ref2 = *ref1; // FATAL: violates Rust's aliasing rules
673///
674/// // Note that aliasing applies to strings as well, for example this is
675/// // not valid because the slices overlap.
676/// let slice1: &mut [u8] = &mut mem.data_unchecked_mut()[0x100..][..3];
677/// let slice2: &mut [u8] = &mut mem.data_unchecked_mut()[0x102..][..4];
678/// // println!("{:?} {:?}", slice1, slice2); // FATAL: aliasing mutable pointers
679///
680/// Ok(())
681/// }
682/// # fn some_other_function() {}
683/// ```
684///
685/// Overall there's some general rules of thumb when working with `Memory` and
686/// getting raw pointers inside of it:
687///
688/// * If you never have a "long lived" pointer into memory, you're likely in the
689/// clear. Care still needs to be taken in threaded scenarios or when/where
690/// data is read, but you'll be shielded from many classes of issues.
691/// * Long-lived pointers must always respect Rust'a aliasing rules. It's ok for
692/// shared borrows to overlap with each other, but mutable borrows must
693/// overlap with nothing.
694/// * Long-lived pointers are only valid if `Memory` isn't used in an unsafe way
695/// while the pointer is valid. This includes both aliasing and growth.
696///
697/// At this point it's worth reiterating again that working with `Memory` is
698/// pretty tricky and that's not great! Proposals such as [interface types] are
699/// intended to prevent wasm modules from even needing to import/export memory
700/// in the first place, which obviates the need for all of these safety caveats!
701/// Additionally over time we're still working out the best idioms to expose in
702/// `wasmtime`, so if you've got ideas or questions please feel free to [open an
703/// issue]!
704///
705/// ## `Memory` Safety and Threads
706///
707/// Currently the `wasmtime` crate does not implement the wasm threads proposal,
708/// but it is planned to do so. It's additionally worthwhile discussing how this
709/// affects memory safety and what was previously just discussed as well.
710///
711/// Once threads are added into the mix, all of the above rules still apply.
712/// There's an additional, rule, however, that all reads and writes can
713/// happen *concurrently*. This effectively means that long-lived borrows into
714/// wasm memory are virtually never safe to have.
715///
716/// Mutable pointers are fundamentally unsafe to have in a concurrent scenario
717/// in the face of arbitrary wasm code. Only if you dynamically know for sure
718/// that wasm won't access a region would it be safe to construct a mutable
719/// pointer. Additionally even shared pointers are largely unsafe because their
720/// underlying contents may change, so unless `UnsafeCell` in one form or
721/// another is used everywhere there's no safety.
722///
723/// One important point about concurrency is that `Memory::grow` can indeed
724/// happen concurrently. This, however, will never relocate the base pointer.
725/// Shared memories must always have a maximum size and they will be
726/// preallocated such that growth will never relocate the base pointer. The
727/// maximum length of the memory, however, will change over time.
728///
729/// Overall the general rule of thumb for shared memories is that you must
730/// atomically read and write everything. Nothing can be borrowed and everything
731/// must be eagerly copied out.
732///
733/// [interface types]: https://github.com/webassembly/interface-types
734/// [open an issue]: https://github.com/bytecodealliance/wasmtime/issues/new
735#[derive(Clone)]
736pub struct Memory {
737 instance: StoreInstanceHandle,
738 wasmtime_export: wasmtime_runtime::ExportMemory,
739}
740
741impl Memory {
742 /// Creates a new WebAssembly memory given the configuration of `ty`.
743 ///
744 /// The `store` argument is a general location for cache information, and
745 /// otherwise the memory will immediately be allocated according to the
746 /// type's configuration. All WebAssembly memory is initialized to zero.
747 ///
748 /// # Examples
749 ///
750 /// ```
751 /// # use wasmtime::*;
752 /// # fn main() -> anyhow::Result<()> {
753 /// let engine = Engine::default();
754 /// let store = Store::new(&engine);
755 ///
756 /// let memory_ty = MemoryType::new(Limits::new(1, None));
757 /// let memory = Memory::new(&store, memory_ty);
758 ///
759 /// let module = Module::new(&engine, "(module (memory (import \"\" \"\") 1))")?;
760 /// let instance = Instance::new(&store, &module, &[memory.into()])?;
761 /// // ...
762 /// # Ok(())
763 /// # }
764 /// ```
765 pub fn new(store: &Store, ty: MemoryType) -> Memory {
766 let (instance, wasmtime_export) =
767 generate_memory_export(store, &ty).expect("generated memory");
768 Memory {
769 instance,
770 wasmtime_export,
771 }
772 }
773
774 /// Returns the underlying type of this memory.
775 ///
776 /// # Examples
777 ///
778 /// ```
779 /// # use wasmtime::*;
780 /// # fn main() -> anyhow::Result<()> {
781 /// let engine = Engine::default();
782 /// let store = Store::new(&engine);
783 /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1))")?;
784 /// let instance = Instance::new(&store, &module, &[])?;
785 /// let memory = instance.get_memory("mem").unwrap();
786 /// let ty = memory.ty();
787 /// assert_eq!(ty.limits().min(), 1);
788 /// # Ok(())
789 /// # }
790 /// ```
791 pub fn ty(&self) -> MemoryType {
792 MemoryType::from_wasmtime_memory(&self.wasmtime_export.memory.memory)
793 }
794
795 /// Returns this memory as a slice view that can be read natively in Rust.
796 ///
797 /// # Safety
798 ///
799 /// This is an unsafe operation because there is no guarantee that the
800 /// following operations do not happen concurrently while the slice is in
801 /// use:
802 ///
803 /// * Data could be modified by calling into a wasm module.
804 /// * Memory could be relocated through growth by calling into a wasm
805 /// module.
806 /// * When threads are supported, non-atomic reads will race with other
807 /// writes.
808 ///
809 /// Extreme care need be taken when the data of a `Memory` is read. The
810 /// above invariants all need to be upheld at a bare minimum, and in
811 /// general you'll need to ensure that while you're looking at slice you're
812 /// the only one who can possibly look at the slice and read/write it.
813 ///
814 /// Be sure to keep in mind that `Memory` is reference counted, meaning
815 /// that there may be other users of this `Memory` instance elsewhere in
816 /// your program. Additionally `Memory` can be shared and used in any number
817 /// of wasm instances, so calling any wasm code should be considered
818 /// dangerous while you're holding a slice of memory.
819 ///
820 /// For more information and examples see the documentation on the
821 /// [`Memory`] type.
822 pub unsafe fn data_unchecked(&self) -> &[u8] {
823 self.data_unchecked_mut()
824 }
825
826 /// Returns this memory as a slice view that can be read and written
827 /// natively in Rust.
828 ///
829 /// # Safety
830 ///
831 /// All of the same safety caveats of [`Memory::data_unchecked`] apply
832 /// here, doubly so because this is returning a mutable slice! As a
833 /// double-extra reminder, remember that `Memory` is reference counted, so
834 /// you can very easily acquire two mutable slices by simply calling this
835 /// function twice. Extreme caution should be used when using this method,
836 /// and in general you probably want to result to unsafe accessors and the
837 /// `data` methods below.
838 ///
839 /// For more information and examples see the documentation on the
840 /// [`Memory`] type.
841 pub unsafe fn data_unchecked_mut(&self) -> &mut [u8] {
842 let definition = &*self.wasmtime_export.definition;
843 slice::from_raw_parts_mut(definition.base, definition.current_length)
844 }
845
846 /// Returns the base pointer, in the host's address space, that the memory
847 /// is located at.
848 ///
849 /// When reading and manipulating memory be sure to read up on the caveats
850 /// of [`Memory::data_unchecked`] to make sure that you can safely
851 /// read/write the memory.
852 ///
853 /// For more information and examples see the documentation on the
854 /// [`Memory`] type.
855 pub fn data_ptr(&self) -> *mut u8 {
856 unsafe { (*self.wasmtime_export.definition).base }
857 }
858
859 /// Returns the byte length of this memory.
860 ///
861 /// The returned value will be a multiple of the wasm page size, 64k.
862 ///
863 /// For more information and examples see the documentation on the
864 /// [`Memory`] type.
865 pub fn data_size(&self) -> usize {
866 unsafe { (*self.wasmtime_export.definition).current_length }
867 }
868
869 /// Returns the size, in pages, of this wasm memory.
870 pub fn size(&self) -> u32 {
871 (self.data_size() / wasmtime_environ::WASM_PAGE_SIZE as usize) as u32
872 }
873
874 /// Grows this WebAssembly memory by `delta` pages.
875 ///
876 /// This will attempt to add `delta` more pages of memory on to the end of
877 /// this `Memory` instance. If successful this may relocate the memory and
878 /// cause [`Memory::data_ptr`] to return a new value. Additionally previous
879 /// slices into this memory may no longer be valid.
880 ///
881 /// On success returns the number of pages this memory previously had
882 /// before the growth succeeded.
883 ///
884 /// # Errors
885 ///
886 /// Returns an error if memory could not be grown, for example if it exceeds
887 /// the maximum limits of this memory.
888 ///
889 /// # Examples
890 ///
891 /// ```
892 /// # use wasmtime::*;
893 /// # fn main() -> anyhow::Result<()> {
894 /// let engine = Engine::default();
895 /// let store = Store::new(&engine);
896 /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1 2))")?;
897 /// let instance = Instance::new(&store, &module, &[])?;
898 /// let memory = instance.get_memory("mem").unwrap();
899 ///
900 /// assert_eq!(memory.size(), 1);
901 /// assert_eq!(memory.grow(1)?, 1);
902 /// assert_eq!(memory.size(), 2);
903 /// assert!(memory.grow(1).is_err());
904 /// assert_eq!(memory.size(), 2);
905 /// assert_eq!(memory.grow(0)?, 2);
906 /// # Ok(())
907 /// # }
908 /// ```
909 pub fn grow(&self, delta: u32) -> Result<u32> {
910 let index = self
911 .instance
912 .memory_index(unsafe { &*self.wasmtime_export.definition });
913 self.instance
914 .memory_grow(index, delta)
915 .ok_or_else(|| anyhow!("failed to grow memory"))
916 }
917
918 pub(crate) fn from_wasmtime_memory(
919 wasmtime_export: wasmtime_runtime::ExportMemory,
920 instance: StoreInstanceHandle,
921 ) -> Memory {
922 Memory {
923 instance,
924 wasmtime_export,
925 }
926 }
927}
928
929/// A linear memory. This trait provides an interface for raw memory buffers which are used
930/// by wasmtime, e.g. inside ['Memory']. Such buffers are in principle not thread safe.
931/// By implementing this trait together with MemoryCreator,
932/// one can supply wasmtime with custom allocated host managed memory.
933///
934/// # Safety
935/// The memory should be page aligned and a multiple of page size.
936/// To prevent possible silent overflows, the memory should be protected by a guard page.
937/// Additionally the safety concerns explained in ['Memory'], for accessing the memory
938/// apply here as well.
939///
940/// Note that this is a relatively new and experimental feature and it is recommended
941/// to be familiar with wasmtime runtime code to use it.
942pub unsafe trait LinearMemory {
943 /// Returns the number of allocated wasm pages.
944 fn size(&self) -> u32;
945
946 /// Grow memory by the specified amount of wasm pages.
947 ///
948 /// Returns `None` if memory can't be grown by the specified amount
949 /// of wasm pages.
950 fn grow(&self, delta: u32) -> Option<u32>;
951
952 /// Return the allocated memory as a mutable pointer to u8.
953 fn as_ptr(&self) -> *mut u8;
954}
955
956/// A memory creator. Can be used to provide a memory creator
957/// to wasmtime which supplies host managed memory.
958///
959/// # Safety
960/// This trait is unsafe, as the memory safety depends on proper implementation of
961/// memory management. Memories created by the MemoryCreator should always be treated
962/// as owned by wasmtime instance, and any modification of them outside of wasmtime
963/// invoked routines is unsafe and may lead to corruption.
964///
965/// Note that this is a relatively new and experimental feature and it is recommended
966/// to be familiar with wasmtime runtime code to use it.
967pub unsafe trait MemoryCreator: Send + Sync {
968 /// Create a new `LinearMemory` object from the specified parameters.
969 ///
970 /// The type of memory being created is specified by `ty` which indicates
971 /// both the minimum and maximum size, in wasm pages.
972 ///
973 /// The `reserved_size_in_bytes` value indicates the expected size of the
974 /// reservation that is to be made for this memory. If this value is `None`
975 /// than the implementation is free to allocate memory as it sees fit. If
976 /// the value is `Some`, however, then the implementation is expected to
977 /// reserve that many bytes for the memory's allocation, plus the guard
978 /// size at the end. Note that this reservation need only be a virtual
979 /// memory reservation, physical memory does not need to be allocated
980 /// immediately. In this case `grow` should never move the base pointer and
981 /// the maximum size of `ty` is guaranteed to fit within `reserved_size_in_bytes`.
982 ///
983 /// The `guard_size_in_bytes` parameter indicates how many bytes of space, after the
984 /// memory allocation, is expected to be unmapped. JIT code will elide
985 /// bounds checks based on the `guard_size_in_bytes` provided, so for JIT code to
986 /// work correctly the memory returned will need to be properly guarded with
987 /// `guard_size_in_bytes` bytes left unmapped after the base allocation.
988 ///
989 /// Note that the `reserved_size_in_bytes` and `guard_size_in_bytes` options are tuned from
990 /// the various [`Config`](crate::Config) methods about memory
991 /// sizes/guards. Additionally these two values are guaranteed to be
992 /// multiples of the system page size.
993 fn new_memory(
994 &self,
995 ty: MemoryType,
996 reserved_size_in_bytes: Option<u64>,
997 guard_size_in_bytes: u64,
998 ) -> Result<Box<dyn LinearMemory>, String>;
999}
1000
1001#[cfg(test)]
1002mod tests {
1003 use crate::*;
1004
1005 // Assert that creating a memory via `Memory::new` respects the limits/tunables
1006 // in `Config`.
1007 #[test]
1008 fn respect_tunables() {
1009 let mut cfg = Config::new();
1010 cfg.static_memory_maximum_size(0)
1011 .dynamic_memory_guard_size(0);
1012 let store = Store::new(&Engine::new(&cfg));
1013 let ty = MemoryType::new(Limits::new(1, None));
1014 let mem = Memory::new(&store, ty);
1015 assert_eq!(mem.wasmtime_export.memory.offset_guard_size, 0);
1016 match mem.wasmtime_export.memory.style {
1017 wasmtime_environ::MemoryStyle::Dynamic => {}
1018 other => panic!("unexpected style {:?}", other),
1019 }
1020 }
1021}
1022
1023// Exports
1024
1025/// An exported WebAssembly value.
1026///
1027/// This type is primarily accessed from the
1028/// [`Instance::exports`](crate::Instance::exports) accessor and describes what
1029/// names and items are exported from a wasm instance.
1030#[derive(Clone)]
1031pub struct Export<'instance> {
1032 /// The name of the export.
1033 name: &'instance str,
1034
1035 /// The definition of the export.
1036 definition: Extern,
1037}
1038
1039impl<'instance> Export<'instance> {
1040 /// Creates a new export which is exported with the given `name` and has the
1041 /// given `definition`.
1042 pub(crate) fn new(name: &'instance str, definition: Extern) -> Export<'instance> {
1043 Export { name, definition }
1044 }
1045
1046 /// Returns the name by which this export is known.
1047 pub fn name(&self) -> &'instance str {
1048 self.name
1049 }
1050
1051 /// Return the `ExternType` of this export.
1052 pub fn ty(&self) -> ExternType {
1053 self.definition.ty()
1054 }
1055
1056 /// Consume this `Export` and return the contained `Extern`.
1057 pub fn into_extern(self) -> Extern {
1058 self.definition
1059 }
1060
1061 /// Consume this `Export` and return the contained `Func`, if it's a function,
1062 /// or `None` otherwise.
1063 pub fn into_func(self) -> Option<Func> {
1064 self.definition.into_func()
1065 }
1066
1067 /// Consume this `Export` and return the contained `Table`, if it's a table,
1068 /// or `None` otherwise.
1069 pub fn into_table(self) -> Option<Table> {
1070 self.definition.into_table()
1071 }
1072
1073 /// Consume this `Export` and return the contained `Memory`, if it's a memory,
1074 /// or `None` otherwise.
1075 pub fn into_memory(self) -> Option<Memory> {
1076 self.definition.into_memory()
1077 }
1078
1079 /// Consume this `Export` and return the contained `Global`, if it's a global,
1080 /// or `None` otherwise.
1081 pub fn into_global(self) -> Option<Global> {
1082 self.definition.into_global()
1083 }
1084}