cranelift: Forbid argument extensions for floats and SIMD vectors (#5536)

* fuzzgen: Generate argument extensions only for integer argumetns

* cranelift: Add verifier check for argument extensions
This commit is contained in:
Afonso Bordado
2023-01-10 18:26:30 +00:00
committed by GitHub
parent 23ea435a91
commit 9556cb190f
3 changed files with 74 additions and 32 deletions

View File

@@ -61,9 +61,9 @@ use crate::dbg::DisplayList;
use crate::dominator_tree::DominatorTree; use crate::dominator_tree::DominatorTree;
use crate::entity::SparseSet; use crate::entity::SparseSet;
use crate::flowgraph::{BlockPredecessor, ControlFlowGraph}; use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
use crate::ir;
use crate::ir::entities::AnyEntity; use crate::ir::entities::AnyEntity;
use crate::ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint}; use crate::ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint};
use crate::ir::{self, ArgumentExtension};
use crate::ir::{ use crate::ir::{
types, ArgumentPurpose, Block, Constant, DynamicStackSlot, FuncRef, Function, GlobalValue, types, ArgumentPurpose, Block, Constant, DynamicStackSlot, FuncRef, Function, GlobalValue,
Inst, JumpTable, MemFlags, Opcode, SigRef, StackSlot, Type, Value, ValueDef, ValueList, Inst, JumpTable, MemFlags, Opcode, SigRef, StackSlot, Type, Value, ValueDef, ValueList,
@@ -1648,45 +1648,57 @@ impl<'a> Verifier<'a> {
} }
fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
self.func let params = self
.func
.signature .signature
.params .params
.iter() .iter()
.enumerate() .enumerate()
.filter(|(_, &param)| param.value_type == types::INVALID) .map(|p| (true, p));
.for_each(|(i, _)| { let returns = self
.func
.signature
.returns
.iter()
.enumerate()
.map(|p| (false, p));
for (is_argument, (i, param)) in params.chain(returns) {
let is_return = !is_argument;
let item = if is_argument {
"Parameter"
} else {
"Return value"
};
if param.value_type == types::INVALID {
errors.report(( errors.report((
AnyEntity::Function, AnyEntity::Function,
format!("Parameter at position {} has an invalid type", i), format!("{item} at position {i} has an invalid type"),
)); ));
}); }
self.func if let ArgumentPurpose::StructArgument(_) = param.purpose {
.signature if is_return {
.returns
.iter()
.enumerate()
.filter(|(_, &ret)| ret.value_type == types::INVALID)
.for_each(|(i, _)| {
errors.report(( errors.report((
AnyEntity::Function, AnyEntity::Function,
format!("Return value at position {} has an invalid type", i), format!("{item} at position {i} can't be an struct argument"),
))
});
self.func
.signature
.returns
.iter()
.enumerate()
.for_each(|(i, ret)| {
if let ArgumentPurpose::StructArgument(_) = ret.purpose {
errors.report((
AnyEntity::Function,
format!("Return value at position {} can't be an struct argument", i),
)) ))
} }
}); }
let ty_allows_extension = param.value_type.is_int();
let has_extension = param.extension != ArgumentExtension::None;
if !ty_allows_extension && has_extension {
errors.report((
AnyEntity::Function,
format!(
"{} at position {} has invalid extension {:?}",
item, i, param.extension
),
));
}
}
if errors.has_error() { if errors.has_error() {
Err(()) Err(())

View File

@@ -0,0 +1,26 @@
test verifier
function %float_with_sext(f32 sext) -> f32 { ; error: Parameter at position 0 has invalid extension Sext
block0(v0: f32):
return v0
}
function %float_with_uext(f32 uext) -> f32 { ; error: Parameter at position 0 has invalid extension Uext
block0(v0: f32):
return v0
}
function %float_ret_with_sext(f32) -> f32 sext { ; error: Return value at position 0 has invalid extension Sext
block0(v0: f32):
return v0
}
function %float_ret_with_uext(f32) -> f32 uext { ; error: Return value at position 0 has invalid extension Uext
block0(v0: f32):
return v0
}
function %simd_ext(i32x4 sext) -> i32x4 { ; error: Parameter at position 0 has invalid extension Sext
block0(v0: i32x4):
return v0
}

View File

@@ -1230,10 +1230,14 @@ where
let value_type = self.generate_type()?; let value_type = self.generate_type()?;
// TODO: There are more argument purposes to be explored... // TODO: There are more argument purposes to be explored...
let purpose = ArgumentPurpose::Normal; let purpose = ArgumentPurpose::Normal;
let extension = match self.u.int_in_range(0..=2)? { let extension = if value_type.is_int() {
2 => ArgumentExtension::Sext, *self.u.choose(&[
1 => ArgumentExtension::Uext, ArgumentExtension::Sext,
_ => ArgumentExtension::None, ArgumentExtension::Uext,
ArgumentExtension::None,
])?
} else {
ArgumentExtension::None
}; };
Ok(AbiParam { Ok(AbiParam {