From 2d521291f4aa1e4b3a8ef736bb0847be3b5df1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Tue, 31 Jan 2023 14:49:39 +0000 Subject: [PATCH 1/2] valid: Fix handle dependency validation The handle dependency validation code was using the handle's index directly while trying to erase the handle type. This would cause the validator to crash while processing the first handle of the arena since it would be trying to construct a `NonZeroU32` with a zero. This commit fixes the issue by adding 1 to the index which not only fixes this panic but also makes so that the created Handle is equal to the passed handle (minus the type that was erased) It also fixes the error message not including the subject's kind --- src/valid/handles.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/valid/handles.rs b/src/valid/handles.rs index 5b3375a873..062624daf1 100644 --- a/src/valid/handles.rs +++ b/src/valid/handles.rs @@ -532,8 +532,8 @@ pub enum InvalidHandleError { #[derive(Clone, Debug, thiserror::Error)] #[error( - "{subject:?} of kind depends on {depends_on:?} of kind {depends_on_kind}, which has not been \ - processed yet" + "{subject:?} of kind {subject_kind:?} depends on {depends_on:?} of kind {depends_on_kind}, \ + which has not been processed yet" )] pub struct FwdDepError { // This error is used for many `Handle` types, but there's no point in making this generic, so @@ -580,7 +580,7 @@ impl Handle { Ok(self) } else { let erase_handle_type = |handle: Handle<_>| { - Handle::new(NonZeroU32::new(handle.index().try_into().unwrap()).unwrap()) + Handle::new(NonZeroU32::new((handle.index() + 1).try_into().unwrap()).unwrap()) }; Err(FwdDepError { subject: erase_handle_type(self), From fd636800161f473734017d0a8cfa825e92acf272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Tue, 31 Jan 2023 14:58:36 +0000 Subject: [PATCH 2/2] valid: Check dependencies between functions calls This commit enforces the forward dependency rules on the IR across functions and their calls, this fixes a crash in a later stage of the validator. --- src/valid/handles.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/valid/handles.rs b/src/valid/handles.rs index 062624daf1..be87e54d48 100644 --- a/src/valid/handles.rs +++ b/src/valid/handles.rs @@ -131,7 +131,7 @@ impl super::Validator { } } - let validate_function = |function: &_| -> Result<_, InvalidHandleError> { + let validate_function = |function_handle, function: &_| -> Result<_, InvalidHandleError> { let &crate::Function { name: _, ref arguments, @@ -175,6 +175,7 @@ impl super::Validator { local_variables, global_variables, functions, + function_handle, )?; } @@ -184,11 +185,11 @@ impl super::Validator { }; for entry_point in entry_points.iter() { - validate_function(&entry_point.function)?; + validate_function(None, &entry_point.function)?; } - for (_function_handle, function) in functions.iter() { - validate_function(function)?; + for (function_handle, function) in functions.iter() { + validate_function(Some(function_handle), function)?; } Ok(()) @@ -229,6 +230,8 @@ impl super::Validator { local_variables: &Arena, global_variables: &Arena, functions: &Arena, + // The handle of the current function or `None` if it's an entry point + current_function: Option>, ) -> Result<(), InvalidHandleError> { let validate_constant = |handle| Self::validate_constant_handle(handle, constants); let validate_type = |handle| Self::validate_type_handle(handle, types); @@ -373,6 +376,9 @@ impl super::Validator { } crate::Expression::CallResult(function) => { Self::validate_function_handle(function, functions)?; + if let Some(handle) = current_function { + handle.check_dep(function)?; + } } crate::Expression::AtomicResult { .. } => (), crate::Expression::ArrayLength(array) => {