@@ -2369,6 +2369,22 @@ impl Bindgen for FunctionBindgen<'_, '_> {
23692369 }
23702370
23712371 Instruction :: Return { amt, .. } => {
2372+ // Bind return operands to locals BEFORE cleanup to avoid
2373+ // use-after-free when operands contain inline loads from
2374+ // return_area or other freed memory.
2375+ let return_locals: Vec < String > = if * amt > 0 {
2376+ operands
2377+ . iter ( )
2378+ . map ( |op| {
2379+ let local = self . locals . tmp ( "ret" ) ;
2380+ uwriteln ! ( self . src, "let {local} = {op}" ) ;
2381+ local
2382+ } )
2383+ . collect ( )
2384+ } else {
2385+ Vec :: new ( )
2386+ } ;
2387+
23722388 for clean in & self . cleanup {
23732389 let address = & clean. address ;
23742390 self . r#gen . ffi_imports . insert ( ffi:: FREE ) ;
@@ -2377,19 +2393,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
23772393
23782394 if self . needs_cleanup_list {
23792395 self . r#gen . ffi_imports . insert ( ffi:: FREE ) ;
2380- uwrite ! (
2381- self . src,
2382- "
2383- cleanup_list.each(mbt_ffi_free)
2384- " ,
2385- ) ;
2396+ uwriteln ! ( self . src, "cleanup_list.each(mbt_ffi_free)" , ) ;
23862397 }
23872398
23882399 match * amt {
23892400 0 => ( ) ,
2390- 1 => uwriteln ! ( self . src, "return {}" , operands [ 0 ] ) ,
2401+ 1 => uwriteln ! ( self . src, "return {}" , return_locals [ 0 ] ) ,
23912402 _ => {
2392- let results = operands . join ( ", " ) ;
2403+ let results = return_locals . join ( ", " ) ;
23932404 uwriteln ! ( self . src, "return ({results})" ) ;
23942405 }
23952406 }
@@ -2708,10 +2719,94 @@ impl Bindgen for FunctionBindgen<'_, '_> {
27082719 Instruction :: ErrorContextLower { .. }
27092720 | Instruction :: ErrorContextLift { .. }
27102721 | Instruction :: DropHandle { .. } => todo ! ( ) ,
2711- Instruction :: FixedLengthListLift { .. } => todo ! ( ) ,
2712- Instruction :: FixedLengthListLower { .. } => todo ! ( ) ,
2713- Instruction :: FixedLengthListLowerToMemory { .. } => todo ! ( ) ,
2714- Instruction :: FixedLengthListLiftFromMemory { .. } => todo ! ( ) ,
2722+ Instruction :: FixedLengthListLift {
2723+ element : _,
2724+ size,
2725+ id : _,
2726+ } => {
2727+ let array = self . locals . tmp ( "array" ) ;
2728+ let mut elements = String :: new ( ) ;
2729+ for a in operands. drain ( 0 ..( * size as usize ) ) {
2730+ elements. push_str ( & a) ;
2731+ elements. push_str ( ", " ) ;
2732+ }
2733+ uwriteln ! ( self . src, "let {array} : FixedArray[_] = [{elements}]" ) ;
2734+ results. push ( array) ;
2735+ }
2736+ Instruction :: FixedLengthListLower {
2737+ element : _,
2738+ size,
2739+ id : _,
2740+ } => {
2741+ for i in 0 ..( * size as usize ) {
2742+ results. push ( format ! ( "({})[{i}]" , operands[ 0 ] ) ) ;
2743+ }
2744+ }
2745+ Instruction :: FixedLengthListLowerToMemory {
2746+ element,
2747+ size : _,
2748+ id : _,
2749+ } => {
2750+ let Block {
2751+ body,
2752+ results : block_results,
2753+ } = self . blocks . pop ( ) . unwrap ( ) ;
2754+ assert ! ( block_results. is_empty( ) ) ;
2755+
2756+ let vec = operands[ 0 ] . clone ( ) ;
2757+ let target = operands[ 1 ] . clone ( ) ;
2758+ let size = self . r#gen . r#gen . sizes . size ( element) . size_wasm32 ( ) ;
2759+ let index = self . locals . tmp ( "index" ) ;
2760+
2761+ uwrite ! (
2762+ self . src,
2763+ "
2764+ for {index} = 0; {index} < ({vec}).length(); {index} = {index} + 1 {{
2765+ let iter_elem = ({vec})[{index}]
2766+ let iter_base = ({target}) + ({index} * {size})
2767+ {body}
2768+ }}
2769+ " ,
2770+ ) ;
2771+ }
2772+ Instruction :: FixedLengthListLiftFromMemory {
2773+ element,
2774+ size : fll_size,
2775+ id : _,
2776+ } => {
2777+ let Block {
2778+ body,
2779+ results : block_results,
2780+ } = self . blocks . pop ( ) . unwrap ( ) ;
2781+ let address = & operands[ 0 ] ;
2782+ let array = self . locals . tmp ( "array" ) ;
2783+ let ty = self
2784+ . r#gen
2785+ . r#gen
2786+ . pkg_resolver
2787+ . type_name ( self . r#gen . name , element) ;
2788+ let elem_size = self . r#gen . r#gen . sizes . size ( element) . size_wasm32 ( ) ;
2789+ let index = self . locals . tmp ( "index" ) ;
2790+
2791+ let result = match & block_results[ ..] {
2792+ [ result] => result,
2793+ _ => todo ! ( "result count == {}" , block_results. len( ) ) ,
2794+ } ;
2795+
2796+ uwrite ! (
2797+ self . src,
2798+ "
2799+ let {array} : Array[{ty}] = []
2800+ for {index} = 0; {index} < {fll_size}; {index} = {index} + 1 {{
2801+ let iter_base = ({address}) + ({index} * {elem_size})
2802+ {body}
2803+ {array}.push({result})
2804+ }}
2805+ " ,
2806+ ) ;
2807+
2808+ results. push ( format ! ( "FixedArray::from_array({array}[:])" ) ) ;
2809+ }
27152810 }
27162811 }
27172812
@@ -2747,11 +2842,10 @@ impl Bindgen for FunctionBindgen<'_, '_> {
27472842
27482843 if !self . cleanup . is_empty ( ) {
27492844 self . needs_cleanup_list = true ;
2750- self . r#gen . ffi_imports . insert ( ffi:: FREE ) ;
27512845
27522846 for cleanup in & self . cleanup {
27532847 let address = & cleanup. address ;
2754- uwriteln ! ( self . src, "mbt_ffi_free ({address})" , ) ;
2848+ uwriteln ! ( self . src, "cleanup_list.push ({address})" , ) ;
27552849 }
27562850 }
27572851
0 commit comments