diff options
| author | Oliver Schneider <oli-obk@users.noreply.github.com> | 2017-08-28 16:11:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-28 16:11:48 +0200 |
| commit | 44a360d8ba3cd77e86fcb510808e2b1c550d4c46 (patch) | |
| tree | a9a59063b49dd176107e30694c42d49596a6f390 | |
| parent | b93462a8db2794151a653cc0c01c87216c0c3457 (diff) | |
| parent | 385b5b9fd138a9d27d05c21876665fdc5dca052a (diff) | |
| download | rust-44a360d8ba3cd77e86fcb510808e2b1c550d4c46.tar.gz rust-44a360d8ba3cd77e86fcb510808e2b1c550d4c46.zip | |
Merge pull request #316 from solson/priroda
Fix relocation copying in overlapping copies
| -rw-r--r-- | miri/lib.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/memory.rs | 38 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/mod.rs | 2 | ||||
| -rw-r--r-- | tests/run-pass/btreemap.rs | 17 |
4 files changed, 38 insertions, 28 deletions
diff --git a/miri/lib.rs b/miri/lib.rs index 204746244c8..852a4cbe2aa 100644 --- a/miri/lib.rs +++ b/miri/lib.rs @@ -6,11 +6,8 @@ // From rustc. #[macro_use] extern crate log; -extern crate log_settings; #[macro_use] extern crate rustc; -extern crate rustc_const_math; -extern crate rustc_data_structures; extern crate syntax; use rustc::ty::{self, TyCtxt}; @@ -146,9 +143,9 @@ pub fn eval_main<'a, 'tcx: 'a>( } } -struct Evaluator; +pub struct Evaluator; #[derive(Default)] -struct EvaluatorData { +pub struct EvaluatorData { /// Environment variables set by `setenv` /// Miri does not expose env vars from the host to the emulated program pub(crate) env_vars: HashMap<Vec<u8>, MemoryPointer>, @@ -163,7 +160,7 @@ pub struct TlsEntry<'tcx> { } #[derive(Default)] -struct MemoryData<'tcx> { +pub struct MemoryData<'tcx> { /// The Key to use for the next thread-local allocation. next_thread_local: TlsKey, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9930555c199..34de9596f24 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -79,7 +79,7 @@ impl LockInfo { pub struct AllocId(u64); #[derive(Debug)] -enum AllocIdKind { +pub enum AllocIdKind { /// We can't ever have more than `usize::max_value` functions at the same time /// since we never "deallocate" functions Function(usize), @@ -89,7 +89,7 @@ enum AllocIdKind { } impl AllocIdKind { - fn into_alloc_id(self) -> AllocId { + pub fn into_alloc_id(self) -> AllocId { match self { AllocIdKind::Function(n) => AllocId(n as u64), AllocIdKind::Runtime(n) => AllocId((1 << 63) | n), @@ -103,10 +103,10 @@ impl AllocId { self.0 >> 63 } /// Yields everything but the discriminant bits - fn index(self) -> u64 { + pub fn index(self) -> u64 { self.0 & ((1 << 63) - 1) } - fn into_alloc_id_kind(self) -> AllocIdKind { + pub fn into_alloc_id_kind(self) -> AllocIdKind { match self.discriminant() { 0 => AllocIdKind::Function(self.index() as usize), 1 => AllocIdKind::Runtime(self.index()), @@ -1088,6 +1088,17 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { let dest = dest.to_ptr()?; self.check_relocation_edges(src, size)?; + // first copy the relocations to a temporary buffer, because + // `get_bytes_mut` will clear the relocations, which is correct, + // since we don't want to keep any relocations at the target. + + let relocations: Vec<_> = self.relocations(src, size)? + .map(|(&offset, &alloc_id)| { + // Update relocation offsets for the new positions in the destination allocation. + (offset + dest.offset - src.offset, alloc_id) + }) + .collect(); + let src_bytes = self.get_bytes_unchecked(src, size, align)?.as_ptr(); let dest_bytes = self.get_bytes_mut(dest, size, align)?.as_mut_ptr(); @@ -1113,7 +1124,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } self.copy_undef_mask(src, dest, size)?; - self.copy_relocations(src, dest, size)?; + // copy back the relocations + self.get_mut(dest.alloc_id)?.relocations.extend(relocations); Ok(()) } @@ -1388,22 +1400,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> { } Ok(()) } - - fn copy_relocations( - &mut self, - src: MemoryPointer, - dest: MemoryPointer, - size: u64, - ) -> EvalResult<'tcx> { - let relocations: Vec<_> = self.relocations(src, size)? - .map(|(&offset, &alloc_id)| { - // Update relocation offsets for the new positions in the destination allocation. - (offset + dest.offset - src.offset, alloc_id) - }) - .collect(); - self.get_mut(dest.alloc_id)?.relocations.extend(relocations); - Ok(()) - } } /// Undefined bytes diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index 3a5fdf273a4..603451a9442 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -27,7 +27,7 @@ pub use self::eval_context::{EvalContext, Frame, ResourceLimits, StackPopCleanup pub use self::lvalue::{Lvalue, LvalueExtra, GlobalId}; -pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory}; +pub use self::memory::{AllocId, Memory, MemoryPointer, MemoryKind, HasMemory, AllocIdKind}; use self::memory::{PointerArithmetic, Lock, AccessKind}; diff --git a/tests/run-pass/btreemap.rs b/tests/run-pass/btreemap.rs new file mode 100644 index 00000000000..55e6b07a658 --- /dev/null +++ b/tests/run-pass/btreemap.rs @@ -0,0 +1,17 @@ +// mir validation can't cope with `mem::uninitialized::<SomeEnum>()` +// compile-flags: -Zmir-emit-validate=0 + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum Foo { + A(&'static str), + _B, + _C, +} + +pub fn main() { + let mut b = std::collections::BTreeSet::new(); + b.insert(Foo::A("\'")); + b.insert(Foo::A("/=")); + b.insert(Foo::A("#")); + b.insert(Foo::A("0o")); +} |
