Skip to content

Commit 5719f57

Browse files
committed
miri add write_bytes method to Memory doing bounds-checks and supporting iterators
1 parent e66a628 commit 5719f57

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

src/librustc/mir/interpret/allocation.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,16 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
346346
&mut self,
347347
cx: &impl HasDataLayout,
348348
ptr: Pointer<Tag>,
349-
src: &[u8],
349+
src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
350350
) -> InterpResult<'tcx>
351351
{
352+
let mut src = src.into_iter();
352353
let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?;
353-
bytes.clone_from_slice(src);
354+
// `zip` would stop when the first iterator ends; we want to definitely
355+
// cover all of `bytes`.
356+
for dest in bytes {
357+
*dest = src.next().expect("iterator was shorter than it said it would be");
358+
}
354359
Ok(())
355360
}
356361

src/librustc_mir/interpret/memory.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! short-circuiting the empty case!
88
99
use std::collections::VecDeque;
10-
use std::ptr;
10+
use std::{ptr, iter};
1111
use std::borrow::Cow;
1212

1313
use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
@@ -785,6 +785,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
785785
self.get(ptr.alloc_id)?.read_c_str(self, ptr)
786786
}
787787

788+
/// Writes the given stream of bytes into memory.
789+
///
790+
/// Performs appropriate bounds checks.
791+
pub fn write_bytes(
792+
&mut self,
793+
ptr: Scalar<M::PointerTag>,
794+
src: impl IntoIterator<Item=u8, IntoIter: iter::ExactSizeIterator>,
795+
) -> InterpResult<'tcx>
796+
{
797+
let src = src.into_iter();
798+
let size = Size::from_bytes(src.len() as u64);
799+
let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
800+
Some(ptr) => ptr,
801+
None => return Ok(()), // zero-sized access
802+
};
803+
let tcx = self.tcx.tcx;
804+
self.get_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
805+
}
806+
788807
/// Expects the caller to have checked bounds and alignment.
789808
pub fn copy(
790809
&mut self,

0 commit comments

Comments
 (0)