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

rustup for big refactor; kill most of validation #434

Merged
merged 25 commits into from
Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
259cc6e
rustup for big refactor; kill most of validation
RalfJung Aug 15, 2018
c424e21
update for memory signedness removal; test some float casts
RalfJung Aug 16, 2018
ea27e46
fix compilation after rustc change
RalfJung Aug 17, 2018
6203bf4
update for rustc memory changes; fix (un)init intrinsic for ZST
RalfJung Aug 18, 2018
1a23b3c
rustup
RalfJung Aug 20, 2018
ee7f222
Merge remote-tracking branch 'origin/master'
RalfJung Aug 20, 2018
6819418
fix type renaming
RalfJung Aug 23, 2018
1a4ad2b
update for miri engine: new function handling, new static handling, f…
RalfJung Aug 23, 2018
2ee4aac
fix leaks with -Zmiri-start-fn
RalfJung Aug 23, 2018
42bce6c
rustup
RalfJung Aug 24, 2018
40cc726
update for bool/char being checked at binops
RalfJung Aug 24, 2018
bb5079b
rustup
RalfJung Aug 24, 2018
9280d17
test VecDeque
RalfJung Aug 24, 2018
8238379
update for enum discriminant changes
RalfJung Aug 25, 2018
1ba6140
rustup
RalfJung Aug 25, 2018
1b41b71
update for MUT_STATIC_KIND
RalfJung Aug 26, 2018
5ccdbb8
small test for extern_type
RalfJung Aug 26, 2018
755c68f
some unary operator tests
RalfJung Aug 26, 2018
addcbd8
VecDeque now requries full MIR; update to new nightly
RalfJung Aug 30, 2018
d7a3e04
pthreads test needs full MIR on Windows
RalfJung Aug 30, 2018
0db1c6a
ignore memory leaks on Windows
RalfJung Aug 30, 2018
b4ebe72
stack address functions for macOS
RalfJung Aug 30, 2018
d1cd254
no RwLock on Windows
RalfJung Aug 30, 2018
e2ec521
pretend mprotect works
RalfJung Aug 30, 2018
2a244dc
no TLS dtor and no leak checks on macOS
RalfJung Aug 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
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2018-08-14
nightly-2018-08-30
485 changes: 207 additions & 278 deletions src/fn_call.rs

Large diffs are not rendered by default.

161 changes: 52 additions & 109 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,128 +1,71 @@
use mir;
use rustc::ty::Ty;
use rustc::ty::layout::{LayoutOf, Size};
use rustc::ty::layout::Size;

use super::{Scalar, ScalarExt, EvalResult, EvalContext, ValTy};
use rustc_mir::interpret::sign_extend;
use super::{Scalar, ScalarMaybeUndef, EvalResult};

pub trait EvalContextExt<'tcx> {
fn wrapping_pointer_offset(
&self,
ptr: Scalar,
pointee_ty: Ty<'tcx>,
offset: i64,
) -> EvalResult<'tcx, Scalar>;

fn pointer_offset(
&self,
ptr: Scalar,
pointee_ty: Ty<'tcx>,
offset: i64,
) -> EvalResult<'tcx, Scalar>;

fn value_to_isize(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, i64>;
pub trait ScalarExt {
fn null(size: Size) -> Self;
fn from_i32(i: i32) -> Self;
fn from_uint(i: impl Into<u128>, ptr_size: Size) -> Self;
fn from_int(i: impl Into<i128>, ptr_size: Size) -> Self;
fn from_f32(f: f32) -> Self;
fn from_f64(f: f64) -> Self;
fn is_null(self) -> bool;
}

fn value_to_usize(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, u64>;
pub trait FalibleScalarExt {
/// HACK: this function just extracts all bits if `defined != 0`
/// Mainly used for args of C-functions and we should totally correctly fetch the size
/// of their arguments
fn to_bytes(self) -> EvalResult<'static, u128>;
}

fn value_to_i32(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, i32>;
impl ScalarExt for Scalar {
fn null(size: Size) -> Self {
Scalar::Bits { bits: 0, size: size.bytes() as u8 }
}

fn value_to_u8(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, u8>;
}
fn from_i32(i: i32) -> Self {
Scalar::Bits { bits: i as u32 as u128, size: 4 }
}

impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
fn wrapping_pointer_offset(
&self,
ptr: Scalar,
pointee_ty: Ty<'tcx>,
offset: i64,
) -> EvalResult<'tcx, Scalar> {
// FIXME: assuming here that type size is < i64::max_value()
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
let offset = offset.overflowing_mul(pointee_size).0;
Ok(ptr.ptr_wrapping_signed_offset(offset, self))
fn from_uint(i: impl Into<u128>, size: Size) -> Self {
Scalar::Bits { bits: i.into(), size: size.bytes() as u8 }
}

fn pointer_offset(
&self,
ptr: Scalar,
pointee_ty: Ty<'tcx>,
offset: i64,
) -> EvalResult<'tcx, Scalar> {
// This function raises an error if the offset moves the pointer outside of its allocation. We consider
// ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0).
// We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own
// allocation.
fn from_int(i: impl Into<i128>, size: Size) -> Self {
Scalar::Bits { bits: i.into() as u128, size: size.bytes() as u8 }
}

if ptr.is_null() {
// NULL pointers must only be offset by 0
return if offset == 0 {
Ok(ptr)
} else {
err!(InvalidNullPointerUsage)
};
}
// FIXME: assuming here that type size is < i64::max_value()
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
if let Some(offset) = offset.checked_mul(pointee_size) {
let ptr = ptr.ptr_signed_offset(offset, self)?;
// Do not do bounds-checking for integers; they can never alias a normal pointer anyway.
if let Scalar::Ptr(ptr) = ptr {
self.memory.check_bounds(ptr, false)?;
} else if ptr.is_null() {
// We moved *to* a NULL pointer. That seems wrong, LLVM considers the NULL pointer its own small allocation. Reject this, for now.
return err!(InvalidNullPointerUsage);
}
Ok(ptr)
} else {
err!(Overflow(mir::BinOp::Mul))
}
fn from_f32(f: f32) -> Self {
Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
}

fn value_to_isize(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, i64> {
assert_eq!(value.ty, self.tcx.types.isize);
let raw = self.value_to_scalar(value)?.to_bits(self.memory.pointer_size())?;
let raw = sign_extend(raw, self.layout_of(self.tcx.types.isize).unwrap());
Ok(raw as i64)
fn from_f64(f: f64) -> Self {
Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
}

fn value_to_usize(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, u64> {
assert_eq!(value.ty, self.tcx.types.usize);
self.value_to_scalar(value)?.to_bits(self.memory.pointer_size()).map(|v| v as u64)
fn is_null(self) -> bool {
match self {
Scalar::Bits { bits, .. } => bits == 0,
Scalar::Ptr(_) => false
}
}
}

fn value_to_i32(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, i32> {
assert_eq!(value.ty, self.tcx.types.i32);
let raw = self.value_to_scalar(value)?.to_bits(Size::from_bits(32))?;
let raw = sign_extend(raw, self.layout_of(self.tcx.types.i32).unwrap());
Ok(raw as i32)
impl FalibleScalarExt for Scalar {
fn to_bytes(self) -> EvalResult<'static, u128> {
match self {
Scalar::Bits { bits, size } => {
assert_ne!(size, 0);
Ok(bits)
},
Scalar::Ptr(_) => err!(ReadPointerAsBytes),
}
}
}

fn value_to_u8(
&self,
value: ValTy<'tcx>,
) -> EvalResult<'tcx, u8> {
assert_eq!(value.ty, self.tcx.types.u8);
self.value_to_scalar(value)?.to_bits(Size::from_bits(8)).map(|v| v as u8)
impl FalibleScalarExt for ScalarMaybeUndef {
fn to_bytes(self) -> EvalResult<'static, u128> {
self.not_undef()?.to_bytes()
}
}
Loading