Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacked Borrows NG #492

Merged
merged 19 commits into from
Oct 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1ae1b9b
adapt to rustc API changes and factor out computing the tag for ty+mutbl
RalfJung Oct 18, 2018
dd1558f
rustc update and be very selective about what we accept on a deref
RalfJung Oct 19, 2018
fda03e9
some more compile-fail tests
RalfJung Oct 19, 2018
01828fd
respect memory's privacy
RalfJung Oct 19, 2018
26bb4f7
get rid of implicit Raw at bottom of stack; locals get a uniq at thei…
RalfJung Oct 22, 2018
44b3c38
make sure raw ptrs only have to be valid as far as they are used
RalfJung Oct 22, 2018
8cd73e5
use as(_mut)_ptr on slices to entirely escape them to raw
RalfJung Oct 22, 2018
cc328f6
test passing invalid refs around
RalfJung Oct 23, 2018
fe83ef3
also run compile-fail tests with and without optimizations
RalfJung Oct 23, 2018
5388037
remove code duplication by letting reactivatable() compute what react…
RalfJung Oct 23, 2018
356369d
test against passing invalid shared refs around
RalfJung Oct 23, 2018
a34b9c7
make some things public for the benefit of priroda
RalfJung Oct 24, 2018
4a98f64
Merge remote-tracking branch 'origin/master' into rustup
RalfJung Oct 26, 2018
559f63a
Merge remote-tracking branch 'origin/master' into rustup
RalfJung Oct 30, 2018
942204e
bump Rust version
RalfJung Oct 30, 2018
a48b2cc
disable validation for some tests that need further investigation
RalfJung Oct 30, 2018
6cbe280
Merge remote-tracking branch 'origin/master' into rustup
RalfJung Oct 30, 2018
9c95522
test cargo-miri without validation, and fix how we invoke it so we se…
RalfJung Oct 30, 2018
1fa0ff8
fix nits
RalfJung Oct 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,34 @@ script:
- |
# Test and install plain miri
cargo build --release --all-features &&
cargo test --release --all-features &&
#cargo test --release --all-features &&
cargo install --all-features --force --path .
- |
# get ourselves a MIR-full libstd
xargo/build.sh &&
export MIRI_SYSROOT=~/.xargo/HOST
#- |
# # run all tests with full mir
# cargo test --release --all-features
- |
# run all tests with full mir
cargo test --release --all-features
- |
# test `cargo miri`
# Test cargo integration
cd cargo-miri-test &&
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
cargo miri -q
else
cargo miri -q >stdout.real 2>stderr.real &&
cat stdout.real stderr.real &&
# Test `cargo miri` output. Not on mac because output redirecting doesn't
# work. There is no error. It just stops CI.
# Test `cargo miri`
# We ignore the exit code because we want to see the output even on failure, and
# I found no way to preserve the exit code so that we can test for it later.
# Variables set in this subshell in the parenthesis are not available
# on the outside.
# We assume that if this fails, it'll also print something about the failure on
# stdout/stderr and we'll catch that.
# FIXME: Disabling validation, still investigating whether there is UB here
(cargo miri -q >stdout.real 2>stderr.real -- -Zmiri-disable-validation || true) &&
# Print file names and contents (`cat` would just print contents)
tail -n +0 stdout.real stderr.real &&
# Verify output
diff -u stdout.ref stdout.real &&
diff -u stderr.ref stderr.real
fi &&
diff -u stderr.ref stderr.real &&
# test `cargo miri test`
cargo miri test &&
cargo miri test &&
cd ..

notifications:
Expand Down
2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2018-10-29
nightly-2018-10-30
79 changes: 44 additions & 35 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,15 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
self.write_null(dest)?;
} else {
let align = self.tcx.data_layout.pointer_align;
let ptr = self.memory.allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into())?;
self.write_scalar(Scalar::Ptr(ptr), dest)?;
let ptr = self.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into())?;
self.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?;
}
}

"free" => {
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation, no tag
if !ptr.is_null_ptr(&self) {
self.memory.deallocate(
self.memory_mut().deallocate(
ptr.to_ptr()?.with_default_tag(),
None,
MiriMemoryKind::C.into(),
Expand All @@ -150,9 +150,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let ptr = self.memory.allocate(Size::from_bytes(size),
Align::from_bytes(align, align).unwrap(),
MiriMemoryKind::Rust.into())?;
let ptr = self.memory_mut()
.allocate(
Size::from_bytes(size),
Align::from_bytes(align, align).unwrap(),
MiriMemoryKind::Rust.into()
)?
.with_default_tag();
self.write_scalar(Scalar::Ptr(ptr), dest)?;
}
"__rust_alloc_zeroed" => {
Expand All @@ -164,10 +168,14 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let ptr = self.memory.allocate(Size::from_bytes(size),
Align::from_bytes(align, align).unwrap(),
MiriMemoryKind::Rust.into())?;
self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
let ptr = self.memory_mut()
.allocate(
Size::from_bytes(size),
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
Align::from_bytes(align, align).unwrap(),
MiriMemoryKind::Rust.into()
)?
.with_default_tag();
self.memory_mut().write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
self.write_scalar(Scalar::Ptr(ptr), dest)?;
}
"__rust_dealloc" => {
Expand All @@ -180,7 +188,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
self.memory.deallocate(
self.memory_mut().deallocate(
ptr.with_default_tag(),
Some((Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap())),
MiriMemoryKind::Rust.into(),
Expand All @@ -197,15 +205,15 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
if !align.is_power_of_two() {
return err!(HeapAllocNonPowerOfTwoAlignment(align));
}
let new_ptr = self.memory.reallocate(
let new_ptr = self.memory_mut().reallocate(
ptr.with_default_tag(),
Size::from_bytes(old_size),
Align::from_bytes(align, align).unwrap(),
Size::from_bytes(new_size),
Align::from_bytes(align, align).unwrap(),
MiriMemoryKind::Rust.into(),
)?;
self.write_scalar(Scalar::Ptr(new_ptr), dest)?;
self.write_scalar(Scalar::Ptr(new_ptr.with_default_tag()), dest)?;
}

"syscall" => {
Expand All @@ -231,7 +239,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
"dlsym" => {
let _handle = self.read_scalar(args[0])?;
let symbol = self.read_scalar(args[1])?.to_ptr()?.erase_tag();
let symbol_name = self.memory.read_c_str(symbol.with_default_tag())?;
let symbol_name = self.memory().read_c_str(symbol.with_default_tag())?;
let err = format!("bad c unicode symbol: {:?}", symbol_name);
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
return err!(Unimplemented(format!(
Expand All @@ -245,7 +253,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
// We abort on panic, so not much is going on here, but we still have to call the closure
let f = self.read_scalar(args[0])?.to_ptr()?;
let data = self.read_scalar(args[1])?.not_undef()?;
let f_instance = self.memory.get_fn(f)?;
let f_instance = self.memory().get_fn(f)?;
self.write_null(dest)?;
trace!("__rust_maybe_catch_panic: {:?}", f_instance);

Expand Down Expand Up @@ -289,8 +297,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
let n = Size::from_bytes(self.read_scalar(args[2])?.to_usize(&self)?);

let result = {
let left_bytes = self.memory.read_bytes(left.with_default_tag(), n)?;
let right_bytes = self.memory.read_bytes(right.with_default_tag(), n)?;
let left_bytes = self.memory().read_bytes(left.with_default_tag(), n)?;
let right_bytes = self.memory().read_bytes(right.with_default_tag(), n)?;

use std::cmp::Ordering::*;
match left_bytes.cmp(right_bytes) {
Expand All @@ -311,7 +319,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
let ptr = ptr.with_default_tag();
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
let num = self.read_scalar(args[2])?.to_usize(&self)?;
if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?
.iter().rev().position(|&c| c == val)
{
let new_ptr = ptr.ptr_offset(Size::from_bytes(num - idx as u64 - 1), &self)?;
Expand All @@ -326,7 +334,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
let ptr = ptr.with_default_tag();
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
let num = self.read_scalar(args[2])?.to_usize(&self)?;
if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().position(
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?.iter().position(
|&c| c == val,
)
{
Expand All @@ -340,7 +348,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
"getenv" => {
let result = {
let name_ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation
let name = self.memory.read_c_str(name_ptr.with_default_tag())?;
let name = self.memory().read_c_str(name_ptr.with_default_tag())?;
match self.machine.env_vars.get(name) {
Some(&var) => Scalar::Ptr(var),
None => Scalar::ptr_null(*self.tcx),
Expand All @@ -354,15 +362,16 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
{
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
if !name_ptr.is_null_ptr(&self) {
let name = self.memory.read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
let name = self.memory().read_c_str(name_ptr.to_ptr()?
.with_default_tag())?.to_owned();
if !name.is_empty() && !name.contains(&b'=') {
success = Some(self.machine.env_vars.remove(name));
success = Some(self.machine.env_vars.remove(&name));
}
}
}
if let Some(old) = success {
if let Some(var) = old {
self.memory.deallocate(var, None, MiriMemoryKind::Env.into())?;
self.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
}
self.write_null(dest)?;
} else {
Expand All @@ -375,30 +384,30 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
{
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
let value_ptr = self.read_scalar(args[1])?.to_ptr()?.erase_tag(); // raw ptr operation
let value = self.memory.read_c_str(value_ptr.with_default_tag())?;
let value = self.memory().read_c_str(value_ptr.with_default_tag())?;
if !name_ptr.is_null_ptr(&self) {
let name = self.memory.read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
let name = self.memory().read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
if !name.is_empty() && !name.contains(&b'=') {
new = Some((name.to_owned(), value.to_owned()));
}
}
}
if let Some((name, value)) = new {
// +1 for the null terminator
let value_copy = self.memory.allocate(
let value_copy = self.memory_mut().allocate(
Size::from_bytes((value.len() + 1) as u64),
Align::from_bytes(1, 1).unwrap(),
MiriMemoryKind::Env.into(),
)?;
self.memory.write_bytes(value_copy.into(), &value)?;
)?.with_default_tag();
self.memory_mut().write_bytes(value_copy.into(), &value)?;
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), &self)?.into();
self.memory.write_bytes(trailing_zero_ptr, &[0])?;
self.memory_mut().write_bytes(trailing_zero_ptr, &[0])?;
if let Some(var) = self.machine.env_vars.insert(
name.to_owned(),
value_copy,
)
{
self.memory.deallocate(var, None, MiriMemoryKind::Env.into())?;
self.memory_mut().deallocate(var, None, MiriMemoryKind::Env.into())?;
}
self.write_null(dest)?;
} else {
Expand All @@ -415,7 +424,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
// stdout/stderr
use std::io::{self, Write};

let buf_cont = self.memory.read_bytes(buf.with_default_tag(), Size::from_bytes(n))?;
let buf_cont = self.memory().read_bytes(buf.with_default_tag(), Size::from_bytes(n))?;
let res = if fd == 1 {
io::stdout().write(buf_cont)
} else {
Expand All @@ -437,7 +446,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

"strlen" => {
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag();
let n = self.memory.read_c_str(ptr.with_default_tag())?.len();
let n = self.memory().read_c_str(ptr.with_default_tag())?.len();
self.write_scalar(Scalar::from_uint(n as u64, dest.layout.size), dest)?;
}

Expand Down Expand Up @@ -487,9 +496,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo

// Extract the function type out of the signature (that seems easier than constructing it ourselves...)
let dtor = match self.read_scalar(args[1])?.not_undef()? {
Scalar::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?),
Scalar::Ptr(dtor_ptr) => Some(self.memory().get_fn(dtor_ptr)?),
Scalar::Bits { bits: 0, size } => {
assert_eq!(size as u64, self.memory.pointer_size().bytes());
assert_eq!(size as u64, self.memory().pointer_size().bytes());
None
},
Scalar::Bits { .. } => return err!(ReadBytesAsPointer),
Expand All @@ -505,7 +514,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128) {
return err!(OutOfTls);
}
self.memory.write_scalar(
self.memory_mut().write_scalar(
key_ptr.with_default_tag(),
key_layout.align,
Scalar::from_uint(key, key_layout.size).into(),
Expand Down
10 changes: 5 additions & 5 deletions src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
// erase tags: this is a raw ptr operation
let src = self.read_scalar(args[0])?.not_undef()?.erase_tag();
let dest = self.read_scalar(args[1])?.not_undef()?.erase_tag();
self.memory.copy(
self.memory_mut().copy(
src.with_default_tag(),
elem_align,
dest.with_default_tag(),
Expand Down Expand Up @@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
// Do it in memory
let mplace = self.force_allocation(dest)?;
assert!(mplace.meta.is_none());
self.memory.write_repeat(mplace.ptr, 0, dest.layout.size)?;
self.memory_mut().write_repeat(mplace.ptr, 0, dest.layout.size)?;
}
}
}
Expand Down Expand Up @@ -423,7 +423,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
// Do it in memory
let mplace = self.force_allocation(dest)?;
assert!(mplace.meta.is_none());
self.memory.mark_definedness(mplace.ptr.to_ptr()?, dest.layout.size, false)?;
self.memory_mut().mark_definedness(mplace.ptr.to_ptr()?, dest.layout.size, false)?;
}
}
}
Expand All @@ -435,8 +435,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
let val_byte = self.read_scalar(args[1])?.to_u8()?;
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag().with_default_tag();
let count = self.read_scalar(args[2])?.to_usize(&self)?;
self.memory.check_align(ptr, ty_layout.align)?;
self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?;
self.memory().check_align(ptr, ty_layout.align)?;
self.memory_mut().write_repeat(ptr, val_byte, ty_layout.size * count)?;
}

name => return err!(Unimplemented(format!("unimplemented intrinsic: {}", name))),
Expand Down
Loading