Skip to main content

wasmtime/runtime/
memory.rs

1use crate::Trap;
2use crate::prelude::*;
3use crate::runtime::vm::{self, ExportMemory};
4use crate::store::{StoreInstanceId, StoreOpaque, StoreResourceLimiter};
5use crate::trampoline::generate_memory_export;
6#[cfg(feature = "async")]
7use crate::vm::VMStore;
8use crate::{AsContext, AsContextMut, Engine, MemoryType, StoreContext, StoreContextMut};
9use alloc::sync::Arc;
10use core::any::Any;
11use core::cell::UnsafeCell;
12use core::fmt;
13use core::slice;
14use core::time::Duration;
15use wasmtime_environ::{DefinedMemoryIndex, MemoryTunables};
16
17pub use crate::runtime::vm::WaitResult;
18
19/// Error for out of bounds [`Memory`] access.
20#[derive(Debug)]
21#[non_exhaustive]
22pub struct MemoryAccessError {
23    // Keep struct internals private for future extensibility.
24    _private: (),
25}
26
27impl fmt::Display for MemoryAccessError {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        write!(f, "out of bounds memory access")
30    }
31}
32
33impl core::error::Error for MemoryAccessError {}
34
35/// A WebAssembly linear memory.
36///
37/// WebAssembly memories represent a contiguous array of bytes that have a size
38/// that is always a multiple of the WebAssembly page size, currently 64
39/// kilobytes.
40///
41/// WebAssembly memory is used for global data (not to be confused with wasm
42/// `global` items), statics in C/C++/Rust, shadow stack memory, etc. Accessing
43/// wasm memory is generally quite fast.
44///
45/// Memories, like other wasm items, are owned by a [`Store`](crate::Store).
46///
47/// # `Memory` and Safety
48///
49/// Linear memory is a lynchpin of safety for WebAssembly. In Wasmtime there are
50/// safe methods of interacting with a [`Memory`]:
51///
52/// * [`Memory::read`]
53/// * [`Memory::write`]
54/// * [`Memory::data`]
55/// * [`Memory::data_mut`]
56///
57/// Note that all of these consider the entire store context as borrowed for the
58/// duration of the call or the duration of the returned slice. This largely
59/// means that while the function is running you'll be unable to borrow anything
60/// else from the store. This includes getting access to the `T` on
61/// [`Store<T>`](crate::Store), but it also means that you can't recursively
62/// call into WebAssembly for instance.
63///
64/// If you'd like to dip your toes into handling [`Memory`] in a more raw
65/// fashion (e.g. by using raw pointers or raw slices), then there's a few
66/// important points to consider when doing so:
67///
68/// * Any recursive calls into WebAssembly can possibly modify any byte of the
69///   entire memory. This means that whenever wasm is called Rust can't have any
70///   long-lived borrows live across the wasm function call. Slices like `&mut
71///   [u8]` will be violated because they're not actually exclusive at that
72///   point, and slices like `&[u8]` are also violated because their contents
73///   may be mutated.
74///
75/// * WebAssembly memories can grow, and growth may change the base pointer.
76///   This means that even holding a raw pointer to memory over a wasm function
77///   call is also incorrect. Anywhere in the function call the base address of
78///   memory may change. Note that growth can also be requested from the
79///   embedding API as well.
80///
81/// As a general rule of thumb it's recommended to stick to the safe methods of
82/// [`Memory`] if you can. It's not advised to use raw pointers or `unsafe`
83/// operations because of how easy it is to accidentally get things wrong.
84///
85/// Some examples of safely interacting with memory are:
86///
87/// ```rust
88/// use wasmtime::{Memory, Store, MemoryAccessError};
89///
90/// // Memory can be read and written safely with the `Memory::read` and
91/// // `Memory::write` methods.
92/// // An error is returned if the copy did not succeed.
93/// fn safe_examples(mem: Memory, store: &mut Store<()>) -> Result<(), MemoryAccessError> {
94///     let offset = 5;
95///     mem.write(&mut *store, offset, b"hello")?;
96///     let mut buffer = [0u8; 5];
97///     mem.read(&store, offset, &mut buffer)?;
98///     assert_eq!(b"hello", &buffer);
99///
100///     // Note that while this is safe care must be taken because the indexing
101///     // here may panic if the memory isn't large enough.
102///     assert_eq!(&mem.data(&store)[offset..offset + 5], b"hello");
103///     mem.data_mut(&mut *store)[offset..offset + 5].copy_from_slice(b"bye!!");
104///
105///     Ok(())
106/// }
107/// ```
108///
109/// It's worth also, however, covering some examples of **incorrect**,
110/// **unsafe** usages of `Memory`. Do not do these things!
111///
112/// ```rust
113/// use wasmtime::{Memory, Result, Store};
114///
115/// // NOTE: All code in this function is not safe to execute and may cause
116/// // segfaults/undefined behavior at runtime. Do not copy/paste these examples
117/// // into production code!
118/// unsafe fn unsafe_examples(mem: Memory, store: &mut Store<()>) -> Result<()> {
119///     // First and foremost, any borrow can be invalidated at any time via the
120///     // `Memory::grow` function. This can relocate memory which causes any
121///     // previous pointer to be possibly invalid now.
122///     unsafe {
123///         let pointer: &u8 = &*mem.data_ptr(&store);
124///         mem.grow(&mut *store, 1)?; // invalidates `pointer`!
125///         // println!("{}", *pointer); // FATAL: use-after-free
126///     }
127///
128///     // Note that the use-after-free also applies to slices, whether they're
129///     // slices of bytes or strings.
130///     unsafe {
131///         let mem_slice = std::slice::from_raw_parts(
132///             mem.data_ptr(&store),
133///             mem.data_size(&store),
134///         );
135///         let slice: &[u8] = &mem_slice[0x100..0x102];
136///         mem.grow(&mut *store, 1)?; // invalidates `slice`!
137///         // println!("{:?}", slice); // FATAL: use-after-free
138///     }
139///
140///     // The `Memory` type may be stored in other locations, so if you hand
141///     // off access to the `Store` then those locations may also call
142///     // `Memory::grow` or similar, so it's not enough to just audit code for
143///     // calls to `Memory::grow`.
144///     unsafe {
145///         let pointer: &u8 = &*mem.data_ptr(&store);
146///         some_other_function(store); // may invalidate `pointer` through use of `store`
147///         // println!("{:?}", pointer); // FATAL: maybe a use-after-free
148///     }
149///
150///     // An especially subtle aspect of accessing a wasm instance's memory is
151///     // that you need to be extremely careful about aliasing. Anyone at any
152///     // time can call `data_unchecked()` or `data_unchecked_mut()`, which
153///     // means you can easily have aliasing mutable references:
154///     unsafe {
155///         let ref1: &u8 = &*mem.data_ptr(&store).add(0x100);
156///         let ref2: &mut u8 = &mut *mem.data_ptr(&store).add(0x100);
157///         // *ref2 = *ref1; // FATAL: violates Rust's aliasing rules
158///     }
159///
160///     Ok(())
161/// }
162/// # fn some_other_function(store: &mut Store<()>) {}
163/// ```
164///
165/// Overall there's some general rules of thumb when unsafely working with
166/// `Memory` and getting raw pointers inside of it:
167///
168/// * If you never have a "long lived" pointer into memory, you're likely in the
169///   clear. Care still needs to be taken in threaded scenarios or when/where
170///   data is read, but you'll be shielded from many classes of issues.
171/// * Long-lived pointers must always respect Rust'a aliasing rules. It's ok for
172///   shared borrows to overlap with each other, but mutable borrows must
173///   overlap with nothing.
174/// * Long-lived pointers are only valid if they're not invalidated for their
175///   lifetime. This means that [`Store`](crate::Store) isn't used to reenter
176///   wasm or the memory itself is never grown or otherwise modified/aliased.
177///
178/// At this point it's worth reiterating again that unsafely working with
179/// `Memory` is pretty tricky and not recommended! It's highly recommended to
180/// use the safe methods to interact with [`Memory`] whenever possible.
181///
182/// ## `Memory` Safety and Threads
183///
184/// Currently the `wasmtime` crate does not implement the wasm threads proposal,
185/// but it is planned to do so. It may be interesting to readers to see how this
186/// affects memory safety and what was previously just discussed as well.
187///
188/// Once threads are added into the mix, all of the above rules still apply.
189/// There's an additional consideration that all reads and writes can happen
190/// concurrently, though. This effectively means that any borrow into wasm
191/// memory are virtually never safe to have.
192///
193/// Mutable pointers are fundamentally unsafe to have in a concurrent scenario
194/// in the face of arbitrary wasm code. Only if you dynamically know for sure
195/// that wasm won't access a region would it be safe to construct a mutable
196/// pointer. Additionally even shared pointers are largely unsafe because their
197/// underlying contents may change, so unless `UnsafeCell` in one form or
198/// another is used everywhere there's no safety.
199///
200/// One important point about concurrency is that while [`Memory::grow`] can
201/// happen concurrently it will never relocate the base pointer. Shared
202/// memories must always have a maximum size and they will be preallocated such
203/// that growth will never relocate the base pointer. The current size of the
204/// memory may still change over time though.
205///
206/// Overall the general rule of thumb for shared memories is that you must
207/// atomically read and write everything. Nothing can be borrowed and everything
208/// must be eagerly copied out. This means that [`Memory::data`] and
209/// [`Memory::data_mut`] won't work in the future (they'll probably return an
210/// error) for shared memories when they're implemented. When possible it's
211/// recommended to use [`Memory::read`] and [`Memory::write`] which will still
212/// be provided.
213#[derive(Copy, Clone, Debug)]
214#[repr(C)] // here for the C API
215pub struct Memory {
216    /// The internal store instance that this memory belongs to.
217    instance: StoreInstanceId,
218    /// The index of the memory, within `instance` above, that this memory
219    /// refers to.
220    index: DefinedMemoryIndex,
221}
222
223// Double-check that the C representation in `extern.h` matches our in-Rust
224// representation here in terms of size/alignment/etc.
225const _: () = {
226    #[repr(C)]
227    struct Tmp(u64, u32);
228    #[repr(C)]
229    struct C(Tmp, u32);
230    assert!(core::mem::size_of::<C>() == core::mem::size_of::<Memory>());
231    assert!(core::mem::align_of::<C>() == core::mem::align_of::<Memory>());
232    assert!(core::mem::offset_of!(Memory, instance) == 0);
233};
234
235impl Memory {
236    /// Creates a new WebAssembly memory given the configuration of `ty`.
237    ///
238    /// The `store` argument will be the owner of the returned [`Memory`]. All
239    /// WebAssembly memory is initialized to zero.
240    ///
241    /// # Panics
242    ///
243    /// This function will panic if the [`Store`](`crate::Store`) has a
244    /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`) (see also:
245    /// [`Store::limiter_async`](`crate::Store::limiter_async`)). When
246    /// using an async resource limiter, use [`Memory::new_async`] instead.
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// # use wasmtime::*;
252    /// # fn main() -> Result<()> {
253    /// let engine = Engine::default();
254    /// let mut store = Store::new(&engine, ());
255    ///
256    /// let memory_ty = MemoryType::new(1, None)?;
257    /// let memory = Memory::new(&mut store, memory_ty)?;
258    ///
259    /// let module = Module::new(&engine, "(module (memory (import \"\" \"\") 1))")?;
260    /// let instance = Instance::new(&mut store, &module, &[memory.into()])?;
261    /// // ...
262    /// # Ok(())
263    /// # }
264    /// ```
265    ///
266    /// # Errors
267    ///
268    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
269    /// memory allocation fails. See the `OutOfMemory` type's documentation for
270    /// details on Wasmtime's out-of-memory handling.
271    pub fn new(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory> {
272        let (mut limiter, store) = store
273            .as_context_mut()
274            .0
275            .validate_sync_resource_limiter_and_store_opaque()?;
276        vm::assert_ready(Self::_new(store, limiter.as_mut(), ty))
277    }
278
279    /// Async variant of [`Memory::new`]. You must use this variant with
280    /// [`Store`](`crate::Store`)s which have a
281    /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
282    ///
283    /// # Panics
284    ///
285    /// This function will panic when used with a non-async
286    /// [`Store`](`crate::Store`).
287    ///
288    /// # Errors
289    ///
290    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
291    /// memory allocation fails. See the `OutOfMemory` type's documentation for
292    /// details on Wasmtime's out-of-memory handling.
293    #[cfg(feature = "async")]
294    pub async fn new_async(mut store: impl AsContextMut, ty: MemoryType) -> Result<Memory> {
295        let (mut limiter, store) = store.as_context_mut().0.resource_limiter_and_store_opaque();
296        Self::_new(store, limiter.as_mut(), ty).await
297    }
298
299    /// Helper function for attaching the memory to a "frankenstein" instance
300    async fn _new(
301        store: &mut StoreOpaque,
302        limiter: Option<&mut StoreResourceLimiter<'_>>,
303        ty: MemoryType,
304    ) -> Result<Memory> {
305        if ty.is_shared() {
306            bail!("shared memories must be created through `SharedMemory`")
307        }
308        store.bump_memory_count()?;
309        Ok(generate_memory_export(store, limiter, &ty, None)
310            .await?
311            .unshared()
312            .unwrap())
313    }
314
315    /// Returns the underlying type of this memory.
316    ///
317    /// # Panics
318    ///
319    /// Panics if this memory doesn't belong to `store`.
320    ///
321    /// # Examples
322    ///
323    /// ```
324    /// # use wasmtime::*;
325    /// # fn main() -> Result<()> {
326    /// let engine = Engine::default();
327    /// let mut store = Store::new(&engine, ());
328    /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1))")?;
329    /// let instance = Instance::new(&mut store, &module, &[])?;
330    /// let memory = instance.get_memory(&mut store, "mem").unwrap();
331    /// let ty = memory.ty(&store);
332    /// assert_eq!(ty.minimum(), 1);
333    /// # Ok(())
334    /// # }
335    /// ```
336    pub fn ty(&self, store: impl AsContext) -> MemoryType {
337        let store = store.as_context();
338        MemoryType::from_wasmtime_memory(self.wasmtime_ty(store.0))
339    }
340
341    /// Safely reads memory contents at the given offset into a buffer.
342    ///
343    /// The entire buffer will be filled.
344    ///
345    /// If `offset + buffer.len()` exceed the current memory capacity, then the
346    /// buffer is left untouched and a [`MemoryAccessError`] is returned.
347    ///
348    /// # Errors
349    ///
350    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
351    /// memory allocation fails. See the `OutOfMemory` type's documentation for
352    /// details on Wasmtime's out-of-memory handling.
353    ///
354    /// # Panics
355    ///
356    /// Panics if this memory doesn't belong to `store`.
357    pub fn read(
358        &self,
359        store: impl AsContext,
360        offset: usize,
361        buffer: &mut [u8],
362    ) -> Result<(), MemoryAccessError> {
363        let store = store.as_context();
364        let slice = self
365            .data(&store)
366            .get(offset..)
367            .and_then(|s| s.get(..buffer.len()))
368            .ok_or(MemoryAccessError { _private: () })?;
369        buffer.copy_from_slice(slice);
370        Ok(())
371    }
372
373    /// Safely writes contents of a buffer to this memory at the given offset.
374    ///
375    /// If the `offset + buffer.len()` exceeds the current memory capacity, then
376    /// none of the buffer is written to memory and a [`MemoryAccessError`] is
377    /// returned.
378    ///
379    /// # Errors
380    ///
381    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
382    /// memory allocation fails. See the `OutOfMemory` type's documentation for
383    /// details on Wasmtime's out-of-memory handling.
384    ///
385    /// # Panics
386    ///
387    /// Panics if this memory doesn't belong to `store`.
388    pub fn write(
389        &self,
390        mut store: impl AsContextMut,
391        offset: usize,
392        buffer: &[u8],
393    ) -> Result<(), MemoryAccessError> {
394        let mut context = store.as_context_mut();
395        self.data_mut(&mut context)
396            .get_mut(offset..)
397            .and_then(|s| s.get_mut(..buffer.len()))
398            .ok_or(MemoryAccessError { _private: () })?
399            .copy_from_slice(buffer);
400        Ok(())
401    }
402
403    /// Returns this memory as a native Rust slice.
404    ///
405    /// Note that this method will consider the entire store context provided as
406    /// borrowed for the duration of the lifetime of the returned slice.
407    ///
408    /// # Panics
409    ///
410    /// Panics if this memory doesn't belong to `store`.
411    pub fn data<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a [u8] {
412        unsafe {
413            let store = store.into();
414            let definition = store[self.instance].memory(self.index);
415            debug_assert!(!self.ty(store).is_shared());
416            slice::from_raw_parts(definition.base.as_ptr(), definition.current_length())
417        }
418    }
419
420    /// Returns this memory as a native Rust mutable slice.
421    ///
422    /// Note that this method will consider the entire store context provided as
423    /// borrowed for the duration of the lifetime of the returned slice.
424    ///
425    /// # Panics
426    ///
427    /// Panics if this memory doesn't belong to `store`.
428    pub fn data_mut<'a, T: 'static>(
429        &self,
430        store: impl Into<StoreContextMut<'a, T>>,
431    ) -> &'a mut [u8] {
432        unsafe {
433            let store = store.into();
434            let definition = store[self.instance].memory(self.index);
435            debug_assert!(!self.ty(store).is_shared());
436            slice::from_raw_parts_mut(definition.base.as_ptr(), definition.current_length())
437        }
438    }
439
440    /// Same as [`Memory::data_mut`], but also returns the `T` from the
441    /// [`StoreContextMut`].
442    ///
443    /// This method can be used when you want to simultaneously work with the
444    /// `T` in the store as well as the memory behind this [`Memory`]. Using
445    /// [`Memory::data_mut`] would consider the entire store borrowed, whereas
446    /// this method allows the Rust compiler to see that the borrow of this
447    /// memory and the borrow of `T` are disjoint.
448    ///
449    /// # Panics
450    ///
451    /// Panics if this memory doesn't belong to `store`.
452    pub fn data_and_store_mut<'a, T: 'static>(
453        &self,
454        store: impl Into<StoreContextMut<'a, T>>,
455    ) -> (&'a mut [u8], &'a mut T) {
456        // Note the unsafety here. Our goal is to simultaneously borrow the
457        // memory and custom data from `store`, and the store it's connected
458        // to. Rust will not let us do that, however, because we must call two
459        // separate methods (both of which borrow the whole `store`) and one of
460        // our borrows is mutable (the custom data).
461        //
462        // This operation, however, is safe because these borrows do not overlap
463        // and in the process of borrowing them mutability doesn't actually
464        // touch anything. This is akin to mutably borrowing two indices in an
465        // array, which is safe so long as the indices are separate.
466        unsafe {
467            let mut store = store.into();
468            let data = &mut *(store.data_mut() as *mut T);
469            (self.data_mut(store), data)
470        }
471    }
472
473    /// Returns the base pointer, in the host's address space, that the memory
474    /// is located at.
475    ///
476    /// For more information and examples see the documentation on the
477    /// [`Memory`] type.
478    ///
479    /// # Panics
480    ///
481    /// Panics if this memory doesn't belong to `store`.
482    pub fn data_ptr(&self, store: impl AsContext) -> *mut u8 {
483        store.as_context()[self.instance]
484            .memory(self.index)
485            .base
486            .as_ptr()
487    }
488
489    /// Returns the byte length of this memory.
490    ///
491    /// WebAssembly memories are made up of a whole number of pages, so the byte
492    /// size returned will always be a multiple of this memory's page size. Note
493    /// that different Wasm memories may have different page sizes. You can get
494    /// a memory's page size via the [`Memory::page_size`] method.
495    ///
496    /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
497    /// `65536`) but [the custom-page-sizes proposal] allows a memory to opt
498    /// into a page size of `1`. Future extensions might allow any power of two
499    /// as a page size.
500    ///
501    /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
502    ///
503    /// For more information and examples see the documentation on the
504    /// [`Memory`] type.
505    ///
506    /// # Panics
507    ///
508    /// Panics if this memory doesn't belong to `store`.
509    pub fn data_size(&self, store: impl AsContext) -> usize {
510        self.internal_data_size(store.as_context().0)
511    }
512
513    pub(crate) fn internal_data_size(&self, store: &StoreOpaque) -> usize {
514        store[self.instance].memory(self.index).current_length()
515    }
516
517    /// Returns the size, in units of pages, of this Wasm memory.
518    ///
519    /// WebAssembly memories are made up of a whole number of pages, so the byte
520    /// size returned will always be a multiple of this memory's page size. Note
521    /// that different Wasm memories may have different page sizes. You can get
522    /// a memory's page size via the [`Memory::page_size`] method.
523    ///
524    /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
525    /// `65536`) but [the custom-page-sizes proposal] allows a memory to opt
526    /// into a page size of `1`. Future extensions might allow any power of two
527    /// as a page size.
528    ///
529    /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
530    ///
531    /// # Panics
532    ///
533    /// Panics if this memory doesn't belong to `store`.
534    pub fn size(&self, store: impl AsContext) -> u64 {
535        self.internal_size(store.as_context().0)
536    }
537
538    pub(crate) fn internal_size(&self, store: &StoreOpaque) -> u64 {
539        let byte_size = self.internal_data_size(store);
540        let page_size = usize::try_from(self._page_size(store)).unwrap();
541        u64::try_from(byte_size / page_size).unwrap()
542    }
543
544    /// Returns the size of a page, in bytes, for this memory.
545    ///
546    /// WebAssembly memories are made up of a whole number of pages, so the byte
547    /// size (as returned by [`Memory::data_size`]) will always be a multiple of
548    /// their page size. Different Wasm memories may have different page sizes.
549    ///
550    /// By default this is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or `65536`)
551    /// but [the custom-page-sizes proposal] allows opting into a page size of
552    /// `1`. Future extensions might allow any power of two as a page size.
553    ///
554    /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
555    pub fn page_size(&self, store: impl AsContext) -> u64 {
556        self._page_size(store.as_context().0)
557    }
558
559    pub(crate) fn _page_size(&self, store: &StoreOpaque) -> u64 {
560        self.wasmtime_ty(store).page_size()
561    }
562
563    /// Returns the log2 of this memory's page size, in bytes.
564    ///
565    /// WebAssembly memories are made up of a whole number of pages, so the byte
566    /// size (as returned by [`Memory::data_size`]) will always be a multiple of
567    /// their page size. Different Wasm memories may have different page sizes.
568    ///
569    /// By default the page size is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or
570    /// `65536`) but [the custom-page-sizes proposal] allows opting into a page
571    /// size of `1`. Future extensions might allow any power of two as a page
572    /// size.
573    ///
574    /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
575    pub fn page_size_log2(&self, store: impl AsContext) -> u8 {
576        self._page_size_log2(store.as_context().0)
577    }
578
579    pub(crate) fn _page_size_log2(&self, store: &StoreOpaque) -> u8 {
580        self.wasmtime_ty(store).page_size_log2
581    }
582
583    /// Grows this WebAssembly memory by `delta` pages.
584    ///
585    /// This will attempt to add `delta` more pages of memory on to the end of
586    /// this `Memory` instance. If successful this may relocate the memory and
587    /// cause [`Memory::data_ptr`] to return a new value. Additionally any
588    /// unsafely constructed slices into this memory may no longer be valid.
589    ///
590    /// On success returns the number of pages this memory previously had
591    /// before the growth succeeded.
592    ///
593    /// Note that, by default, a WebAssembly memory's page size is 64KiB (aka
594    /// 65536 or 2<sup>16</sup>). The [custom-page-sizes proposal] allows Wasm
595    /// memories to opt into a page size of one byte (and this may be further
596    /// relaxed to any power of two in a future extension).
597    ///
598    /// [custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
599    ///
600    /// # Errors
601    ///
602    /// Returns an error if memory could not be grown, for example if it exceeds
603    /// the maximum limits of this memory. A
604    /// [`ResourceLimiter`](crate::ResourceLimiter) is another example of
605    /// preventing a memory to grow.
606    ///
607    /// This function will return an error if the [`Store`](`crate::Store`) has
608    /// a [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`) (see also:
609    /// [`Store::limiter_async`](`crate::Store::limiter_async`). When using an
610    /// async resource limiter, use [`Memory::grow_async`] instead.
611    ///
612    /// This function will handle out-of-memory conditions and report an error
613    /// in such cases, see the `OutOfMemory` type's documentation for details on
614    /// Wasmtime's out-of-memory handling. Note that the `OutOfMemory` type may
615    /// not literally be returned for detecting this condition.
616    ///
617    /// # Panics
618    ///
619    /// Panics if this memory doesn't belong to `store`.
620    ///
621    /// # Examples
622    ///
623    /// ```
624    /// # use wasmtime::*;
625    /// # fn main() -> Result<()> {
626    /// let engine = Engine::default();
627    /// let mut store = Store::new(&engine, ());
628    /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1 2))")?;
629    /// let instance = Instance::new(&mut store, &module, &[])?;
630    /// let memory = instance.get_memory(&mut store, "mem").unwrap();
631    ///
632    /// assert_eq!(memory.size(&store), 1);
633    /// assert_eq!(memory.grow(&mut store, 1)?, 1);
634    /// assert_eq!(memory.size(&store), 2);
635    /// assert!(memory.grow(&mut store, 1).is_err());
636    /// assert_eq!(memory.size(&store), 2);
637    /// assert_eq!(memory.grow(&mut store, 0)?, 2);
638    /// # Ok(())
639    /// # }
640    /// ```
641    pub fn grow(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64> {
642        let store = store.as_context_mut().0;
643        let (mut limiter, store) = store.validate_sync_resource_limiter_and_store_opaque()?;
644        vm::assert_ready(self._grow(store, limiter.as_mut(), delta))
645    }
646
647    /// Async variant of [`Memory::grow`]. Required when using a
648    /// [`ResourceLimiterAsync`](`crate::ResourceLimiterAsync`).
649    ///
650    /// # Panics
651    ///
652    /// This function will panic when used with a non-async
653    /// [`Store`](`crate::Store`).
654    ///
655    /// # Errors
656    ///
657    /// This function will return errors for the same reasons as
658    /// [`Memory::grow`].
659    #[cfg(feature = "async")]
660    pub async fn grow_async(&self, mut store: impl AsContextMut, delta: u64) -> Result<u64> {
661        let store = store.as_context_mut();
662        let (mut limiter, store) = store.0.resource_limiter_and_store_opaque();
663        self._grow(store, limiter.as_mut(), delta).await
664    }
665
666    async fn _grow(
667        &self,
668        store: &mut StoreOpaque,
669        limiter: Option<&mut StoreResourceLimiter<'_>>,
670        delta: u64,
671    ) -> Result<u64> {
672        let result = self
673            .instance
674            .get_mut(store)
675            .memory_grow(limiter, self.index, delta)
676            .await?;
677        match result {
678            Some(size) => {
679                let page_size = self.wasmtime_ty(store).page_size();
680                Ok(u64::try_from(size).unwrap() / page_size)
681            }
682            None => bail!("failed to grow memory by `{delta}`"),
683        }
684    }
685
686    /// Creates a new memory from its raw component parts.
687    ///
688    /// # Safety
689    ///
690    /// The caller must ensure that the memory pointed to by `instance` and
691    /// `index` is not a shared memory. For that `SharedMemory` must be used
692    /// instead.
693    pub(crate) unsafe fn from_raw(instance: StoreInstanceId, index: DefinedMemoryIndex) -> Memory {
694        Memory { instance, index }
695    }
696
697    pub(crate) fn wasmtime_ty<'a>(&self, store: &'a StoreOpaque) -> &'a wasmtime_environ::Memory {
698        let module = store[self.instance].env_module();
699        let index = module.memory_index(self.index);
700        &module.memories[index]
701    }
702
703    pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
704        store[self.instance].get_defined_memory_vmimport(self.index)
705    }
706
707    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
708        store.id() == self.instance.store_id()
709    }
710
711    /// Returns a stable identifier for this memory within its store.
712    ///
713    /// This allows distinguishing memories when introspecting them
714    /// e.g. via debug APIs.
715    #[cfg(feature = "debug")]
716    pub fn debug_index_in_store(&self) -> u64 {
717        u64::from(self.instance.instance().as_u32()) << 32 | u64::from(self.index.as_u32())
718    }
719
720    /// Get a stable hash key for this memory.
721    ///
722    /// Even if the same underlying memory definition is added to the
723    /// `StoreData` multiple times and becomes multiple `wasmtime::Memory`s,
724    /// this hash key will be consistent across all of these memories.
725    #[cfg(feature = "coredump")]
726    pub(crate) fn hash_key(&self, store: &StoreOpaque) -> impl core::hash::Hash + Eq + use<> {
727        store[self.instance].memory_ptr(self.index).as_ptr().addr()
728    }
729}
730
731/// A linear memory. This trait provides an interface for raw memory buffers
732/// which are used by wasmtime, e.g. inside ['Memory']. Such buffers are in
733/// principle not thread safe. By implementing this trait together with
734/// MemoryCreator, one can supply wasmtime with custom allocated host managed
735/// memory.
736///
737/// Note that this is a relatively advanced feature and it is recommended to be
738/// familiar with wasmtime runtime code to use it.
739///
740/// In the following, `minimum`, `reserved_size_in_bytes`, and `guard_size_in_bytes` arguments are given to a
741/// [`MemoryCreator::new_memory`] implementation.
742///
743/// # Safety
744///
745/// Wasmtime's compiled code and runtime rely on the following invariants for memory safety.
746/// Note that while we strive to be thorough in this documentation, we do not guarantee that the
747/// following points are exhaustive.
748/// When using a custom memory backend in a security-sensitive context auditing just the external
749/// implementation of this trait is not sufficient.
750///
751/// - **Valid region.** From creation until the memory is dropped, the first
752/// [`byte_size`] bytes starting at the [`as_ptr`]
753/// memory location must be allocated, initialized, readable, and writeable.
754/// The pointer must be non-null.
755/// Nothing other than Wasmtime may read, write, unmap, or otherwise modify this region while the
756/// memory is in use by Wasmtime.
757/// If the memory moves (although see conditions on stability below), the previous region is no
758/// longer in use by Wasmtime.
759/// Moreover, be aware that Wasmtime currently has a soundness hole for shared memory,
760/// as multiple threads may access the same slice of memory mutably at the same time (aliasing) (see
761/// [issue #4203](https://github.com/bytecodealliance/wasmtime/issues/4203)).
762///
763/// - **Size.** [`byte_size`] must be at least `minimum` after creation
764/// and at least `new_size` after a successful call to [`grow_to`],
765/// and it must never decrease.
766///
767/// - **Base pointer stability.** A call to [`as_ptr`] must return the same
768/// address until the next successful call to [`grow_to`].
769/// Moreover, a successful [`grow_to(new_size)`][`grow_to`] call where `new_size` is at most the [`byte_capacity`](LinearMemory::byte_capacity)
770/// reported before the call must not change the result of [`as_ptr`].
771/// If static memory is forced (e.g. when using shared memory or when [`Config::memory_may_move`](crate::Config::memory_may_move) is disabled), Wasmtime will never ask the memory to grow beyond its [`byte_capacity`].
772///
773/// - **Base pointer alignment.** The base pointer returned by [`as_ptr`] must always be 8-byte aligned.
774/// Moreover, if `guard_size_in_bytes` is non-zero, or `reserved_size_in_bytes` is `Some` and non-zero, then [`as_ptr`] must be
775/// aligned to the host page size at all times.
776///
777/// - **Inaccessible region.** If: `guard_size_in_bytes` is non-zero, or `reserved_size_in_bytes` is `Some` and non-zero;
778/// then every byte from `as_ptr() + byte_size()`, rounded up to the next host page boundary, up to
779/// `as_ptr() + max(reserved_size_in_bytes, byte_size()) + guard_size_in_bytes` must be
780/// inaccessible, so that any access to it faults. This must hold at all times, including after growth.
781///
782/// Additionally, observe the safety requirements when the memory is accessed, as explained in [`Memory`].
783///
784/// # Correctness
785///
786/// The following constraints do not cause memory safety issues, but break WebAssembly semantics,
787/// or expose potentially unwanted data to WebAssembly programs:
788///
789/// - [`byte_size`] should be exactly `minimum` after creation and exactly `new_size` after a
790/// successful call to [`grow_to(new_size)`][`grow_to`]. Wasmtime only requests sizes that are
791/// multiples of the Wasm page size.
792///
793/// - The memory's contents must be zeroed at creation, and bytes made accessible by [`grow_to`] must
794/// be zeroed.
795///
796/// - If [`init_from_image`] returns `Ok(true)`, then the bytes at [`MemoryImage::linear_memory_offset`]
797/// must equal the image and all other bytes must be zero.
798///
799/// [`grow_to`]: LinearMemory::grow_to
800/// [`byte_size`]: LinearMemory::byte_size
801/// [`as_ptr`]: LinearMemory::as_ptr
802/// [`byte_capacity`]: LinearMemory::byte_capacity
803/// [`init_from_image`]: LinearMemory::init_from_image
804pub unsafe trait LinearMemory: Any + Send + Sync {
805    /// Returns the number of allocated bytes which are accessible at this time.
806    fn byte_size(&self) -> usize;
807
808    /// Returns byte capacity of this linear memory's current allocation.
809    ///
810    /// Growth up to this value should not relocate the linear memory base
811    /// pointer.
812    fn byte_capacity(&self) -> usize;
813
814    /// Grows this memory to have the `new_size`, in bytes, specified.
815    ///
816    /// Returns `Err` if memory can't be grown by the specified amount
817    /// of bytes. The error may be downcastable to `std::io::Error`.
818    /// Returns `Ok` if memory was grown successfully.
819    fn grow_to(&mut self, new_size: usize) -> Result<()>;
820
821    /// Return the allocated memory as a mutable pointer to u8.
822    fn as_ptr(&self) -> *mut u8;
823
824    /// Optionally initializes this memory's contents from a copy-on-write
825    /// [`MemoryImage`].
826    ///
827    /// When [copy-on-write memory initialization][cow_config] is enabled and a
828    /// module's data segments for this memory can be represented as an image,
829    /// Wasmtime calls this method once, right after the memory is created
830    /// and before anything else reads or writes it.
831    ///
832    /// If the function succeeds with `false`, the runtime assumes the memory was not initialized.
833    /// It then fully copies the module's data segments into the memory region.
834    /// This is always correct and is essentially equivalent to CoW being disabled.
835    ///
836    /// If the function succeeds with `true`, the runtime assumes the memory's contents match `image` exactly.
837    /// The bytes of the image must start at [`MemoryImage::linear_memory_offset`] and all other bytes must be zero.
838    ///
839    /// ## Shortcut for memory maps
840    ///
841    /// [`MemoryImage`] exposes a shortcut, [`MemoryImage::map_at`], which allows an implementation
842    /// backed by a memory map to replace a portion of its mapping with the pages of the image.
843    /// Consult that function's documentation for safety notes.
844    ///
845    /// Returning an error causes instantiation to fail with that error.
846    ///
847    /// [cow_config]: crate::Config::memory_init_cow
848    fn init_from_image(&mut self, image: &MemoryImage) -> Result<bool> {
849        let _ = image;
850        Ok(false)
851    }
852}
853
854/// A copy-on-write image of the initial contents of a linear memory.
855///
856/// When [`Config::memory_init_cow`](crate::Config::memory_init_cow) is enabled
857/// Wasmtime prepares, where possible, an image of a module's data segments for
858/// each of its linear memories that can be mapped into memory copy-on-write
859/// instead of being copied byte-by-byte. Such images are handed to
860/// [`LinearMemory::init_from_image`] for the specific memory implementation to map into its
861/// underlying representation.
862///
863/// An image covers [`len()`](MemoryImage::len) bytes of the linear memory starting at
864/// [`linear_memory_offset()`](MemoryImage::linear_memory_offset).
865/// Both values are multiples of the host page size, and the image always lies within
866/// the minimum size of the memory it was created for.
867/// All other bytes are expected to be zero.
868///
869/// Cloning a `MemoryImage` is cheap and keeps the underlying image alive.
870#[derive(Clone)]
871pub struct MemoryImage {
872    image: Arc<vm::MemoryImage>,
873}
874
875impl MemoryImage {
876    pub(crate) fn new(image: Arc<vm::MemoryImage>) -> MemoryImage {
877        MemoryImage { image }
878    }
879
880    /// This is a convenience method for the internal `MmapMemory` to access the underlying image
881    /// directly and use its [`map_at`](vm::MemoryImage::map_at) function.
882    #[cfg(has_virtual_memory)]
883    pub(crate) fn vm(&self) -> &vm::MemoryImage {
884        &self.image
885    }
886
887    /// Returns the offset, in bytes, within linear memory where this image
888    /// starts.
889    ///
890    /// This is guaranteed to be a multiple of the host page size.
891    pub fn linear_memory_offset(&self) -> usize {
892        self.image.linear_memory_offset()
893    }
894
895    /// Returns the length, in bytes, of this image.
896    ///
897    /// This is guaranteed to be a multiple of the host page size.
898    pub fn len(&self) -> usize {
899        self.image.len()
900    }
901
902    /// Returns whether this image is empty (length equal to zero).
903    pub fn is_empty(&self) -> bool {
904        self.len() == 0
905    }
906
907    /// Returns the bytes of this image.
908    ///
909    /// The returned slice is [`len()`](MemoryImage::len) bytes long and holds
910    /// the initial contents of linear memory starting at
911    /// [`linear_memory_offset()`](MemoryImage::linear_memory_offset). All
912    /// bytes of the memory outside of that range are initially zero.
913    pub fn data(&self) -> &[u8] {
914        self.image.data()
915    }
916
917    /// Maps this image copy-on-write into the linear memory starting at
918    /// `base`.
919    ///
920    /// The bytes `base + linear_memory_offset()` up to
921    /// `base + linear_memory_offset() + len()` are replaced with a private,
922    /// readable and writable copy-on-write mapping of the image. Nothing
923    /// outside of that range is modified.
924    ///
925    /// Returns an error if `base` is not aligned to the host page size or if
926    /// the underlying mapping operation fails.
927    ///
928    /// # Safety
929    ///
930    /// The caller must exclusively own the virtual memory range being mapped
931    /// over, nothing may hold references into it, and it must be valid for
932    /// its pages to be replaced by a new mapping (for example by `mmap` with
933    /// `MAP_FIXED` on Unix). Any previous contents and memory protections of
934    /// that range are lost. The mapping lives until the range is unmapped or
935    /// mapped over again by its owner. In particular, the runtime does not unmap the image by itself.
936    /// The owner of the virtual memory range must clean it up after usage.
937    ///
938    /// The typical usage is owning a memory-mapped region and requesting the image to be mapped
939    /// into a subrange of that mapping. Unmapping the entire region at the end of the memory's
940    /// lifetime takes care of the cleanup.
941    pub unsafe fn map_at(&self, base: *mut u8) -> Result<()> {
942        // SAFETY: forwarded to the caller.
943        unsafe { self.image.map_at_ptr(base) }
944    }
945}
946
947impl fmt::Debug for MemoryImage {
948    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
949        f.debug_struct("MemoryImage")
950            .field("linear_memory_offset", &self.linear_memory_offset())
951            .field("len", &self.len())
952            .finish_non_exhaustive()
953    }
954}
955
956impl PartialEq for MemoryImage {
957    fn eq(&self, other: &Self) -> bool {
958        Arc::ptr_eq(&self.image, &other.image)
959    }
960}
961
962impl Eq for MemoryImage {}
963
964impl core::hash::Hash for MemoryImage {
965    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
966        core::ptr::hash(Arc::as_ptr(&self.image), state)
967    }
968}
969
970/// A memory creator. Can be used to provide a memory creator
971/// to wasmtime which supplies host managed memory.
972///
973/// # Safety
974///
975/// This trait is unsafe, as the memory safety depends on proper implementation
976/// of memory management. Memories created by the MemoryCreator should always be
977/// treated as owned by wasmtime instance, and any modification of them outside
978/// of wasmtime invoked routines is unsafe and may lead to corruption.
979///
980/// Note that this is a relatively advanced feature and it is recommended to be
981/// familiar with Wasmtime runtime code to use it.
982pub unsafe trait MemoryCreator: Send + Sync {
983    /// Create a new [`LinearMemory`] object from the specified parameters.
984    ///
985    /// The returned memory must satisfy all of the properties of the [`MemoryRequest`]
986    /// and be zero filled.
987    fn new_memory(&self, request: &MemoryRequest<'_>) -> Result<Box<dyn LinearMemory>>;
988}
989
990/// The kind of memory that [`MemoryCreator`] is asked to create.
991#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
992#[non_exhaustive]
993pub enum MemoryKind {
994    /// A standard WebAssembly linear memory (module or host).
995    LinearMemory,
996    /// The memory backing a store's GC heap.
997    ///
998    /// It differs from standard linear memory:
999    /// - It is created lazily, at most once per store: when a module that needs a GC heap is
1000    ///   instantiated or when the first GC object is allocated. This might happen in the middle of
1001    ///   execution of WebAssembly code.
1002    /// - It grows as GC objects are allocated, independently of `memory.grow`.
1003    /// - Its contents are Wasmtime's internal representation of GC objects, not data of the guest
1004    ///   program. They are only meaningful to the store that created the GC heap, so they should not
1005    ///   be shared, persisted, copied to other memories, etc.
1006    GcHeap,
1007}
1008
1009impl From<wasmtime_environ::MemoryKind> for MemoryKind {
1010    fn from(value: wasmtime_environ::MemoryKind) -> Self {
1011        match value {
1012            wasmtime_environ::MemoryKind::LinearMemory => Self::LinearMemory,
1013            wasmtime_environ::MemoryKind::GcHeap => Self::GcHeap,
1014        }
1015    }
1016}
1017
1018/// A request to a [`MemoryCreator::new_memory`].
1019pub struct MemoryRequest<'a> {
1020    ty: &'a wasmtime_environ::Memory,
1021    tunables: &'a MemoryTunables<'a>,
1022    minimum: usize,
1023    maximum: Option<usize>,
1024}
1025
1026impl<'a> MemoryRequest<'a> {
1027    pub(crate) fn new(
1028        ty: &'a wasmtime_environ::Memory,
1029        tunables: &'a MemoryTunables<'a>,
1030        minimum: usize,
1031        maximum: Option<usize>,
1032    ) -> Self {
1033        Self {
1034            ty,
1035            tunables,
1036            minimum,
1037            maximum,
1038        }
1039    }
1040
1041    /// The type of memory being created. Indicates
1042    /// both the minimum and maximum size, in wasm pages. The minimum and
1043    /// maximum sizes, in bytes, are also specified as [`minimum`](Self::minimum) and [`maximum`](Self::maximum)
1044    /// to avoid integer conversion if desired.
1045    pub fn ty(&self) -> MemoryType {
1046        MemoryType::from_wasmtime_memory(self.ty)
1047    }
1048
1049    /// Minimum size of the memory in bytes.
1050    /// Same as the minimum of [`ty`](Self::ty), but in bytes.
1051    pub fn minimum(&self) -> usize {
1052        self.minimum
1053    }
1054
1055    /// Limit on the maximum size of the memory in bytes, if any.
1056    /// Same as the maximum of [`ty`](Self::ty), but in bytes.
1057    pub fn maximum(&self) -> Option<usize> {
1058        self.maximum
1059    }
1060
1061    /// Indicates the expected size of the reservation that is to be made for this memory.
1062    /// The implementation must reserve this many bytes for the memory's allocation, plus the guard
1063    /// size at the end. Note that this reservation need only be a virtual
1064    /// memory reservation, physical memory does not need to be allocated
1065    /// immediately.
1066    ///
1067    /// If this value is not zero, [`grow_to`](LinearMemory::grow_to) should never move the base pointer and
1068    /// the maximum size of [`ty`](Self::ty) is guaranteed to fit within `reserved_size_in_bytes`.
1069    ///
1070    /// This value is tuned from the various [`Config`](crate::Config) methods about
1071    /// memory sizes/guards. It is guaranteed to be a multiple of the system page size.
1072    pub fn reserved_size_in_bytes(&self) -> usize {
1073        usize::try_from(self.tunables.reservation()).unwrap()
1074    }
1075
1076    /// Indicates how many bytes of space after the memory allocation is expected to be unmapped. JIT code will
1077    /// elide bounds checks based on the `guard_size_in_bytes` provided, so for
1078    /// JIT code to work correctly the memory returned will need to be properly
1079    /// guarded with `guard_size_in_bytes` bytes left unmapped after the base
1080    /// allocation.
1081    ///
1082    /// This value is tuned from the various [`Config`](crate::Config) methods about
1083    /// memory sizes/guards. It is guaranteed to be a multiple of the system page size.
1084    pub fn guard_size_in_bytes(&self) -> usize {
1085        usize::try_from(self.tunables.guard_size()).unwrap()
1086    }
1087
1088    /// What kind of memory is requested.
1089    pub fn kind(&self) -> MemoryKind {
1090        self.tunables.kind().into()
1091    }
1092
1093    /// Internal parameter: detailed internal representation of the memory being created.
1094    pub(crate) fn wasmtime_memory(&self) -> &'a wasmtime_environ::Memory {
1095        self.ty
1096    }
1097
1098    /// Internal parameter: all the tunables, including those not exposed to the public API.
1099    pub(crate) fn tunables(&self) -> &'a MemoryTunables<'a> {
1100        self.tunables
1101    }
1102}
1103
1104impl fmt::Debug for MemoryRequest<'_> {
1105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106        f.debug_struct("MemoryRequest")
1107            .field("ty", &self.ty())
1108            .field("minimum", &self.minimum)
1109            .field("maximum", &self.maximum)
1110            .field("reserved_size_in_bytes", &self.reserved_size_in_bytes())
1111            .field("guard_size_in_bytes", &self.guard_size_in_bytes())
1112            .field("kind", &self.kind())
1113            .finish()
1114    }
1115}
1116
1117/// A constructor for externally-created shared memory.
1118///
1119/// The [threads proposal] adds the concept of "shared memory" to WebAssembly.
1120/// This is much the same as a Wasm linear memory (i.e., [`Memory`]), but can be
1121/// used concurrently by multiple agents. Because these agents may execute in
1122/// different threads, [`SharedMemory`] must be thread-safe.
1123///
1124/// When the [threads proposal is enabled](crate::Config::wasm_threads) and the
1125/// [the creation of shared memories is enabled](crate::Config::shared_memory),
1126/// there are multiple ways to construct shared memory:
1127///  1. for imported shared memory, e.g., `(import "env" "memory" (memory 1 1
1128///     shared))`, the user must supply a [`SharedMemory`] with the
1129///     externally-created memory as an import to the instance--e.g.,
1130///     `shared_memory.into()`.
1131///  2. for private or exported shared memory, e.g., `(export "env" "memory"
1132///     (memory 1 1 shared))`, Wasmtime will create the memory internally during
1133///     instantiation--access using `Instance::get_shared_memory()`.
1134///
1135/// [threads proposal]:
1136///     https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md
1137///
1138/// # Examples
1139///
1140/// ```
1141/// # use wasmtime::*;
1142/// # fn main() -> Result<()> {
1143/// let mut config = Config::new();
1144/// config.wasm_threads(true);
1145/// config.shared_memory(true);
1146/// # if Engine::new(&config).is_err() { return Ok(()); }
1147/// let engine = Engine::new(&config)?;
1148/// let mut store = Store::new(&engine, ());
1149///
1150/// let shared_memory = SharedMemory::new(&engine, MemoryType::shared(1, 2)?)?;
1151/// let module = Module::new(&engine, r#"(module (memory (import "" "") 1 2 shared))"#)?;
1152/// let instance = Instance::new(&mut store, &module, &[shared_memory.into()])?;
1153/// // ...
1154/// # Ok(())
1155/// # }
1156/// ```
1157#[derive(Clone)]
1158pub struct SharedMemory {
1159    vm: crate::runtime::vm::SharedMemory,
1160    engine: Engine,
1161}
1162
1163impl SharedMemory {
1164    /// Construct a [`SharedMemory`] by providing both the `minimum` and
1165    /// `maximum` number of 64K-sized pages. This call allocates the necessary
1166    /// pages on the system.
1167    ///
1168    /// # Errors
1169    ///
1170    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
1171    /// memory allocation fails. See the `OutOfMemory` type's documentation for
1172    /// details on Wasmtime's out-of-memory handling.
1173    #[cfg(feature = "threads")]
1174    pub fn new(engine: &Engine, ty: MemoryType) -> Result<Self> {
1175        if !ty.is_shared() {
1176            bail!("shared memory must have the `shared` flag enabled on its memory type")
1177        }
1178        debug_assert!(ty.maximum().is_some());
1179
1180        let ty = ty.wasmtime_memory();
1181        let memory = crate::runtime::vm::SharedMemory::new(engine, ty)?;
1182
1183        Ok(Self {
1184            vm: memory,
1185            engine: engine.clone(),
1186        })
1187    }
1188
1189    /// Return the type of the shared memory.
1190    pub fn ty(&self) -> MemoryType {
1191        MemoryType::from_wasmtime_memory(&self.vm.ty())
1192    }
1193
1194    /// Returns the size, in WebAssembly pages, of this wasm memory.
1195    pub fn size(&self) -> u64 {
1196        let byte_size = u64::try_from(self.data_size()).unwrap();
1197        let page_size = self.page_size();
1198        byte_size / page_size
1199    }
1200
1201    /// Returns the size of a page, in bytes, for this memory.
1202    ///
1203    /// By default this is 64KiB (aka `0x10000`, `2**16`, `1<<16`, or `65536`)
1204    /// but [the custom-page-sizes proposal] allows opting into a page size of
1205    /// `1`. Future extensions might allow any power of two as a page size.
1206    ///
1207    /// [the custom-page-sizes proposal]: https://github.com/WebAssembly/custom-page-sizes
1208    pub fn page_size(&self) -> u64 {
1209        self.ty().page_size()
1210    }
1211
1212    /// Returns the byte length of this memory.
1213    ///
1214    /// The returned value will be a multiple of the wasm page size, 64k.
1215    ///
1216    /// For more information and examples see the documentation on the
1217    /// [`Memory`] type.
1218    pub fn data_size(&self) -> usize {
1219        self.vm.byte_size()
1220    }
1221
1222    /// Return access to the available portion of the shared memory.
1223    ///
1224    /// The slice returned represents the region of accessible memory at the
1225    /// time that this function was called. The contents of the returned slice
1226    /// will reflect concurrent modifications happening on other threads.
1227    ///
1228    /// # Safety
1229    ///
1230    /// The returned slice is valid for the entire duration of the lifetime of
1231    /// this instance of [`SharedMemory`]. The base pointer of a shared memory
1232    /// does not change. This [`SharedMemory`] may grow further after this
1233    /// function has been called, but the slice returned will not grow.
1234    ///
1235    /// Concurrent modifications may be happening to the data returned on other
1236    /// threads. The `UnsafeCell<u8>` represents that safe access to the
1237    /// contents of the slice is not possible through normal loads and stores.
1238    ///
1239    /// The memory returned must be accessed safely through the `Atomic*` types
1240    /// in the [`std::sync::atomic`] module. Casting to those types must
1241    /// currently be done unsafely.
1242    pub fn data(&self) -> &[UnsafeCell<u8>] {
1243        unsafe {
1244            let definition = self.vm.vmmemory_ptr().as_ref();
1245            slice::from_raw_parts(definition.base.as_ptr().cast(), definition.current_length())
1246        }
1247    }
1248
1249    /// Grows this WebAssembly memory by `delta` pages.
1250    ///
1251    /// This will attempt to add `delta` more pages of memory on to the end of
1252    /// this `Memory` instance. If successful this may relocate the memory and
1253    /// cause [`Memory::data_ptr`] to return a new value. Additionally any
1254    /// unsafely constructed slices into this memory may no longer be valid.
1255    ///
1256    /// On success returns the number of pages this memory previously had
1257    /// before the growth succeeded.
1258    ///
1259    /// # Errors
1260    ///
1261    /// This function will return errors for a similar reason as
1262    /// [`Memory::grow`].
1263    pub fn grow(&self, delta: u64) -> Result<u64> {
1264        match self.vm.grow(delta)? {
1265            Some((old_size, _new_size)) => {
1266                // For shared memory, the `VMMemoryDefinition` is updated inside
1267                // the locked region.
1268                Ok(u64::try_from(old_size).unwrap() / self.page_size())
1269            }
1270            None => bail!("failed to grow memory by `{delta}`"),
1271        }
1272    }
1273
1274    /// Returns a stable identifier for this shared memory when introspecting
1275    /// it through the debug APIs.
1276    #[cfg(feature = "debug")]
1277    pub fn debug_index_in_store(&self) -> u64 {
1278        u64::try_from(self.vm.vmmemory_ptr().as_ptr().addr()).unwrap()
1279    }
1280
1281    /// Equivalent of the WebAssembly `memory.atomic.notify` instruction for
1282    /// this shared memory.
1283    ///
1284    /// This method allows embedders to notify threads blocked on the specified
1285    /// `addr`, an index into wasm linear memory. Threads could include
1286    /// wasm threads blocked on a `memory.atomic.wait*` instruction or embedder
1287    /// threads blocked on [`SharedMemory::atomic_wait32`], for example.
1288    ///
1289    /// The `count` argument is the number of threads to wake up.
1290    ///
1291    /// This function returns the number of threads awoken.
1292    ///
1293    /// # Errors
1294    ///
1295    /// This function will return an error if `addr` is not within bounds or
1296    /// not aligned to a 4-byte boundary.
1297    pub fn atomic_notify(&self, addr: u64, count: u32) -> Result<u32, Trap> {
1298        self.vm.atomic_notify(addr, count)
1299    }
1300
1301    /// Equivalent of the WebAssembly `memory.atomic.wait32` instruction for
1302    /// this shared memory.
1303    ///
1304    /// This method allows embedders to block the current thread until notified
1305    /// via the `memory.atomic.notify` instruction or the
1306    /// [`SharedMemory::atomic_notify`] method, enabling synchronization with
1307    /// the wasm guest as desired.
1308    ///
1309    /// The `expected` argument is the expected 32-bit value to be stored at
1310    /// the byte address `addr` specified. The `addr` specified is an index
1311    /// into this linear memory.
1312    ///
1313    /// The optional `timeout` argument is the maximum amount of time to block
1314    /// the current thread. If not specified the thread may sleep indefinitely.
1315    ///
1316    /// This function returns one of three possible values:
1317    ///
1318    /// * `WaitResult::Ok` - this function, loaded the value at `addr`, found
1319    ///   it was equal to `expected`, and then blocked (all as one atomic
1320    ///   operation). The thread was then awoken with a `memory.atomic.notify`
1321    ///   instruction or the [`SharedMemory::atomic_notify`] method.
1322    /// * `WaitResult::Mismatch` - the value at `addr` was loaded but was not
1323    ///   equal to `expected` so the thread did not block and immediately
1324    ///   returned.
1325    /// * `WaitResult::TimedOut` - all the steps of `Ok` happened, except this
1326    ///   thread was woken up due to a timeout.
1327    ///
1328    /// This function will not return due to spurious wakeups.
1329    ///
1330    /// # Errors
1331    ///
1332    /// This function will return an error if `addr` is not within bounds or
1333    /// not aligned to a 4-byte boundary.
1334    pub fn atomic_wait32(
1335        &self,
1336        addr: u64,
1337        expected: u32,
1338        timeout: Option<Duration>,
1339    ) -> Result<WaitResult, Trap> {
1340        self.vm.atomic_wait32(addr, expected, timeout)
1341    }
1342
1343    /// Equivalent of the WebAssembly `memory.atomic.wait64` instruction for
1344    /// this shared memory.
1345    ///
1346    /// For more information see [`SharedMemory::atomic_wait32`].
1347    ///
1348    /// # Errors
1349    ///
1350    /// Returns the same error as [`SharedMemory::atomic_wait32`] except that
1351    /// the specified address must be 8-byte aligned instead of 4-byte aligned.
1352    pub fn atomic_wait64(
1353        &self,
1354        addr: u64,
1355        expected: u64,
1356        timeout: Option<Duration>,
1357    ) -> Result<WaitResult, Trap> {
1358        self.vm.atomic_wait64(addr, expected, timeout)
1359    }
1360
1361    /// Return a reference to the [`Engine`] used to configure the shared
1362    /// memory.
1363    pub(crate) fn engine(&self) -> &Engine {
1364        &self.engine
1365    }
1366
1367    /// Construct a single-memory instance to provide a way to import
1368    /// [`SharedMemory`] into other modules.
1369    pub(crate) fn vmimport(&self, store: &mut StoreOpaque) -> crate::runtime::vm::VMMemoryImport {
1370        // Note `vm::assert_ready` shouldn't panic here because this isn't
1371        // actually allocating any new memory (also no limiter), so resource
1372        // limiting shouldn't kick in.
1373        let memory = vm::assert_ready(generate_memory_export(
1374            store,
1375            None,
1376            &self.ty(),
1377            Some(&self.vm),
1378        ))
1379        .unwrap();
1380        match memory {
1381            ExportMemory::Unshared(_) => unreachable!(),
1382            ExportMemory::Shared(_shared, vmimport) => vmimport,
1383        }
1384    }
1385
1386    /// Creates a [`SharedMemory`] from its constituent parts.
1387    pub(crate) fn from_raw(vm: crate::runtime::vm::SharedMemory, engine: Engine) -> Self {
1388        SharedMemory { vm, engine }
1389    }
1390}
1391
1392impl fmt::Debug for SharedMemory {
1393    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1394        f.debug_struct("SharedMemory").finish_non_exhaustive()
1395    }
1396}
1397
1398#[cfg(test)]
1399mod tests {
1400    use crate::*;
1401
1402    // Assert that creating a memory via `Memory::new` respects the limits/tunables
1403    // in `Config`.
1404    #[test]
1405    fn respect_tunables() {
1406        let mut cfg = Config::new();
1407        cfg.memory_reservation(0).memory_guard_size(0);
1408        let mut store = Store::new(&Engine::new(&cfg).unwrap(), ());
1409        let ty = MemoryType::new(1, None).unwrap();
1410        let mem = Memory::new(&mut store, ty).unwrap();
1411        let store = store.as_context();
1412        let tunables = store.engine().tunables();
1413        assert_eq!(tunables.memory_guard_size, 0);
1414        assert!(!mem.wasmtime_ty(store.0).can_elide_bounds_check(
1415            &wasmtime_environ::MemoryTunables::new(
1416                tunables,
1417                wasmtime_environ::MemoryKind::LinearMemory,
1418            ),
1419            12,
1420        ));
1421    }
1422
1423    #[test]
1424    fn hash_key_is_stable_across_duplicate_store_data_entries() -> Result<()> {
1425        let mut store = Store::<()>::default();
1426        let module = Module::new(
1427            store.engine(),
1428            r#"
1429                (module
1430                    (memory (export "m") 1 1)
1431                )
1432            "#,
1433        )?;
1434        let instance = Instance::new(&mut store, &module, &[])?;
1435
1436        // Each time we `get_memory`, we call `Memory::from_wasmtime` which adds
1437        // a new entry to `StoreData`, so `g1` and `g2` will have different
1438        // indices into `StoreData`.
1439        let m1 = instance.get_memory(&mut store, "m").unwrap();
1440        let m2 = instance.get_memory(&mut store, "m").unwrap();
1441
1442        // That said, they really point to the same memory.
1443        assert_eq!(m1.data(&store)[0], 0);
1444        assert_eq!(m2.data(&store)[0], 0);
1445        m1.data_mut(&mut store)[0] = 42;
1446        assert_eq!(m1.data(&mut store)[0], 42);
1447        assert_eq!(m2.data(&mut store)[0], 42);
1448
1449        // And therefore their hash keys are the same.
1450        assert!(m1.hash_key(&store.as_context().0) == m2.hash_key(&store.as_context().0));
1451
1452        // But the hash keys are different from different memories.
1453        let instance2 = Instance::new(&mut store, &module, &[])?;
1454        let m3 = instance2.get_memory(&mut store, "m").unwrap();
1455        assert!(m1.hash_key(&store.as_context().0) != m3.hash_key(&store.as_context().0));
1456
1457        Ok(())
1458    }
1459
1460    /// Offset of the data segment used by the `MemoryImage` tests: inside the
1461    /// second Wasm page, but not at the start of a host page.
1462    #[cfg(all(target_os = "linux", not(miri)))]
1463    const IMAGE_DATA_OFFSET: usize = 0x10000 + 8;
1464
1465    /// Compiles a module whose single memory is initialized by one data segment
1466    /// at `IMAGE_DATA_OFFSET` and returns the CoW image Wasmtime builds for it.
1467    /// The module is never instantiated, we just take the image of the memory.
1468    #[cfg(all(target_os = "linux", not(miri)))]
1469    fn memory_image_for_data(data: &str) -> Result<MemoryImage> {
1470        let mut config = Config::new();
1471        config.memory_init_cow(true);
1472        let engine = Engine::new(&config)?;
1473        let module = Module::new(
1474            &engine,
1475            // Module with (at least) 2 pages of memory with data written at IMAGE_DATA_OFFSET.
1476            format!("(module (memory 2) (data (i32.const {IMAGE_DATA_OFFSET}) \"{data}\"))"),
1477        )?;
1478        let images = module.memory_images()?.expect("module has memory images");
1479        let image = images
1480            .get_memory_image(wasmtime_environ::DefinedMemoryIndex::from_u32(0))
1481            .expect("memory 0 has an image");
1482        Ok(MemoryImage::new(image.clone()))
1483    }
1484
1485    /// The public accessors report the internal image's placement, and:
1486    /// - both values are multiples of the host page size; and
1487    /// - the image covers the module's data.
1488    #[test]
1489    #[cfg(all(target_os = "linux", not(miri)))]
1490    fn memory_image_accessors() -> Result<()> {
1491        let page_size = crate::runtime::vm::host_page_size();
1492        let image = memory_image_for_data("hello")?;
1493        let offset = image.linear_memory_offset();
1494        let len = image.len();
1495
1496        assert_eq!(offset, image.vm().linear_memory_offset());
1497        assert_eq!(len, image.vm().len());
1498        assert_eq!(offset % page_size, 0);
1499        assert_eq!(len % page_size, 0);
1500        assert!(!image.is_empty());
1501        // Image starts at or before the data...
1502        assert!(offset <= IMAGE_DATA_OFFSET);
1503        // ... and reaches past the end of the data.
1504        assert!(offset + len >= IMAGE_DATA_OFFSET + "hello".len());
1505
1506        let data = image.data();
1507        assert_eq!(data.len(), len);
1508        assert_eq!(data, image.vm().data());
1509        let data_start = IMAGE_DATA_OFFSET - offset;
1510        assert_eq!(&data[data_start..][..5], b"hello");
1511        assert!(data[..data_start].iter().all(|b| *b == 0));
1512        assert!(data[data_start + 5..].iter().all(|b| *b == 0));
1513
1514        // Clones share the same underlying image.
1515        let clone = image.clone();
1516        assert!(core::ptr::eq(clone.vm(), image.vm()));
1517        Ok(())
1518    }
1519
1520    #[test]
1521    #[cfg(all(target_os = "linux", not(miri)))]
1522    fn memory_image_identity() -> Result<()> {
1523        use std::hash::{BuildHasher, RandomState};
1524
1525        let mut config = Config::new();
1526        config.memory_init_cow(true);
1527        let engine = Engine::new(&config)?;
1528        let wat = r#"(module (memory 1) (data (i32.const 0) "hello"))"#;
1529        let image_of = |module: &Module| -> Result<MemoryImage> {
1530            let images = module.memory_images()?.expect("module has memory images");
1531            let image = images
1532                .get_memory_image(wasmtime_environ::DefinedMemoryIndex::from_u32(0))
1533                .expect("memory 0 has an image");
1534            Ok(MemoryImage::new(image.clone()))
1535        };
1536
1537        let module = Module::new(&engine, wat)?;
1538        let image = image_of(&module)?;
1539        let same = image_of(&module)?; // Same module instance gives the same image.
1540        let clone = image.clone(); // Clone just clones an Arc.
1541
1542        assert_eq!(image, same);
1543        assert_eq!(image, clone);
1544
1545        let hasher = RandomState::new();
1546        assert_eq!(hasher.hash_one(&image), hasher.hash_one(&same));
1547        assert_eq!(hasher.hash_one(&image), hasher.hash_one(&clone));
1548
1549        Ok(())
1550    }
1551
1552    /// `MemoryImage::map_at` places the image's bytes at
1553    /// `base + linear_memory_offset()` and zeroes the rest.
1554    #[test]
1555    #[cfg(all(target_os = "linux", not(miri)))]
1556    fn memory_image_map_at() -> Result<()> {
1557        use crate::runtime::vm::{HostAlignedByteCount, Mmap};
1558
1559        let image = memory_image_for_data("hello")?;
1560        let size =
1561            HostAlignedByteCount::new_rounded_up(image.linear_memory_offset() + image.len())?;
1562        let mmap = Mmap::accessible_reserved(HostAlignedByteCount::ZERO, size)?;
1563        let base = mmap.as_non_null().as_ptr();
1564
1565        // SAFETY: `mmap` was just created, is owned by this test and covers
1566        // the whole range the image is mapped into.
1567        unsafe { image.map_at(base)? };
1568
1569        // SAFETY: `map_at` made the image's range readable.
1570        let mapped = unsafe {
1571            core::slice::from_raw_parts(base.add(image.linear_memory_offset()), image.len())
1572        };
1573        let data_start = IMAGE_DATA_OFFSET - image.linear_memory_offset();
1574
1575        assert_eq!(mapped, image.data());
1576        assert_eq!(&mapped[data_start..][..5], b"hello");
1577        assert!(mapped[..data_start].iter().all(|b| *b == 0));
1578        assert!(mapped[data_start + 5..].iter().all(|b| *b == 0));
1579
1580        Ok(())
1581    }
1582}