@@ -807,12 +807,9 @@ impl<'a> StreamingDecoder<'a> {
807807 } ,
808808 0x01 => {
809809 // Table import - need to parse table type
810- // ref_type (1 byte) + limits (flags + min, optional max)
811- if offset >= data. len ( ) {
812- return Err ( Error :: parse_error ( "Unexpected end of table import" ) ) ;
813- }
814- let ref_type_byte = data[ offset] ;
815- offset += 1 ;
810+ // ref_type (may be multi-byte for GC types) + limits (flags + min, optional max)
811+ let ( ref_value_type, new_offset) = self . parse_value_type ( data, offset) ?;
812+ offset = new_offset;
816813
817814 // Parse limits
818815 if offset >= data. len ( ) {
@@ -848,12 +845,10 @@ impl<'a> StreamingDecoder<'a> {
848845 use wrt_format:: module:: { Import , ImportDesc } ;
849846 use wrt_foundation:: types:: { Limits , RefType , TableType } ;
850847
851- // Convert ref_type byte to RefType
852- let ref_type = match ref_type_byte {
853- 0x70 => RefType :: Funcref ,
854- 0x6F => RefType :: Externref ,
855- _ => RefType :: Funcref , // Default for unknown
856- } ;
848+ // Convert parsed ValueType to RefType
849+ let ref_type = RefType :: try_from ( ref_value_type) . map_err ( |_| {
850+ Error :: parse_error ( "Unknown table element type in import" )
851+ } ) ?;
857852
858853 let limits = Limits { min, max } ;
859854
@@ -978,12 +973,13 @@ impl<'a> StreamingDecoder<'a> {
978973 } ,
979974 0x03 => {
980975 // Global import - need to parse global type
981- // value_type (1 byte) + mutability (1 byte)
982- if offset + 1 >= data. len ( ) {
976+ // value_type (may be multi-byte for GC types) + mutability (1 byte)
977+ let ( value_type, new_offset) = self . parse_value_type ( data, offset) ?;
978+ offset = new_offset;
979+
980+ if offset >= data. len ( ) {
983981 return Err ( Error :: parse_error ( "Unexpected end of global import" ) ) ;
984982 }
985- let value_type_byte = data[ offset] ;
986- offset += 1 ;
987983 let mutability_byte = data[ offset] ;
988984 offset += 1 ;
989985
@@ -992,19 +988,6 @@ impl<'a> StreamingDecoder<'a> {
992988 return Err ( Error :: parse_error ( "malformed mutability" ) ) ;
993989 }
994990
995- // Parse value type
996- let value_type = match value_type_byte {
997- 0x7F => wrt_foundation:: ValueType :: I32 ,
998- 0x7E => wrt_foundation:: ValueType :: I64 ,
999- 0x7D => wrt_foundation:: ValueType :: F32 ,
1000- 0x7C => wrt_foundation:: ValueType :: F64 ,
1001- 0x7B => wrt_foundation:: ValueType :: V128 ,
1002- 0x70 => wrt_foundation:: ValueType :: FuncRef ,
1003- 0x6F => wrt_foundation:: ValueType :: ExternRef ,
1004- 0x69 => wrt_foundation:: ValueType :: ExnRef ,
1005- _ => return Err ( Error :: parse_error ( "Invalid global import value type" ) ) ,
1006- } ;
1007-
1008991 #[ cfg( feature = "tracing" ) ]
1009992 trace ! ( import_index = i, value_type = ?value_type, mutable = ( mutability_byte != 0 ) , "import: global" ) ;
1010993
@@ -1162,22 +1145,13 @@ impl<'a> StreamingDecoder<'a> {
11621145 offset += 1 ;
11631146 }
11641147
1165- // Now parse the ref_type
1166- if offset >= data. len ( ) {
1167- return Err ( Error :: parse_error (
1168- "Unexpected end of table section (ref_type)" ,
1169- ) ) ;
1170- }
1171- let ref_type_byte = data[ offset] ;
1172- offset += 1 ;
1148+ // Now parse the ref_type using the full GC-aware parser
1149+ let ( value_type, new_offset) = self . parse_value_type ( data, offset) ?;
1150+ offset = new_offset;
11731151
1174- let element_type = match ref_type_byte {
1175- 0x70 => RefType :: Funcref , // funcref
1176- 0x6F => RefType :: Externref , // externref
1177- _ => {
1178- return Err ( Error :: parse_error ( "Unknown table element type" ) ) ;
1179- } ,
1180- } ;
1152+ let element_type = RefType :: try_from ( value_type) . map_err ( |_| {
1153+ Error :: parse_error ( "Unknown table element type" )
1154+ } ) ?;
11811155
11821156 // Parse limits (flags + min, optional max)
11831157 if offset >= data. len ( ) {
@@ -1742,13 +1716,11 @@ impl<'a> StreamingDecoder<'a> {
17421716 } ,
17431717 1 => {
17441718 // Passive, element type, expressions
1745- let elem_type = data[ offset] ;
1746- offset += 1 ;
1747- let ref_type = match elem_type {
1748- 0x70 => wrt_format:: types:: RefType :: Funcref ,
1749- 0x6F => wrt_format:: types:: RefType :: Externref ,
1750- _ => wrt_format:: types:: RefType :: Funcref ,
1751- } ;
1719+ let ( vt, new_offset) = self . parse_value_type ( data, offset) ?;
1720+ offset = new_offset;
1721+ let ref_type = wrt_format:: types:: RefType :: try_from ( vt) . map_err ( |_| {
1722+ Error :: parse_error ( "Invalid element segment reference type" )
1723+ } ) ?;
17521724 #[ cfg( feature = "tracing" ) ]
17531725 trace ! ( elem_idx = elem_idx, ref_type = ?ref_type, "element: passive" ) ;
17541726 ( PureElementMode :: Passive , Vec :: new ( ) , ref_type)
@@ -1789,13 +1761,11 @@ impl<'a> StreamingDecoder<'a> {
17891761 } ,
17901762 3 => {
17911763 // Declarative, element type, expressions
1792- let elem_type = data[ offset] ;
1793- offset += 1 ;
1794- let ref_type = match elem_type {
1795- 0x70 => wrt_format:: types:: RefType :: Funcref ,
1796- 0x6F => wrt_format:: types:: RefType :: Externref ,
1797- _ => wrt_format:: types:: RefType :: Funcref ,
1798- } ;
1764+ let ( vt, new_offset) = self . parse_value_type ( data, offset) ?;
1765+ offset = new_offset;
1766+ let ref_type = wrt_format:: types:: RefType :: try_from ( vt) . map_err ( |_| {
1767+ Error :: parse_error ( "Invalid element segment reference type" )
1768+ } ) ?;
17991769 #[ cfg( feature = "tracing" ) ]
18001770 trace ! ( elem_idx = elem_idx, ref_type = ?ref_type, "element: declarative" ) ;
18011771 ( PureElementMode :: Declared , Vec :: new ( ) , ref_type)
@@ -1825,13 +1795,11 @@ impl<'a> StreamingDecoder<'a> {
18251795 } ,
18261796 5 => {
18271797 // Passive, expressions with type
1828- let ref_type_byte = data[ offset] ;
1829- offset += 1 ;
1830- let ref_type = match ref_type_byte {
1831- 0x70 => wrt_format:: types:: RefType :: Funcref ,
1832- 0x6F => wrt_format:: types:: RefType :: Externref ,
1833- _ => wrt_format:: types:: RefType :: Funcref ,
1834- } ;
1798+ let ( vt, new_offset) = self . parse_value_type ( data, offset) ?;
1799+ offset = new_offset;
1800+ let ref_type = wrt_format:: types:: RefType :: try_from ( vt) . map_err ( |_| {
1801+ Error :: parse_error ( "Invalid element segment reference type" )
1802+ } ) ?;
18351803 #[ cfg( feature = "tracing" ) ]
18361804 trace ! ( elem_idx = elem_idx, ref_type = ?ref_type, "element: passive with type" ) ;
18371805 ( PureElementMode :: Passive , Vec :: new ( ) , ref_type)
@@ -1848,18 +1816,11 @@ impl<'a> StreamingDecoder<'a> {
18481816 let offset_expr_bytes: Vec < u8 > = data[ expr_start..offset] . to_vec ( ) ;
18491817
18501818 // Parse ref_type (comes after offset expression, before items)
1851- if offset >= data. len ( ) {
1852- return Err ( Error :: parse_error (
1853- "Unexpected end of element segment (ref_type)" ,
1854- ) ) ;
1855- }
1856- let ref_type_byte = data[ offset] ;
1857- offset += 1 ;
1858- let ref_type = match ref_type_byte {
1859- 0x70 => wrt_format:: types:: RefType :: Funcref ,
1860- 0x6F => wrt_format:: types:: RefType :: Externref ,
1861- _ => wrt_format:: types:: RefType :: Funcref ,
1862- } ;
1819+ let ( vt, new_offset) = self . parse_value_type ( data, offset) ?;
1820+ offset = new_offset;
1821+ let ref_type = wrt_format:: types:: RefType :: try_from ( vt) . map_err ( |_| {
1822+ Error :: parse_error ( "Invalid element segment reference type" )
1823+ } ) ?;
18631824
18641825 #[ cfg( feature = "tracing" ) ]
18651826 trace ! ( elem_idx = elem_idx, table_index = table_index, offset_expr_len = offset_expr_bytes. len( ) , ref_type = ?ref_type, "element: active with expressions" ) ;
@@ -1875,13 +1836,11 @@ impl<'a> StreamingDecoder<'a> {
18751836 } ,
18761837 7 => {
18771838 // Declarative, expressions with type
1878- let ref_type_byte = data[ offset] ;
1879- offset += 1 ;
1880- let ref_type = match ref_type_byte {
1881- 0x70 => wrt_format:: types:: RefType :: Funcref ,
1882- 0x6F => wrt_format:: types:: RefType :: Externref ,
1883- _ => wrt_format:: types:: RefType :: Funcref ,
1884- } ;
1839+ let ( vt, new_offset) = self . parse_value_type ( data, offset) ?;
1840+ offset = new_offset;
1841+ let ref_type = wrt_format:: types:: RefType :: try_from ( vt) . map_err ( |_| {
1842+ Error :: parse_error ( "Invalid element segment reference type" )
1843+ } ) ?;
18851844 #[ cfg( feature = "tracing" ) ]
18861845 trace ! ( elem_idx = elem_idx, ref_type = ?ref_type, "element: declarative with type" ) ;
18871846 ( PureElementMode :: Declared , Vec :: new ( ) , ref_type)
@@ -2050,34 +2009,40 @@ impl<'a> StreamingDecoder<'a> {
20502009
20512010 // Code section index i corresponds to module-defined function at index (num_imports + i)
20522011 let func_index = num_imports + i as usize ;
2053- if let Some ( func) = self . module . functions . get_mut ( func_index) {
2054- // Parse local variable declarations
2055- for _ in 0 ..local_count {
2056- let ( count, bytes) = read_leb128_u32 ( & data[ body_start..body_end] , body_offset) ?;
2057- body_offset += bytes;
20582012
2059- if body_offset >= body_size as usize {
2060- return Err ( Error :: parse_error ( "Unexpected end of function body" ) ) ;
2061- }
2013+ // Parse local variable declarations first (requires &self for parse_value_type)
2014+ // We collect locals into a temporary vec to avoid borrow conflicts with self.module
2015+ let mut parsed_locals: Vec < ( u32 , wrt_foundation:: types:: ValueType ) > = Vec :: new ( ) ;
2016+ let mut total_locals_count: usize = 0 ;
2017+ for _ in 0 ..local_count {
2018+ let ( count, bytes) = read_leb128_u32 ( & data[ body_start..body_end] , body_offset) ?;
2019+ body_offset += bytes;
20622020
2063- let value_type = data[ body_start + body_offset] ;
2064- body_offset += 1 ;
2065-
2066- // Convert to ValueType and add to locals
2067- let vt = match value_type {
2068- 0x7F => wrt_foundation:: types:: ValueType :: I32 ,
2069- 0x7E => wrt_foundation:: types:: ValueType :: I64 ,
2070- 0x7D => wrt_foundation:: types:: ValueType :: F32 ,
2071- 0x7C => wrt_foundation:: types:: ValueType :: F64 ,
2072- 0x7B => wrt_foundation:: types:: ValueType :: V128 ,
2073- 0x70 => wrt_foundation:: types:: ValueType :: FuncRef ,
2074- 0x6F => wrt_foundation:: types:: ValueType :: ExternRef ,
2075- 0x69 => wrt_foundation:: types:: ValueType :: ExnRef ,
2076- _ => return Err ( Error :: parse_error ( "Invalid local type" ) ) ,
2077- } ;
2021+ if body_offset >= body_size as usize {
2022+ return Err ( Error :: parse_error ( "Unexpected end of function body" ) ) ;
2023+ }
2024+
2025+ // Use the full GC-aware value type parser for local types
2026+ let ( vt, new_abs_offset) =
2027+ self . parse_value_type ( data, body_start + body_offset) ?;
2028+ body_offset = new_abs_offset - body_start;
20782029
2079- // Validate total locals against platform limits before allocation
2080- let new_total = func. locals . len ( ) + count as usize ;
2030+ // Validate total locals against platform limits before allocation
2031+ total_locals_count += count as usize ;
2032+ if total_locals_count > limits:: MAX_FUNCTION_LOCALS {
2033+ return Err ( Error :: parse_error (
2034+ "Function exceeds maximum local count for platform" ,
2035+ ) ) ;
2036+ }
2037+
2038+ parsed_locals. push ( ( count, vt) ) ;
2039+ }
2040+
2041+ // Now apply the parsed locals to the function (requires &mut self.module)
2042+ if let Some ( func) = self . module . functions . get_mut ( func_index) {
2043+ for ( count, vt) in & parsed_locals {
2044+ // Validate total locals including existing ones
2045+ let new_total = func. locals . len ( ) + * count as usize ;
20812046 if new_total > limits:: MAX_FUNCTION_LOCALS {
20822047 return Err ( Error :: parse_error (
20832048 "Function exceeds maximum local count for platform" ,
@@ -2089,12 +2054,12 @@ impl<'a> StreamingDecoder<'a> {
20892054 AllocationPhase :: Decode ,
20902055 "streaming_decoder:func_locals" ,
20912056 "locals" ,
2092- count as usize
2057+ * count as usize
20932058 ) ;
20942059
20952060 // Add 'count' locals of this type
2096- for _ in 0 ..count {
2097- func. locals . push ( vt) ;
2061+ for _ in 0 ..* count {
2062+ func. locals . push ( * vt) ;
20982063 }
20992064 }
21002065
0 commit comments