Skip to content

GapBuffer Data Structure Is Excessively Unsafe` #359

@Barca545

Description

@Barca545

The current implementation of the BackingBuffer which relies on a NonNull and unsafe operations introduces more unsafety into the GapBuffer than I believe is strictly necessary.

Here is the relevant code:

enum BackingBuffer {
    VirtualMemory(NonNull<u8>, usize),
    Vec(Vec<u8>),
}

impl Drop for BackingBuffer {
    fn drop(&mut self) {
        unsafe {
            if let Self::VirtualMemory(ptr, reserve) = *self {
                sys::virtual_release(ptr, reserve);
            }
        }
    }
}

After going through the codebase, my understanding is this is to allow for BackingBuffer::VirtualMemory to be obtained via Windows' VirtualAlloc and unix's memmap function as used in sys::unix::virtual_reserve and sys::windows::virtual_reserve.

I believe this unsafety could be avoided by making BackingBuffer::VirtualMemory wrap a vector Vec<u8, VirtualAllocator> which relies on a VirtualAllocator struct which implements Allocator.

This would allow the GapBuffer methods which currently rely on unsafe pointer arithmetic such as move_gap and delete_text to switch to using safe vector/slice operations such as copy_within.

Below I included and example of what a "VirtualAllocator" might look like:

#[derive(Debug, Clone, Copy,)]
struct VirtualAllocator;

unsafe impl Allocator for VirtualAllocator {
  /// When defining the `layout` its size should be `sizeof::<T> * num` not
  /// `sizeof::<T>`.
  fn allocate(&self, layout: Layout,) -> Result<NonNull<[u8],>, AllocError,> {
    let base = ptr::null_mut();
    let len = layout.size();
    unsafe {
      let c_ptr = Memory::VirtualAlloc(base, len, Memory::MEM_RESERVE, Memory::PAGE_READWRITE,);
      match NonNull::new(ptr::from_raw_parts_mut(c_ptr, len,),) {
        Some(ptr,) => Ok(ptr,),
        None => todo!(),
      }
    }
  }

  unsafe fn deallocate(&self, ptr: NonNull<u8,>, layout: std::alloc::Layout,) {
    todo!()
  }
}

static ALLOCATOR: VirtualAllocator = VirtualAllocator;

enum BackingBuffer {
    VirtualMemory(Vec<u8, VirtualAllocator>,),
    Vec(Vec<u8>),
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions