add missing indirect buffer offset validation

This commit is contained in:
teoxoy 2024-07-18 21:00:14 +02:00 committed by Erich Gubler
parent 0903ba6d47
commit 7ac533a312
2 changed files with 16 additions and 0 deletions

View File

@ -136,6 +136,8 @@ pub enum ComputePassErrorInner {
BindGroupIndexOutOfRange { index: u32, max: u32 }, BindGroupIndexOutOfRange { index: u32, max: u32 },
#[error(transparent)] #[error(transparent)]
DestroyedResource(#[from] DestroyedResourceError), DestroyedResource(#[from] DestroyedResourceError),
#[error("Indirect buffer offset {0:?} is not a multiple of 4")]
UnalignedIndirectBufferOffset(BufferAddress),
#[error("Indirect buffer uses bytes {offset}..{end_offset} which overruns indirect buffer of size {buffer_size}")] #[error("Indirect buffer uses bytes {offset}..{end_offset} which overruns indirect buffer of size {buffer_size}")]
IndirectBufferOverrun { IndirectBufferOverrun {
offset: u64, offset: u64,
@ -845,6 +847,10 @@ fn dispatch_indirect(
.merge_single(&buffer, hal::BufferUses::INDIRECT)?; .merge_single(&buffer, hal::BufferUses::INDIRECT)?;
buffer.check_usage(wgt::BufferUsages::INDIRECT)?; buffer.check_usage(wgt::BufferUsages::INDIRECT)?;
if offset % 4 != 0 {
return Err(ComputePassErrorInner::UnalignedIndirectBufferOffset(offset));
}
let end_offset = offset + size_of::<wgt::DispatchIndirectArgs>() as u64; let end_offset = offset + size_of::<wgt::DispatchIndirectArgs>() as u64;
if end_offset > buffer.size { if end_offset > buffer.size {
return Err(ComputePassErrorInner::IndirectBufferOverrun { return Err(ComputePassErrorInner::IndirectBufferOverrun {

View File

@ -638,6 +638,8 @@ pub enum RenderPassErrorInner {
MissingFeatures(#[from] MissingFeatures), MissingFeatures(#[from] MissingFeatures),
#[error(transparent)] #[error(transparent)]
MissingDownlevelFlags(#[from] MissingDownlevelFlags), MissingDownlevelFlags(#[from] MissingDownlevelFlags),
#[error("Indirect buffer offset {0:?} is not a multiple of 4")]
UnalignedIndirectBufferOffset(BufferAddress),
#[error("Indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}", #[error("Indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}",
count.map_or_else(String::new, |v| format!("(using count {v})")))] count.map_or_else(String::new, |v| format!("(using count {v})")))]
IndirectBufferOverrun { IndirectBufferOverrun {
@ -2450,6 +2452,10 @@ fn multi_draw_indirect(
let actual_count = count.map_or(1, |c| c.get()); let actual_count = count.map_or(1, |c| c.get());
if offset % 4 != 0 {
return Err(RenderPassErrorInner::UnalignedIndirectBufferOffset(offset));
}
let end_offset = offset + stride as u64 * actual_count as u64; let end_offset = offset + stride as u64 * actual_count as u64;
if end_offset > indirect_buffer.size { if end_offset > indirect_buffer.size {
return Err(RenderPassErrorInner::IndirectBufferOverrun { return Err(RenderPassErrorInner::IndirectBufferOverrun {
@ -2534,6 +2540,10 @@ fn multi_draw_indirect_count(
count_buffer.check_usage(BufferUsages::INDIRECT)?; count_buffer.check_usage(BufferUsages::INDIRECT)?;
let count_raw = count_buffer.try_raw(state.snatch_guard)?; let count_raw = count_buffer.try_raw(state.snatch_guard)?;
if offset % 4 != 0 {
return Err(RenderPassErrorInner::UnalignedIndirectBufferOffset(offset));
}
let end_offset = offset + stride * max_count as u64; let end_offset = offset + stride * max_count as u64;
if end_offset > indirect_buffer.size { if end_offset > indirect_buffer.size {
return Err(RenderPassErrorInner::IndirectBufferOverrun { return Err(RenderPassErrorInner::IndirectBufferOverrun {