diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-04-24 12:22:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-24 12:22:21 +0200 |
commit | 1f0360c07382dbd86066d1aa8aa4bae34aff18c5 (patch) | |
tree | cc82d00aea829f0b3d3949f40df9696b099ee662 /ext/node/ops/zlib/alloc.rs | |
parent | 28e2c7204fe02304a8fc3339d7758eec0f64f723 (diff) |
refactor(ext/node): reorganize ops (#18799)
Move all op related code of "ext/node" to "ext/node/ops" module.
These files were unnecessarily scattered around the extension.
Diffstat (limited to 'ext/node/ops/zlib/alloc.rs')
-rw-r--r-- | ext/node/ops/zlib/alloc.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/ext/node/ops/zlib/alloc.rs b/ext/node/ops/zlib/alloc.rs new file mode 100644 index 000000000..c7fecadd8 --- /dev/null +++ b/ext/node/ops/zlib/alloc.rs @@ -0,0 +1,64 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +// Workaround for https://github.com/rust-lang/libz-sys/issues/55 +// See https://github.com/rust-lang/flate2-rs/blob/31fb07820345691352aaa64f367c1e482ad9cfdc/src/ffi/c.rs#L60 +use std::alloc::Layout; +use std::alloc::{self}; +use std::os::raw::c_void; +use std::ptr; + +const ALIGN: usize = std::mem::align_of::<usize>(); + +fn align_up(size: usize, align: usize) -> usize { + (size + align - 1) & !(align - 1) +} + +pub extern "C" fn zalloc( + _ptr: *mut c_void, + items: u32, + item_size: u32, +) -> *mut c_void { + // We need to multiply `items` and `item_size` to get the actual desired + // allocation size. Since `zfree` doesn't receive a size argument we + // also need to allocate space for a `usize` as a header so we can store + // how large the allocation is to deallocate later. + let size = match (items as usize) + .checked_mul(item_size as usize) + .map(|size| align_up(size, ALIGN)) + .and_then(|i| i.checked_add(std::mem::size_of::<usize>())) + { + Some(i) => i, + None => return ptr::null_mut(), + }; + + // Make sure the `size` isn't too big to fail `Layout`'s restrictions + let layout = match Layout::from_size_align(size, ALIGN) { + Ok(layout) => layout, + Err(_) => return ptr::null_mut(), + }; + + // SAFETY: `layout` has non-zero size, guaranteed to be a sentinel address + // or a null pointer. + unsafe { + // Allocate the data, and if successful store the size we allocated + // at the beginning and then return an offset pointer. + let ptr = alloc::alloc(layout) as *mut usize; + if ptr.is_null() { + return ptr as *mut c_void; + } + *ptr = size; + ptr.add(1) as *mut c_void + } +} + +pub extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) { + // SAFETY: Move our address being free'd back one pointer, read the size we + // stored in `zalloc`, and then free it using the standard Rust + // allocator. + unsafe { + let ptr = (address as *mut usize).offset(-1); + let size = *ptr; + let layout = Layout::from_size_align_unchecked(size, ALIGN); + alloc::dealloc(ptr as *mut u8, layout) + } +} |