Skip to content

Commit 4404847

Browse files
authored
docs: update Memory trait documentation (#352)
This PR documents that `Memory` trait methods panic or trap on out-of-bounds access.
1 parent 08b8fbc commit 4404847

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

docs/src/concepts/memory-trait.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ pub trait Memory {
99
fn size(&self) -> u64;
1010

1111
/// Equivalent to WebAssembly memory.grow.
12+
/// Returns the previous size, or -1 if the grow fails.
1213
fn grow(&self, pages: u64) -> i64;
1314

1415
/// Copies bytes from this memory to the heap (in Wasm, memory 0).
16+
/// Panics or traps if out of bounds.
1517
fn read(&self, offset: u64, dst: &mut [u8]);
1618

1719
/// Writes bytes from the heap (in Wasm, memory 0) to this memory.
20+
/// Panics or traps if out of bounds.
1821
fn write(&self, offset: u64, src: &[u8]);
1922
}
2023
```
@@ -23,6 +26,13 @@ The `Memory` trait intentionally models a [WebAssembly memory instance](https://
2326
This design choice ensures consistency with the interface of memories available to canisters.
2427
It also provides future compatibility with potential multi-memory support in canisters.
2528

29+
## Panics
30+
31+
⚠️ `read` and `write` **assume the caller will not access memory outside the current size**.
32+
33+
If the range `[offset … offset + len)` exceeds available memory, the call panics (in native tests) or traps (in a Wasm canister).
34+
Callers must store and check data lengths themselves or use higher-level containers such as `StableVec`.
35+
2636
## Available Memory Implementations
2737

2838
The library provides several implementations of the `Memory` trait, each designed for specific use cases:

src/lib.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,39 @@ const WASM_PAGE_SIZE: u64 = 65536;
4545
/// The maximum number of stable memory pages a canister can address.
4646
pub const MAX_PAGES: u64 = u64::MAX / WASM_PAGE_SIZE;
4747

48+
/// Abstraction over a WebAssembly-style linear memory (e.g., stable memory).
49+
///
50+
/// Implementations are expected to mirror WebAssembly semantics:
51+
/// out-of-bounds accesses will cause a panic (in native) or trap (in Wasm).
4852
pub trait Memory {
49-
/// Returns the current size of the stable memory in WebAssembly
50-
/// pages. (One WebAssembly page is 64Ki bytes.)
53+
/// Returns the current size of the memory in WebAssembly pages.
54+
///
55+
/// One WebAssembly page is 64 KiB.
5156
fn size(&self) -> u64;
5257

53-
/// Tries to grow the memory by `pages` many pages containing
54-
/// zeroes. If successful, returns the previous size of the
55-
/// memory (in pages). Otherwise, returns -1.
58+
/// Grows the memory by `pages` pages filled with zeroes.
59+
///
60+
/// Returns the previous size in pages on success, or -1 if the
61+
/// memory could not be grown.
5662
fn grow(&self, pages: u64) -> i64;
5763

58-
/// Copies the data referred to by `offset` out of the stable memory
59-
/// and replaces the corresponding bytes in `dst`.
64+
/// Copies `dst.len()` bytes from memory starting at `offset` into `dst`.
65+
///
66+
/// Panics or traps if the read would go out of bounds.
6067
fn read(&self, offset: u64, dst: &mut [u8]);
6168

62-
/// Copies `count` number of bytes of the data starting from `offset` out of the stable memory
63-
/// into the buffer starting at `dst`.
69+
/// Unsafe variant of `read` for advanced use.
6470
///
65-
/// This method is an alternative to `read` which does not require initializing a buffer and may
66-
/// therefore be faster.
71+
/// Copies `count` bytes from memory starting at `offset` into the
72+
/// raw pointer `dst`. Initializes the destination before reading.
6773
///
6874
/// # Safety
6975
///
70-
/// Callers must guarantee that
71-
/// * it is valid to write `count` number of bytes starting from `dst`,
72-
/// * `dst..dst + count` does not overlap with `self`.
76+
/// Caller must ensure:
77+
/// - `dst` points to valid writable memory of at least `count` bytes.
78+
/// - The memory range `dst..dst+count` does not overlap with `self`.
7379
///
74-
/// Implementations must guarantee that before the method returns, `count` number of bytes
75-
/// starting from `dst` will be initialized.
80+
/// Panics or traps if the read would go out of bounds.
7681
#[inline]
7782
unsafe fn read_unsafe(&self, offset: u64, dst: *mut u8, count: usize) {
7883
// Initialize the buffer to make the slice valid.
@@ -81,8 +86,9 @@ pub trait Memory {
8186
self.read(offset, slice)
8287
}
8388

84-
/// Copies the data referred to by `src` and replaces the
85-
/// corresponding segment starting at offset in the stable memory.
89+
/// Copies `src.len()` bytes from `src` into memory starting at `offset`.
90+
///
91+
/// Panics or traps if the write would go out of bounds.
8692
fn write(&self, offset: u64, src: &[u8]);
8793
}
8894

0 commit comments

Comments
 (0)