From d7049634a933b9b00b8440b7e5fffe4fb87a25fa Mon Sep 17 00:00:00 2001 From: Nathan Gill Date: Mon, 6 Jul 2026 14:02:54 +0100 Subject: [PATCH] buffer: explicitly enforce dimension bounds - enforce dimensions are greater than zero - don't use `new_unchecked` for `NonZeroUsize` - implicitly cleanup buffers on drop, remove explicit `destroy` closes #83 --- src/buffer.rs | 19 +++++++++++++++---- src/state.rs | 3 ++- src/surface.rs | 8 ++++++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 49a4314..991100d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -14,6 +14,7 @@ use nix::{ sys::mman::{MapFlags, ProtFlags, mmap, munmap}, unistd::ftruncate, }; +use tracing::warn; use wayland_client::{ Dispatch, QueueHandle, protocol::{wl_buffer, wl_shm, wl_surface}, @@ -72,6 +73,14 @@ impl NLockBuffer { format: wl_shm::Format, qh: &QueueHandle, ) -> Option { + if width <= 0 || height <= 0 { + warn!( + "cannot create a buffer with dimensions: {}x{}", + width, height + ); + return None; + } + let stride = width * 4; let size = stride * height; @@ -81,7 +90,7 @@ impl NLockBuffer { let data = unsafe { mmap( None, - std::num::NonZeroUsize::new_unchecked(size as usize), + std::num::NonZeroUsize::new(size as usize)?, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, MapFlags::MAP_SHARED, &fd, @@ -105,7 +114,7 @@ impl NLockBuffer { cairo::Format::ARgb32, width, height, - width * 4, + stride, ) } .ok()?; @@ -128,7 +137,7 @@ impl NLockBuffer { if self.state.in_use.swap(true, Ordering::AcqRel) { None } else { - // Buffer is now "in_use", explicit manage state + // Buffer is now "in_use", explicitly manage state Some(NLockBufferGuard { wl_buffer: &self.buffer, state: &self.state, @@ -136,8 +145,10 @@ impl NLockBuffer { }) } } +} - pub fn destroy(&mut self) { +impl Drop for NLockBuffer { + fn drop(&mut self) { self.buffer.destroy(); let _ = unsafe { munmap(self.data, self.size) }; } diff --git a/src/state.rs b/src/state.rs index 11445e4..7adcceb 100644 --- a/src/state.rs +++ b/src/state.rs @@ -132,7 +132,8 @@ impl NLockState { session_lock.destroy(); } - self.surfaces.iter_mut().for_each(|s| s.destroy()); + // free any held surfaces + self.surfaces = Vec::new(); self.display.sync(qh, ()); self.session_lock = None; diff --git a/src/surface.rs b/src/surface.rs index 9cc5001..8968da8 100644 --- a/src/surface.rs +++ b/src/surface.rs @@ -438,13 +438,17 @@ impl NLockSurface { Ok(()) } +} - pub fn destroy(&mut self) { +impl Drop for NLockSurface { + fn drop(&mut self) { if let Some(lock_surface) = &self.lock_surface { lock_surface.destroy(); } - self.buffers.iter_mut().for_each(|buf| buf.destroy()); + // free any held buffers + self.buffers = Vec::new(); + self.output.release(); } }