From ec5ac3cb11dcb49632ffd0605fa1d5095fd438d0 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 29 Dec 2023 00:52:53 -0500 Subject: [PATCH 01/10] merges --- src/module/mod.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/module/mod.rs b/src/module/mod.rs index 881b30f9..58b9689d 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -128,9 +128,20 @@ impl Module { ModuleConfig::new().parse(wasm) } + /// Merge a module from the in-memory wasm buffer with the default configuration + pub fn merge_buffer(&mut self, wasm: &[u8]) -> Result<()>{ + return Self::parse_in(wasm, &ModuleConfig::default(), self); + } + fn parse(wasm: &[u8], config: &ModuleConfig) -> Result { let mut ret = Module::default(); ret.config = config.clone(); + Self::parse_in(wasm, config, &mut ret)?; + return Ok(ret); + } + fn parse_in(wasm: &[u8], config: &ModuleConfig, ret: &mut Module) -> Result<()> { + // let mut ret = Module::default(); + // ret.config = config.clone(); let mut indices = IndicesToIds::default(); let mut validator = Validator::new(); validator.wasm_features(WasmFeatures { @@ -307,11 +318,11 @@ impl Module { .add_processed_by("walrus", env!("CARGO_PKG_VERSION")); if let Some(on_parse) = &config.on_parse { - on_parse(&mut ret, &indices)?; + on_parse(ret, &indices)?; } log::debug!("parse complete"); - Ok(ret) + Ok(()) } /// Emit this module into a `.wasm` file at the given path. From 66b1c0ef0b6cbde62f2f80392fe33d2cd3230b82 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 29 Dec 2023 00:58:33 -0500 Subject: [PATCH 02/10] rustfmt and config method --- src/module/config.rs | 6 ++++++ src/module/mod.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/module/config.rs b/src/module/config.rs index 66470a65..cefeaa50 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -208,6 +208,12 @@ impl ModuleConfig { Module::parse(wasm, self) } + /// Parses an in-memory WebAssembly file into an existing `Module` using this + /// configuration. + pub fn parse_into(&self, wasm: &[u8], pre: &mut Module) -> Result<()> { + Module::parse_in(wasm, self, pre) + } + /// Parses a WebAssembly file into a `Module` using this configuration. pub fn parse_file

(&self, path: P) -> Result where diff --git a/src/module/mod.rs b/src/module/mod.rs index 58b9689d..f4e4e63f 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -129,7 +129,7 @@ impl Module { } /// Merge a module from the in-memory wasm buffer with the default configuration - pub fn merge_buffer(&mut self, wasm: &[u8]) -> Result<()>{ + pub fn merge_buffer(&mut self, wasm: &[u8]) -> Result<()> { return Self::parse_in(wasm, &ModuleConfig::default(), self); } From 3fe6cb9c831d574186127a79e43513f3e7d033ef Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 29 Dec 2023 09:57:05 -0500 Subject: [PATCH 03/10] start stuff --- src/module/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/module/mod.rs b/src/module/mod.rs index f4e4e63f..c2cced73 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -15,6 +15,7 @@ mod producers; mod tables; mod types; +use crate::FunctionBuilder; use crate::emit::{Emit, EmitContext, IdsToIndices}; use crate::error::Result; pub use crate::ir::InstrLocId; @@ -142,6 +143,7 @@ impl Module { fn parse_in(wasm: &[u8], config: &ModuleConfig, ret: &mut Module) -> Result<()> { // let mut ret = Module::default(); // ret.config = config.clone(); + let old_start = ret.start.take(); let mut indices = IndicesToIds::default(); let mut validator = Validator::new(); validator.wasm_features(WasmFeatures { @@ -317,6 +319,16 @@ impl Module { ret.producers .add_processed_by("walrus", env!("CARGO_PKG_VERSION")); + match ret.start{ + Some(a) => if let Some(r) = old_start{ + let mut new_builder = FunctionBuilder::new(&mut ret.types, &[], &[]); + new_builder.func_body().call(r).call(a).return_(); + let new = new_builder.local_func(vec![]); + let new = ret.funcs.add_local(new); + ret.start = Some(new); + }, + None => ret.start = old_start, + } if let Some(on_parse) = &config.on_parse { on_parse(ret, &indices)?; } From 8ecb9fdfbee6f89252c66968dfc06788cc9fa9b8 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 29 Dec 2023 10:09:07 -0500 Subject: [PATCH 04/10] optionally not read dwarf --- src/module/config.rs | 9 +++++++++ src/module/mod.rs | 28 +++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/module/config.rs b/src/module/config.rs index cefeaa50..4f97640a 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -18,6 +18,7 @@ pub struct ModuleConfig { pub(crate) on_parse: Option Result<()> + Sync + Send + 'static>>, pub(crate) on_instr_loc: Option InstrLocId + Sync + Send + 'static>>, + pub(crate) no_read_dwarf: bool, } impl Clone for ModuleConfig { @@ -32,6 +33,7 @@ impl Clone for ModuleConfig { skip_producers_section: self.skip_producers_section, skip_name_section: self.skip_name_section, preserve_code_transform: self.preserve_code_transform, + no_read_dwarf: self.no_read_dwarf, // ... and this is left empty. on_parse: None, @@ -54,6 +56,7 @@ impl fmt::Debug for ModuleConfig { ref preserve_code_transform, ref on_parse, ref on_instr_loc, + ref no_read_dwarf, } = self; f.debug_struct("ModuleConfig") @@ -69,6 +72,7 @@ impl fmt::Debug for ModuleConfig { .field("preserve_code_transform", preserve_code_transform) .field("on_parse", &on_parse.as_ref().map(|_| "..")) .field("on_instr_loc", &on_instr_loc.as_ref().map(|_| "..")) + .field("no_read_dwarf", no_read_dwarf) .finish() } } @@ -79,6 +83,11 @@ impl ModuleConfig { ModuleConfig::default() } + /// Sets a flag to whether DWARF debug sections are read for this module. + pub fn read_dwarf(&mut self, dw: bool) -> &mut ModuleConfig{ + self.no_read_dwarf = !dw; + return self; + } /// Sets a flag to whether DWARF debug sections are generated for this /// module. /// diff --git a/src/module/mod.rs b/src/module/mod.rs index c2cced73..0e902625 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -15,7 +15,6 @@ mod producers; mod tables; mod types; -use crate::FunctionBuilder; use crate::emit::{Emit, EmitContext, IdsToIndices}; use crate::error::Result; pub use crate::ir::InstrLocId; @@ -39,6 +38,7 @@ pub use crate::module::producers::ModuleProducers; pub use crate::module::tables::{ModuleTables, Table, TableId}; pub use crate::module::types::ModuleTypes; use crate::parse::IndicesToIds; +use crate::FunctionBuilder; use anyhow::{bail, Context}; use id_arena::Id; use log::warn; @@ -312,21 +312,23 @@ impl Module { config.on_instr_loc.as_ref().map(|f| f.as_ref()), ) .context("failed to parse code section")?; - - ret.parse_debug_sections(debug_sections) - .context("failed to parse debug data section")?; - + if !config.no_read_dwarf { + ret.parse_debug_sections(debug_sections) + .context("failed to parse debug data section")?; + } ret.producers .add_processed_by("walrus", env!("CARGO_PKG_VERSION")); - match ret.start{ - Some(a) => if let Some(r) = old_start{ - let mut new_builder = FunctionBuilder::new(&mut ret.types, &[], &[]); - new_builder.func_body().call(r).call(a).return_(); - let new = new_builder.local_func(vec![]); - let new = ret.funcs.add_local(new); - ret.start = Some(new); - }, + match ret.start { + Some(a) => { + if let Some(r) = old_start { + let mut new_builder = FunctionBuilder::new(&mut ret.types, &[], &[]); + new_builder.func_body().call(r).call(a).return_(); + let new = new_builder.local_func(vec![]); + let new = ret.funcs.add_local(new); + ret.start = Some(new); + } + } None => ret.start = old_start, } if let Some(on_parse) = &config.on_parse { From 2bff359bef27f547ac0e290b1ae6fcb7679e4724 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 29 Dec 2023 10:15:02 -0500 Subject: [PATCH 05/10] rustfmt --- src/module/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module/config.rs b/src/module/config.rs index 4f97640a..09eaf507 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -84,7 +84,7 @@ impl ModuleConfig { } /// Sets a flag to whether DWARF debug sections are read for this module. - pub fn read_dwarf(&mut self, dw: bool) -> &mut ModuleConfig{ + pub fn read_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { self.no_read_dwarf = !dw; return self; } From 94ec3c541a011c569b2d39add96b0fda30b01165 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Sat, 30 Dec 2023 11:46:15 -0500 Subject: [PATCH 06/10] fixup funs --- src/module/functions/mod.rs | 2 +- src/module/imports.rs | 1 + src/parse.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/module/functions/mod.rs b/src/module/functions/mod.rs index 530ce720..d86ad6d1 100644 --- a/src/module/functions/mod.rs +++ b/src/module/functions/mod.rs @@ -350,7 +350,7 @@ impl Module { // necessary and it's a bottleneck! let mut bodies = Vec::with_capacity(functions.len()); for (i, (body, mut validator)) in functions.into_iter().enumerate() { - let index = (num_imports + i) as u32; + let index = (indices.num_fun_imports + i) as u32; let id = indices.get_func(index)?; let ty = match self.funcs.arena[id].kind { FunctionKind::Uninitialized(ty) => ty, diff --git a/src/module/imports.rs b/src/module/imports.rs index e7e02289..868bd5d5 100644 --- a/src/module/imports.rs +++ b/src/module/imports.rs @@ -160,6 +160,7 @@ impl Module { entry.field.expect("module linking not supported"), ty, ); + ids.num_fun_imports += 1; ids.push_func(id.0); } wasmparser::ImportSectionEntryType::Table(t) => { diff --git a/src/parse.rs b/src/parse.rs index 77195e38..7d5eb92d 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -26,6 +26,7 @@ pub struct IndicesToIds { elements: Vec, data: Vec, locals: IdHashMap>, + pub(crate) num_fun_imports: usize, } macro_rules! define_push_get { From 5276c4af84947e250733c105ccea67ea2bbbc0e2 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Sat, 30 Dec 2023 11:49:52 -0500 Subject: [PATCH 07/10] counters --- src/module/imports.rs | 3 +++ src/parse.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/module/imports.rs b/src/module/imports.rs index 868bd5d5..bc5e0909 100644 --- a/src/module/imports.rs +++ b/src/module/imports.rs @@ -172,6 +172,7 @@ impl Module { t.maximum, ty, ); + ids.num_table_imports += 1; ids.push_table(id.0); } wasmparser::ImportSectionEntryType::Memory(m) => { @@ -185,6 +186,7 @@ impl Module { m.initial as u32, m.maximum.map(|m| m as u32), ); + ids.num_mem_imports += 1; ids.push_memory(id.0); } wasmparser::ImportSectionEntryType::Global(g) => { @@ -194,6 +196,7 @@ impl Module { ValType::parse(&g.content_type)?, g.mutable, ); + ids.num_global_imports += 1; ids.push_global(id.0); } wasmparser::ImportSectionEntryType::Module(_) diff --git a/src/parse.rs b/src/parse.rs index 7d5eb92d..6f224db2 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -27,6 +27,9 @@ pub struct IndicesToIds { data: Vec, locals: IdHashMap>, pub(crate) num_fun_imports: usize, + pub(crate) num_mem_imports: usize, + pub(crate) num_global_imports: usize, + pub(crate) num_table_imports: usize, } macro_rules! define_push_get { From 24ddee4b10d2ec1405754f585bbf8bb690be3e88 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Wed, 3 Jan 2024 17:42:44 -0500 Subject: [PATCH 08/10] fix a few issues pointed out by @guybedford --- src/module/config.rs | 18 +++++++++----- src/module/mod.rs | 58 ++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/module/config.rs b/src/module/config.rs index 09eaf507..9f994f0c 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -18,7 +18,7 @@ pub struct ModuleConfig { pub(crate) on_parse: Option Result<()> + Sync + Send + 'static>>, pub(crate) on_instr_loc: Option InstrLocId + Sync + Send + 'static>>, - pub(crate) no_read_dwarf: bool, + pub(crate) skip_debug_sections: bool, } impl Clone for ModuleConfig { @@ -33,7 +33,7 @@ impl Clone for ModuleConfig { skip_producers_section: self.skip_producers_section, skip_name_section: self.skip_name_section, preserve_code_transform: self.preserve_code_transform, - no_read_dwarf: self.no_read_dwarf, + skip_debug_sections: self.skip_debug_sections, // ... and this is left empty. on_parse: None, @@ -56,7 +56,7 @@ impl fmt::Debug for ModuleConfig { ref preserve_code_transform, ref on_parse, ref on_instr_loc, - ref no_read_dwarf, + ref skip_debug_sections, } = self; f.debug_struct("ModuleConfig") @@ -72,7 +72,7 @@ impl fmt::Debug for ModuleConfig { .field("preserve_code_transform", preserve_code_transform) .field("on_parse", &on_parse.as_ref().map(|_| "..")) .field("on_instr_loc", &on_instr_loc.as_ref().map(|_| "..")) - .field("no_read_dwarf", no_read_dwarf) + .field("skip_debug_sections", skip_debug_sections) .finish() } } @@ -85,9 +85,15 @@ impl ModuleConfig { /// Sets a flag to whether DWARF debug sections are read for this module. pub fn read_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { - self.no_read_dwarf = !dw; + self.skip_debug_sections = !dw; return self; } + + /// Sets a flag to whether DWARF debug sections are skipped for this module. + pub fn skip_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { + self.skip_debug_sections = dw; + return self; + } /// Sets a flag to whether DWARF debug sections are generated for this /// module. /// @@ -220,7 +226,7 @@ impl ModuleConfig { /// Parses an in-memory WebAssembly file into an existing `Module` using this /// configuration. pub fn parse_into(&self, wasm: &[u8], pre: &mut Module) -> Result<()> { - Module::parse_in(wasm, self, pre) + pre.parse_in(wasm, self) } /// Parses a WebAssembly file into a `Module` using this configuration. diff --git a/src/module/mod.rs b/src/module/mod.rs index 0e902625..615bc625 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -131,19 +131,19 @@ impl Module { /// Merge a module from the in-memory wasm buffer with the default configuration pub fn merge_buffer(&mut self, wasm: &[u8]) -> Result<()> { - return Self::parse_in(wasm, &ModuleConfig::default(), self); + return self.parse_in(wasm, &ModuleConfig::default()); } fn parse(wasm: &[u8], config: &ModuleConfig) -> Result { let mut ret = Module::default(); ret.config = config.clone(); - Self::parse_in(wasm, config, &mut ret)?; + ret.parse_in(wasm, config)?; return Ok(ret); } - fn parse_in(wasm: &[u8], config: &ModuleConfig, ret: &mut Module) -> Result<()> { + fn parse_in(&mut self,wasm: &[u8], config: &ModuleConfig) -> Result<()> { // let mut ret = Module::default(); // ret.config = config.clone(); - let old_start = ret.start.take(); + let old_start = self.start.take(); let mut indices = IndicesToIds::default(); let mut validator = Validator::new(); validator.wasm_features(WasmFeatures { @@ -168,67 +168,67 @@ impl Module { validator .data_section(&s) .context("failed to parse data section")?; - ret.parse_data(s, &mut indices)?; + self.parse_data(s, &mut indices)?; } Payload::TypeSection(s) => { validator .type_section(&s) .context("failed to parse type section")?; - ret.parse_types(s, &mut indices)?; + self.parse_types(s, &mut indices)?; } Payload::ImportSection(s) => { validator .import_section(&s) .context("failed to parse import section")?; - ret.parse_imports(s, &mut indices)?; + self.parse_imports(s, &mut indices)?; } Payload::TableSection(s) => { validator .table_section(&s) .context("failed to parse table section")?; - ret.parse_tables(s, &mut indices)?; + self.parse_tables(s, &mut indices)?; } Payload::MemorySection(s) => { validator .memory_section(&s) .context("failed to parse memory section")?; - ret.parse_memories(s, &mut indices)?; + self.parse_memories(s, &mut indices)?; } Payload::GlobalSection(s) => { validator .global_section(&s) .context("failed to parse global section")?; - ret.parse_globals(s, &mut indices)?; + self.parse_globals(s, &mut indices)?; } Payload::ExportSection(s) => { validator .export_section(&s) .context("failed to parse export section")?; - ret.parse_exports(s, &mut indices)?; + self.parse_exports(s, &mut indices)?; } Payload::ElementSection(s) => { validator .element_section(&s) .context("failed to parse element section")?; - ret.parse_elements(s, &mut indices)?; + self.parse_elements(s, &mut indices)?; } Payload::StartSection { func, range, .. } => { validator.start_section(func, &range)?; - ret.start = Some(indices.get_func(func)?); + self.start = Some(indices.get_func(func)?); } Payload::FunctionSection(s) => { validator .function_section(&s) .context("failed to parse function section")?; - ret.declare_local_functions(s, &mut indices)?; + self.declare_local_functions(s, &mut indices)?; } Payload::DataCountSection { count, range } => { validator.data_count_section(count, &range)?; - ret.reserve_data(count, &mut indices); + self.reserve_data(count, &mut indices); } Payload::CodeSectionStart { count, range, .. } => { validator.code_section_start(count, &range)?; - ret.funcs.code_section_offset = range.start; + self.funcs.code_section_offset = range.start; } Payload::CodeSectionEntry(body) => { let validator = validator.code_section_entry()?; @@ -243,10 +243,10 @@ impl Module { let result = match name { "producers" => wasmparser::ProducersSectionReader::new(data, data_offset) .map_err(anyhow::Error::from) - .and_then(|s| ret.parse_producers_section(s)), + .and_then(|s| self.parse_producers_section(s)), "name" => wasmparser::NameSectionReader::new(data, data_offset) .map_err(anyhow::Error::from) - .and_then(|r| ret.parse_name_section(r, &indices)), + .and_then(|r| self.parse_name_section(r, &indices)), _ => { log::debug!("parsing custom section `{}`", name); if name.starts_with(".debug") { @@ -255,7 +255,7 @@ impl Module { data: data.to_vec(), }); } else { - ret.customs.add(RawCustomSection { + self.customs.add(RawCustomSection { name: name.to_string(), data: data.to_vec(), }); @@ -306,33 +306,33 @@ impl Module { } } - ret.parse_local_functions( + self.parse_local_functions( local_functions, &mut indices, config.on_instr_loc.as_ref().map(|f| f.as_ref()), ) .context("failed to parse code section")?; - if !config.no_read_dwarf { - ret.parse_debug_sections(debug_sections) + if !config.skip_debug_sections { + self.parse_debug_sections(debug_sections) .context("failed to parse debug data section")?; } - ret.producers + self.producers .add_processed_by("walrus", env!("CARGO_PKG_VERSION")); - match ret.start { + match self.start { Some(a) => { if let Some(r) = old_start { - let mut new_builder = FunctionBuilder::new(&mut ret.types, &[], &[]); + let mut new_builder = FunctionBuilder::new(&mut self.types, &[], &[]); new_builder.func_body().call(r).call(a).return_(); let new = new_builder.local_func(vec![]); - let new = ret.funcs.add_local(new); - ret.start = Some(new); + let new = self.funcs.add_local(new); + self.start = Some(new); } } - None => ret.start = old_start, + None => self.start = old_start, } if let Some(on_parse) = &config.on_parse { - on_parse(ret, &indices)?; + on_parse(self, &indices)?; } log::debug!("parse complete"); From 6c6d070504edeeaca7df847f0a4fad43ef152979 Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Wed, 3 Jan 2024 17:45:02 -0500 Subject: [PATCH 09/10] rustfmt (again) --- src/module/config.rs | 12 ++++++------ src/module/mod.rs | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/module/config.rs b/src/module/config.rs index 9f994f0c..fbed961a 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -89,11 +89,11 @@ impl ModuleConfig { return self; } - /// Sets a flag to whether DWARF debug sections are skipped for this module. - pub fn skip_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { - self.skip_debug_sections = dw; - return self; - } + /// Sets a flag to whether DWARF debug sections are skipped for this module. + pub fn skip_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { + self.skip_debug_sections = dw; + return self; + } /// Sets a flag to whether DWARF debug sections are generated for this /// module. /// @@ -226,7 +226,7 @@ impl ModuleConfig { /// Parses an in-memory WebAssembly file into an existing `Module` using this /// configuration. pub fn parse_into(&self, wasm: &[u8], pre: &mut Module) -> Result<()> { - pre.parse_in(wasm, self) + pre.parse_in(wasm, self) } /// Parses a WebAssembly file into a `Module` using this configuration. diff --git a/src/module/mod.rs b/src/module/mod.rs index 615bc625..defd721a 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -137,10 +137,10 @@ impl Module { fn parse(wasm: &[u8], config: &ModuleConfig) -> Result { let mut ret = Module::default(); ret.config = config.clone(); - ret.parse_in(wasm, config)?; + ret.parse_in(wasm, config)?; return Ok(ret); } - fn parse_in(&mut self,wasm: &[u8], config: &ModuleConfig) -> Result<()> { + fn parse_in(&mut self, wasm: &[u8], config: &ModuleConfig) -> Result<()> { // let mut ret = Module::default(); // ret.config = config.clone(); let old_start = self.start.take(); @@ -316,7 +316,7 @@ impl Module { self.parse_debug_sections(debug_sections) .context("failed to parse debug data section")?; } - self.producers + self.producers .add_processed_by("walrus", env!("CARGO_PKG_VERSION")); match self.start { From ee4cc5c0c6acda9f4d64960b31b8e8830fcaf4ce Mon Sep 17 00:00:00 2001 From: Graham Kelly Date: Fri, 12 Jan 2024 22:28:48 -0500 Subject: [PATCH 10/10] new fuzz, some cleanups --- crates/fuzz-utils/src/lib.rs | 24 ++++++++++++++++++++++++ fuzz/fuzz_targets/watmerge.rs | 18 ++++++++++++++++++ src/module/config.rs | 6 ------ 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 fuzz/fuzz_targets/watmerge.rs diff --git a/crates/fuzz-utils/src/lib.rs b/crates/fuzz-utils/src/lib.rs index c595f25c..40711489 100755 --- a/crates/fuzz-utils/src/lib.rs +++ b/crates/fuzz-utils/src/lib.rs @@ -131,6 +131,30 @@ where .into()) } + fn test_merge(&self, wata: &str, watb: &str) -> Result<()> { + let wasma = self.wat2wasm(&wata)?; + let wasmb = self.wat2wasm(&watb)?; + let mut module = walrus::Module::from_buffer(&wasma) + .context("walrus failed to parse the first wasm buffer")?; + walrus::ModuleConfig::default() + .generate_dwarf(false) + .parse_into(&wasmb, &mut module) + .context("walrus failed to merge the second wasm buffer")?; + + module.emit_wasm(); + return Ok(()); + } + /// Generate two wasm files and confirm that merging them is valid in `walrus` + /// /// + /// Does not attempt to reduce any failing test cases. + pub fn run_merge(&mut self) -> Result<()> { + let wata = self.gen_wat(); + let watb = self.gen_wat(); + self.test_merge(&wata, &watb) + .with_context(|| format!("wata = {}, watb = {}", wata, watb))?; + return Ok(()); + } + /// Generate a single wasm file and then compare its output in the reference /// interpreter before and after round tripping it through `walrus`. /// diff --git a/fuzz/fuzz_targets/watmerge.rs b/fuzz/fuzz_targets/watmerge.rs new file mode 100644 index 00000000..e00a0375 --- /dev/null +++ b/fuzz/fuzz_targets/watmerge.rs @@ -0,0 +1,18 @@ +#![no_main] + +#[macro_use] +extern crate libfuzzer_sys; + +use bufrng::BufRng; +use walrus_fuzz_utils::{Config, WatGen}; + +fuzz_target!(|data: &[u8]| { + let data = if data.is_empty() { &[0] } else { data }; + let fuel = data.len(); + let rng = BufRng::new(data); + let mut config = Config::, BufRng>::new(rng).set_fuel(fuel); + if let Err(e) = config.run_merge() { + walrus_fuzz_utils::print_err(&e); + panic!("Found an error! {}", e); + } +}); diff --git a/src/module/config.rs b/src/module/config.rs index fbed961a..90cbe758 100644 --- a/src/module/config.rs +++ b/src/module/config.rs @@ -83,12 +83,6 @@ impl ModuleConfig { ModuleConfig::default() } - /// Sets a flag to whether DWARF debug sections are read for this module. - pub fn read_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { - self.skip_debug_sections = !dw; - return self; - } - /// Sets a flag to whether DWARF debug sections are skipped for this module. pub fn skip_dwarf(&mut self, dw: bool) -> &mut ModuleConfig { self.skip_debug_sections = dw;