rusticl/mem: don't create svm_pointers slice from null raw pointer

std::slice::from_raw_parts requires that the slice pointer be non-null,
even when the slice contains zero elements. Failing this invariant is
undefined behavior.

v2: reordered commits to allow cherry-picking bugfixes

Reviewed-by: Karol Herbst <kherbst@redhat.com>
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33989>
This commit is contained in:
Seán de Búrca 2025-03-11 16:05:11 -07:00 committed by Marge Bot
parent faad7a8aad
commit 5e365f1674
2 changed files with 23 additions and 12 deletions

View file

@ -2419,10 +2419,16 @@ 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.
// SAFETY: num_svm_pointers specifies the amount of elements in svm_pointers
let mut svm_pointers =
unsafe { slice::from_raw_parts(svm_pointers.cast(), num_svm_pointers as usize) }.to_vec();
// 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()
} else {
// A slice must not be created from a raw null pointer, so simply create
// an empty vec instead.
Vec::new()
};
// SAFETY: The requirements on `SVMFreeCb::new` match the requirements
// imposed by the OpenCL specification. It is the caller's duty to uphold them.
let cb_opt = unsafe { SVMFreeCb::new(pfn_free_func, user_data) }.ok();

View file

@ -189,17 +189,22 @@ cl_callback!(
impl SVMFreeCb {
pub fn call(self, queue: &Queue, svm_pointers: &mut [usize]) {
let (num_svm_pointers, svm_pointers) = if !svm_pointers.is_empty() {
(
svm_pointers.len() as cl_uint,
svm_pointers.as_mut_ptr().cast(),
)
} else {
// The specification requires that an empty `svm_pointers` list be
// null when passed to enqueue and callbacks may expect it to be
// passed back in the same manner.
(0, std::ptr::null_mut())
};
let cl = cl_command_queue::from_ptr(queue);
// SAFETY: `cl` must be a valid pointer to an OpenCL queue, which is where we just got it from.
// All other requirements are covered by this callback's type invariants.
unsafe {
(self.func)(
cl,
svm_pointers.len() as u32,
svm_pointers.as_mut_ptr().cast(),
self.data,
)
};
unsafe { (self.func)(cl, num_svm_pointers, svm_pointers, self.data) };
}
}