mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 16:08:04 +02:00
rusticl: correct calculation of maximum allocation size
This verifies that the requested allocation doesn't exceed the maximum in cases where the size passed to `clSVMAlloc()` isn't a multiple of the provided alignment. It also clamps the maximum allocation to `i32::MAX`, which prevents overflowing `pipe_box`'s `width` field. Both of these changes prevent possible undefined behavior on 32-bit systems due to violation of `Layout` prerequisites. v2: use safe layout creation for maintainability, add a few comments v3: use Layout utils for aligned size calc, split out max alloc changes v4: use `checked_compare()` for alloc/size comparison Reviewed-by: Karol Herbst <kherbst@redhat.com> Cc: stable Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34166>
This commit is contained in:
parent
7c88a52350
commit
5b1088220e
1 changed files with 25 additions and 21 deletions
|
|
@ -2330,7 +2330,7 @@ pub fn svm_alloc(
|
|||
context: cl_context,
|
||||
flags: cl_svm_mem_flags,
|
||||
size: usize,
|
||||
mut alignment: cl_uint,
|
||||
alignment: cl_uint,
|
||||
) -> CLResult<*mut c_void> {
|
||||
// clSVMAlloc will fail if
|
||||
|
||||
|
|
@ -2347,29 +2347,33 @@ pub fn svm_alloc(
|
|||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
// size is 0 or > CL_DEVICE_MAX_MEM_ALLOC_SIZE value for any device in context.
|
||||
if size == 0 || checked_compare(size, Ordering::Greater, c.max_mem_alloc()) {
|
||||
let alignment = if alignment != 0 {
|
||||
alignment as usize
|
||||
} else {
|
||||
// When alignment is 0, the size of the largest supported type is used.
|
||||
// In the case of the full profile, that's `long16`.
|
||||
mem::size_of::<[u64; 16]>()
|
||||
};
|
||||
|
||||
// clSVMAlloc will fail if alignment is not a power of two.
|
||||
// `from_size_align()` verifies this condition is met.
|
||||
let layout = Layout::from_size_align(size, alignment).or(Err(CL_INVALID_VALUE))?;
|
||||
|
||||
// clSVMAlloc will fail if size is 0 or > CL_DEVICE_MAX_MEM_ALLOC_SIZE value
|
||||
// for any device in context.
|
||||
// Verify that the requested size, once adjusted to be a multiple of
|
||||
// alignment, fits within the maximum allocation size. While
|
||||
// `from_size_align()` ensures that the allocation will fit in host memory,
|
||||
// the maximum allocation may be smaller due to limitations from gallium or
|
||||
// devices.
|
||||
let size_aligned = layout.pad_to_align().size();
|
||||
if size == 0 || checked_compare(size_aligned, Ordering::Greater, c.max_mem_alloc()) {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
if alignment == 0 {
|
||||
alignment = mem::size_of::<[u64; 16]>() as cl_uint;
|
||||
}
|
||||
|
||||
// alignment is not a power of two
|
||||
if !alignment.is_power_of_two() {
|
||||
return Err(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
let layout;
|
||||
let ptr;
|
||||
|
||||
// SAFETY: we already verify the parameters to from_size_align above and layout is of non zero
|
||||
// size
|
||||
unsafe {
|
||||
layout = Layout::from_size_align_unchecked(size, alignment as usize);
|
||||
ptr = alloc::alloc(layout);
|
||||
}
|
||||
// SAFETY: `size` is verified to be non-zero and the returned pointer is not
|
||||
// expected to point to initialized memory.
|
||||
let ptr = unsafe { alloc::alloc(layout) };
|
||||
|
||||
if ptr.is_null() {
|
||||
return Err(CL_OUT_OF_HOST_MEMORY);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue