Stream: git-wasmtime

Topic: wasmtime / issue #3218 Call WASM's Memory Allocation Func...


view this post on Zulip Wasmtime GitHub notifications bot (Aug 20 2021 at 10:00):

HighCWu opened issue #3218:

I don’t know if it has been implemented, but I searched the warehouse and didn’t find the relevant description.

Feature

// Modified from https://docs.wasmtime.dev/api/wasmtime/struct.Memory.html
use wasmtime::{Memory, Store, MemoryAccessError};

// An error is returned if the copy did not succeed.
fn safe_examples(mem: Memory, store: &mut Store<()>) -> Result<(), MemoryAccessError> {
    let offset = mem.malloc(5); // return offset or raise 'Out of memory' exception
    mem.write(&mut *store, offset, b"hello")?;
    let mut buffer = [0u8; 5];
    mem.read(&store, offset, &mut buffer)?;
    assert_eq!(b"hello", &buffer);

    // Note that while this is safe care must be taken because the indexing
    // here may panic if the memory isn't large enough.
    assert_eq!(&mem.data(&store)[offset..offset + 5], b"hello");
    mem.data_mut(&mut *store)[offset..offset + 5].copy_from_slice(b"bye!!");

    mem.free(offset); // The internal block is released, but the host should still be able to obtain the content of that block normally, although it may be allocated to others during operation

    Ok(())
}

Benefit

Should implement a series of host calls to wasm internal memory allocation functions, such as alloc, malloc, calloc, realloc, free. The dynamic offset is returned, and the host performs data operations, which makes it easier to expand wasmtime.

My current situation is that I have a third-party native function that will perform a series of memory allocations, but I need to call this wrapped function from wasm. I hope this native function will not break the sandbox of wasmtime. This third-party library only allows me to modify its memory allocator for debugging, memory allocation range limitation and other operations. If I can replace the function used by its memory allocator with the memory allocation function used internally by wasm, it will ensure the safe execution of the function. And after wrapping, I can better let wasm call this native function.

Alternatives

wasm-micro-runtime implemented the feature using wasm_runtime_module_malloc and so on.

In wasmtime, I can use get_typed_func to get 'malloc' funciton of wasm. But it seems that I need to wrap a malloc function in the c code before compiling wasm. That seems very inconvenient. I hope there is no need to make changes to the source code of wasm.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 20 2021 at 10:08):

HighCWu edited issue #3218:

I don’t know if it has been implemented, but I searched the warehouse and didn’t find the relevant description.

Feature

// Modified from https://docs.wasmtime.dev/api/wasmtime/struct.Memory.html
use wasmtime::{Memory, Store, MemoryAccessError};

// An error is returned if the copy did not succeed.
fn safe_examples(mem: Memory, store: &mut Store<()>) -> Result<(), MemoryAccessError> {
    let offset = mem.malloc(5); // return offset or raise 'Out of memory' exception
    mem.write(&mut *store, offset, b"hello")?;
    let mut buffer = [0u8; 5];
    mem.read(&store, offset, &mut buffer)?;
    assert_eq!(b"hello", &buffer);

    // Note that while this is safe care must be taken because the indexing
    // here may panic if the memory isn't large enough.
    assert_eq!(&mem.data(&store)[offset..offset + 5], b"hello");
    mem.data_mut(&mut *store)[offset..offset + 5].copy_from_slice(b"bye!!");

    mem.free(offset); // The internal block is released, but the host should still be able to obtain the content of that block normally, although it may be allocated to others during operation

    Ok(())
}

Benefit

Should implement a series of host calls to wasm internal memory allocation functions, such as alloc, malloc, calloc, realloc, free. The dynamic offset is returned, and the host performs data operations, which makes it easier to expand wasmtime.

My current situation is that I have a third-party native function that will perform a series of memory allocations, but I need to call this wrapped function from wasm. I hope this native function will not break the sandbox of wasmtime. This third-party library only allows me to modify its memory allocator for debugging, memory allocation range limitation and other operations. If I can replace the function used by its memory allocator with the memory allocation function used internally by wasm, it will ensure the safe execution of the function. And after wrapping, I can better let wasm call this native function.

Alternatives

wasm-micro-runtime implemented the feature using wasm_runtime_module_malloc and so on.

In wasmtime, I can use get_typed_func to get 'malloc' funciton of wasm. But it seems that I need to wrap a malloc function in the c code before compiling wasm. That seems very inconvenient. I hope there is no need to make changes to the source code of wasm.

Thank you for creating this excellent project and hope it could be better.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 20 2021 at 10:12):

bjorn3 commented on issue #3218:

WASM doesn't have a memory allocator. It only has an instruction to grow the memory. It is then up to the wasm module itself to implement a memory allocator if it needs one at all. You could export the memory allocator functions from the wasm module and then call then from the embedder.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 20 2021 at 11:12):

HighCWu commented on issue #3218:

WASM doesn't have a memory allocator. It only has an instruction to grow the memory. It is then up to the wasm module itself to implement a memory allocator if it needs one at all. You could export the memory allocator functions from the wasm module and then call then from the embedder.

Yes, I mentioned this above.

There is a function of memory allocation in wasi-libc. However, manual export may involve modifying the c source code, which is not conducive to expansion.

I hope to be able to use it more conveniently. In wasm-micro-runtime, it can be easily done with wasm_runtime_module_malloc. Since two repo are all belong to bytecodealliance, I think there should be commonality.

Wasm-micro-runtime is pure C, and sometimes it can be troublesome to compile. And wasmtime is rust, it will be more convenient to be used. So I want to ask about the implementation of wasmtime.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 20 2021 at 16:43):

bjorn3 commented on issue #3218:

I hope to be able to use it more conveniently. In wasm-micro-runtime, it can be easily done with wasm_runtime_module_malloc.

I traced through the code of wasm-micro-runtime and it literally looks for an malloc function exported by the wasm module or in case of a module using the wasi-sdk it directly peeks at the data structures used by the memory allocator of wasi-sdk:

https://github.com/bytecodealliance/wasm-micro-runtime/blob/7cdfc9fe11742c5a1ec384467d545a3c96dda7be/core/iwasm/interpreter/wasm_loader.c#L3123-L3209

https://github.com/bytecodealliance/wasm-micro-runtime/blob/541f577164437c706e02b9271a10f5fdca08747c/core/iwasm/interpreter/wasm_runtime.c#L1825

wasm-micro-runtime actually suggests recompiling the wasm module to export malloc and free in an error message:

https://github.com/bytecodealliance/wasm-micro-runtime/blob/541f577164437c706e02b9271a10f5fdca08747c/core/iwasm/interpreter/wasm_runtime.c#L1844-L1847

said error message also suggests that it is possible for wasm_runtime_module_malloc to corrupt the heap of the wasm module if it is compiled with an incompatible version of wasi-sdk. I don't think this is an acceptable risk that wasmtime can take.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2021 at 01:39):

HighCWu commented on issue #3218:

I got it. Thanks for your answer @bjorn3

It seems that I need to add something like -Wl, --export=malloc to the compilation option of compiling c into wasm when using wasi-sdk >= 12. This is much more convenient than modifying the source code of c.

Although wasmtime does not have a direct function, it is sufficient to call the malloc function exported in the compiler option through instance.get_typed_func. With a little wrapping, it should be able to achieve a similar effect to wasm-micro-runtime.
Indeed, if functions such as malloc are not exported, forced calling will cause code errors. And it is not too good to be compatible with the wasi-sdk version.

I haven't tried one thing yet. If the call to malloc is not mentioned in my c source code, and the header of malloc is not included, is it possible to export malloc? If possible, this passage can be used as a solution.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2021 at 02:32):

HighCWu commented on issue #3218:

I completed the verification using wasi-sdk==12.0 .

// main.c
#include <stdio.h>

int main()
{
  printf("hello world");

  return 0;
}

Run $CC main.c -o main.wasm -Wl,--export=malloc -Wl,--export=free

Decompile main.wasm to main.wat, I can see malloc function in it:

(func $malloc (export "malloc") (type $t5) (param $p0 i32) (result i32)
    (call $dlmalloc
      (local.get $p0)))

The memory allocator seems to be a group of built-in functions, and its implementation is directly built into wasm, which is not like using import "wasi_snapshot_preview1" to use printf.

I think the problem should be basically solved now.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 21 2021 at 02:32):

HighCWu closed issue #3218:

I don’t know if it has been implemented, but I searched the warehouse and didn’t find the relevant description.

Feature

// Modified from https://docs.wasmtime.dev/api/wasmtime/struct.Memory.html
use wasmtime::{Memory, Store, MemoryAccessError};

// An error is returned if the copy did not succeed.
fn safe_examples(mem: Memory, store: &mut Store<()>) -> Result<(), MemoryAccessError> {
    let offset = mem.malloc(5); // return offset or raise 'Out of memory' exception
    mem.write(&mut *store, offset, b"hello")?;
    let mut buffer = [0u8; 5];
    mem.read(&store, offset, &mut buffer)?;
    assert_eq!(b"hello", &buffer);

    // Note that while this is safe care must be taken because the indexing
    // here may panic if the memory isn't large enough.
    assert_eq!(&mem.data(&store)[offset..offset + 5], b"hello");
    mem.data_mut(&mut *store)[offset..offset + 5].copy_from_slice(b"bye!!");

    mem.free(offset); // The internal block is released, but the host should still be able to obtain the content of that block normally, although it may be allocated to others during operation

    Ok(())
}

Benefit

Should implement a series of host calls to wasm internal memory allocation functions, such as alloc, malloc, calloc, realloc, free. The dynamic offset is returned, and the host performs data operations, which makes it easier to expand wasmtime.

My current situation is that I have a third-party native function that will perform a series of memory allocations, but I need to call this wrapped function from wasm. I hope this native function will not break the sandbox of wasmtime. This third-party library only allows me to modify its memory allocator for debugging, memory allocation range limitation and other operations. If I can replace the function used by its memory allocator with the memory allocation function used internally by wasm, it will ensure the safe execution of the function. And after wrapping, I can better let wasm call this native function.

Alternatives

wasm-micro-runtime implemented the feature using wasm_runtime_module_malloc and so on.

In wasmtime, I can use get_typed_func to get 'malloc' funciton of wasm. But it seems that I need to wrap a malloc function in the c code before compiling wasm. That seems very inconvenient. I hope there is no need to make changes to the source code of wasm.

Thank you for creating this excellent project and hope it could be better.


Last updated: Dec 23 2024 at 13:07 UTC