@@ -215,9 +215,7 @@ impl Interval {
215
215
}
216
216
217
217
fn write_from_interval ( & self , memory : & mut Evaluator < ' _ > , interval : Interval ) -> Result < ( ) > {
218
- // FIXME: this could be more efficient
219
- let bytes = & interval. get ( memory) ?. to_vec ( ) ;
220
- memory. write_memory ( self . addr , bytes)
218
+ memory. copy_from_interval ( self . addr , interval)
221
219
}
222
220
223
221
fn slice ( self , range : Range < usize > ) -> Interval {
@@ -1760,6 +1758,48 @@ impl Evaluator<'_> {
1760
1758
Ok ( ( ) )
1761
1759
}
1762
1760
1761
+ fn copy_from_interval ( & mut self , addr : Address , r : Interval ) -> Result < ( ) > {
1762
+ if r. size == 0 {
1763
+ return Ok ( ( ) ) ;
1764
+ }
1765
+
1766
+ let oob = || MirEvalError :: UndefinedBehavior ( "out of bounds memory write" . to_string ( ) ) ;
1767
+
1768
+ match ( addr, r. addr ) {
1769
+ ( Stack ( dst) , Stack ( src) ) => {
1770
+ if self . stack . len ( ) < src + r. size || self . stack . len ( ) < dst + r. size {
1771
+ return Err ( oob ( ) ) ;
1772
+ }
1773
+ self . stack . copy_within ( src..src + r. size , dst)
1774
+ }
1775
+ ( Heap ( dst) , Heap ( src) ) => {
1776
+ if self . stack . len ( ) < src + r. size || self . stack . len ( ) < dst + r. size {
1777
+ return Err ( oob ( ) ) ;
1778
+ }
1779
+ self . heap . copy_within ( src..src + r. size , dst)
1780
+ }
1781
+ ( Stack ( dst) , Heap ( src) ) => {
1782
+ self . stack
1783
+ . get_mut ( dst..dst + r. size )
1784
+ . ok_or_else ( oob) ?
1785
+ . copy_from_slice ( self . heap . get ( src..src + r. size ) . ok_or_else ( oob) ?) ;
1786
+ }
1787
+ ( Heap ( dst) , Stack ( src) ) => {
1788
+ self . heap
1789
+ . get_mut ( dst..dst + r. size )
1790
+ . ok_or_else ( oob) ?
1791
+ . copy_from_slice ( self . stack . get ( src..src + r. size ) . ok_or_else ( oob) ?) ;
1792
+ }
1793
+ _ => {
1794
+ return Err ( MirEvalError :: UndefinedBehavior ( format ! (
1795
+ "invalid memory write at address {addr:?}"
1796
+ ) ) )
1797
+ }
1798
+ }
1799
+
1800
+ Ok ( ( ) )
1801
+ }
1802
+
1763
1803
fn size_align_of ( & self , ty : & Ty , locals : & Locals ) -> Result < Option < ( usize , usize ) > > {
1764
1804
if let Some ( layout) = self . layout_cache . borrow ( ) . get ( ty) {
1765
1805
return Ok ( layout
0 commit comments