From aa9109f0b54f1338d4989e2f91b45b0a56feba5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=C3=A1n=20de=20B=C3=BArca?= Date: Wed, 12 Mar 2025 09:59:46 -0700 Subject: [PATCH] rusticl/mem: use cl_slice::from_raw_parts in place of std::slice The cl_slice version of this function checks several invariants for us, providing a slight safety net. v2: reordered commits to allow cherry-picking bugfixes Reviewed-by: Karol Herbst Part-of: --- src/gallium/frontends/rusticl/api/memory.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/gallium/frontends/rusticl/api/memory.rs b/src/gallium/frontends/rusticl/api/memory.rs index 0e562151f9c..4aa80b2df2d 100644 --- a/src/gallium/frontends/rusticl/api/memory.rs +++ b/src/gallium/frontends/rusticl/api/memory.rs @@ -26,7 +26,6 @@ use std::cmp::Ordering; use std::mem::{self, MaybeUninit}; use std::os::raw::c_void; use std::ptr; -use std::slice; use std::sync::Arc; fn validate_mem_flags(flags: cl_mem_flags, images: bool) -> CLResult<()> { @@ -1612,8 +1611,12 @@ fn enqueue_fill_buffer( return Err(CL_INVALID_CONTEXT); } - // we have to copy memory - let pattern = unsafe { slice::from_raw_parts(pattern.cast(), pattern_size).to_vec() }; + // The caller may free `pattern` once the `clEnqueueFillBuffer()` call + // returns, so we need to duplicate its contents to hold onto. + // SAFETY: `cl_slice::from_raw_parts()` verifies the testable invariants of + // `slice::from_raw_parts()`. The caller is responsible for providing a + // pointer to appropriately-sized, initialized memory. + let pattern = unsafe { cl_slice::from_raw_parts(pattern.cast(), pattern_size)? }.to_vec(); create_and_queue( q, CL_COMMAND_FILL_BUFFER, @@ -2421,8 +2424,12 @@ fn enqueue_svm_free_impl( // The application is allowed to reuse or free the memory referenced by `svm_pointers` after this // function returns, so we have to make a copy. let mut svm_pointers = if !svm_pointers.is_null() { - // SAFETY: num_svm_pointers specifies the amount of elements in svm_pointers - unsafe { slice::from_raw_parts(svm_pointers.cast(), num_svm_pointers as usize) }.to_vec() + // SAFETY: `cl_slice::from_raw_parts()` verifies that testable + // invariants of `slice::from_raw_parts()` are satisfied. Callers are + // responsible for providing pointers to appropriately-sized, + // initialized memory. + unsafe { cl_slice::from_raw_parts(svm_pointers.cast(), num_svm_pointers as usize)? } + .to_vec() } else { // A slice must not be created from a raw null pointer, so simply create // an empty vec instead.