@@ -1759,7 +1759,6 @@ impl<'a, 'b> Compiler<'a, 'b> {
17591759 dst_enc : FE ,
17601760 ) -> WasmString < ' c > {
17611761 assert ! ( dst_enc. width( ) >= src_enc. width( ) ) ;
1762- self . validate_string_length ( src, dst_enc) ;
17631762
17641763 let src_mem_opts = {
17651764 match & src. opts . data_model {
@@ -1774,22 +1773,8 @@ impl<'a, 'b> Compiler<'a, 'b> {
17741773 }
17751774 } ;
17761775
1777- // Calculate the source byte length given the size of each code
1778- // unit. Note that this shouldn't overflow given
1779- // `validate_string_length` above.
1780- let mut src_byte_len_tmp = None ;
1781- let src_byte_len = if src_enc. width ( ) == 1 {
1782- src. len . idx
1783- } else {
1784- assert_eq ! ( src_enc. width( ) , 2 ) ;
1785- self . instruction ( LocalGet ( src. len . idx ) ) ;
1786- self . ptr_uconst ( src_mem_opts, 1 ) ;
1787- self . ptr_shl ( src_mem_opts) ;
1788- let tmp = self . local_set_new_tmp ( src. opts . data_model . unwrap_memory ( ) . ptr ( ) ) ;
1789- let ret = tmp. idx ;
1790- src_byte_len_tmp = Some ( tmp) ;
1791- ret
1792- } ;
1776+ let ( src_byte_len_tmp, src_byte_len) =
1777+ self . source_string_byte_len ( src, src_enc, src_mem_opts) ;
17931778
17941779 // Convert the source code units length to the destination byte
17951780 // length type.
@@ -1851,6 +1836,39 @@ impl<'a, 'b> Compiler<'a, 'b> {
18511836
18521837 dst
18531838 }
1839+
1840+ /// Calculate the source byte length given the size of each code
1841+ /// unit.
1842+ ///
1843+ /// Returns an optional temporary local if it was needed, which the caller
1844+ /// needs to deallocate with `free_temp_local`. Additionally returns the
1845+ /// index of the local which contains the byte length of the string, which
1846+ /// may point to the temporary local passed in.
1847+ fn source_string_byte_len (
1848+ & mut self ,
1849+ src : & WasmString < ' _ > ,
1850+ src_enc : FE ,
1851+ src_mem_opts : & LinearMemoryOptions ,
1852+ ) -> ( Option < TempLocal > , u32 ) {
1853+ self . validate_string_length ( src, src_enc) ;
1854+
1855+ if src_enc. width ( ) == 1 {
1856+ ( None , src. len . idx )
1857+ } else {
1858+ assert_eq ! ( src_enc. width( ) , 2 ) ;
1859+
1860+ // Note that this shouldn't overflow given `validate_string_length`
1861+ // above.
1862+ self . instruction ( LocalGet ( src. len . idx ) ) ;
1863+ self . ptr_uconst ( src_mem_opts, 1 ) ;
1864+ self . ptr_shl ( src_mem_opts) ;
1865+ let tmp = self . local_set_new_tmp ( src. opts . data_model . unwrap_memory ( ) . ptr ( ) ) ;
1866+
1867+ let idx = tmp. idx ;
1868+ ( Some ( tmp) , idx)
1869+ }
1870+ }
1871+
18541872 // Corresponding function for `store_string_to_utf8` in the spec.
18551873 //
18561874 // This translation works by possibly performing a number of
@@ -2252,7 +2270,9 @@ impl<'a, 'b> Compiler<'a, 'b> {
22522270 DataModel :: LinearMemory ( opts) => opts,
22532271 } ;
22542272
2255- self . validate_string_length ( src, src_enc) ;
2273+ let ( src_byte_len_tmp, src_byte_len) =
2274+ self . source_string_byte_len ( src, src_enc, src_mem_opts) ;
2275+
22562276 self . convert_src_len_to_dst ( src. len . idx , src_mem_opts. ptr ( ) , dst_mem_opts. ptr ( ) ) ;
22572277 let dst_len = self . local_tee_new_tmp ( dst_mem_opts. ptr ( ) ) ;
22582278 let dst_byte_len = self . local_set_new_tmp ( dst_mem_opts. ptr ( ) ) ;
@@ -2265,7 +2285,7 @@ impl<'a, 'b> Compiler<'a, 'b> {
22652285 }
22662286 } ;
22672287
2268- self . validate_string_inbounds ( src, src . len . idx ) ;
2288+ self . validate_string_inbounds ( src, src_byte_len ) ;
22692289 self . validate_string_inbounds ( & dst, dst_byte_len. idx ) ;
22702290
22712291 // Perform the initial latin1 transcode. This returns the number of
@@ -2384,6 +2404,9 @@ impl<'a, 'b> Compiler<'a, 'b> {
23842404
23852405 self . free_temp_local ( src_len_tmp) ;
23862406 self . free_temp_local ( dst_byte_len) ;
2407+ if let Some ( tmp) = src_byte_len_tmp {
2408+ self . free_temp_local ( tmp) ;
2409+ }
23872410
23882411 dst
23892412 }
0 commit comments