From bead4183123bc493e07bbb2210a4f247481da3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20L=C3=B3pez?= <00xc@protonmail.com> Date: Mon, 2 Oct 2023 21:45:41 +0200 Subject: [PATCH] Fix potential panic due to huge layout If a user provides a layout with a big enough size, the allocator might panic on an unwrap instead of returning an error. The reason is that, even though the layout size is properly rounded to a power of two, Layout::from_size_align() will fail if the size overflows isize when rounded to the layout alignment. Fix this by handling the error instead of unwrapping it. Keep an unwrap in the HoleList::deallocate() as the validity of the layout must be guaranteed by the caller since it is an unsafe function. --- src/hole.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hole.rs b/src/hole.rs index f7481bf..baf9d96 100644 --- a/src/hole.rs +++ b/src/hole.rs @@ -1,4 +1,4 @@ -use core::alloc::Layout; +use core::alloc::{Layout, LayoutError}; use core::mem; use core::mem::{align_of, size_of}; use core::ptr::null_mut; @@ -365,13 +365,13 @@ impl HoleList { /// The [`allocate_first_fit`][HoleList::allocate_first_fit] and /// [`deallocate`][HoleList::deallocate] methods perform the required alignment /// themselves, so calling this function manually is not necessary. - pub fn align_layout(layout: Layout) -> Layout { + pub fn align_layout(layout: Layout) -> Result { let mut size = layout.size(); if size < Self::min_size() { size = Self::min_size(); } let size = align_up_size(size, mem::align_of::()); - Layout::from_size_align(size, layout.align()).unwrap() + Layout::from_size_align(size, layout.align()) } /// Searches the list for a big enough hole. @@ -389,7 +389,7 @@ impl HoleList { // release to remove this clippy warning #[allow(clippy::result_unit_err)] pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<(NonNull, Layout), ()> { - let aligned_layout = Self::align_layout(layout); + let aligned_layout = Self::align_layout(layout).map_err(|_| ())?; let mut cursor = self.cursor().ok_or(())?; loop { @@ -419,7 +419,7 @@ impl HoleList { /// The function performs exactly the same layout adjustments as [`allocate_first_fit`] and /// returns the aligned layout. pub unsafe fn deallocate(&mut self, ptr: NonNull, layout: Layout) -> Layout { - let aligned_layout = Self::align_layout(layout); + let aligned_layout = Self::align_layout(layout).unwrap(); deallocate(self, ptr.as_ptr(), aligned_layout.size()); aligned_layout }