Compare commits

..

2 Commits

Author SHA1 Message Date
Benjamin Eckel
14d7eae99c ignore already published 2023-09-21 10:15:12 -05:00
Benjamin Eckel
e89ddd5a2a chore: Bump to 0.5.2 2023-09-21 09:41:27 -05:00
7 changed files with 38 additions and 111 deletions

View File

@@ -33,8 +33,7 @@ jobs:
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_API_TOKEN }}
run: |
cargo publish --manifest-path runtime/Cargo.toml --no-verify
#cargo publish --manifest-path runtime/Cargo.toml --no-verify
cargo publish --manifest-path rust/Cargo.toml

View File

@@ -87,22 +87,19 @@ pub enum MemoryStatus {
///
/// The overall layout of the Extism-manged memory is organized like this:
/// |------|-------+---------|-------+--------------|
/// | Root | Block + Data | Block + Data | ...
/// |------|-------+---------|-------+--------------|
/// |------|-------|---------|-------|--------------|
/// | Root | Block | Data | Block | Data | ...
/// |------|-------|---------|-------|--------------|
///
/// Where `Root` and `Block` are fixed to the size of the `MemoryRoot` and `MemoryBlock` structs. But
/// the size of `Data` is dependent on the allocation size.
///
/// This means that the offset of a `Block` is the size of `Root` plus the size of all existing `Blocks`
/// including their data.
#[repr(C)]
pub struct MemoryRoot {
/// Position of the bump allocator, relative to `blocks` field
/// Position of the bump allocator, relative to `START_PAGE`
pub position: AtomicU64,
/// The total size of all data allocated using this allocator
pub length: AtomicU64,
/// A pointer to the start of the first block
/// A pointer to where the blocks begin
pub blocks: [MemoryBlock; 0],
}
@@ -183,22 +180,6 @@ impl MemoryRoot {
self.position.store(0, Ordering::Release);
}
#[inline(always)]
#[allow(unused)]
fn pointer_in_bounds(&self, p: Pointer) -> bool {
let start_ptr = self.blocks.as_ptr() as Pointer;
p >= start_ptr && p < start_ptr + self.length.load(Ordering::Acquire) as Pointer
}
#[inline(always)]
#[allow(unused)]
fn pointer_in_bounds_fast(p: Pointer) -> bool {
// Similar to `pointer_in_bounds` but less accurate on the upper bound. This uses the total memory size,
// instead of checking `MemoryRoot::length`
let end = core::arch::wasm32::memory_size(0) << 16;
p >= core::mem::size_of::<Self>() as Pointer && p <= end as Pointer
}
// Find a block that is free to use, this can be a new block or an existing freed block. The `self_position` argument
// is used to avoid loading the allocators position more than once when performing an allocation.
unsafe fn find_free_block(
@@ -213,7 +194,6 @@ impl MemoryRoot {
while (block as u64) < self.blocks.as_ptr() as u64 + self_position {
let b = &mut *block;
// Get the block status, this lets us know if we are able to re-use it
let status = b.status.load(Ordering::Acquire);
// An unused block is safe to use
@@ -267,13 +247,12 @@ impl MemoryRoot {
// Get the number of bytes available
let mem_left = self_length - self_position - core::mem::size_of::<MemoryRoot>() as u64;
let mem_left = mem_left;
// When the allocation is larger than the number of bytes available
// we will need to try to grow the memory
if length + 1 >= mem_left {
if length >= mem_left {
// Calculate the number of pages needed to cover the remaining bytes
let npages = num_pages(length - mem_left) + 1;
let npages = num_pages(length - mem_left);
let x = core::arch::wasm32::memory_grow(0, npages);
if x == usize::MAX {
return None;
@@ -301,7 +280,8 @@ impl MemoryRoot {
/// Finds the block at an offset in memory
pub unsafe fn find_block(&mut self, offs: Pointer) -> Option<&mut MemoryBlock> {
if !Self::pointer_in_bounds_fast(offs) {
if offs >= self.blocks.as_ptr() as Pointer + self.length.load(Ordering::Acquire) as Pointer
{
return None;
}
let ptr = offs - core::mem::size_of::<MemoryBlock>() as u64;
@@ -317,7 +297,9 @@ impl MemoryBlock {
/// is calculated based on metadata provided by the current block
#[inline]
pub unsafe fn next_ptr(&mut self) -> *mut MemoryBlock {
self.data.as_mut_ptr().add(self.size) as *mut MemoryBlock
self.data
.as_mut_ptr()
.add(self.size + core::mem::size_of::<MemoryBlock>()) as *mut MemoryBlock
}
/// Mark a block as free
@@ -327,14 +309,11 @@ impl MemoryBlock {
}
}
// Extism functions
// Extism functions - these functions should be
/// Allocate a block of memory and return the offset
#[no_mangle]
pub unsafe fn extism_alloc(n: Length) -> Pointer {
if n == 0 {
return 0;
}
let region = MemoryRoot::new();
let block = region.alloc(n);
match block {
@@ -346,18 +325,9 @@ pub unsafe fn extism_alloc(n: Length) -> Pointer {
/// Free allocated memory
#[no_mangle]
pub unsafe fn extism_free(p: Pointer) {
if p == 0 {
return;
}
let block = MemoryRoot::new().find_block(p);
if let Some(block) = block {
block.free();
// If the input pointer is freed for some reason, make sure the input length to 0
// since the original data is gone
if p == INPUT_OFFSET {
INPUT_LENGTH = 0;
}
}
}
@@ -377,89 +347,57 @@ pub unsafe fn extism_length(p: Pointer) -> Length {
/// Load a byte from Extism-managed memory
#[no_mangle]
pub unsafe fn extism_load_u8(p: Pointer) -> u8 {
#[cfg(feature = "bounds-checking")]
if !MemoryRoot::pointer_in_bounds_fast(p) {
return 0;
}
*(p as *mut u8)
}
/// Load a u64 from Extism-managed memory
#[no_mangle]
pub unsafe fn extism_load_u64(p: Pointer) -> u64 {
#[cfg(feature = "bounds-checking")]
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
return 0;
}
*(p as *mut u64)
}
/// Load a byte from the input data
#[no_mangle]
pub unsafe fn extism_input_load_u8(p: Pointer) -> u8 {
#[cfg(feature = "bounds-checking")]
if p >= INPUT_LENGTH {
return 0;
}
*((INPUT_OFFSET + p) as *mut u8)
}
/// Load a u64 from the input data
#[no_mangle]
pub unsafe fn extism_input_load_u64(p: Pointer) -> u64 {
#[cfg(feature = "bounds-checking")]
if p + core::mem::size_of::<u64>() as Pointer > INPUT_LENGTH {
return 0;
}
*((INPUT_OFFSET + p) as *mut u64)
}
/// Write a byte in Extism-managed memory
#[no_mangle]
pub unsafe fn extism_store_u8(p: Pointer, x: u8) {
#[cfg(feature = "bounds-checking")]
if !MemoryRoot::pointer_in_bounds_fast(p) {
return;
}
*(p as *mut u8) = x;
}
/// Write a u64 in Extism-managed memory
#[no_mangle]
pub unsafe fn extism_store_u64(p: Pointer, x: u64) {
#[cfg(feature = "bounds-checking")]
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
return;
unsafe {
*(p as *mut u64) = x;
}
*(p as *mut u64) = x;
}
/// Set the range of the input data in memory
#[no_mangle]
pub unsafe fn extism_input_set(p: Pointer, len: Length) {
#[cfg(feature = "bounds-checking")]
{
let root = MemoryRoot::new();
if !root.pointer_in_bounds(p) || !root.pointer_in_bounds(p + len - 1) {
return;
}
pub fn extism_input_set(p: Pointer, len: Length) {
unsafe {
INPUT_OFFSET = p;
INPUT_LENGTH = len;
}
INPUT_OFFSET = p;
INPUT_LENGTH = len;
}
/// Set the range of the output data in memory
#[no_mangle]
pub unsafe fn extism_output_set(p: Pointer, len: Length) {
#[cfg(feature = "bounds-checking")]
{
let root = MemoryRoot::new();
if !root.pointer_in_bounds(p) || !root.pointer_in_bounds(p + len - 1) {
return;
}
pub fn extism_output_set(p: Pointer, len: Length) {
unsafe {
OUTPUT_OFFSET = p;
OUTPUT_LENGTH = len;
}
OUTPUT_OFFSET = p;
OUTPUT_LENGTH = len;
}
/// Get the input length
@@ -496,16 +434,6 @@ pub unsafe fn extism_reset() {
/// Set the error message offset
#[no_mangle]
pub unsafe fn extism_error_set(ptr: Pointer) {
// Allow ERROR to be set to 0
if ptr == 0 {
ERROR.store(ptr, Ordering::SeqCst);
return;
}
#[cfg(feature = "bounds-checking")]
if !MemoryRoot::new().pointer_in_bounds(ptr) {
return;
}
ERROR.store(ptr, Ordering::SeqCst);
}

View File

@@ -1,6 +1,6 @@
[package]
name = "libextism"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"

View File

@@ -1,6 +1,6 @@
[package]
name = "extism-runtime"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
authors = ["The Extism Authors", "oss@extism.org"]
license = "BSD-3-Clause"

Binary file not shown.

View File

@@ -10,8 +10,8 @@ description = "Extism Host SDK for Rust"
[dependencies]
extism-manifest = { version = "0.5.0", path = "../manifest" }
extism-runtime = { version = "0.5.1", path = "../runtime"}
extism-runtime = { version = "0.5.2", path = "../runtime"}
serde_json = "1"
log = "0.4"
anyhow = "1"
uuid = { version = "1", features = ["v4"] }
uuid = { version = "1", features = ["v4"] }

View File

@@ -310,16 +310,16 @@ mod tests {
}
}
// #[test]
// fn test_globals() {
// let context = Context::new();
// let mut plugin = Plugin::new(&context, WASM_GLOBALS, [], true).unwrap();
// for i in 0..1000 {
// let output = plugin.call("globals", "").unwrap();
// let count: serde_json::Value = serde_json::from_slice(&output).unwrap();
// assert_eq!(count.get("count").unwrap().as_i64().unwrap(), i);
// }
// }
#[test]
fn test_globals() {
let context = Context::new();
let mut plugin = Plugin::new(&context, WASM_GLOBALS, [], true).unwrap();
for i in 0..1000 {
let output = plugin.call("globals", "").unwrap();
let count: serde_json::Value = serde_json::from_slice(&output).unwrap();
assert_eq!(count.get("count").unwrap().as_i64().unwrap(), i);
}
}
#[test]
fn test_fuzz_reflect_plugin() {