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: always check buffer clear offset for OOB #5282

Merged

Conversation

ErichDonGubler
Copy link
Member

@ErichDonGubler ErichDonGubler commented Feb 21, 2024

Recommended review experience is commit-by-commit.

Connections
Link to the issues addressed by this PR, or dependent PRs in other repositories

This fix was prompted by Firefox's bug 1881065.

Description
Describe what problem this is solving, and how it's solved.

Fuzz testing in Firefox encountered crashes for calls of Global::command_encoder_clear_buffer where:

  • offset is greater than buffer.size, but…
  • size is None.

Oops! We should always check this (i.e., even when size is None), because we have no guarantee that offset and the fallback value of size is in bounds. 😅 So, we change validation here to unconditionally compute size and run checks we previously gated behind if let Some(size) = size { … }.

For convenience, the spec. link for this method: https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-clearbuffer

Testing
Explain how this change is tested.

The following new tests have been added, and can be tested as arguments to cargo xtask test:

  • wgpu_test::buffer::clear_offset_outside_resource_bounds
  • wgpu_test::buffer::clear_offset_plus_size_outside_u64_bounds

Checklist

  • Run cargo fmt.
  • Run cargo clippy. If applicable, add:
    • --target wasm32-unknown-unknown
    • --target wasm32-unknown-emscripten
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

@ErichDonGubler ErichDonGubler added area: validation Issues related to validation, diagnostics, and error handling area: correctness We're behaving incorrectly labels Feb 21, 2024
@ErichDonGubler ErichDonGubler self-assigned this Feb 21, 2024
@ErichDonGubler ErichDonGubler requested a review from a team as a code owner February 21, 2024 22:09
@ErichDonGubler ErichDonGubler force-pushed the clear_buffer-fix-offset-ck branch from 46b4398 to 5b12fc6 Compare February 21, 2024 22:27
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.

Love to see it!

tests/tests/buffer.rs Outdated Show resolved Hide resolved
tests/tests/buffer.rs Show resolved Hide resolved
Fuzz testing in Firefox encountered crashes for calls of
`Global::command_encoder_clear_buffer` where:

* `offset` is greater than `buffer.size`, but…
* `size` is `None`.

Oops! We should _always_ check this (i.e., even when `size` is `None`),
because we have no guarantee that `offset` and the fallback value of
`size` is in bounds. 😅 So, we change validation here to unconditionally
compute `size` and run checks we previously gated behind `if let
Some(size) = size { … }`.

For convenience, the spec. link for this method:
<https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-clearbuffer>
Rust would have made this operation either an overflow in release mode,
or a panic in debug mode. Neither seem appropriate for this context,
where I suspect an error should be returned instead. Web browsers, for
instance, shouldn't crash simply because of an issue of this nature.
Users may, quite reasonably, have bad arguments to this in early stages
of development!
@ErichDonGubler ErichDonGubler force-pushed the clear_buffer-fix-offset-ck branch from 2e6138e to 2cbb42d Compare February 22, 2024 19:43
@ErichDonGubler ErichDonGubler dismissed cwfitzgerald’s stale review February 23, 2024 19:10

Concerns handled, AFAICT.

@ErichDonGubler ErichDonGubler requested a review from a team February 23, 2024 22:32
@ErichDonGubler ErichDonGubler merged commit d646570 into gfx-rs:trunk Feb 26, 2024
27 checks passed
@ErichDonGubler ErichDonGubler deleted the clear_buffer-fix-offset-ck branch February 26, 2024 14:34
@cwfitzgerald cwfitzgerald added the PR: needs back-porting PR with a fix that needs to land on crates label Feb 29, 2024
cwfitzgerald pushed a commit to cwfitzgerald/wgpu that referenced this pull request Feb 29, 2024
…e > buffer.size` was not checked when `size` was omitted. (gfx-rs#5282)

style: fix fmt. of `assert!(…)` in `clear_texture_via_buffer_copies`

refactor: `command_encoder_clear_buffer`: s/end/end_offset

fix: always check buffer clear `offset` for OOB

Fuzz testing in Firefox encountered crashes for calls of
`Global::command_encoder_clear_buffer` where:

* `offset` is greater than `buffer.size`, but…
* `size` is `None`.

Oops! We should _always_ check this (i.e., even when `size` is `None`),
because we have no guarantee that `offset` and the fallback value of
`size` is in bounds. 😅 So, we change validation here to unconditionally
compute `size` and run checks we previously gated behind `if let
Some(size) = size { … }`.

For convenience, the spec. link for this method:
<https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-clearbuffer>

fix: `command_encoder_clear_buffer`: err. on `offset + size > u64::MAX`

Rust would have made this operation either an overflow in release mode,
or a panic in debug mode. Neither seem appropriate for this context,
where I suspect an error should be returned instead. Web browsers, for
instance, shouldn't crash simply because of an issue of this nature.
Users may, quite reasonably, have bad arguments to this in early stages
of development!
cwfitzgerald pushed a commit to cwfitzgerald/wgpu that referenced this pull request Feb 29, 2024
…e > buffer.size` was not checked when `size` was omitted. (gfx-rs#5282)

style: fix fmt. of `assert!(…)` in `clear_texture_via_buffer_copies`

refactor: `command_encoder_clear_buffer`: s/end/end_offset

fix: always check buffer clear `offset` for OOB

Fuzz testing in Firefox encountered crashes for calls of
`Global::command_encoder_clear_buffer` where:

* `offset` is greater than `buffer.size`, but…
* `size` is `None`.

Oops! We should _always_ check this (i.e., even when `size` is `None`),
because we have no guarantee that `offset` and the fallback value of
`size` is in bounds. 😅 So, we change validation here to unconditionally
compute `size` and run checks we previously gated behind `if let
Some(size) = size { … }`.

For convenience, the spec. link for this method:
<https://gpuweb.github.io/gpuweb/#dom-gpucommandencoder-clearbuffer>

fix: `command_encoder_clear_buffer`: err. on `offset + size > u64::MAX`

Rust would have made this operation either an overflow in release mode,
or a panic in debug mode. Neither seem appropriate for this context,
where I suspect an error should be returned instead. Web browsers, for
instance, shouldn't crash simply because of an issue of this nature.
Users may, quite reasonably, have bad arguments to this in early stages
of development!
@cwfitzgerald cwfitzgerald removed the PR: needs back-porting PR with a fix that needs to land on crates label Mar 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: correctness We're behaving incorrectly area: validation Issues related to validation, diagnostics, and error handling
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants