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"
[dependencies]
wasmparser = "0.95"
wasm-encoder = "0.20"
wasmparser = "0.202"
wasm-encoder = "0.202"
anyhow = "1.0"
structopt = "0.3"
log = "0.4"
env_logger = "0.9"
env_logger = "0.11"
fxhash = "0.2"
smallvec = "1.7"
rayon = "1.5"
smallvec = "1.13"
rayon = "1.10"
lazy_static = "1.4"
libc = "0.2"
addr2line = "0.19"
addr2line = "0.21"
# For fuzzing only. Versions must match those in fuzz/Cargo.toml.
libfuzzer-sys = { version = "0.4", optional = true }
wasm-smith = { version = "0.8", optional = true }
wasm-smith = { version = "0.202", optional = true }
[features]
default = []

View file

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

View file

@ -96,10 +96,17 @@ fn handle_payload<'a>(
trace!("Wasm parser item: {:?}", payload);
match payload {
Payload::TypeSection(reader) => {
for ty in reader {
let ty = ty?;
let wasmparser::Type::Func(fty) = ty;
module.signatures.push(fty.into());
for rec_group in reader {
for ty in rec_group?.into_types() {
match &ty.composite_type {
wasmparser::CompositeType::Func(fty) => {
module.signatures.push(fty.into());
}
_ => bail!(FrontendError::UnsupportedFeature(
"non-function type in type section".into()
)),
}
}
}
}
Payload::ImportSection(reader) => {
@ -167,7 +174,7 @@ fn handle_payload<'a>(
Payload::TableSection(reader) => {
for table in reader {
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) => {
@ -237,7 +244,7 @@ fn handle_payload<'a>(
}
}
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 {
let subsection = subsection?;
match subsection {
@ -302,12 +309,6 @@ fn handle_payload<'a>(
Payload::ElementSection(reader) => {
for element in reader {
let element = element?;
if element.ty != wasmparser::ValType::FuncRef {
bail!(FrontendError::UnsupportedFeature(format!(
"Unsupported table type: {:?}",
element.ty
)));
}
match &element.kind {
wasmparser::ElementKind::Passive => {}
wasmparser::ElementKind::Declared => {}
@ -315,44 +316,45 @@ fn handle_payload<'a>(
table_index,
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 items = element
.items
.get_items_reader()?
.into_iter()
.collect::<Result<Vec<_>, _>>()?;
let mut funcs = vec![];
for item in items {
let func = match item {
wasmparser::ElementItem::Func(func_idx) => Func::from(func_idx),
_ => bail!(FrontendError::UnsupportedFeature(format!(
"Unsupported element item: {:?}",
item
))),
};
funcs.push(func);
}
match element.items {
wasmparser::ElementItems::Functions(items) => {
let mut funcs = vec![];
for item in items {
let item = item?;
let func = Func::from(item);
funcs.push(func);
}
let table_items = module.tables[table].func_elements.as_mut().unwrap();
let new_size = offset.checked_add(funcs.len()).ok_or_else(|| {
FrontendError::TooLarge(format!(
"Overflowing element offset + length: {} + {}",
offset,
funcs.len()
))
})?;
if new_size > table_items.len() {
static MAX_TABLE: usize = 100_000;
if new_size > MAX_TABLE {
bail!(FrontendError::TooLarge(format!(
"Too many table elements: {:?}",
new_size
)));
let table_items =
module.tables[table].func_elements.as_mut().unwrap();
let new_size =
offset.checked_add(funcs.len()).ok_or_else(|| {
FrontendError::TooLarge(format!(
"Overflowing element offset + length: {} + {}",
offset,
funcs.len()
))
})?;
if new_size > table_items.len() {
static MAX_TABLE: usize = 100_000;
if new_size > MAX_TABLE {
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,
V128,
FuncRef,
TypedFuncRef(bool, u32),
}
impl From<wasmparser::ValType> for Type {
fn from(ty: wasmparser::ValType) -> Self {
@ -19,23 +20,39 @@ impl From<wasmparser::ValType> for Type {
wasmparser::ValType::F32 => Type::F32,
wasmparser::ValType::F64 => Type::F64,
wasmparser::ValType::V128 => Type::V128,
wasmparser::ValType::FuncRef => Type::FuncRef,
_ => panic!("Unsupported type: {:?}", ty),
wasmparser::ValType::Ref(r) => r.into(),
}
}
}
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 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let s = match self {
Type::I32 => "i32",
Type::I64 => "i64",
Type::F32 => "f32",
Type::F64 => "f64",
Type::V128 => "v128",
Type::FuncRef => "funcref",
};
write!(f, "{}", s)
match self {
Type::I32 => write!(f, "i32"),
Type::I64 => write!(f, "i64"),
Type::F32 => write!(f, "f32"),
Type::F64 => write!(f, "f64"),
Type::V128 => write!(f, "v128"),
Type::FuncRef => write!(f, "funcref"),
Type::TypedFuncRef(nullable, idx) => write!(
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::F64 => wasm_encoder::ValType::F64,
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),
}
}
}