Fix br_table validation (#67)
Fixes #63 Fix is simple: all labels refered by the br_table instruction must have same value type (or NoResult in case if they don't have result). So we just take the default label and check other labels against it.
This commit is contained in:
parent
8a96bc2649
commit
7c88c6ad65
|
@ -492,32 +492,39 @@ impl Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_br_table(context: &mut FunctionValidationContext, table: &[u32], default: u32) -> Result<InstructionOutcome, Error> {
|
fn validate_br_table(context: &mut FunctionValidationContext, table: &[u32], default: u32) -> Result<InstructionOutcome, Error> {
|
||||||
let mut required_block_type = None;
|
let required_block_type: BlockType = {
|
||||||
|
|
||||||
{
|
|
||||||
let default_block = context.require_label(default)?;
|
let default_block = context.require_label(default)?;
|
||||||
if default_block.frame_type != BlockFrameType::Loop {
|
let required_block_type = if default_block.frame_type != BlockFrameType::Loop {
|
||||||
required_block_type = Some(default_block.block_type);
|
default_block.block_type
|
||||||
}
|
} else {
|
||||||
|
BlockType::NoResult
|
||||||
|
};
|
||||||
|
|
||||||
for label in table {
|
for label in table {
|
||||||
let label_block = context.require_label(*label)?;
|
let label_block = context.require_label(*label)?;
|
||||||
if label_block.frame_type != BlockFrameType::Loop {
|
let label_block_type = if label_block.frame_type != BlockFrameType::Loop {
|
||||||
if let Some(required_block_type) = required_block_type {
|
label_block.block_type
|
||||||
if required_block_type != label_block.block_type {
|
} else {
|
||||||
return Err(Error(format!("Labels in br_table points to block of different types: {:?} and {:?}", required_block_type, label_block.block_type)));
|
BlockType::NoResult
|
||||||
}
|
};
|
||||||
}
|
if required_block_type != label_block_type {
|
||||||
required_block_type = Some(label_block.block_type);
|
return Err(
|
||||||
|
Error(
|
||||||
|
format!(
|
||||||
|
"Labels in br_table points to block of different types: {:?} and {:?}",
|
||||||
|
required_block_type,
|
||||||
|
label_block.block_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
required_block_type
|
||||||
|
};
|
||||||
|
|
||||||
context.pop_value(ValueType::I32.into())?;
|
context.pop_value(ValueType::I32.into())?;
|
||||||
if let Some(required_block_type) = required_block_type {
|
if let BlockType::Value(value_type) = required_block_type {
|
||||||
if let BlockType::Value(value_type) = required_block_type {
|
context.tee_value(value_type.into())?;
|
||||||
context.tee_value(value_type.into())?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(InstructionOutcome::Unreachable)
|
Ok(InstructionOutcome::Unreachable)
|
||||||
|
|
Loading…
Reference in New Issue