rusticl/mem: return errors for OOB accesses
authorKarol Herbst <kherbst@redhat.com>
Sun, 25 Sep 2022 12:20:59 +0000 (14:20 +0200)
committerMarge Bot <emma+marge@anholt.net>
Mon, 26 Sep 2022 23:59:13 +0000 (23:59 +0000)
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>

src/gallium/drivers/llvmpipe/ci/llvmpipe-rusticl.txt
src/gallium/frontends/rusticl/api/memory.rs
src/gallium/frontends/rusticl/api/types.rs

index 4829d24..c8aa38e 100644 (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
index 4cb8604..80d7955 100644 (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.
index 64efe8c..954d0df 100644 (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],
 }