From f82e1ef4c9b66972e370c18e781f8190258bfdf3 Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Tue, 16 Dec 2025 17:39:08 +0100 Subject: [PATCH 1/7] fix(naga): crash on zero value of runtime-sized array --- naga/src/valid/expression.rs | 9 ++++++++- naga/src/valid/mod.rs | 2 ++ naga/src/valid/zero_value.rs | 26 ++++++++++++++++++++++++++ naga/tests/naga/validation.rs | 29 +++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 naga/src/valid/zero_value.rs diff --git a/naga/src/valid/expression.rs b/naga/src/valid/expression.rs index 68023b5bf01..43039c3738c 100644 --- a/naga/src/valid/expression.rs +++ b/naga/src/valid/expression.rs @@ -1,5 +1,6 @@ use super::{compose::validate_compose, FunctionInfo, ModuleInfo, ShaderStages, TypeFlags}; use crate::arena::UniqueArena; +use crate::valid::zero_value::validate_zero_value; use crate::{ arena::Handle, proc::OverloadSet as _, @@ -36,6 +37,8 @@ pub enum ExpressionError { #[error(transparent)] Compose(#[from] super::ComposeError), #[error(transparent)] + ZeroValue(#[from] super::ZeroValueError), + #[error(transparent)] IndexableLength(#[from] IndexableLengthError), #[error("Operation {0:?} can't work with {1:?}")] InvalidUnaryOperandType(crate::UnaryOperator, Handle), @@ -375,7 +378,11 @@ impl super::Validator { self.validate_literal(literal)?; ShaderStages::all() } - E::Constant(_) | E::Override(_) | E::ZeroValue(_) => ShaderStages::all(), + E::Constant(_) | E::Override(_) => ShaderStages::all(), + E::ZeroValue(ty) => { + validate_zero_value(ty, module.to_ctx())?; + ShaderStages::all() + } E::Compose { ref components, ty } => { validate_compose( ty, diff --git a/naga/src/valid/mod.rs b/naga/src/valid/mod.rs index 43103188a56..2e704c1914c 100644 --- a/naga/src/valid/mod.rs +++ b/naga/src/valid/mod.rs @@ -9,6 +9,7 @@ mod function; mod handles; mod interface; mod r#type; +mod zero_value; use alloc::{boxed::Box, string::String, vec, vec::Vec}; use core::ops; @@ -32,6 +33,7 @@ pub use expression::{ConstExpressionError, ExpressionError}; pub use function::{CallError, FunctionError, LocalVariableError, SubgroupError}; pub use interface::{EntryPointError, GlobalVariableError, VaryingError}; pub use r#type::{Disalignment, ImmediateError, TypeError, TypeFlags, WidthError}; +pub use zero_value::ZeroValueError; use self::handles::InvalidHandleError; diff --git a/naga/src/valid/zero_value.rs b/naga/src/valid/zero_value.rs new file mode 100644 index 00000000000..d570bbccd0e --- /dev/null +++ b/naga/src/valid/zero_value.rs @@ -0,0 +1,26 @@ +use crate::arena::Handle; + +#[derive(Clone, Debug, thiserror::Error)] +#[cfg_attr(test, derive(PartialEq))] +pub enum ZeroValueError { + #[error("ZeroValue construction of runtime-sized array is not allowed")] + RuntimeSizedArray, +} + +pub fn validate_zero_value( + self_ty_handle: Handle, + gctx: crate::proc::GlobalCtx, +) -> Result<(), ZeroValueError> { + use crate::TypeInner as Ti; + match gctx.types[self_ty_handle].inner { + Ti::Array { + base: _, + size: crate::ArraySize::Dynamic, + stride: _, + } => { + log::error!("Constructing zero value of runtime-sized array"); + Err(ZeroValueError::RuntimeSizedArray) + } + _ => Ok(()), + } +} diff --git a/naga/tests/naga/validation.rs b/naga/tests/naga/validation.rs index 78d5ff19f79..789c3a1ec20 100644 --- a/naga/tests/naga/validation.rs +++ b/naga/tests/naga/validation.rs @@ -727,6 +727,35 @@ fn bad_texture_dimensions_level() { assert!(validate("1").is_ok()); } +#[test] +fn zero_value_dyn_array_error() { + let source = r#" + @compute @workgroup_size(1) + fn main() { + let a = array(); + } + "#; + let module = naga::front::wgsl::parse_str(source).expect("module should parse"); + let err = valid::Validator::new(Default::default(), valid::Capabilities::all()) + .validate(&module) + .map_err(|err| err.into_inner()); // discard spans + assert!(matches!( + err, + Err(naga::valid::ValidationError::EntryPoint { + stage: _, + name: _, + source: naga::valid::EntryPointError::Function( + naga::valid::FunctionError::Expression { + handle: _, + source: naga::valid::ExpressionError::ZeroValue( + naga::valid::ZeroValueError::RuntimeSizedArray + ) + } + ) + }) + )); +} + #[test] fn arity_check() { use ir::MathFunction as Mf; From cf02424c9888ad8ecc610d99948a32db2f5cbfdd Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Wed, 17 Dec 2025 12:03:22 +0100 Subject: [PATCH 2/7] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73802dd8408..bb8eab128c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -250,6 +250,7 @@ By @cwfitzgerald in [#8609](https://github.com/gfx-rs/wgpu/pull/8609). - Prevent UB with invalid ray query calls on spirv. By @Vecvec in [#8390](https://github.com/gfx-rs/wgpu/pull/8390). - Update the set of binding_array capabilities. In most cases, they are set automatically from `wgpu` features, and this change should not be user-visible. By @andyleiserson in [#8671](https://github.com/gfx-rs/wgpu/pull/8671). - Naga now accepts the `var` syntax for declaring local variables. By @andyleiserson in [#8710](https://github.com/gfx-rs/wgpu/pull/8710). +- Fix crash when constructing the zero value of a dynamically sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). ### Bug Fixes From df2ff7426c6b81b649b8e3d8669456d8d8e447f9 Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Wed, 17 Dec 2025 12:12:38 +0100 Subject: [PATCH 3/7] Make wording consistent --- naga/src/valid/zero_value.rs | 8 ++++---- naga/tests/naga/validation.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/naga/src/valid/zero_value.rs b/naga/src/valid/zero_value.rs index d570bbccd0e..b398abeb448 100644 --- a/naga/src/valid/zero_value.rs +++ b/naga/src/valid/zero_value.rs @@ -3,8 +3,8 @@ use crate::arena::Handle; #[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pub enum ZeroValueError { - #[error("ZeroValue construction of runtime-sized array is not allowed")] - RuntimeSizedArray, + #[error("ZeroValue construction of dynamically-sized array is not allowed")] + DynamicallySizedArray, } pub fn validate_zero_value( @@ -18,8 +18,8 @@ pub fn validate_zero_value( size: crate::ArraySize::Dynamic, stride: _, } => { - log::error!("Constructing zero value of runtime-sized array"); - Err(ZeroValueError::RuntimeSizedArray) + log::error!("Constructing zero value of dynamically-sized array"); + Err(ZeroValueError::DynamicallySizedArray) } _ => Ok(()), } diff --git a/naga/tests/naga/validation.rs b/naga/tests/naga/validation.rs index 789c3a1ec20..66f83dbe3dd 100644 --- a/naga/tests/naga/validation.rs +++ b/naga/tests/naga/validation.rs @@ -748,7 +748,7 @@ fn zero_value_dyn_array_error() { naga::valid::FunctionError::Expression { handle: _, source: naga::valid::ExpressionError::ZeroValue( - naga::valid::ZeroValueError::RuntimeSizedArray + naga::valid::ZeroValueError::DynamicallySizedArray ) } ) From 0ddc21986d05e67fde09d1229450b44286989e96 Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Tue, 6 Jan 2026 17:27:49 +0100 Subject: [PATCH 4/7] rename `dynamically -> runtime` --- CHANGELOG.md | 2 +- naga/src/valid/zero_value.rs | 8 ++++---- naga/tests/naga/validation.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c4b7b8b34..1ce304c3772 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -383,7 +383,7 @@ By @cwfitzgerald in [#8609](https://github.com/gfx-rs/wgpu/pull/8609). - Prevent UB with invalid ray query calls on spirv. By @Vecvec in [#8390](https://github.com/gfx-rs/wgpu/pull/8390). - Update the set of binding_array capabilities. In most cases, they are set automatically from `wgpu` features, and this change should not be user-visible. By @andyleiserson in [#8671](https://github.com/gfx-rs/wgpu/pull/8671). - Naga now accepts the `var` syntax for declaring local variables. By @andyleiserson in [#8710](https://github.com/gfx-rs/wgpu/pull/8710). -- Fix crash when constructing the zero value of a dynamically sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). +- Fix crash when constructing the zero value of a runtime-sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). ### Bug Fixes diff --git a/naga/src/valid/zero_value.rs b/naga/src/valid/zero_value.rs index b398abeb448..d570bbccd0e 100644 --- a/naga/src/valid/zero_value.rs +++ b/naga/src/valid/zero_value.rs @@ -3,8 +3,8 @@ use crate::arena::Handle; #[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pub enum ZeroValueError { - #[error("ZeroValue construction of dynamically-sized array is not allowed")] - DynamicallySizedArray, + #[error("ZeroValue construction of runtime-sized array is not allowed")] + RuntimeSizedArray, } pub fn validate_zero_value( @@ -18,8 +18,8 @@ pub fn validate_zero_value( size: crate::ArraySize::Dynamic, stride: _, } => { - log::error!("Constructing zero value of dynamically-sized array"); - Err(ZeroValueError::DynamicallySizedArray) + log::error!("Constructing zero value of runtime-sized array"); + Err(ZeroValueError::RuntimeSizedArray) } _ => Ok(()), } diff --git a/naga/tests/naga/validation.rs b/naga/tests/naga/validation.rs index 66f83dbe3dd..789c3a1ec20 100644 --- a/naga/tests/naga/validation.rs +++ b/naga/tests/naga/validation.rs @@ -748,7 +748,7 @@ fn zero_value_dyn_array_error() { naga::valid::FunctionError::Expression { handle: _, source: naga::valid::ExpressionError::ZeroValue( - naga::valid::ZeroValueError::DynamicallySizedArray + naga::valid::ZeroValueError::RuntimeSizedArray ) } ) From 3609b2341312cb6d11744f6765e03fc2a059baa3 Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Tue, 6 Jan 2026 17:44:14 +0100 Subject: [PATCH 5/7] `zero_value.rs -> expression/builtin.rs` --- naga/src/valid/expression.rs | 4 +++- naga/src/valid/{zero_value.rs => expression/builtin.rs} | 0 naga/src/valid/mod.rs | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) rename naga/src/valid/{zero_value.rs => expression/builtin.rs} (100%) diff --git a/naga/src/valid/expression.rs b/naga/src/valid/expression.rs index f6e0cc0576f..bf5a265c11b 100644 --- a/naga/src/valid/expression.rs +++ b/naga/src/valid/expression.rs @@ -1,12 +1,14 @@ use super::{compose::validate_compose, FunctionInfo, ModuleInfo, ShaderStages, TypeFlags}; use crate::arena::UniqueArena; -use crate::valid::zero_value::validate_zero_value; +use crate::valid::expression::builtin::validate_zero_value; use crate::{ arena::Handle, proc::OverloadSet as _, proc::{IndexableLengthError, ResolveError}, }; +pub mod builtin; + #[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pub enum ExpressionError { diff --git a/naga/src/valid/zero_value.rs b/naga/src/valid/expression/builtin.rs similarity index 100% rename from naga/src/valid/zero_value.rs rename to naga/src/valid/expression/builtin.rs diff --git a/naga/src/valid/mod.rs b/naga/src/valid/mod.rs index c3e7592a242..984a47262b5 100644 --- a/naga/src/valid/mod.rs +++ b/naga/src/valid/mod.rs @@ -9,7 +9,6 @@ mod function; mod handles; mod interface; mod r#type; -mod zero_value; use alloc::{boxed::Box, string::String, vec, vec::Vec}; use core::ops; @@ -28,12 +27,12 @@ use crate::{ use crate::span::{AddSpan as _, WithSpan}; pub use analyzer::{ExpressionInfo, FunctionInfo, GlobalUse, Uniformity, UniformityRequirements}; pub use compose::ComposeError; +pub use expression::builtin::ZeroValueError; pub use expression::{check_literal_value, LiteralError}; pub use expression::{ConstExpressionError, ExpressionError}; pub use function::{CallError, FunctionError, LocalVariableError, SubgroupError}; pub use interface::{EntryPointError, GlobalVariableError, VaryingError}; pub use r#type::{Disalignment, ImmediateError, TypeError, TypeFlags, WidthError}; -pub use zero_value::ZeroValueError; use self::handles::InvalidHandleError; From 6fae90e3476b025ad04547fac96abbab23d6dd17 Mon Sep 17 00:00:00 2001 From: Moritz Zielke Date: Tue, 6 Jan 2026 17:54:20 +0100 Subject: [PATCH 6/7] Move changelog entry to `unreleased` section --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ce304c3772..ff87ac24f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,10 @@ Bottom level categories: - `DisplayHandle` should now be passed to `InstanceDescriptor` for correct EGL initialization on Wayland. By @MarijnS95 in [#8012](https://github.com/gfx-rs/wgpu/pull/8012) Note that the existing workaround to create surfaces before the adapter is no longer valid. +#### naga + +- Fix crash when constructing the zero value of a runtime-sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). + ### Documentation #### General @@ -383,7 +387,6 @@ By @cwfitzgerald in [#8609](https://github.com/gfx-rs/wgpu/pull/8609). - Prevent UB with invalid ray query calls on spirv. By @Vecvec in [#8390](https://github.com/gfx-rs/wgpu/pull/8390). - Update the set of binding_array capabilities. In most cases, they are set automatically from `wgpu` features, and this change should not be user-visible. By @andyleiserson in [#8671](https://github.com/gfx-rs/wgpu/pull/8671). - Naga now accepts the `var` syntax for declaring local variables. By @andyleiserson in [#8710](https://github.com/gfx-rs/wgpu/pull/8710). -- Fix crash when constructing the zero value of a runtime-sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). ### Bug Fixes From 47d78621e39e0b1c3d273e92d389ff96aba58596 Mon Sep 17 00:00:00 2001 From: Andy Leiserson Date: Tue, 6 Jan 2026 17:31:14 -0800 Subject: [PATCH 7/7] Slightly reword changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff87ac24f6b..e3a0b25ee95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ Bottom level categories: #### naga -- Fix crash when constructing the zero value of a runtime-sized array. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). +- Reject zero-value construction of a runtime-sized array with a validation error. Previously it would crash in the HLSL backend. By @mooori in [#8741](https://github.com/gfx-rs/wgpu/pull/8741). ### Documentation