rusticl/mem: return errors for OOB accesses

There is a little bit more to do, but this at least resolves crashes due
to OOB accesses and/or assertions.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7346

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18806>
This commit is contained in:
Karol Herbst
2022-09-25 14:20:59 +02:00
committed by Marge Bot
parent e6ecd22140
commit 8b9a5adf8b
3 changed files with 34 additions and 7 deletions

View File

@@ -1,7 +1,7 @@
api/clbuildprogram: fail
api/clcompileprogram: fail
api/clcreateprogramwithbinary: fail
api/clenqueuefillimage: crash
api/clenqueuefillimage: fail
api/clenqueuemigratememobjects: fail
api/clgetcommandqueueinfo: fail
api/clgetdeviceinfo: fail

View File

@@ -508,6 +508,14 @@ fn validate_image_desc(
Ok((desc, parent))
}
fn validate_image_bounds(i: &Mem, origin: CLVec<usize>, region: CLVec<usize>) -> CLResult<()> {
let bound = region + origin;
if bound > i.image_desc.size() {
return Err(CL_INVALID_VALUE);
}
Ok(())
}
fn desc_eq_no_buffer(a: &cl_image_desc, b: &cl_image_desc) -> bool {
a.image_type == b.image_type
&& a.image_width == b.image_width
@@ -1666,6 +1674,10 @@ pub fn enqueue_read_image(
let r = unsafe { CLVec::from_raw(region) };
let o = unsafe { CLVec::from_raw(origin) };
// CL_INVALID_VALUE if the region being read or written specified by origin and region is out of
// bounds.
validate_image_bounds(&i, o, r)?;
// If row_pitch (or input_row_pitch) is set to 0, the appropriate row pitch is calculated based
// on the size of each element in bytes multiplied by width.
if row_pitch == 0 {
@@ -1700,7 +1712,6 @@ pub fn enqueue_read_image(
}),
)
//• CL_INVALID_VALUE if the region being read or written specified by origin and region is out of bounds.
//• CL_INVALID_VALUE if values in origin and region do not follow rules described in the argument description for origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for image are not supported by device associated with queue.
@@ -1752,6 +1763,10 @@ pub fn enqueue_write_image(
let r = unsafe { CLVec::from_raw(region) };
let o = unsafe { CLVec::from_raw(origin) };
// CL_INVALID_VALUE if the region being read or written specified by origin and region is out of
// bounds.
validate_image_bounds(&i, o, r)?;
// If row_pitch (or input_row_pitch) is set to 0, the appropriate row pitch is calculated based
// on the size of each element in bytes multiplied by width.
if row_pitch == 0 {
@@ -1786,7 +1801,6 @@ pub fn enqueue_write_image(
}),
)
//• CL_INVALID_VALUE if the region being read or written specified by origin and region is out of bounds.
//• CL_INVALID_VALUE if values in origin and region do not follow rules described in the argument description for origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for image are not supported by device associated with queue.
@@ -1829,6 +1843,14 @@ pub fn enqueue_copy_image(
let dst_origin = unsafe { CLVec::from_raw(dst_origin) };
let src_origin = unsafe { CLVec::from_raw(src_origin) };
// CL_INVALID_VALUE if the 2D or 3D rectangular region specified by src_origin and
// src_origin + region refers to a region outside src_image, ...
validate_image_bounds(&src_image, src_origin, region)?;
// ... or if the 2D or 3D rectangular region specified by dst_origin and dst_origin + region
// refers to a region outside dst_image.
validate_image_bounds(&dst_image, dst_origin, region)?;
create_and_queue(
q,
CL_COMMAND_COPY_IMAGE,
@@ -1840,7 +1862,6 @@ pub fn enqueue_copy_image(
}),
)
//• CL_INVALID_VALUE if the 2D or 3D rectangular region specified by src_origin and src_origin + region refers to a region outside src_image, or if the 2D or 3D rectangular region specified by dst_origin and dst_origin + region refers to a region outside dst_image.
//• CL_INVALID_VALUE if values in src_origin, dst_origin and region do not follow rules described in the argument description for src_origin, dst_origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for src_image or dst_image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for src_image or dst_image are not supported by device associated with queue.
@@ -1876,6 +1897,10 @@ pub fn enqueue_fill_image(
let region = unsafe { CLVec::from_raw(region.cast()) };
let origin = unsafe { CLVec::from_raw(origin.cast()) };
// CL_INVALID_VALUE if the region being filled as specified by origin and region is out of
// bounds.
validate_image_bounds(&i, origin, region)?;
// we have to copy memory and it's always a 4 component int value
// TODO but not for CL_DEPTH
let fill_color = unsafe { slice::from_raw_parts(fill_color.cast(), 4).to_vec() };
@@ -1888,7 +1913,6 @@ pub fn enqueue_fill_image(
Box::new(move |q, ctx| i.fill_image(q, ctx, &fill_color, &origin, &region)),
)
//• CL_INVALID_VALUE if the region being filled as specified by origin and region is out of bounds.
//• CL_INVALID_VALUE if values in origin and region do not follow rules described in the argument description for origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for
@@ -2013,6 +2037,7 @@ pub fn enqueue_map_image(
let block = check_cl_bool(blocking_map).ok_or(CL_INVALID_VALUE)?;
let evs = event_list_from_cl(&q, num_events_in_wait_list, event_wait_list)?;
// CL_INVALID_VALUE ... or if values specified in map_flags are not valid.
validate_map_flags(&i, map_flags)?;
// CL_INVALID_CONTEXT if context associated with command_queue and image are not the same
@@ -2029,6 +2054,9 @@ pub fn enqueue_map_image(
let region = unsafe { CLVec::from_raw(region) };
let origin = unsafe { CLVec::from_raw(origin) };
// CL_INVALID_VALUE if region being mapped given by (origin, origin + region) is out of bounds
validate_image_bounds(&i, origin, region)?;
let mut dummy_slice_pitch: usize = 0;
let image_slice_pitch = if image_slice_pitch.is_null() {
// CL_INVALID_VALUE if image is a 3D image, 1D or 2D image array object and
@@ -2096,7 +2124,6 @@ pub fn enqueue_map_image(
ptr
}
//• CL_INVALID_VALUE if region being mapped given by (origin, origin + region) is out of bounds or if values specified in map_flags are not valid.
//• CL_INVALID_VALUE if values in origin and region do not follow rules described in the argument description for origin and region.
//• CL_INVALID_IMAGE_SIZE if image dimensions (image width, height, specified or compute row and/or slice pitch) for image are not supported by device associated with queue.
//• CL_IMAGE_FORMAT_NOT_SUPPORTED if image format (image channel order and data type) for image are not supported by device associated with queue.

View File

@@ -72,7 +72,7 @@ cl_callback!(
);
// a lot of APIs use 3 component vectors passed as C arrays
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct CLVec<T> {
vals: [T; 3],
}