Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect offset in get_mapped_range #3233

Merged
merged 3 commits into from
Nov 30, 2022
Merged

Conversation

nical
Copy link
Contributor

@nical nical commented Nov 24, 2022

Checklist

  • Run cargo clippy.
  • Add change to CHANGELOG.md. See simple instructions inside file.

Connections

Found the issue while fuzzing Gecko's WebGPU integration.

Description

This one is kind of serious.

get_mapped_range (spec) takes a range that is relative to the beginning of the buffer. The implementation in webgpu seems to want to agree judging by how the validation checks that the range is contained in the mapped one. However internally the ptr stored in BufferMapState::Active is actually relative to the beginning of the mapped range (rather than beginning of the buffer). This means that we have to subtract the mapped offset to the one provided in get_mapped_range, otherwise seriously scary things happen.

Testing

Added a simple test.

Note that in the process of adding the test I found out that tests/buffer.rs was not run (oops!). I hadn't finished it when it landed a little while ago, it was not quite working yet because of how wgpu does not accept empty slices, I had put it on hold for a bit and when it landed anyway without breaking the build I didn't think too much of it but the version that landed was not part of the build. So this commit puts the file back in the build with a #[ignore] slapped on it, and of course it got reformatted in the process.

@codecov-commenter
Copy link

codecov-commenter commented Nov 24, 2022

Codecov Report

Merging #3233 (d364b06) into master (183ba3f) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##           master    #3233   +/-   ##
=======================================
  Coverage   65.40%   65.40%           
=======================================
  Files          82       82           
  Lines       39451    39454    +3     
=======================================
+ Hits        25802    25805    +3     
  Misses      13649    13649           
Impacted Files Coverage Δ
wgpu-core/src/device/mod.rs 66.64% <100.00%> (+0.02%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@nical
Copy link
Contributor Author

nical commented Nov 24, 2022

@cwfitzgerald Perhaps this one fixes a sufficiently bad issue to warrant being rebased on top of the current release and publishing it as 0.14.1? It allows you to do arbitrary reads and writes past the buffer mapping without unsafe code.

Copy link
Member

@cwfitzgerald cwfitzgerald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that feels backport worthy.

Are you able to backport the change, and I'll take the release to the finish line?

Comment on lines 149 to 151
while !status.load(Ordering::SeqCst) {
ctx.device.poll(wgpu::MaintainBase::Poll);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of this vs just waiting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to using MaintainBase::Wait instead of Poll ? I don't know, both appear to work, changing it to Wait.

write_buf
.slice(32..)
.map_async(wgpu::MapMode::Write, move |result| {
assert!(result.is_ok());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets do result.unwrap() as it gives a better message

Comment on lines 100 to 102
for _ in 0..10 {
ctx.device.poll(wgpu::MaintainBase::Poll);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is simiarly weird

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's in the old unfinished stuff, I'm not sure what I meant by "poll ten times". My guess is that I probably wanted the test to get a chance to run unfinished async code in case there is anything queued up while not have anything in particular to wait for, if that makes any sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just do Wait everywhere, otherwise there's still technically a potential race.

.map_async(wgpu::MapMode::Read, move |result| {
assert!(result.is_ok());
done.store(true, Ordering::SeqCst);
});

while !status.load(Ordering::SeqCst) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By waiting, you guarentee that all pending map_asyncs are finished, so this atomic code can all go away.

Comment on lines 100 to 102
for _ in 0..10 {
ctx.device.poll(wgpu::MaintainBase::Poll);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just do Wait everywhere, otherwise there's still technically a potential race.

@@ -91,18 +97,100 @@ fn test_empty_buffer_range(ctx: &TestingContext, buffer_size: u64, label: &str)

b1.unmap();

for _ in 0..10 {
for _ in 0..10 {
ctx.device.poll(wgpu::MaintainBase::Poll);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ctx.device.poll(wgpu::MaintainBase::Poll);
ctx.device.poll(wgpu::Maintain::Wair);

@nical
Copy link
Contributor Author

nical commented Nov 29, 2022

The linux failure looks like an unrelated driver sneeze.

Copy link
Member

@cwfitzgerald cwfitzgerald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Party

@cwfitzgerald cwfitzgerald merged commit a9d3319 into gfx-rs:master Nov 30, 2022
@nical nical deleted the mappedrange branch December 1, 2022 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants