Reject constant/initializer cycles in handle validation.

This commit is contained in:
Jim Blandy
2023-06-30 16:31:12 -07:00
parent a3dff6b840
commit 63bc66bc70

View File

@@ -216,6 +216,7 @@ impl super::Validator {
crate::Expression::Literal(_) => {}
crate::Expression::Constant(constant) => {
validate_constant(constant)?;
handle.check_dep(constants[constant].init)?;
}
crate::Expression::ZeroValue(ty) => {
validate_type(ty)?;
@@ -661,3 +662,51 @@ impl<T> crate::arena::Range<T> {
arena.check_contains_range(self)
}
}
#[test]
#[cfg(feature = "validate")]
fn constant_deps() {
use crate::{Constant, Expression, Literal, Span, Type, TypeInner};
let nowhere = Span::default();
let mut types = UniqueArena::new();
let mut const_exprs = Arena::new();
let mut fun_exprs = Arena::new();
let mut constants = Arena::new();
let i32_handle = types.insert(
Type {
name: None,
inner: TypeInner::Scalar {
kind: crate::ScalarKind::Sint,
width: 4,
},
},
nowhere,
);
// Construct a self-referential constant by misusing a handle to
// fun_exprs as a constant initializer.
let fun_expr = fun_exprs.append(Expression::Literal(Literal::I32(42)), nowhere);
let self_referential_const = constants.append(
Constant {
name: None,
r#override: crate::Override::None,
ty: i32_handle,
init: fun_expr,
},
nowhere,
);
let _self_referential_expr =
const_exprs.append(Expression::Constant(self_referential_const), nowhere);
for handle_and_expr in const_exprs.iter() {
assert!(super::Validator::validate_const_expression_handles(
handle_and_expr,
&constants,
&types,
)
.is_err());
}
}