From 97bd1a49fdc1808680359ebc60efc97ab4e3aa23 Mon Sep 17 00:00:00 2001 From: Khagan Karimov Date: Tue, 3 Feb 2026 17:48:02 -0700 Subject: [PATCH 1/5] Add structref local/global/table access for structs --- .../fuzzing/src/generators/gc_ops/limits.rs | 2 + crates/fuzzing/src/generators/gc_ops/ops.rs | 263 ++++++++++++++++-- crates/fuzzing/src/generators/gc_ops/tests.rs | 48 +++- crates/fuzzing/src/oracles.rs | 4 +- 4 files changed, 280 insertions(+), 37 deletions(-) diff --git a/crates/fuzzing/src/generators/gc_ops/limits.rs b/crates/fuzzing/src/generators/gc_ops/limits.rs index dd97888cd0f3..59fe17e812a4 100644 --- a/crates/fuzzing/src/generators/gc_ops/limits.rs +++ b/crates/fuzzing/src/generators/gc_ops/limits.rs @@ -15,6 +15,8 @@ pub const TABLE_SIZE_RANGE: RangeInclusive = 0..=100; pub const MAX_REC_GROUPS_RANGE: RangeInclusive = 0..=10; /// Maximum number of operations. pub const MAX_OPS: usize = 100; +/// Range for the number of structref locals. +pub const NUM_STRUCT_LOCALS_RANGE: RangeInclusive = 0..=10; /// Limits controlling the structure of a generated Wasm module. #[derive(Debug, Default, Serialize, Deserialize)] diff --git a/crates/fuzzing/src/generators/gc_ops/ops.rs b/crates/fuzzing/src/generators/gc_ops/ops.rs index ef8cfa5a25ea..6e65514b7e39 100644 --- a/crates/fuzzing/src/generators/gc_ops/ops.rs +++ b/crates/fuzzing/src/generators/gc_ops/ops.rs @@ -14,6 +14,19 @@ use wasm_encoder::{ TypeSection, ValType, }; +// This is used as ctx to pass to the function +#[derive(Clone, Copy)] +struct StorageBases { + struct_type_base: u32, + typed_first_func_index: u32, + struct_local_idx: u32, + typed_local_base: u32, + struct_global_idx: u32, + typed_global_base: u32, + struct_table_idx: u32, + typed_table_base: u32, +} + /// A description of a Wasm module that makes a series of `externref` table /// operations. #[derive(Debug, Default, Serialize, Deserialize)] @@ -60,6 +73,8 @@ impl GcOps { for _i in 0..self.limits.num_params { params.push(ValType::EXTERNREF); } + let params_len = + u32::try_from(params.len()).expect("params len should be within u32 range"); let results = vec![]; types.ty().function(params, results); @@ -78,8 +93,11 @@ impl GcOps { // 4: `take_struct` types.ty().function( vec![ValType::Ref(RefType { - nullable: false, - heap_type: wasm_encoder::HeapType::ANY, + nullable: true, + heap_type: wasm_encoder::HeapType::Abstract { + shared: false, + ty: wasm_encoder::AbstractHeapType::Struct, + }, })], vec![], ); @@ -130,7 +148,7 @@ impl GcOps { let concrete = struct_type_base + i; types.ty().function( vec![ValType::Ref(RefType { - nullable: false, + nullable: true, heap_type: wasm_encoder::HeapType::Concrete(concrete), })], vec![], @@ -163,6 +181,37 @@ impl GcOps { table64: false, shared: false, }); + + let struct_table_idx = tables.len(); + tables.table(TableType { + element_type: RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Abstract { + shared: false, + ty: wasm_encoder::AbstractHeapType::Struct, + }, + }, + minimum: u64::from(self.limits.table_size), + maximum: None, + table64: false, + shared: false, + }); + + let typed_table_base = tables.len(); + for i in 0..struct_count { + let concrete = struct_type_base + i; + tables.table(TableType { + element_type: RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Concrete(concrete), + }, + minimum: u64::from(self.limits.table_size), + maximum: None, + table64: false, + shared: false, + }); + } + // Define our globals. let mut globals = GlobalSection::new(); for _ in 0..self.limits.num_globals { @@ -176,6 +225,43 @@ impl GcOps { ); } + // Add exactly one (ref any) global. + let struct_global_idx = globals.len(); + globals.global( + wasm_encoder::GlobalType { + val_type: ValType::Ref(RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Abstract { + shared: false, + ty: wasm_encoder::AbstractHeapType::Struct, + }, + }), + mutable: true, + shared: false, + }, + &ConstExpr::ref_null(wasm_encoder::HeapType::Abstract { + shared: false, + ty: wasm_encoder::AbstractHeapType::Struct, + }), + ); + + // Add one typed (ref ) global per struct type. + let typed_global_base = globals.len(); + for i in 0..struct_count { + let concrete = struct_type_base + i; + globals.global( + wasm_encoder::GlobalType { + val_type: ValType::Ref(RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Concrete(concrete), + }), + mutable: true, + shared: false, + }, + &ConstExpr::ref_null(wasm_encoder::HeapType::Concrete(concrete)), + ); + } + // Define the "run" function export. let mut functions = FunctionSection::new(); let mut exports = ExportSection::new(); @@ -187,17 +273,48 @@ impl GcOps { // Give ourselves one scratch local that we can use in various `GcOp` // implementations. - let local_decls: Vec<(u32, ValType)> = vec![(1, ValType::EXTERNREF)]; + let mut local_decls: Vec<(u32, ValType)> = vec![(1, ValType::EXTERNREF)]; + + let scratch_local = params_len; + let struct_local_idx = scratch_local + 1; + local_decls.push(( + 1, + ValType::Ref(RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Abstract { + shared: false, + ty: wasm_encoder::AbstractHeapType::Struct, + }, + }), + )); + + let typed_local_base: u32 = struct_local_idx + 1; + for i in 0..struct_count { + let concrete = struct_type_base + i; + local_decls.push(( + 1, + ValType::Ref(RefType { + nullable: true, + heap_type: wasm_encoder::HeapType::Concrete(concrete), + }), + )); + } + + let storage_bases = StorageBases { + struct_type_base, + typed_first_func_index, + struct_local_idx, + typed_local_base, + struct_global_idx, + typed_global_base, + struct_table_idx, + typed_table_base, + }; let mut func = Function::new(local_decls); func.instruction(&Instruction::Loop(wasm_encoder::BlockType::Empty)); for op in &self.ops { - op.insert( - &mut func, - self.limits.num_params, - struct_type_base, - typed_first_func_index, - ); + op.insert(&mut func, scratch_local, storage_bases); } func.instruction(&Instruction::Br(0)); func.instruction(&Instruction::End); @@ -244,7 +361,21 @@ impl GcOps { if self.limits.max_types == 0 && matches!( op, - GcOp::StructNew(..) | GcOp::TakeStructCall(..) | GcOp::TakeTypedStructCall(..) + GcOp::StructNew(..) + | GcOp::TakeStructCall(..) + | GcOp::TakeTypedStructCall(..) + | GcOp::TypedStructLocalSet(..) + | GcOp::TypedStructLocalGet(..) + | GcOp::TypedStructGlobalSet(..) + | GcOp::TypedStructGlobalGet(..) + | GcOp::TypedStructTableSet(..) + | GcOp::TypedStructTableGet(..) + | GcOp::StructTableSet(..) + | GcOp::StructTableGet(..) + | GcOp::StructLocalSet(..) + | GcOp::StructLocalGet(..) + | GcOp::StructGlobalSet(..) + | GcOp::StructGlobalGet(..) ) { continue; @@ -330,6 +461,15 @@ macro_rules! define_gc_ops { Self::TakeTypedStructCall(t) => { out.push(Some(StackType::Struct(Some(*t)))); } + Self::TypedStructLocalSet(t) => { + out.push(Some(StackType::Struct(Some(*t)))); + } + Self::TypedStructGlobalSet(t) => { + out.push(Some(StackType::Struct(Some(*t)))); + } + Self::TypedStructTableSet(_, t) => { + out.push(Some(StackType::Struct(Some(*t)))); + } $( Self::$op(..) => { $( out.push($operand); )* @@ -344,6 +484,15 @@ macro_rules! define_gc_ops { Self::StructNew(t) => { out.push(StackType::Struct(Some(*t))); } + Self::TypedStructLocalGet(t) => { + out.push(StackType::Struct(Some(*t))); + } + Self::TypedStructGlobalGet(t) => { + out.push(StackType::Struct(Some(*t))); + } + Self::TypedStructTableGet(_, t) => { + out.push(StackType::Struct(Some(*t))); + } $( Self::$op(..) => { $( out.push($result); )* }, )* } } @@ -355,7 +504,9 @@ macro_rules! define_gc_ops { $( $( let limit_fn = $limit as fn(&GcOpsLimits) -> $ty; let limit = (limit_fn)(limits); - debug_assert!(limit > 0); + if limit == 0 { + return None; + } *$limit_var = *$limit_var % limit; )* )? } @@ -364,7 +515,15 @@ macro_rules! define_gc_ops { match self { Self::StructNew(t) | Self::TakeStructCall(t) - | Self::TakeTypedStructCall(t) => { + | Self::TakeTypedStructCall(t) + | Self::TypedStructLocalSet(t) + | Self::TypedStructLocalGet(t) + | Self::TypedStructGlobalSet(t) + | Self::TypedStructGlobalGet(t) + | Self::TypedStructTableSet(_, t) + | Self::TypedStructTableGet(_, t) + + => { if num_types == 0 { return None; } @@ -454,19 +613,34 @@ define_gc_ops! { TakeTypedStructCall(type_index: |ops| ops.max_types => u32) : [] => [], + StructLocalSet() : [Some(StackType::Struct(None))] => [], + StructLocalGet() : [] => [StackType::Struct(None)], + // `TypedStructLocalSet` operand is special-cased to require `Struct(Some(t))`, so operands list is empty. + TypedStructLocalSet(type_index: |ops| ops.max_types => u32) : [] => [], + // `TypedStructLocalGet` result is special-cased to push `Struct(Some(t))`, so results list is empty. + TypedStructLocalGet(type_index: |ops| ops.max_types => u32) : [] => [], + + StructGlobalSet() : [Some(StackType::Struct(None))] => [], + StructGlobalGet() : [] => [StackType::Struct(None)], + // `TypedStructGlobalSet` operand is special-cased to require `Struct(Some(t))`, so operands list is empty. + TypedStructGlobalSet(type_index: |ops| ops.max_types => u32) : [] => [], + // `TypedStructGlobalGet` result is special-cased to push `Struct(Some(t))`, so results list is empty. + TypedStructGlobalGet(type_index: |ops| ops.max_types => u32) : [] => [], + + StructTableSet(elem_index: |ops| ops.table_size => u32) : [Some(StackType::Struct(None))] => [], + StructTableGet(elem_index: |ops| ops.table_size => u32) : [] => [StackType::Struct(None)], + // `TypedStructTableSet` operand is special-cased to require `Struct(Some(t))`, so operands list is empty. + TypedStructTableSet(elem_index: |ops| ops.table_size => u32, type_index: |ops| ops.max_types => u32) : [] => [], + // `TypedStructTableGet` result is special-cased to push `Struct(Some(t))`, so results list is empty. + TypedStructTableGet(elem_index: |ops| ops.table_size => u32, type_index: |ops| ops.max_types => u32) : [] => [], + Drop : [None] => [], Null : [] => [StackType ::ExternRef], } impl GcOp { - fn insert( - self, - func: &mut Function, - scratch_local: u32, - struct_type_base: u32, - typed_first_func_index: u32, - ) { + fn insert(self, func: &mut Function, scratch_local: u32, storage_bases: StorageBases) { let gc_func_idx = 0; let take_refs_func_idx = 1; let make_refs_func_idx = 2; @@ -511,15 +685,60 @@ impl GcOp { func.instruction(&Instruction::RefNull(wasm_encoder::HeapType::EXTERN)); } Self::StructNew(x) => { - func.instruction(&Instruction::StructNew(x + struct_type_base)); + func.instruction(&Instruction::StructNew(x + storage_bases.struct_type_base)); } Self::TakeStructCall(_x) => { func.instruction(&Instruction::Call(take_structref_idx)); } Self::TakeTypedStructCall(x) => { - let f = typed_first_func_index + x; + let f = storage_bases.typed_first_func_index + x; func.instruction(&Instruction::Call(f)); } + Self::StructLocalGet() => { + func.instruction(&Instruction::LocalGet(storage_bases.struct_local_idx)); + } + Self::TypedStructLocalGet(x) => { + func.instruction(&Instruction::LocalGet(storage_bases.typed_local_base + x)); + } + Self::StructLocalSet() => { + func.instruction(&Instruction::LocalSet(storage_bases.struct_local_idx)); + } + Self::TypedStructLocalSet(x) => { + func.instruction(&Instruction::LocalSet(storage_bases.typed_local_base + x)); + } + Self::StructGlobalGet() => { + func.instruction(&Instruction::GlobalGet(storage_bases.struct_global_idx)); + } + Self::TypedStructGlobalGet(x) => { + func.instruction(&Instruction::GlobalGet(storage_bases.typed_global_base + x)); + } + Self::StructGlobalSet() => { + func.instruction(&Instruction::GlobalSet(storage_bases.struct_global_idx)); + } + Self::TypedStructGlobalSet(x) => { + func.instruction(&Instruction::GlobalSet(storage_bases.typed_global_base + x)); + } + Self::StructTableGet(elem_index) => { + func.instruction(&Instruction::I32Const(elem_index.cast_signed())); + func.instruction(&Instruction::TableGet(storage_bases.struct_table_idx)); + } + Self::TypedStructTableGet(elem_index, x) => { + func.instruction(&Instruction::I32Const(elem_index.cast_signed())); + func.instruction(&Instruction::TableGet(storage_bases.typed_table_base + x)); + } + Self::StructTableSet(elem_index) => { + // Use struct_local_idx (anyref) to temporarily store the value before table.set + func.instruction(&Instruction::LocalSet(storage_bases.struct_local_idx)); + func.instruction(&Instruction::I32Const(elem_index.cast_signed())); + func.instruction(&Instruction::LocalGet(storage_bases.struct_local_idx)); + func.instruction(&Instruction::TableSet(storage_bases.struct_table_idx)); + } + Self::TypedStructTableSet(elem_index, x) => { + func.instruction(&Instruction::LocalSet(storage_bases.typed_local_base + x)); + func.instruction(&Instruction::I32Const(elem_index.cast_signed())); + func.instruction(&Instruction::LocalGet(storage_bases.typed_local_base + x)); + func.instruction(&Instruction::TableSet(storage_bases.typed_table_base + x)); + } } } } diff --git a/crates/fuzzing/src/generators/gc_ops/tests.rs b/crates/fuzzing/src/generators/gc_ops/tests.rs index f1911de86593..871bd56e749c 100644 --- a/crates/fuzzing/src/generators/gc_ops/tests.rs +++ b/crates/fuzzing/src/generators/gc_ops/tests.rs @@ -71,7 +71,7 @@ fn mutate_gc_ops_with_default_mutator() -> mutatis::Result<()> { let mut session = mutatis::Session::new(); - for _ in 0..2048 { + for _ in 0..1024 { session.mutate(&mut res)?; let wasm = res.to_wasm_binary(); @@ -187,7 +187,7 @@ fn test_wat_string() -> mutatis::Result<()> { (type (;1;) (func (param externref externref))) (type (;2;) (func (param externref externref externref))) (type (;3;) (func (result externref externref externref))) - (type (;4;) (func (param (ref any)))) + (type (;4;) (func (param structref))) (rec (type (;5;) (struct)) ) @@ -211,16 +211,16 @@ fn test_wat_string() -> mutatis::Result<()> { (rec (type (;14;) (struct)) ) - (type (;15;) (func (param (ref 5)))) - (type (;16;) (func (param (ref 6)))) - (type (;17;) (func (param (ref 7)))) - (type (;18;) (func (param (ref 8)))) - (type (;19;) (func (param (ref 9)))) - (type (;20;) (func (param (ref 10)))) - (type (;21;) (func (param (ref 11)))) - (type (;22;) (func (param (ref 12)))) - (type (;23;) (func (param (ref 13)))) - (type (;24;) (func (param (ref 14)))) + (type (;15;) (func (param (ref null 5)))) + (type (;16;) (func (param (ref null 6)))) + (type (;17;) (func (param (ref null 7)))) + (type (;18;) (func (param (ref null 8)))) + (type (;19;) (func (param (ref null 9)))) + (type (;20;) (func (param (ref null 10)))) + (type (;21;) (func (param (ref null 11)))) + (type (;22;) (func (param (ref null 12)))) + (type (;23;) (func (param (ref null 13)))) + (type (;24;) (func (param (ref null 14)))) (import "" "gc" (func (;0;) (type 0))) (import "" "take_refs" (func (;1;) (type 2))) (import "" "make_refs" (func (;2;) (type 3))) @@ -236,11 +236,33 @@ fn test_wat_string() -> mutatis::Result<()> { (import "" "take_struct_13" (func (;12;) (type 23))) (import "" "take_struct_14" (func (;13;) (type 24))) (table (;0;) 5 externref) + (table (;1;) 5 structref) + (table (;2;) 5 (ref null 5)) + (table (;3;) 5 (ref null 6)) + (table (;4;) 5 (ref null 7)) + (table (;5;) 5 (ref null 8)) + (table (;6;) 5 (ref null 9)) + (table (;7;) 5 (ref null 10)) + (table (;8;) 5 (ref null 11)) + (table (;9;) 5 (ref null 12)) + (table (;10;) 5 (ref null 13)) + (table (;11;) 5 (ref null 14)) (global (;0;) (mut externref) ref.null extern) (global (;1;) (mut externref) ref.null extern) + (global (;2;) (mut structref) ref.null struct) + (global (;3;) (mut (ref null 5)) ref.null 5) + (global (;4;) (mut (ref null 6)) ref.null 6) + (global (;5;) (mut (ref null 7)) ref.null 7) + (global (;6;) (mut (ref null 8)) ref.null 8) + (global (;7;) (mut (ref null 9)) ref.null 9) + (global (;8;) (mut (ref null 10)) ref.null 10) + (global (;9;) (mut (ref null 11)) ref.null 11) + (global (;10;) (mut (ref null 12)) ref.null 12) + (global (;11;) (mut (ref null 13)) ref.null 13) + (global (;12;) (mut (ref null 14)) ref.null 14) (export "run" (func 14)) (func (;14;) (type 1) (param externref externref) - (local externref) + (local externref structref (ref null 5) (ref null 6) (ref null 7) (ref null 8) (ref null 9) (ref null 10) (ref null 11) (ref null 12) (ref null 13) (ref null 14)) loop ;; label = @1 ref.null extern drop diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index 5b3024421ffc..b12a5ec52de4 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -927,13 +927,13 @@ pub fn gc_ops(mut fuzz_config: generators::Config, mut ops: GcOps) -> Result, _params, _results| { - log::info!("gc_ops: take_struct()"); + log::info!("gc_ops: take_struct()"); Ok(()) } }); From 907ca307dd2f6513abeed8e1473305a014b0ae56 Mon Sep 17 00:00:00 2001 From: Khagan Karimov Date: Tue, 3 Feb 2026 17:51:00 -0700 Subject: [PATCH 2/5] The number of iters back to 2048 --- crates/fuzzing/src/generators/gc_ops/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fuzzing/src/generators/gc_ops/tests.rs b/crates/fuzzing/src/generators/gc_ops/tests.rs index 871bd56e749c..dcb2568614a4 100644 --- a/crates/fuzzing/src/generators/gc_ops/tests.rs +++ b/crates/fuzzing/src/generators/gc_ops/tests.rs @@ -71,7 +71,7 @@ fn mutate_gc_ops_with_default_mutator() -> mutatis::Result<()> { let mut session = mutatis::Session::new(); - for _ in 0..1024 { + for _ in 0..2048 { session.mutate(&mut res)?; let wasm = res.to_wasm_binary(); From aa2d97355e613ab11a2fd426d33b0edb9d5bfc59 Mon Sep 17 00:00:00 2001 From: Khagan Karimov Date: Tue, 3 Feb 2026 17:52:37 -0700 Subject: [PATCH 3/5] Remove forgotten struct_num_local from limits --- crates/fuzzing/src/generators/gc_ops/limits.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/fuzzing/src/generators/gc_ops/limits.rs b/crates/fuzzing/src/generators/gc_ops/limits.rs index 59fe17e812a4..dd97888cd0f3 100644 --- a/crates/fuzzing/src/generators/gc_ops/limits.rs +++ b/crates/fuzzing/src/generators/gc_ops/limits.rs @@ -15,8 +15,6 @@ pub const TABLE_SIZE_RANGE: RangeInclusive = 0..=100; pub const MAX_REC_GROUPS_RANGE: RangeInclusive = 0..=10; /// Maximum number of operations. pub const MAX_OPS: usize = 100; -/// Range for the number of structref locals. -pub const NUM_STRUCT_LOCALS_RANGE: RangeInclusive = 0..=10; /// Limits controlling the structure of a generated Wasm module. #[derive(Debug, Default, Serialize, Deserialize)] From 293b6fb4c9071761b35a5e5348986ea8fec60ff3 Mon Sep 17 00:00:00 2001 From: Khagan Karimov Date: Wed, 4 Feb 2026 14:21:27 -0700 Subject: [PATCH 4/5] Address initial reviews --- crates/fuzzing/src/generators/gc_ops/ops.rs | 11 ++++++----- crates/fuzzing/src/oracles.rs | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/fuzzing/src/generators/gc_ops/ops.rs b/crates/fuzzing/src/generators/gc_ops/ops.rs index 6e65514b7e39..b692bb6ca70f 100644 --- a/crates/fuzzing/src/generators/gc_ops/ops.rs +++ b/crates/fuzzing/src/generators/gc_ops/ops.rs @@ -14,9 +14,10 @@ use wasm_encoder::{ TypeSection, ValType, }; -// This is used as ctx to pass to the function +/// The base offsets and indices for various Wasm entities within +// their index spaces in the the encoded Wasm binary. #[derive(Clone, Copy)] -struct StorageBases { +struct WasmEncodingBases { struct_type_base: u32, typed_first_func_index: u32, struct_local_idx: u32, @@ -225,7 +226,7 @@ impl GcOps { ); } - // Add exactly one (ref any) global. + // Add exactly one (ref.null struct) global. let struct_global_idx = globals.len(); globals.global( wasm_encoder::GlobalType { @@ -300,7 +301,7 @@ impl GcOps { )); } - let storage_bases = StorageBases { + let storage_bases = WasmEncodingBases { struct_type_base, typed_first_func_index, struct_local_idx, @@ -640,7 +641,7 @@ define_gc_ops! { } impl GcOp { - fn insert(self, func: &mut Function, scratch_local: u32, storage_bases: StorageBases) { + fn insert(self, func: &mut Function, scratch_local: u32, storage_bases: WasmEncodingBases) { let gc_func_idx = 0; let take_refs_func_idx = 1; let make_refs_func_idx = 2; diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index b12a5ec52de4..060bbaf86368 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -933,7 +933,7 @@ pub fn gc_ops(mut fuzz_config: generators::Config, mut ops: GcOps) -> Result, _params, _results| { - log::info!("gc_ops: take_struct()"); + log::info!("gc_ops: take_struct()"); Ok(()) } }); From 43961360f6f991f65b937856404c437da35d1f3f Mon Sep 17 00:00:00 2001 From: Khagan Karimov Date: Wed, 4 Feb 2026 14:22:49 -0700 Subject: [PATCH 5/5] Idiomatic comments --- crates/fuzzing/src/generators/gc_ops/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fuzzing/src/generators/gc_ops/ops.rs b/crates/fuzzing/src/generators/gc_ops/ops.rs index b692bb6ca70f..8d09e163a097 100644 --- a/crates/fuzzing/src/generators/gc_ops/ops.rs +++ b/crates/fuzzing/src/generators/gc_ops/ops.rs @@ -15,7 +15,7 @@ use wasm_encoder::{ }; /// The base offsets and indices for various Wasm entities within -// their index spaces in the the encoded Wasm binary. +/// their index spaces in the the encoded Wasm binary. #[derive(Clone, Copy)] struct WasmEncodingBases { struct_type_base: u32,