Check for types::INVALID in the function signature, resolves
@@ -1838,12 +1838,51 @@ impl<'a> Verifier<'a> {
Ok(())
}
+ fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
+ self.func
+ .signature
+ .params
+ .iter()
+ .enumerate()
+ .filter(|(_, &param)| param.value_type == types::INVALID)
+ .for_each(|(i, _)| {
+ report!(
+ errors,
+ AnyEntity::Function,
+ "Parameter at position {} has an invalid type",
+ i
+ );
+ });
+
+ self.func
+ .signature
+ .returns
+ .iter()
+ .enumerate()
+ .filter(|(_, &ret)| ret.value_type == types::INVALID)
+ .for_each(|(i, _)| {
+ report!(
+ errors,
+ AnyEntity::Function,
+ "Return value at position {} has an invalid type",
+ i
+ )
+ });
+
+ if errors.has_error() {
+ Err(())
+ } else {
+ Ok(())
+ }
+ }
+
pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
self.verify_global_values(errors)?;
self.verify_heaps(errors)?;
self.verify_tables(errors)?;
self.verify_jump_tables(errors)?;
self.typecheck_entry_block_params(errors)?;
+ self.typecheck_function_signature(errors)?;
for ebb in self.func.layout.ebbs() {
for inst in self.func.layout.ebb_insts(ebb) {
@@ -1870,7 +1909,7 @@ mod tests {
use super::{Verifier, VerifierError, VerifierErrors};
use crate::entity::EntityList;
use crate::ir::instructions::{InstructionData, Opcode};
- use crate::ir::Function;
+ use crate::ir::{types, AbiParam, Function};
use crate::settings;
macro_rules! assert_err_with_msg {
@@ -1929,4 +1968,30 @@ mod tests {
assert_err_with_msg!(errors, "instruction format");
}
+
+ #[test]
+ fn test_function_invalid_param() {
+ let mut func = Function::new();
+ func.signature.params.push(AbiParam::new(types::INVALID));
+
+ let mut errors = VerifierErrors::default();
+ let flags = &settings::Flags::new(settings::builder());
+ let verifier = Verifier::new(&func, flags.into());
+
+ let _ = verifier.typecheck_function_signature(&mut errors);
+ assert_err_with_msg!(errors, "Parameter at position 0 has an invalid type");
+ }
+
+ #[test]
+ fn test_function_invalid_return_value() {
+ let mut func = Function::new();
+ func.signature.returns.push(AbiParam::new(types::INVALID));
+
+ let mut errors = VerifierErrors::default();
+ let flags = &settings::Flags::new(settings::builder());
+ let verifier = Verifier::new(&func, flags.into());
+
+ let _ = verifier.typecheck_function_signature(&mut errors);
+ assert_err_with_msg!(errors, "Return value at position 0 has an invalid type");
+ }
}
