From a05c8dc2dc846a78b98152d70f5a613699fc5695 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 1 Aug 2022 00:05:18 +0200 Subject: [PATCH] Fix buffer zeroing with offset in map_buffer (#2916) Co-authored-by: Connor Fitzgerald --- CHANGELOG.md | 1 + wgpu-core/src/device/mod.rs | 25 +++++++++---------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f91d440ad5..793fc94050 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,7 @@ the same every time it is rendered, we now warn if it is missing. - Fix panics that occur when using `as_hal` functions when the hal generic type does not match the hub being looked up in by @i509VCB [#2871](https://github.com/gfx-rs/wgpu/pull/2871) - Add some validation in map_async by @nical in [#2876](https://github.com/gfx-rs/wgpu/pull/2876) - Fix bugs when mapping/unmapping zero-sized buffers and ranges by @nical in [#2877](https://github.com/gfx-rs/wgpu/pull/2877) +- Fix out-of-bound write in `map_buffer` with non-zero offset by @nical in [#2916](https://github.com/gfx-rs/wgpu/pull/2916) - Validate the number of color attachments in `create_render_pipeline` by @nical in [#2913](https://github.com/gfx-rs/wgpu/pull/2913) #### DX12 diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index fb32d8580a..dfb30d8607 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -190,24 +190,17 @@ fn map_buffer( // // If this is a write mapping zeroing out the memory here is the only reasonable way as all data is pushed to GPU anyways. let zero_init_needs_flush_now = mapping.is_coherent && buffer.sync_mapped_writes.is_none(); // No need to flush if it is flushed later anyways. - for uninitialized_range in buffer.initialization_status.drain(offset..(size + offset)) { - let num_bytes = uninitialized_range.end - uninitialized_range.start; - unsafe { - ptr::write_bytes( - mapping - .ptr - .as_ptr() - .offset(uninitialized_range.start as isize), - 0, - num_bytes as usize, - ) - }; + let mapped = unsafe { std::slice::from_raw_parts_mut(mapping.ptr.as_ptr(), size as usize) }; + + for uninitialized in buffer.initialization_status.drain(offset..(size + offset)) { + // The mapping's pointer is already offset, however we track the uninitialized range relative to the buffer's start. + let fill_range = + (uninitialized.start - offset) as usize..(uninitialized.end - offset) as usize; + mapped[fill_range].fill(0); + if zero_init_needs_flush_now { unsafe { - raw.flush_mapped_ranges( - buffer.raw.as_ref().unwrap(), - iter::once(uninitialized_range.start..uninitialized_range.start + num_bytes), - ) + raw.flush_mapped_ranges(buffer.raw.as_ref().unwrap(), iter::once(uninitialized)) }; } }