diff --git a/codecs/oxipng/pkg/oxipng_bg.wasm b/codecs/oxipng/pkg/oxipng_bg.wasm index 0e15d13e..7c094e40 100644 Binary files a/codecs/oxipng/pkg/oxipng_bg.wasm and b/codecs/oxipng/pkg/oxipng_bg.wasm differ diff --git a/codecs/oxipng/src/malloc_shim.rs b/codecs/oxipng/src/malloc_shim.rs index af5154c2..ff199d4b 100644 --- a/codecs/oxipng/src/malloc_shim.rs +++ b/codecs/oxipng/src/malloc_shim.rs @@ -2,6 +2,26 @@ //! These implementations are compatible with the standard signatures //! but use Rust allocator instead of including libc one as well. //! +//! Rust allocator APIs requires passing size and alignment to the +//! `dealloc` function. This is different from C API, which only +//! expects a pointer in `free` and expects allocators to take care of +//! storing any necessary information elsewhere. +//! +//! In order to simulate C API, we allocate a `size_and_data_ptr` +//! of size `sizeof(usize) + size` where `size` is the requested number +//! of bytes. Then, we store `size` at the beginning of the allocated +//! chunk (within those `sizeof(usize)` bytes) and return +//! `data_ptr = size_and_data_ptr + sizeof(usize)` to the calleer: +//! +//! [`size`][...actual data] +//! -^------------------ `size_and_data_ptr` +//! ---------^---------- `data_ptr` +//! +//! Then, in `free`, the caller gives us `data_ptr`. We can subtract +//! `sizeof(usize)` back and get the original `size_and_data_ptr`. +//! At this point we can read `size` back and call the Rust `dealloc` +//! for the whole allocated chunk. +//! //! I've raised an upstream issue to hopefully make this easier in //! future: https://github.com/ebiggers/libdeflate/issues/62 @@ -20,8 +40,8 @@ pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 { } #[no_mangle] -pub unsafe extern "C" fn free(ptr: *mut u8) { - let size_and_data_ptr = ptr.sub(size_of::()); +pub unsafe extern "C" fn free(data_ptr: *mut u8) { + let size_and_data_ptr = data_ptr.sub(size_of::()); let size = *(size_and_data_ptr as *const usize); - dealloc(ptr, layout_for(size)) + dealloc(size_and_data_ptr, layout_for(size)) }