rusticl: check for overrun status when deserializing

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32253>
(cherry picked from commit 813edb6cea)
This commit is contained in:
Karol Herbst
2024-11-19 02:20:38 +01:00
committed by Dylan Baker
parent 2cc0be2044
commit c489be4522
4 changed files with 35 additions and 27 deletions

View File

@@ -954,7 +954,7 @@
"description": "rusticl: check for overrun status when deserializing", "description": "rusticl: check for overrun status when deserializing",
"nominated": true, "nominated": true,
"nomination_type": 1, "nomination_type": 1,
"resolution": 0, "resolution": 1,
"main_sha": null, "main_sha": null,
"because_sha": null, "because_sha": null,
"notes": null "notes": null

View File

@@ -25,6 +25,7 @@ use std::convert::TryInto;
use std::fmt::Debug; use std::fmt::Debug;
use std::fmt::Display; use std::fmt::Display;
use std::ops::Index; use std::ops::Index;
use std::ops::Not;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
@@ -58,8 +59,10 @@ pub enum KernelArgType {
impl KernelArgType { impl KernelArgType {
fn deserialize(blob: &mut blob_reader) -> Option<Self> { fn deserialize(blob: &mut blob_reader) -> Option<Self> {
Some(match unsafe { blob_read_uint8(blob) } { // SAFETY: we get 0 on an overrun, but we verify that later and act accordingly.
let res = match unsafe { blob_read_uint8(blob) } {
0 => { 0 => {
// SAFETY: same here
let size = unsafe { blob_read_uint16(blob) }; let size = unsafe { blob_read_uint16(blob) };
KernelArgType::Constant(size) KernelArgType::Constant(size)
} }
@@ -71,7 +74,9 @@ impl KernelArgType {
6 => KernelArgType::MemConstant, 6 => KernelArgType::MemConstant,
7 => KernelArgType::MemLocal, 7 => KernelArgType::MemLocal,
_ => return None, _ => return None,
}) };
blob.overrun.not().then_some(res)
} }
fn serialize(&self, blob: &mut blob) { fn serialize(&self, blob: &mut blob) {
@@ -192,13 +197,14 @@ impl KernelArg {
} }
fn deserialize(blob: &mut blob_reader) -> Option<Vec<Self>> { fn deserialize(blob: &mut blob_reader) -> Option<Vec<Self>> {
unsafe { // SAFETY: we check the overrun status, blob_read returns 0 in such a case.
let len = blob_read_uint16(blob) as usize; let len = unsafe { blob_read_uint16(blob) } as usize;
let mut res = Vec::with_capacity(len); let mut res = Vec::with_capacity(len);
for _ in 0..len { for _ in 0..len {
let spirv = spirv::SPIRVKernelArg::deserialize(blob)?; let spirv = spirv::SPIRVKernelArg::deserialize(blob)?;
let dead = blob_read_uint8(blob) != 0; // SAFETY: we check the overrun status
let dead = unsafe { blob_read_uint8(blob) } != 0;
let kind = KernelArgType::deserialize(blob)?; let kind = KernelArgType::deserialize(blob)?;
res.push(Self { res.push(Self {
@@ -208,8 +214,7 @@ impl KernelArg {
}); });
} }
Some(res) blob.overrun.not().then_some(res)
}
} }
} }
@@ -1080,18 +1085,16 @@ impl SPIRVToNirResult {
let args = KernelArg::deserialize(&mut reader)?; let args = KernelArg::deserialize(&mut reader)?;
let default_build = CompilationResult::deserialize(&mut reader, d)?; let default_build = CompilationResult::deserialize(&mut reader, d)?;
// SAFETY: on overrun this returns 0
let optimized = match unsafe { blob_read_uint8(&mut reader) } { let optimized = match unsafe { blob_read_uint8(&mut reader) } {
0 => None, 0 => None,
_ => Some(CompilationResult::deserialize(&mut reader, d)?), _ => Some(CompilationResult::deserialize(&mut reader, d)?),
}; };
Some(SPIRVToNirResult::new( reader
d, .overrun
kernel_info, .not()
args, .then(|| SPIRVToNirResult::new(d, kernel_info, args, default_build, optimized))
default_build,
optimized,
))
} }
// we can't use Self here as the nir shader might be compiled to a cso already and we can't // we can't use Self here as the nir shader might be compiled to a cso already and we can't

View File

@@ -9,6 +9,7 @@ use mesa_rust_util::string::*;
use std::ffi::CString; use std::ffi::CString;
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::Not;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::ptr; use std::ptr;
@@ -484,7 +485,8 @@ impl SPIRVKernelArg {
_ => return None, _ => return None,
}; };
Some(Self { // check overrun to ensure nothing went wrong
blob.overrun.not().then(|| Self {
name: String::from_utf8_unchecked(name.to_owned()), name: String::from_utf8_unchecked(name.to_owned()),
type_name: String::from_utf8_unchecked(type_name.to_owned()), type_name: String::from_utf8_unchecked(type_name.to_owned()),
access_qualifier: clc_kernel_arg_access_qualifier(access_qualifier), access_qualifier: clc_kernel_arg_access_qualifier(access_qualifier),

View File

@@ -5,6 +5,7 @@ use mesa_rust_util::offset_of;
use std::convert::TryInto; use std::convert::TryInto;
use std::ffi::CString; use std::ffi::CString;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::Not;
use std::ptr; use std::ptr;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
@@ -158,7 +159,9 @@ impl NirShader {
blob: &mut blob_reader, blob: &mut blob_reader,
options: *const nir_shader_compiler_options, options: *const nir_shader_compiler_options,
) -> Option<Self> { ) -> Option<Self> {
unsafe { Self::new(nir_deserialize(ptr::null_mut(), options, blob)) } // we already create the NirShader here so it gets automatically deallocated on overrun.
let nir = Self::new(unsafe { nir_deserialize(ptr::null_mut(), options, blob) })?;
blob.overrun.not().then_some(nir)
} }
pub fn serialize(&self, blob: &mut blob) { pub fn serialize(&self, blob: &mut blob) {