From 38effb1c566394c417eb39ecb1a1089dc4894efa Mon Sep 17 00:00:00 2001 From: George Lim Date: Tue, 1 Apr 2025 01:48:30 -0400 Subject: [PATCH 1/2] Fix misaligned pointer dereference --- Cargo.lock | 115 +++++++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 4 +- LICENSE | 2 +- README.md | 2 +- src/lib.rs | 33 ++++++++------- 5 files changed, 119 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f33d27..5fd1869 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + [[package]] name = "cfg-if" version = "1.0.0" @@ -10,50 +16,78 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", + "r-efi", "wasi", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "ordered-pool-allocator" -version = "0.1.0" +version = "0.1.1" dependencies = [ "rand", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "libc", "rand_chacha", "rand_core", + "zerocopy", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -61,15 +95,64 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom", ] +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 8f84c29..a8c383f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ordered-pool-allocator" -version = "0.1.0" +version = "0.1.1" authors = ["George Lim "] edition = "2021" description = "A fast and compact pool allocator with block sorting support." @@ -10,7 +10,7 @@ keywords = ["allocator", "memory-pool"] categories = ["data-structures", "memory-management"] [dev-dependencies] -rand = "0.8" +rand = "0.9" [profile.test] opt-level = 3 diff --git a/LICENSE b/LICENSE index 88f8e80..64b098f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 George Lim +Copyright (c) 2025 George Lim Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 28d23b1..274db1b 100644 --- a/README.md +++ b/README.md @@ -26,4 +26,4 @@ In order to achieve the fastest time complexity for block allocation and dealloc ### Memory Layout -![memory-layout](https://github.com/george-lim/ordered-pool-allocator/assets/21700768/24c78c1d-e0d4-48ce-9d0d-963fb45dde9b) +![memory-layout](https://github.com/user-attachments/assets/994064e0-f7ae-44ea-ab9b-1973fdff7985) diff --git a/src/lib.rs b/src/lib.rs index ae9ad32..5ab1450 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,13 +8,10 @@ use std::{ }; /// An allocator for `T` objects, with a block index of `N` bytes. -/// -/// If `N` is 1, then `blocks_capacity` will be `u8::MAX`. -/// If `N` is 2, then `blocks_capacity` will be `u16::MAX`. pub struct OrderedPoolAllocator<'buf, T, const N: usize = { mem::size_of::() }> { + physical_blocks_ptr: *mut MaybeUninit, physical_block_indices_ptr: *mut [u8; N], virtual_block_indices_ptr: *mut [u8; N], - physical_blocks_ptr: *mut MaybeUninit, blocks_len: usize, deallocated_blocks_len: usize, blocks_capacity: usize, @@ -25,18 +22,21 @@ impl<'buf, T, const N: usize> OrderedPoolAllocator<'buf, T, N> { pub fn new_in(buf: &'buf mut [u8]) -> Self { let blocks_capacity = usize::MAX .min(2usize.pow(8).pow(N as u32) - 1) - .min(buf.len() / (2 * mem::size_of::<[u8; N]>() + mem::size_of::>())); + .min(buf.len() / (mem::size_of::>() + 2 * mem::size_of::<[u8; N]>())); unsafe { Self { - physical_block_indices_ptr: buf.as_mut_ptr().cast(), - virtual_block_indices_ptr: buf + physical_blocks_ptr: buf.as_mut_ptr().cast(), + physical_block_indices_ptr: buf .as_mut_ptr() - .add(blocks_capacity * mem::size_of::<[u8; N]>()) + .add(blocks_capacity * mem::size_of::>()) .cast(), - physical_blocks_ptr: buf + virtual_block_indices_ptr: buf .as_mut_ptr() - .add(2 * blocks_capacity * mem::size_of::<[u8; N]>()) + .add( + blocks_capacity + * (mem::size_of::>() + mem::size_of::<[u8; N]>()), + ) .cast(), blocks_len: 0, deallocated_blocks_len: 0, @@ -48,12 +48,12 @@ impl<'buf, T, const N: usize> OrderedPoolAllocator<'buf, T, N> { /// Allocates a block and returns a pointer to the block. /// - /// This method will always prioritize reallocating an existing deallocated block over allocating - /// a new block. + /// This method will always prioritize reallocating an existing deallocated block over allocating a new block. /// /// # Safety /// - /// Behavior is undefined if the returned pointer points to an uninitialized instance of `T` when the allocator is dropped. + /// Behavior is undefined if the returned pointer points to an uninitialized instance of `T` when the allocator is + /// dropped. pub unsafe fn allocate(&mut self) -> Result, AllocError> { let physical_block_index = match self.deallocated_blocks_len { 0 if self.is_full() => return Err(AllocError), @@ -96,7 +96,6 @@ impl<'buf, T, const N: usize> OrderedPoolAllocator<'buf, T, N> { /// Behavior is undefined if any of the following conditions are violated: /// /// * `ptr` must point to an instance of `T` allocated by this allocator. - /// /// * `ptr` must not point to an instance of `T` that has already been dropped or deallocated by this allocator. pub unsafe fn deallocate(&mut self, ptr: NonNull) { if self.is_empty() { @@ -327,7 +326,7 @@ mod tests { } unsafe fn deallocate(sut: &mut OrderedPoolAllocator, rng: &mut ThreadRng) { - let i = rng.gen_range(0..sut.len()); + let i = rng.random_range(0..sut.len()); let ptr = NonNull::new_unchecked(sut[i].as_mut_ptr()); sut.deallocate(ptr); assert_eq!(0, ptr.as_ref().0) @@ -336,14 +335,14 @@ mod tests { unsafe { let mut buf = [0u8; 128]; let mut sut = OrderedPoolAllocator::::new_in(&mut buf); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for _ in 0..20_000_000 { if sut.is_empty() { allocate(&mut sut, u32::MAX) } else if sut.is_full() { deallocate(&mut sut, &mut rng) - } else if rng.gen_bool(0.5) { + } else if rng.random_bool(0.5) { allocate(&mut sut, u32::MAX) } else { deallocate(&mut sut, &mut rng) From e583518e45daa7cda8385244abcda2748733686c Mon Sep 17 00:00:00 2001 From: George Lim Date: Thu, 3 Apr 2025 00:48:55 -0400 Subject: [PATCH 2/2] Update Rust --- src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5ab1450..4ee7648 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,10 +205,6 @@ impl<'buf, T, const N: usize> OrderedPoolAllocator<'buf, T, N> { } fn usize_to_bytes(block_index: usize) -> [u8; N] { - if N == mem::size_of::() { - unsafe { return *block_index.to_le_bytes().as_ptr().cast() } - } - let mut buf = [0u8; N]; unsafe {