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

SPIR-V back end skips bounds checks for AccessIndex when applied to runtime-sized arrays #4441

Closed
jimblandy opened this issue Nov 11, 2021 · 2 comments · Fixed by #6351
Closed
Assignees
Labels
area: naga back-end Outputs of naga shader conversion lang: SPIR-V Vulkan's Shading Language naga Shader Translator type: bug Something isn't working

Comments

@jimblandy
Copy link
Member

Naga's SPIR-V back end fails to generate a bounds check for an AccessIndex expression that is indexing into a runtime-sized array.

For example:

[[block]]
struct Unsized {
    arr: array<f32>;
};

[[group(0), binding(0)]] var<storage> unsized: Unsized;

fn fetch(i: i32) -> f32 {
   return unsized.arr[3] + unsized.arr[i];
}

When the ReadZeroSkipWrite policy is applied to buffers, Naga generates the following SPIR-V for the body:

      %fetch = OpFunction %float None %13
          %i = OpFunctionParameter %int
         %10 = OpLabel
               OpBranch %14
         %14 = OpLabel
         %20 = OpAccessChain %_ptr_StorageBuffer_float %unsized %uint_0 %uint_3
         %21 = OpLoad %float %20
         %22 = OpArrayLength %uint %unsized 0
         %23 = OpULessThan %bool %i %22
               OpSelectionMerge %27 None
               OpBranchConditional %23 %28 %27
         %28 = OpLabel
         %25 = OpAccessChain %_ptr_StorageBuffer_float %unsized %uint_0 %i
         %29 = OpLoad %float %25
               OpBranch %27
         %27 = OpLabel
         %30 = OpPhi %float %26 %14 %29 %28
         %31 = OpFAdd %float %21 %30
               OpReturnValue %31
               OpFunctionEnd

Note that the the unsized.arr[3] access has no bounds check, while the unsized.arr[i] access does. Since it is not known until run time whether 3 is a valid index, both accesses should be checked.

Two factors limit the impact of this bug:

  • The problem is restricted to runtime-sized arrays: the validator performs bounds checks for AccessIndex expressions applied to any type whose length is statically known.
  • We expect that many targets will support a form of robust buffer access that would make bounds checks unnecessary on arrays in the storage storage class, which is the only storage class that can hold dynamically sized arrays.

However, Naga is expected to be used in situations where that kind of robust buffer access is not supported, so this is still important to fix.

@jimblandy jimblandy added kind: bug lang: SPIR-V Vulkan's Shading Language area: naga back-end Outputs of naga shader conversion labels Nov 11, 2021
@kvark

This comment was marked as resolved.

@jimblandy

This comment was marked as resolved.

@cwfitzgerald cwfitzgerald transferred this issue from gfx-rs/naga Oct 25, 2023
@cwfitzgerald cwfitzgerald added naga Shader Translator type: bug Something isn't working and removed kind: bug labels Oct 25, 2023
@teoxoy teoxoy added this to the WebGPU Specification V1 milestone Nov 3, 2023
@jimblandy jimblandy self-assigned this May 20, 2024
@jimblandy jimblandy moved this to In Progress in WebGPU for Firefox Sep 24, 2024
jimblandy added a commit to jimblandy/wgpu that referenced this issue Oct 1, 2024
Do not neglect to apply bounds checks to indexing operations on
runtime-sized arrays, even when they are accessed via an `AccessIndex`
instruction.

Before this commit, `BlockContext::write_expression_pointer` would not
apply bounds checks to `OpAccessChain` indices provided by an
`AccessIndex` instruction, apparently with the rationale that any
out-of-bounds accesses should all have been reported by constant
evaluation.

While it is true that the `index` operand of an `AccessIndex`
expression is known at compile time, and that the WGSL constant
evaluation rules require accesses that can be statically determined to
be out-of-bounds to be shader creation or pipeline creation time
errors, accesses to runtime-sized arrays don't follow this pattern:
even if the index is known, the length with which it must be compared
is not.

Fixes gfx-rs#4441.
jimblandy added a commit to jimblandy/wgpu that referenced this issue Oct 1, 2024
Do not neglect to apply bounds checks to indexing operations on
runtime-sized arrays, even when they are accessed via an `AccessIndex`
instruction.

Before this commit, `BlockContext::write_expression_pointer` would not
apply bounds checks to `OpAccessChain` indices provided by an
`AccessIndex` instruction, apparently with the rationale that any
out-of-bounds accesses should have been reported by constant
evaluation.

While it is true that the `index` operand of an `AccessIndex`
expression is known at compile time, and that the WGSL constant
evaluation rules require accesses that can be statically determined to
be out-of-bounds to be shader creation or pipeline creation time
errors, accesses to runtime-sized arrays don't follow this pattern:
even if the index is known, the length with which it must be compared
is not.

Fixes gfx-rs#4441.
jimblandy added a commit to jimblandy/wgpu that referenced this issue Oct 8, 2024
Do not neglect to apply bounds checks to indexing operations on
runtime-sized arrays, even when they are accessed via an `AccessIndex`
instruction.

Before this commit, `BlockContext::write_expression_pointer` would not
apply bounds checks to `OpAccessChain` indices provided by an
`AccessIndex` instruction, apparently with the rationale that any
out-of-bounds accesses should have been reported by constant
evaluation.

While it is true that the `index` operand of an `AccessIndex`
expression is known at compile time, and that the WGSL constant
evaluation rules require accesses that can be statically determined to
be out-of-bounds to be shader creation or pipeline creation time
errors, accesses to runtime-sized arrays don't follow this pattern:
even if the index is known, the length with which it must be compared
is not.

Fixes gfx-rs#4441.
@github-project-automation github-project-automation bot moved this from In Progress to Done in WebGPU for Firefox Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: naga back-end Outputs of naga shader conversion lang: SPIR-V Vulkan's Shading Language naga Shader Translator type: bug Something isn't working
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

4 participants