@@ -1486,6 +1486,25 @@ fn write_to_wasm(
1486
1486
}
1487
1487
}
1488
1488
1489
+ /// Ensure the memory is large enough to write the given number of bytes.
1490
+ fn ensure_memory (
1491
+ memory : & Memory ,
1492
+ store : & mut impl AsContextMut ,
1493
+ required_bytes : usize ,
1494
+ ) -> Result < ( ) , Error > {
1495
+ // Round up division.
1496
+ let required_pages = ( ( required_bytes + 65535 ) / 65536 ) as u64 ;
1497
+ let current_pages = memory. size ( store. as_context_mut ( ) ) ;
1498
+ // If the current memory is not large enough, grow it by the required
1499
+ // number of pages.
1500
+ if current_pages < required_pages {
1501
+ memory
1502
+ . grow ( store. as_context_mut ( ) , required_pages - current_pages)
1503
+ . map_err ( |e| Error :: Wasm ( WasmError :: UnableToWriteMemory ( e. into ( ) ) ) ) ?;
1504
+ }
1505
+ Ok ( ( ) )
1506
+ }
1507
+
1489
1508
/// Convert a Clarity `Value` into one or more Wasm `Val`. If this value
1490
1509
/// requires writing into the Wasm memory, write it to the provided `offset`.
1491
1510
/// Return a vector of `Val`s that can be passed to a Wasm function, and the
@@ -1585,6 +1604,9 @@ fn pass_argument_to_wasm(
1585
1604
Ok ( ( buffer, new_offset, new_in_mem_offset) )
1586
1605
}
1587
1606
Value :: Sequence ( SequenceData :: String ( CharType :: ASCII ( s) ) ) => {
1607
+ let required_bytes = ( in_mem_offset as usize ) + s. data . len ( ) ;
1608
+ ensure_memory ( & memory, & mut store, required_bytes) ?;
1609
+
1588
1610
// For a string, write the bytes into the memory, then pass the
1589
1611
// offset and length to the Wasm function.
1590
1612
let buffer = vec ! [ Val :: I32 ( in_mem_offset) , Val :: I32 ( s. data. len( ) as i32 ) ] ;
@@ -1599,6 +1621,9 @@ fn pass_argument_to_wasm(
1599
1621
Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1600
1622
}
1601
1623
Value :: Sequence ( SequenceData :: String ( CharType :: UTF8 ( s) ) ) => {
1624
+ let required_bytes = ( in_mem_offset as usize ) + s. data . len ( ) ;
1625
+ ensure_memory ( & memory, & mut store, required_bytes) ?;
1626
+
1602
1627
// For a utf8 string, convert the chars to big-endian i32, convert this into a list of
1603
1628
// bytes, then pass the offset and length to the wasm function
1604
1629
let bytes: Vec < u8 > = String :: from_utf8 ( s. items ( ) . iter ( ) . flatten ( ) . copied ( ) . collect ( ) )
@@ -1614,6 +1639,9 @@ fn pass_argument_to_wasm(
1614
1639
Ok ( ( buffer, offset, adjusted_in_mem_offset) )
1615
1640
}
1616
1641
Value :: Sequence ( SequenceData :: Buffer ( b) ) => {
1642
+ let required_bytes = ( in_mem_offset as usize ) + b. data . len ( ) ;
1643
+ ensure_memory ( & memory, & mut store, required_bytes) ?;
1644
+
1617
1645
// For a buffer, write the bytes into the memory, then pass the
1618
1646
// offset and length to the Wasm function.
1619
1647
let buffer = vec ! [ Val :: I32 ( in_mem_offset) , Val :: I32 ( b. data. len( ) as i32 ) ] ;
@@ -1631,6 +1659,13 @@ fn pass_argument_to_wasm(
1631
1659
let TypeSignature :: SequenceType ( SequenceSubtype :: ListType ( ltd) ) = ty else {
1632
1660
return Err ( Error :: Wasm ( WasmError :: ValueTypeMismatch ) ) ;
1633
1661
} ;
1662
+ let total_bytes = l
1663
+ . data
1664
+ . iter ( )
1665
+ . map ( |_| get_type_in_memory_size ( ltd. get_list_item_type ( ) , true ) )
1666
+ . sum :: < i32 > ( ) as usize ;
1667
+ let required_bytes = ( in_mem_offset as usize ) + total_bytes;
1668
+ ensure_memory ( & memory, & mut store, required_bytes) ?;
1634
1669
1635
1670
let mut buffer = vec ! [ Val :: I32 ( offset) ] ;
1636
1671
let mut written = 0 ;
0 commit comments