]> git.lizzy.rs Git - rust.git/commitdiff
Fix merge conflicts
authorChristian Poveda <christianpoveda@protonmail.com>
Tue, 25 Jun 2019 02:47:37 +0000 (21:47 -0500)
committerChristian Poveda <christianpoveda@protonmail.com>
Tue, 25 Jun 2019 05:57:33 +0000 (00:57 -0500)
26 files changed:
.appveyor.yml
.travis.yml
rust-version
src/fn_call.rs
src/intrinsic.rs
src/operator.rs
src/stacked_borrows.rs
tests/compile-fail/generator-pinned-moved.rs [new file with mode: 0644]
tests/compile-fail/ptr_eq_dangling.rs
tests/compile-fail/ptr_eq_out_of_bounds.rs
tests/compile-fail/rc_as_raw.rs
tests/compile-fail/unaligned_ptr1.rs [new file with mode: 0644]
tests/compile-fail/unaligned_ptr2.rs [new file with mode: 0644]
tests/compile-fail/unaligned_ptr3.rs [new file with mode: 0644]
tests/compile-fail/unaligned_ptr_cast1.rs [deleted file]
tests/compile-fail/unaligned_ptr_cast2.rs [deleted file]
tests/compile-fail/unaligned_ptr_cast_zst.rs [deleted file]
tests/compile-fail/unaligned_ptr_zst.rs [new file with mode: 0644]
tests/compile-fail/validity/dangling_ref1.rs
tests/compile-fail/validity/dangling_ref2.rs
tests/compile-fail/zst.rs [deleted file]
tests/compile-fail/zst1.rs [new file with mode: 0644]
tests/compile-fail/zst2.rs [new file with mode: 0644]
tests/compile-fail/zst3.rs [new file with mode: 0644]
tests/run-pass/intptrcast-truncate.rs
tests/run-pass/zst.rs

index 5080a22aded9781e8ec50156b3e1fb611286c77e..f7d3f990ac999943a4a81a127061ff8327bfbf13 100644 (file)
@@ -9,7 +9,8 @@ environment:
 branches:
   # whitelist
   only:
-    - master
+    - auto
+    - try
 
 cache:
     - '%USERPROFILE%\.cargo'
index 1ba55e0c724a527d0422ec4ef71eab94406ad930..7db62bc74bd434b268e273e77fda4acd281e2121 100644 (file)
@@ -12,6 +12,9 @@ os:
 - osx
 dist: xenial
 
+# Run in PRs and for bors, but not on master.
+if: branch = auto OR branch = try OR type = pull_request OR type = cron
+
 env:
   global:
   - RUST_TEST_NOCAPTURE=1
@@ -53,3 +56,5 @@ notifications:
 branches:
   only:
   - master
+  - auto
+  - try
index f09338fca150fc5bd7d12a8559b21e7a638faebd..17338728254ad0f5cd4d48769123abd7b0d5e56c 100644 (file)
@@ -1 +1 @@
-56a12b2ad058f22f1ef090713df15598525ba4a4
+7e08576e4276a97b523c25bfd196d419c39c7b87
index e47e2169121175aa23a8f46999216d40d72ebcc4..e2a4daa6f385353757dbcfa7b5838d03fb4d0c32 100644 (file)
@@ -654,7 +654,7 @@ fn emulate_foreign_item(
 
             // Hook pthread calls that go to the thread-local storage memory subsystem.
             "pthread_key_create" => {
-                let key_ptr = this.read_scalar(args[0])?.to_ptr()?;
+                let key_ptr = this.read_scalar(args[0])?.not_undef()?;
 
                 // Extract the function type out of the signature (that seems easier than constructing it ourselves).
                 let dtor = match this.read_scalar(args[1])?.not_undef()? {
@@ -681,7 +681,8 @@ fn emulate_foreign_item(
                     return err!(OutOfTls);
                 }
 
-                this.memory().check_align(key_ptr.into(), key_layout.align.abi)?;
+                let key_ptr = this.memory().check_ptr_access(key_ptr, key_layout.size, key_layout.align.abi)?
+                    .expect("cannot be a ZST");
                 this.memory_mut().get_mut(key_ptr.alloc_id)?.write_scalar(
                     tcx,
                     key_ptr,
index 0ecccd02d7e1b6a6c92f26c531b8d665dfd03ba9..3f9c4e53f09d6f25ea15955c49f8355172055839 100644 (file)
@@ -505,7 +505,7 @@ fn call_intrinsic(
                             let ptr = mplace.ptr.to_ptr()?;
                             this.memory_mut()
                                 .get_mut(ptr.alloc_id)?
-                                .mark_definedness(ptr, dest.layout.size, false)?;
+                                .mark_definedness(ptr, dest.layout.size, false);
                         }
                     }
                 }
@@ -517,13 +517,16 @@ fn call_intrinsic(
                 let val_byte = this.read_scalar(args[1])?.to_u8()?;
                 let ptr = this.read_scalar(args[0])?.not_undef()?;
                 let count = this.read_scalar(args[2])?.to_usize(this)?;
-                this.memory().check_align(ptr, ty_layout.align.abi)?;
                 let byte_count = ty_layout.size * count;
-                if byte_count.bytes() != 0 {
-                    let ptr = ptr.to_ptr()?;
-                    this.memory_mut()
-                        .get_mut(ptr.alloc_id)?
-                        .write_repeat(tcx, ptr, val_byte, byte_count)?;
+                match this.memory().check_ptr_access(ptr, byte_count, ty_layout.align.abi)? {
+                    Some(ptr) => {
+                        this.memory_mut()
+                            .get_mut(ptr.alloc_id)?
+                            .write_repeat(tcx, ptr, val_byte, byte_count)?;
+                    }
+                    None => {
+                        // Size is 0, nothing to do.
+                    }
                 }
             }
 
index 8f2b75d6043ad835adfedf08245d11d53d483ff8..572794a44add4604126d6929f6129a5c7647092c 100644 (file)
@@ -4,6 +4,11 @@
 use crate::*;
 
 pub trait EvalContextExt<'tcx> {
+    fn pointer_inbounds(
+        &self,
+        ptr: Pointer<Tag>
+    ) -> InterpResult<'tcx>;
+
     fn ptr_op(
         &self,
         bin_op: mir::BinOp,
@@ -34,6 +39,13 @@ fn pointer_offset_inbounds(
 }
 
 impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
+    /// Test if the pointer is in-bounds of a live allocation.
+    #[inline]
+    fn pointer_inbounds(&self, ptr: Pointer<Tag>) -> InterpResult<'tcx> {
+        let (size, _align) = self.memory().get_size_and_align(ptr.alloc_id, AllocCheck::Live)?;
+        ptr.check_in_alloc(size, CheckInAllocMsg::InboundsTest)
+    }
+
     fn ptr_op(
         &self,
         bin_op: mir::BinOp,
@@ -127,8 +139,8 @@ fn ptr_op(
                 let left = left.to_ptr().expect("we checked is_ptr");
                 let right = right.to_bits(self.memory().pointer_size()).expect("we checked is_bits");
                 let (_alloc_size, alloc_align) = self.memory()
-                    .get_size_and_align(left.alloc_id, InboundsCheck::MaybeDead)
-                    .expect("determining size+align of dead ptr cannot fail");
+                    .get_size_and_align(left.alloc_id, AllocCheck::MaybeDead)
+                    .expect("alloc info with MaybeDead cannot fail");
                 let min_ptr_val = u128::from(alloc_align.bytes()) + u128::from(left.offset.bytes());
                 let result = match bin_op {
                     Gt => min_ptr_val > right,
@@ -183,6 +195,7 @@ fn ptr_eq(
                 if left.alloc_id == right.alloc_id {
                     left.offset == right.offset
                 } else {
+                    // Make sure both pointers are in-bounds.
                     // This accepts one-past-the end. Thus, there is still technically
                     // some non-determinism that we do not fully rule out when two
                     // allocations sit right next to each other. The C/C++ standards are
@@ -192,10 +205,12 @@ fn ptr_eq(
                     // Dead allocations in miri cannot overlap with live allocations, but
                     // on read hardware this can easily happen. Thus for comparisons we require
                     // both pointers to be live.
-                    self.memory().check_bounds_ptr(left, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
-                    self.memory().check_bounds_ptr(right, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
-                    // Two in-bounds pointers, we can compare across allocations.
-                    left == right
+                    if self.pointer_inbounds(left).is_ok() && self.pointer_inbounds(right).is_ok() {
+                        // Two in-bounds pointers in different allocations are different.
+                        false
+                    } else {
+                        return err!(InvalidPointerMath);
+                    }
                 }
             }
             // Comparing ptr and integer.
@@ -215,16 +230,16 @@ fn ptr_eq(
                 // alignment 32 or higher, hence the limit of 32.
                 // FIXME: Once we support intptrcast, we could try to fix these holes.
                 if bits < 32 {
-                    // Test if the ptr is in-bounds. Then it cannot be NULL.
-                    // Even dangling pointers cannot be NULL.
-                    if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead, CheckInAllocMsg::NullPointerTest).is_ok() {
+                    // Test if the pointer can be different from NULL or not.
+                    // We assume that pointers that are not NULL are also not "small".
+                    if !self.memory().ptr_may_be_null(ptr) {
                         return Ok(false);
                     }
                 }
 
                 let (alloc_size, alloc_align) = self.memory()
-                    .get_size_and_align(ptr.alloc_id, InboundsCheck::MaybeDead)
-                    .expect("determining size+align of dead ptr cannot fail");
+                    .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
+                    .expect("alloc info with MaybeDead cannot fail");
 
                 // Case II: Alignment gives it away
                 if ptr.offset.bytes() % alloc_align.bytes() == 0 {
@@ -372,9 +387,9 @@ fn pointer_offset_inbounds(
         if let Scalar::Ptr(ptr) = ptr {
             // Both old and new pointer must be in-bounds of a *live* allocation.
             // (Of the same allocation, but that part is trivial with our representation.)
-            self.memory().check_bounds_ptr(ptr, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
+            self.pointer_inbounds(ptr)?;
             let ptr = ptr.signed_offset(offset, self)?;
-            self.memory().check_bounds_ptr(ptr, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
+            self.pointer_inbounds(ptr)?;
             Ok(Scalar::Ptr(ptr))
         } else {
             // An integer pointer. They can only be offset by 0, and we pretend there
index c47ad95c04b3b91c7070648b9038828f7d5a0c81..524ad2b47af0e0147a1fd7254d70aeb2ccdbf4fe 100644 (file)
@@ -10,8 +10,7 @@
 
 use crate::{
     InterpResult, InterpError, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
-    MemoryKind, MiriMemoryKind, RangeMap, AllocId, CheckInAllocMsg, Pointer, Immediate, ImmTy, 
-    PlaceTy, MPlaceTy,
+    MemoryKind, MiriMemoryKind, RangeMap, AllocId, Pointer, Immediate, ImmTy, PlaceTy, MPlaceTy,
 };
 
 pub type PtrId = NonZeroU64;
@@ -531,13 +530,14 @@ fn reborrow(
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let protector = if protect { Some(this.frame().extra) } else { None };
-        let ptr = place.ptr.to_ptr()?;
+        let ptr = this.memory().check_ptr_access(place.ptr, size, place.align)
+            .expect("validity checks should have excluded dangling/unaligned pointer")
+            .expect("we shouldn't get here for ZST");
         trace!("reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
             kind, new_tag, ptr.tag, place.layout.ty, ptr.erase_tag(), size.bytes());
 
         // Get the allocation. It might not be mutable, so we cannot use `get_mut`.
         let alloc = this.memory().get(ptr.alloc_id)?;
-        alloc.check_bounds(this, ptr, size, CheckInAllocMsg::InboundsTest)?;
         // Update the stacks.
         // Make sure that raw pointers and mutable shared references are reborrowed "weak":
         // There could be existing unique pointers reborrowed from them that should remain valid!
diff --git a/tests/compile-fail/generator-pinned-moved.rs b/tests/compile-fail/generator-pinned-moved.rs
new file mode 100644 (file)
index 0000000..2ae98ad
--- /dev/null
@@ -0,0 +1,44 @@
+#![feature(generators, generator_trait)]
+
+use std::{
+    ops::{Generator, GeneratorState},
+    pin::Pin,
+};
+
+fn firstn() -> impl Generator<Yield = u64, Return = ()> {
+    static move || {
+        let mut num = 0;
+        let num = &mut num;
+
+        yield *num;
+        *num += 1; //~ ERROR dangling pointer was dereferenced
+    }
+}
+
+struct GeneratorIteratorAdapter<G>(G);
+
+impl<G> Iterator for GeneratorIteratorAdapter<G>
+where
+    G: Generator<Return = ()>,
+{
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let me = unsafe { Pin::new_unchecked(&mut self.0) };
+        match me.resume() {
+            GeneratorState::Yielded(x) => Some(x),
+            GeneratorState::Complete(_) => None,
+        }
+    }
+}
+
+fn main() {
+    let mut generator_iterator_2 = {
+        let mut generator_iterator = GeneratorIteratorAdapter(firstn());
+        generator_iterator.next(); // pin it
+
+        generator_iterator // move it
+    }; // *deallocate* generator_iterator
+
+    generator_iterator_2.next(); // and use moved value
+}
index d05996a13d562fa26aa7977516b73c202031ec01..5badf099e4391ae5b939aa4f23abbdd2b5826224 100644 (file)
@@ -6,5 +6,5 @@ fn main() {
     let y = &*b as *const i32; // different allocation
     // We cannot compare these even though both are inbounds -- they *could* be
     // equal if memory was reused.
-    assert!(x != y); //~ ERROR dangling pointer
+    assert!(x != y); //~ ERROR invalid arithmetic on pointers
 }
index af4eed8d4e32ddb1acfa43e1e8e1305a7109504b..7efa446d7fca489f97254dd90bb0bdd9b428d979 100644 (file)
@@ -5,5 +5,5 @@ fn main() {
     let y = &*b as *const i32; // different allocation
     // We cannot compare these even though both allocations are live -- they *could* be
     // equal (with the right base addresses).
-    assert!(x != y); //~ ERROR outside bounds
+    assert!(x != y); //~ ERROR invalid arithmetic on pointers
 }
index 3e6e96456fca6695e3d026571495c01a2672c95c..086467eea311bea6d365fbbf20b9e82cd957b88f 100644 (file)
@@ -1,3 +1,5 @@
+// This should fail even without validation
+// compile-flags: -Zmiri-disable-validation
 #![feature(weak_into_raw)]
 
 use std::rc::{Rc, Weak};
diff --git a/tests/compile-fail/unaligned_ptr1.rs b/tests/compile-fail/unaligned_ptr1.rs
new file mode 100644 (file)
index 0000000..bcc4192
--- /dev/null
@@ -0,0 +1,9 @@
+// This should fail even without validation
+// compile-flags: -Zmiri-disable-validation
+
+fn main() {
+    let x = [2u16, 3, 4]; // Make it big enough so we don't get an out-of-bounds error.
+    let x = &x[0] as *const _ as *const u32;
+    // This must fail because alignment is violated: the allocation's base is not sufficiently aligned.
+    let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 2, but alignment 4 is required
+}
diff --git a/tests/compile-fail/unaligned_ptr2.rs b/tests/compile-fail/unaligned_ptr2.rs
new file mode 100644 (file)
index 0000000..225bd14
--- /dev/null
@@ -0,0 +1,10 @@
+// This should fail even without validation.
+// compile-flags: -Zmiri-disable-validation
+
+fn main() {
+    let x = [2u32, 3]; // Make it big enough so we don't get an out-of-bounds error.
+    let x = (x.as_ptr() as *const u8).wrapping_offset(3) as *const u32;
+    // This must fail because alignment is violated: the offset is not sufficiently aligned.
+    // Also make the offset not a power of 2, that used to ICE.
+    let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
+}
diff --git a/tests/compile-fail/unaligned_ptr3.rs b/tests/compile-fail/unaligned_ptr3.rs
new file mode 100644 (file)
index 0000000..f33a80d
--- /dev/null
@@ -0,0 +1,11 @@
+// This should fail even without validation.
+// compile-flags: -Zmiri-disable-validation
+
+fn main() {
+    let x = [2u16, 3, 4, 5]; // Make it big enough so we don't get an out-of-bounds error.
+    let x = &x[0] as *const _ as *const *const u8; // cast to ptr-to-ptr, so that we load a ptr
+    // This must fail because alignment is violated. Test specifically for loading pointers,
+    // which have special code in miri's memory.
+    let _x = unsafe { *x };
+    //~^ ERROR tried to access memory with alignment 2, but alignment
+}
diff --git a/tests/compile-fail/unaligned_ptr_cast1.rs b/tests/compile-fail/unaligned_ptr_cast1.rs
deleted file mode 100644 (file)
index e64594d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// This should fail even without validation
-// compile-flags: -Zmiri-disable-validation
-
-fn main() {
-    let x = &2u16;
-    let x = x as *const _ as *const u32;
-    // This must fail because alignment is violated
-    let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 2, but alignment 4 is required
-}
diff --git a/tests/compile-fail/unaligned_ptr_cast2.rs b/tests/compile-fail/unaligned_ptr_cast2.rs
deleted file mode 100644 (file)
index 9fb138e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// This should fail even without validation.
-// compile-flags: -Zmiri-disable-validation
-
-fn main() {
-    let x = &2u16;
-    let x = x as *const _ as *const *const u8;
-    // This must fail because alignment is violated. Test specifically for loading pointers,
-    // which have special code in miri's memory.
-    let _x = unsafe { *x };
-    //~^ ERROR tried to access memory with alignment 2, but alignment
-}
diff --git a/tests/compile-fail/unaligned_ptr_cast_zst.rs b/tests/compile-fail/unaligned_ptr_cast_zst.rs
deleted file mode 100644 (file)
index d52b569..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    let x = &2u16;
-    let x = x as *const _ as *const [u32; 0];
-    // This must fail because alignment is violated. Test specifically for loading ZST.
-    let _x = unsafe { *x };
-    //~^ ERROR tried to access memory with alignment 2, but alignment 4 is required
-}
diff --git a/tests/compile-fail/unaligned_ptr_zst.rs b/tests/compile-fail/unaligned_ptr_zst.rs
new file mode 100644 (file)
index 0000000..127ec04
--- /dev/null
@@ -0,0 +1,10 @@
+// This should fail even without validation
+// compile-flags: -Zmiri-disable-validation
+
+fn main() {
+    let x = &2u16;
+    let x = x as *const _ as *const [u32; 0];
+    // This must fail because alignment is violated. Test specifically for loading ZST.
+    let _x = unsafe { *x };
+    //~^ ERROR tried to access memory with alignment 2, but alignment 4 is required
+}
index c5845cb693bb3d9796a48092aebdb736d5b87e89..4318c7c90271f00825e9ad4572b86760cdcc7f5e 100644 (file)
@@ -1,5 +1,5 @@
 use std::mem;
 
 fn main() {
-    let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR tried to interpret some bytes as a pointer
+    let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR integer pointer in non-ZST reference
 }
index 21650ebf950673e4943128ef24a8e44c2a2c8cb2..ef76b93d11e2d15bbbb8ee5bc60905b0e49d3e26 100644 (file)
@@ -3,5 +3,5 @@
 fn main() {
     let val = 14;
     let ptr = (&val as *const i32).wrapping_offset(1);
-    let _x: &i32 = unsafe { mem::transmute(ptr) }; //~ ERROR outside bounds of allocation
+    let _x: &i32 = unsafe { mem::transmute(ptr) }; //~ ERROR encountered dangling (not entirely in bounds) reference
 }
diff --git a/tests/compile-fail/zst.rs b/tests/compile-fail/zst.rs
deleted file mode 100644 (file)
index 0488926..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let x = &() as *const () as *const i32;
-    let _val = unsafe { *x }; //~ ERROR access memory with alignment 1, but alignment 4 is required
-}
diff --git a/tests/compile-fail/zst1.rs b/tests/compile-fail/zst1.rs
new file mode 100644 (file)
index 0000000..e4ce7b8
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    // make sure ZST locals cannot be accessed
+    let x = &() as *const () as *const i8;
+    let _val = unsafe { *x }; //~ ERROR pointer must be in-bounds
+}
diff --git a/tests/compile-fail/zst2.rs b/tests/compile-fail/zst2.rs
new file mode 100644 (file)
index 0000000..950f7b3
--- /dev/null
@@ -0,0 +1,12 @@
+fn main() {
+    // Not using the () type here, as writes of that type do not even have MIR generated.
+    // Also not assigning directly as that's array initialization, not assignment.
+    let zst_val = [1u8; 0];
+
+    // make sure ZST accesses are checked against being "truly" dangling pointers
+    // (into deallocated allocations).
+    let mut x_box = Box::new(1u8);
+    let x = &mut *x_box as *mut _ as *mut [u8; 0];
+    drop(x_box);
+    unsafe { *x = zst_val; } //~ ERROR dangling pointer was dereferenced
+}
diff --git a/tests/compile-fail/zst3.rs b/tests/compile-fail/zst3.rs
new file mode 100644 (file)
index 0000000..c945911
--- /dev/null
@@ -0,0 +1,15 @@
+fn main() {
+    // Not using the () type here, as writes of that type do not even have MIR generated.
+    // Also not assigning directly as that's array initialization, not assignment.
+    let zst_val = [1u8; 0];
+
+    // make sure ZST accesses are checked against being "truly" dangling pointers
+    // (that are out-of-bounds).
+    let mut x_box = Box::new(1u8);
+    let x = (&mut *x_box as *mut u8).wrapping_offset(1);
+    // This one is just "at the edge", but still okay
+    unsafe { *(x as *mut [u8; 0]) = zst_val; }
+    // One byte further is OOB.
+    let x = x.wrapping_offset(1);
+    unsafe { *(x as *mut [u8; 0]) = zst_val; } //~ ERROR pointer must be in-bounds
+}
index 7c49af87f88653c6a22d92cf8354338ec8f60cda..4ff57caf95c27755f9890b15fef98339620e3e05 100644 (file)
@@ -3,6 +3,7 @@
 fn main() {
     let x = &42 as *const i32 as usize; 
     let y = x * 2;
+    assert_eq!(y, x + x);
     let z = y as u8 as usize;
     assert_eq!(z, y % 256);
 }
index 9d97210b73db6cfa118d117f4d0a922a448aa019..988473570913999fc83c0dd9d224f5d64b604000 100644 (file)
@@ -21,13 +21,4 @@ fn main() {
     // Reading and writing is ok.
     unsafe { *x = zst_val; }
     unsafe { let _y = *x; }
-
-    // We should even be able to use "true" pointers for ZST when the allocation has been
-    // removed already. The box is for a non-ZST to make sure there actually is an allocation.
-    let mut x_box = Box::new(((), 1u8));
-    let x = &mut x_box.0 as *mut _ as *mut [u8; 0];
-    drop(x_box);
-    // Reading and writing is ok.
-    unsafe { *x = zst_val; }
-    unsafe { let _y = *x; }
 }