Upgrade to latest wasmparser and wasm_encoder.

This commit is contained in:
Chris Fallin 2024-03-28 13:38:34 -07:00
parent 11992bb124
commit fcbd32e6b4
4 changed files with 99 additions and 68 deletions

View file

@ -7,22 +7,22 @@ license = "Apache-2.0 WITH LLVM-exception"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmparser = "0.95" wasmparser = "0.202"
wasm-encoder = "0.20" wasm-encoder = "0.202"
anyhow = "1.0" anyhow = "1.0"
structopt = "0.3" structopt = "0.3"
log = "0.4" log = "0.4"
env_logger = "0.9" env_logger = "0.11"
fxhash = "0.2" fxhash = "0.2"
smallvec = "1.7" smallvec = "1.13"
rayon = "1.5" rayon = "1.10"
lazy_static = "1.4" lazy_static = "1.4"
libc = "0.2" libc = "0.2"
addr2line = "0.19" addr2line = "0.21"
# For fuzzing only. Versions must match those in fuzz/Cargo.toml. # For fuzzing only. Versions must match those in fuzz/Cargo.toml.
libfuzzer-sys = { version = "0.4", optional = true } libfuzzer-sys = { version = "0.4", optional = true }
wasm-smith = { version = "0.8", optional = true } wasm-smith = { version = "0.202", optional = true }
[features] [features]
default = [] default = []

View file

@ -950,7 +950,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
num_table_imports += 1; num_table_imports += 1;
let table = &module.tables[table]; let table = &module.tables[table];
wasm_encoder::EntityType::Table(wasm_encoder::TableType { wasm_encoder::EntityType::Table(wasm_encoder::TableType {
element_type: wasm_encoder::ValType::from(table.ty), element_type: wasm_encoder::RefType::from(table.ty),
minimum: table minimum: table
.func_elements .func_elements
.as_ref() .as_ref()
@ -1000,7 +1000,7 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
let mut tables = wasm_encoder::TableSection::new(); let mut tables = wasm_encoder::TableSection::new();
for table_data in module.tables.values().skip(num_table_imports) { for table_data in module.tables.values().skip(num_table_imports) {
tables.table(wasm_encoder::TableType { tables.table(wasm_encoder::TableType {
element_type: wasm_encoder::ValType::from(table_data.ty), element_type: wasm_encoder::RefType::from(table_data.ty),
minimum: table_data minimum: table_data
.func_elements .func_elements
.as_ref() .as_ref()
@ -1084,7 +1084,6 @@ pub fn compile(module: &Module<'_>) -> anyhow::Result<Vec<u8>> {
elem.active( elem.active(
Some(table.index() as u32), Some(table.index() as u32),
&wasm_encoder::ConstExpr::i32_const(i as i32), &wasm_encoder::ConstExpr::i32_const(i as i32),
wasm_encoder::ValType::FuncRef,
wasm_encoder::Elements::Functions(&[elt.index() as u32]), wasm_encoder::Elements::Functions(&[elt.index() as u32]),
); );
} }

View file

@ -96,10 +96,17 @@ fn handle_payload<'a>(
trace!("Wasm parser item: {:?}", payload); trace!("Wasm parser item: {:?}", payload);
match payload { match payload {
Payload::TypeSection(reader) => { Payload::TypeSection(reader) => {
for ty in reader { for rec_group in reader {
let ty = ty?; for ty in rec_group?.into_types() {
let wasmparser::Type::Func(fty) = ty; match &ty.composite_type {
module.signatures.push(fty.into()); wasmparser::CompositeType::Func(fty) => {
module.signatures.push(fty.into());
}
_ => bail!(FrontendError::UnsupportedFeature(
"non-function type in type section".into()
)),
}
}
} }
} }
Payload::ImportSection(reader) => { Payload::ImportSection(reader) => {
@ -167,7 +174,7 @@ fn handle_payload<'a>(
Payload::TableSection(reader) => { Payload::TableSection(reader) => {
for table in reader { for table in reader {
let table = table?; let table = table?;
module.frontend_add_table(table.element_type.into(), table.maximum); module.frontend_add_table(table.ty.element_type.into(), table.ty.maximum);
} }
} }
Payload::FunctionSection(reader) => { Payload::FunctionSection(reader) => {
@ -237,7 +244,7 @@ fn handle_payload<'a>(
} }
} }
Payload::CustomSection(reader) if reader.name() == "name" => { Payload::CustomSection(reader) if reader.name() == "name" => {
let name_reader = NameSectionReader::new(reader.data(), reader.data_offset())?; let name_reader = NameSectionReader::new(reader.data(), reader.data_offset());
for subsection in name_reader { for subsection in name_reader {
let subsection = subsection?; let subsection = subsection?;
match subsection { match subsection {
@ -302,12 +309,6 @@ fn handle_payload<'a>(
Payload::ElementSection(reader) => { Payload::ElementSection(reader) => {
for element in reader { for element in reader {
let element = element?; let element = element?;
if element.ty != wasmparser::ValType::FuncRef {
bail!(FrontendError::UnsupportedFeature(format!(
"Unsupported table type: {:?}",
element.ty
)));
}
match &element.kind { match &element.kind {
wasmparser::ElementKind::Passive => {} wasmparser::ElementKind::Passive => {}
wasmparser::ElementKind::Declared => {} wasmparser::ElementKind::Declared => {}
@ -315,44 +316,45 @@ fn handle_payload<'a>(
table_index, table_index,
offset_expr, offset_expr,
} => { } => {
let table = Table::from(*table_index); let table = Table::from(table_index.unwrap_or(0));
let offset = parse_init_expr(&offset_expr)?.unwrap_or(0) as usize; let offset = parse_init_expr(&offset_expr)?.unwrap_or(0) as usize;
let items = element match element.items {
.items wasmparser::ElementItems::Functions(items) => {
.get_items_reader()? let mut funcs = vec![];
.into_iter() for item in items {
.collect::<Result<Vec<_>, _>>()?; let item = item?;
let mut funcs = vec![]; let func = Func::from(item);
for item in items { funcs.push(func);
let func = match item { }
wasmparser::ElementItem::Func(func_idx) => Func::from(func_idx),
_ => bail!(FrontendError::UnsupportedFeature(format!(
"Unsupported element item: {:?}",
item
))),
};
funcs.push(func);
}
let table_items = module.tables[table].func_elements.as_mut().unwrap(); let table_items =
let new_size = offset.checked_add(funcs.len()).ok_or_else(|| { module.tables[table].func_elements.as_mut().unwrap();
FrontendError::TooLarge(format!( let new_size =
"Overflowing element offset + length: {} + {}", offset.checked_add(funcs.len()).ok_or_else(|| {
offset, FrontendError::TooLarge(format!(
funcs.len() "Overflowing element offset + length: {} + {}",
)) offset,
})?; funcs.len()
if new_size > table_items.len() { ))
static MAX_TABLE: usize = 100_000; })?;
if new_size > MAX_TABLE { if new_size > table_items.len() {
bail!(FrontendError::TooLarge(format!( static MAX_TABLE: usize = 100_000;
"Too many table elements: {:?}", if new_size > MAX_TABLE {
new_size bail!(FrontendError::TooLarge(format!(
))); "Too many table elements: {:?}",
new_size
)));
}
table_items.resize(new_size, Func::invalid());
}
table_items[offset..new_size].copy_from_slice(&funcs[..]);
}
wasmparser::ElementItems::Expressions(..) => {
bail!(FrontendError::UnsupportedFeature(
"Expression element items".into()
))
} }
table_items.resize(new_size, Func::invalid());
} }
table_items[offset..new_size].copy_from_slice(&funcs[..]);
} }
} }
} }

View file

@ -10,6 +10,7 @@ pub enum Type {
F64, F64,
V128, V128,
FuncRef, FuncRef,
TypedFuncRef(bool, u32),
} }
impl From<wasmparser::ValType> for Type { impl From<wasmparser::ValType> for Type {
fn from(ty: wasmparser::ValType) -> Self { fn from(ty: wasmparser::ValType) -> Self {
@ -19,23 +20,39 @@ impl From<wasmparser::ValType> for Type {
wasmparser::ValType::F32 => Type::F32, wasmparser::ValType::F32 => Type::F32,
wasmparser::ValType::F64 => Type::F64, wasmparser::ValType::F64 => Type::F64,
wasmparser::ValType::V128 => Type::V128, wasmparser::ValType::V128 => Type::V128,
wasmparser::ValType::FuncRef => Type::FuncRef, wasmparser::ValType::Ref(r) => r.into(),
_ => panic!("Unsupported type: {:?}", ty), }
}
}
impl From<wasmparser::RefType> for Type {
fn from(ty: wasmparser::RefType) -> Self {
assert!(ty.is_func_ref(), "only funcrefs are supported right now");
match ty.type_index() {
Some(idx) => {
let nullable = ty.is_nullable();
Type::TypedFuncRef(nullable, idx.as_module_index().unwrap())
}
None => Type::FuncRef,
} }
} }
} }
impl std::fmt::Display for Type { impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let s = match self { match self {
Type::I32 => "i32", Type::I32 => write!(f, "i32"),
Type::I64 => "i64", Type::I64 => write!(f, "i64"),
Type::F32 => "f32", Type::F32 => write!(f, "f32"),
Type::F64 => "f64", Type::F64 => write!(f, "f64"),
Type::V128 => "v128", Type::V128 => write!(f, "v128"),
Type::FuncRef => "funcref", Type::FuncRef => write!(f, "funcref"),
}; Type::TypedFuncRef(nullable, idx) => write!(
write!(f, "{}", s) f,
"funcref({}, {})",
if *nullable { "null" } else { "not_null" },
idx
),
}
} }
} }
@ -47,7 +64,20 @@ impl From<Type> for wasm_encoder::ValType {
Type::F32 => wasm_encoder::ValType::F32, Type::F32 => wasm_encoder::ValType::F32,
Type::F64 => wasm_encoder::ValType::F64, Type::F64 => wasm_encoder::ValType::F64,
Type::V128 => wasm_encoder::ValType::V128, Type::V128 => wasm_encoder::ValType::V128,
Type::FuncRef => wasm_encoder::ValType::FuncRef, Type::FuncRef | Type::TypedFuncRef(..) => wasm_encoder::ValType::Ref(ty.into()),
}
}
}
impl From<Type> for wasm_encoder::RefType {
fn from(ty: Type) -> wasm_encoder::RefType {
match ty {
Type::FuncRef => wasm_encoder::RefType::FUNCREF,
Type::TypedFuncRef(nullable, idx) => wasm_encoder::RefType {
nullable,
heap_type: wasm_encoder::HeapType::Concrete(idx),
},
_ => panic!("Cannot convert {:?} into reftype", ty),
} }
} }
} }