diff --git a/CHANGELOG.md b/CHANGELOG.md index e8d63cadb6..f5262a1368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -119,6 +119,7 @@ Bottom level categories: - Fix timeout when presenting a surface where no work has been done. By @waywardmonkeys in [#5200](https://github.com/gfx-rs/wgpu/pull/5200) - Simplify and speed up the allocation of internal IDs. By @nical in [#5229](https://github.com/gfx-rs/wgpu/pull/5229) - Fix an issue where command encoders weren't properly freed if an error occurred during command encoding. By @ErichDonGubler in [#5251](https://github.com/gfx-rs/wgpu/pull/5251). +- Fix missing validation for `Device::clear_buffer` where `offset + size buffer.size` was not checked when `size` was omitted. By @ErichDonGubler in [#5282](https://github.com/gfx-rs/wgpu/pull/5282). #### WGL diff --git a/tests/tests/buffer.rs b/tests/tests/buffer.rs index 23f244c249..f9d2e03c69 100644 --- a/tests/tests/buffer.rs +++ b/tests/tests/buffer.rs @@ -326,3 +326,30 @@ static MINIMUM_BUFFER_BINDING_SIZE_DISPATCH: GpuTestConfiguration = GpuTestConfi let _ = encoder.finish(); }); }); + +#[gpu_test] +static CLEAR_OFFSET_OUTSIDE_RESOURCE_BOUNDS: GpuTestConfiguration = GpuTestConfiguration::new() + .parameters(TestParameters::default()) + .run_sync(|ctx| { + let size = 16; + + let buffer = ctx.device.create_buffer(&wgpu::BufferDescriptor { + label: None, + size, + usage: wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + let out_of_bounds = size.checked_add(wgpu::COPY_BUFFER_ALIGNMENT).unwrap(); + + ctx.device.push_error_scope(wgpu::ErrorFilter::Validation); + ctx.device + .create_command_encoder(&Default::default()) + .clear_buffer(&buffer, out_of_bounds, None); + let err_msg = pollster::block_on(ctx.device.pop_error_scope()) + .unwrap() + .to_string(); + assert!(err_msg.contains( + "Clear of 20..20 would end up overrunning the bounds of the buffer of size 16" + )); + }); diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 7d09754205..25dc417b80 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -117,24 +117,20 @@ impl Global { if offset % wgt::COPY_BUFFER_ALIGNMENT != 0 { return Err(ClearError::UnalignedBufferOffset(offset)); } - if let Some(size) = size { - if size % wgt::COPY_BUFFER_ALIGNMENT != 0 { - return Err(ClearError::UnalignedFillSize(size)); - } - let destination_end_offset = offset + size; - if destination_end_offset > dst_buffer.size { - return Err(ClearError::BufferOverrun { - start_offset: offset, - end_offset: destination_end_offset, - buffer_size: dst_buffer.size, - }); - } + + let size = size.unwrap_or(dst_buffer.size.saturating_sub(offset)); + if size % wgt::COPY_BUFFER_ALIGNMENT != 0 { + return Err(ClearError::UnalignedFillSize(size)); + } + let end_offset = offset + size; + if end_offset > dst_buffer.size { + return Err(ClearError::BufferOverrun { + start_offset: offset, + end_offset, + buffer_size: dst_buffer.size, + }); } - let end_offset = match size { - Some(size) => offset + size, - None => dst_buffer.size, - }; if offset == end_offset { log::trace!("Ignoring fill_buffer of size 0"); return Ok(());