Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,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<function>` 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

Expand Down
9 changes: 8 additions & 1 deletion naga/src/valid/expression.rs
Original file line number Diff line number Diff line change
@@ -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 _,
Expand Down Expand Up @@ -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<crate::Expression>),
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions naga/src/valid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
26 changes: 26 additions & 0 deletions naga/src/valid/zero_value.rs
Original file line number Diff line number Diff line change
@@ -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 dynamically-sized array is not allowed")]
DynamicallySizedArray,
}

pub fn validate_zero_value(
self_ty_handle: Handle<crate::Type>,
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 dynamically-sized array");
Err(ZeroValueError::DynamicallySizedArray)
}
_ => Ok(()),
}
}
29 changes: 29 additions & 0 deletions naga/tests/naga/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<f32>();
}
"#;
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::DynamicallySizedArray
)
}
)
})
));
}

#[test]
fn arity_check() {
use ir::MathFunction as Mf;
Expand Down