Skip to content

Commit 792d665

Browse files
committed
Fix merge conflicts
2 parents 84cfbb0 + 2bd22c0 commit 792d665

24 files changed

+160
-56
lines changed

.appveyor.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ environment:
99
branches:
1010
# whitelist
1111
only:
12-
- master
12+
- auto
13+
- try
1314

1415
cache:
1516
- '%USERPROFILE%\.cargo'

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ os:
1212
- osx
1313
dist: xenial
1414

15+
# Run in PRs and for bors, but not on master.
16+
if: branch = auto OR branch = try OR type = pull_request OR type = cron
17+
1518
env:
1619
global:
1720
- RUST_TEST_NOCAPTURE=1
@@ -53,3 +56,5 @@ notifications:
5356
branches:
5457
only:
5558
- master
59+
- auto
60+
- try

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
56a12b2ad058f22f1ef090713df15598525ba4a4
1+
7e08576e4276a97b523c25bfd196d419c39c7b87

src/fn_call.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
654654

655655
// Hook pthread calls that go to the thread-local storage memory subsystem.
656656
"pthread_key_create" => {
657-
let key_ptr = this.read_scalar(args[0])?.to_ptr()?;
657+
let key_ptr = this.read_scalar(args[0])?.not_undef()?;
658658

659659
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
660660
let dtor = match this.read_scalar(args[1])?.not_undef()? {
@@ -681,7 +681,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
681681
return err!(OutOfTls);
682682
}
683683

684-
this.memory().check_align(key_ptr.into(), key_layout.align.abi)?;
684+
let key_ptr = this.memory().check_ptr_access(key_ptr, key_layout.size, key_layout.align.abi)?
685+
.expect("cannot be a ZST");
685686
this.memory_mut().get_mut(key_ptr.alloc_id)?.write_scalar(
686687
tcx,
687688
key_ptr,

src/intrinsic.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
505505
let ptr = mplace.ptr.to_ptr()?;
506506
this.memory_mut()
507507
.get_mut(ptr.alloc_id)?
508-
.mark_definedness(ptr, dest.layout.size, false)?;
508+
.mark_definedness(ptr, dest.layout.size, false);
509509
}
510510
}
511511
}
@@ -517,13 +517,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
517517
let val_byte = this.read_scalar(args[1])?.to_u8()?;
518518
let ptr = this.read_scalar(args[0])?.not_undef()?;
519519
let count = this.read_scalar(args[2])?.to_usize(this)?;
520-
this.memory().check_align(ptr, ty_layout.align.abi)?;
521520
let byte_count = ty_layout.size * count;
522-
if byte_count.bytes() != 0 {
523-
let ptr = ptr.to_ptr()?;
524-
this.memory_mut()
525-
.get_mut(ptr.alloc_id)?
526-
.write_repeat(tcx, ptr, val_byte, byte_count)?;
521+
match this.memory().check_ptr_access(ptr, byte_count, ty_layout.align.abi)? {
522+
Some(ptr) => {
523+
this.memory_mut()
524+
.get_mut(ptr.alloc_id)?
525+
.write_repeat(tcx, ptr, val_byte, byte_count)?;
526+
}
527+
None => {
528+
// Size is 0, nothing to do.
529+
}
527530
}
528531
}
529532

src/operator.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ use rustc::mir;
44
use crate::*;
55

66
pub trait EvalContextExt<'tcx> {
7+
fn pointer_inbounds(
8+
&self,
9+
ptr: Pointer<Tag>
10+
) -> InterpResult<'tcx>;
11+
712
fn ptr_op(
813
&self,
914
bin_op: mir::BinOp,
@@ -34,6 +39,13 @@ pub trait EvalContextExt<'tcx> {
3439
}
3540

3641
impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
42+
/// Test if the pointer is in-bounds of a live allocation.
43+
#[inline]
44+
fn pointer_inbounds(&self, ptr: Pointer<Tag>) -> InterpResult<'tcx> {
45+
let (size, _align) = self.memory().get_size_and_align(ptr.alloc_id, AllocCheck::Live)?;
46+
ptr.check_in_alloc(size, CheckInAllocMsg::InboundsTest)
47+
}
48+
3749
fn ptr_op(
3850
&self,
3951
bin_op: mir::BinOp,
@@ -127,8 +139,8 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
127139
let left = left.to_ptr().expect("we checked is_ptr");
128140
let right = right.to_bits(self.memory().pointer_size()).expect("we checked is_bits");
129141
let (_alloc_size, alloc_align) = self.memory()
130-
.get_size_and_align(left.alloc_id, InboundsCheck::MaybeDead)
131-
.expect("determining size+align of dead ptr cannot fail");
142+
.get_size_and_align(left.alloc_id, AllocCheck::MaybeDead)
143+
.expect("alloc info with MaybeDead cannot fail");
132144
let min_ptr_val = u128::from(alloc_align.bytes()) + u128::from(left.offset.bytes());
133145
let result = match bin_op {
134146
Gt => min_ptr_val > right,
@@ -183,6 +195,7 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
183195
if left.alloc_id == right.alloc_id {
184196
left.offset == right.offset
185197
} else {
198+
// Make sure both pointers are in-bounds.
186199
// This accepts one-past-the end. Thus, there is still technically
187200
// some non-determinism that we do not fully rule out when two
188201
// allocations sit right next to each other. The C/C++ standards are
@@ -192,10 +205,12 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
192205
// Dead allocations in miri cannot overlap with live allocations, but
193206
// on read hardware this can easily happen. Thus for comparisons we require
194207
// both pointers to be live.
195-
self.memory().check_bounds_ptr(left, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
196-
self.memory().check_bounds_ptr(right, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
197-
// Two in-bounds pointers, we can compare across allocations.
198-
left == right
208+
if self.pointer_inbounds(left).is_ok() && self.pointer_inbounds(right).is_ok() {
209+
// Two in-bounds pointers in different allocations are different.
210+
false
211+
} else {
212+
return err!(InvalidPointerMath);
213+
}
199214
}
200215
}
201216
// Comparing ptr and integer.
@@ -215,16 +230,16 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
215230
// alignment 32 or higher, hence the limit of 32.
216231
// FIXME: Once we support intptrcast, we could try to fix these holes.
217232
if bits < 32 {
218-
// Test if the ptr is in-bounds. Then it cannot be NULL.
219-
// Even dangling pointers cannot be NULL.
220-
if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead, CheckInAllocMsg::NullPointerTest).is_ok() {
233+
// Test if the pointer can be different from NULL or not.
234+
// We assume that pointers that are not NULL are also not "small".
235+
if !self.memory().ptr_may_be_null(ptr) {
221236
return Ok(false);
222237
}
223238
}
224239

225240
let (alloc_size, alloc_align) = self.memory()
226-
.get_size_and_align(ptr.alloc_id, InboundsCheck::MaybeDead)
227-
.expect("determining size+align of dead ptr cannot fail");
241+
.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)
242+
.expect("alloc info with MaybeDead cannot fail");
228243

229244
// Case II: Alignment gives it away
230245
if ptr.offset.bytes() % alloc_align.bytes() == 0 {
@@ -372,9 +387,9 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
372387
if let Scalar::Ptr(ptr) = ptr {
373388
// Both old and new pointer must be in-bounds of a *live* allocation.
374389
// (Of the same allocation, but that part is trivial with our representation.)
375-
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
390+
self.pointer_inbounds(ptr)?;
376391
let ptr = ptr.signed_offset(offset, self)?;
377-
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live, CheckInAllocMsg::InboundsTest)?;
392+
self.pointer_inbounds(ptr)?;
378393
Ok(Scalar::Ptr(ptr))
379394
} else {
380395
// An integer pointer. They can only be offset by 0, and we pretend there

src/stacked_borrows.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use rustc::mir::RetagKind;
1010

1111
use crate::{
1212
InterpResult, InterpError, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
13-
MemoryKind, MiriMemoryKind, RangeMap, AllocId, CheckInAllocMsg, Pointer, Immediate, ImmTy,
14-
PlaceTy, MPlaceTy,
13+
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Pointer, Immediate, ImmTy, PlaceTy, MPlaceTy,
1514
};
1615

1716
pub type PtrId = NonZeroU64;
@@ -531,13 +530,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
531530
) -> InterpResult<'tcx> {
532531
let this = self.eval_context_mut();
533532
let protector = if protect { Some(this.frame().extra) } else { None };
534-
let ptr = place.ptr.to_ptr()?;
533+
let ptr = this.memory().check_ptr_access(place.ptr, size, place.align)
534+
.expect("validity checks should have excluded dangling/unaligned pointer")
535+
.expect("we shouldn't get here for ZST");
535536
trace!("reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
536537
kind, new_tag, ptr.tag, place.layout.ty, ptr.erase_tag(), size.bytes());
537538

538539
// Get the allocation. It might not be mutable, so we cannot use `get_mut`.
539540
let alloc = this.memory().get(ptr.alloc_id)?;
540-
alloc.check_bounds(this, ptr, size, CheckInAllocMsg::InboundsTest)?;
541541
// Update the stacks.
542542
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
543543
// There could be existing unique pointers reborrowed from them that should remain valid!
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![feature(generators, generator_trait)]
2+
3+
use std::{
4+
ops::{Generator, GeneratorState},
5+
pin::Pin,
6+
};
7+
8+
fn firstn() -> impl Generator<Yield = u64, Return = ()> {
9+
static move || {
10+
let mut num = 0;
11+
let num = &mut num;
12+
13+
yield *num;
14+
*num += 1; //~ ERROR dangling pointer was dereferenced
15+
}
16+
}
17+
18+
struct GeneratorIteratorAdapter<G>(G);
19+
20+
impl<G> Iterator for GeneratorIteratorAdapter<G>
21+
where
22+
G: Generator<Return = ()>,
23+
{
24+
type Item = G::Yield;
25+
26+
fn next(&mut self) -> Option<Self::Item> {
27+
let me = unsafe { Pin::new_unchecked(&mut self.0) };
28+
match me.resume() {
29+
GeneratorState::Yielded(x) => Some(x),
30+
GeneratorState::Complete(_) => None,
31+
}
32+
}
33+
}
34+
35+
fn main() {
36+
let mut generator_iterator_2 = {
37+
let mut generator_iterator = GeneratorIteratorAdapter(firstn());
38+
generator_iterator.next(); // pin it
39+
40+
generator_iterator // move it
41+
}; // *deallocate* generator_iterator
42+
43+
generator_iterator_2.next(); // and use moved value
44+
}

tests/compile-fail/ptr_eq_dangling.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ fn main() {
66
let y = &*b as *const i32; // different allocation
77
// We cannot compare these even though both are inbounds -- they *could* be
88
// equal if memory was reused.
9-
assert!(x != y); //~ ERROR dangling pointer
9+
assert!(x != y); //~ ERROR invalid arithmetic on pointers
1010
}

tests/compile-fail/ptr_eq_out_of_bounds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ fn main() {
55
let y = &*b as *const i32; // different allocation
66
// We cannot compare these even though both allocations are live -- they *could* be
77
// equal (with the right base addresses).
8-
assert!(x != y); //~ ERROR outside bounds
8+
assert!(x != y); //~ ERROR invalid arithmetic on pointers
99
}

0 commit comments

Comments
 (0)