From 5d0e70e79e8981444a26ca5b2e17f35e41d8ea93 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 8 Oct 2025 19:35:08 -0700 Subject: [PATCH] Fix divide by zero We assumed every array/vector/matrix element has a non-zero stride, but `[()]` inside `BitSlice` produced a zero stride which is divide by zero. Fixes https://github.com/Rust-GPU/rust-gpu/issues/424. --- .../src/builder/builder_methods.rs | 14 ++++++++++++-- tests/compiletests/ui/lang/core/issue-424.rs | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 tests/compiletests/ui/lang/core/issue-424.rs diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 8e7fc3a727..eaa59bfef3 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -767,8 +767,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let stride = ty_kind.sizeof(self)?; ty_size = MaybeSized::Sized(stride); - indices.push((offset.bytes() / stride.bytes()).try_into().ok()?); - offset = Size::from_bytes(offset.bytes() % stride.bytes()); + if stride == Size::ZERO { + if offset != Size::ZERO { + trace!("zero-sized element with non-zero offset: {:?}", offset); + return None; + } + + indices.push(0); + offset = Size::ZERO; + } else { + indices.push((offset.bytes() / stride.bytes()).try_into().ok()?); + offset = Size::from_bytes(offset.bytes() % stride.bytes()); + } } _ => { trace!("recovering access chain from SOMETHING ELSE, RETURNING NONE"); diff --git a/tests/compiletests/ui/lang/core/issue-424.rs b/tests/compiletests/ui/lang/core/issue-424.rs new file mode 100644 index 0000000000..d37683126c --- /dev/null +++ b/tests/compiletests/ui/lang/core/issue-424.rs @@ -0,0 +1,15 @@ +// build-pass + +#![no_std] + +use core::marker::PhantomData; +use spirv_std::spirv; + +pub struct BitSlice { + _ord: PhantomData, + _typ: PhantomData<[T]>, + _mem: [()], +} + +#[spirv(compute(threads(1)))] +pub fn issue424() {}