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}