rustc_driver::install_ice_hook();
let result = rustc_driver::catch_fatal_errors(move || {
rustc_driver::run_compiler(&rustc_args, &mut MiriCompilerCalls { miri_config }, None, None)
- })
- .and_then(|result| result);
+ });
std::process::exit(result.is_err() as i32);
}
//! Main evaluator loop and setting up the initial stack frame.
use std::ffi::OsStr;
+use std::convert::TryFrom;
use rand::rngs::StdRng;
use rand::SeedableRng;
// First argument: pointer to `main()`.
let main_ptr = ecx.memory.create_fn_alloc(FnVal::Instance(main_instance));
// Second argument (argc): length of `config.args`.
- let argc = Scalar::from_uint(config.args.len() as u128, ecx.pointer_size());
+ let argc = Scalar::from_uint(u64::try_from(config.args.len()).unwrap(), ecx.pointer_size());
// Third argument (`argv`): created from `config.args`.
let argv = {
// Put each argument in memory, collect pointers.
let mut argvs = Vec::<Scalar<Tag>>::new();
for arg in config.args.iter() {
// Make space for `0` terminator.
- let size = arg.len() as u64 + 1;
+ let size = u64::try_from(arg.len()).unwrap().checked_add(1).unwrap();
let arg_type = tcx.mk_array(tcx.types.u8, size);
let arg_place = ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Machine.into());
ecx.write_os_str_to_c_str(OsStr::new(arg), arg_place.ptr, size)?;
}
// Make an array with all these pointers, in the Miri memory.
let argvs_layout =
- ecx.layout_of(tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), argvs.len() as u64))?;
+ ecx.layout_of(tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), u64::try_from(argvs.len()).unwrap()))?;
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into());
for (idx, arg) in argvs.into_iter().enumerate() {
- let place = ecx.mplace_field(argvs_place, idx as u64)?;
+ let place = ecx.mplace_field(argvs_place, u64::try_from(idx).unwrap())?;
ecx.write_scalar(arg, place.into())?;
}
ecx.memory.mark_immutable(argvs_place.ptr.assert_ptr().alloc_id)?;
cmd.push(std::char::from_u32(0).unwrap());
let cmd_utf16: Vec<u16> = cmd.encode_utf16().collect();
- let cmd_type = tcx.mk_array(tcx.types.u16, cmd_utf16.len() as u64);
+ let cmd_type = tcx.mk_array(tcx.types.u16, u64::try_from(cmd_utf16.len()).unwrap());
let cmd_place = ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into());
ecx.machine.cmd_line = Some(cmd_place.ptr);
// Store the UTF-16 string. We just allocated so we know the bounds are fine.
let char_size = Size::from_bytes(2);
for (idx, &c) in cmd_utf16.iter().enumerate() {
- let place = ecx.mplace_field(cmd_place, idx as u64)?;
+ let place = ecx.mplace_field(cmd_place, u64::try_from(idx).unwrap())?;
ecx.write_scalar(Scalar::from_uint(c, char_size), place.into())?;
}
}
use std::ffi::OsStr;
use std::{iter, mem};
+use std::convert::TryFrom;
use rustc::mir;
use rustc::ty::{
}
/// Generate some random bytes, and write them to `dest`.
- fn gen_random(&mut self, ptr: Scalar<Tag>, len: usize) -> InterpResult<'tcx> {
+ fn gen_random(&mut self, ptr: Scalar<Tag>, len: u64) -> InterpResult<'tcx> {
// Some programs pass in a null pointer and a length of 0
// to their platform's random-generation function (e.g. getrandom())
// on Linux. For compatibility with these programs, we don't perform
}
let this = self.eval_context_mut();
- let mut data = vec![0; len];
+ let mut data = vec![0; usize::try_from(len).unwrap()];
if this.machine.communicate {
// Fill the buffer using the host's rng.
let bytes = os_str_to_bytes(os_str)?;
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
// terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
- let string_length = bytes.len() as u64;
+ let string_length = u64::try_from(bytes.len()).unwrap();
if size <= string_length {
return Ok((false, string_length));
}
os_str: &OsStr,
memkind: MemoryKind<MiriMemoryKind>,
) -> Pointer<Tag> {
- let size = os_str.len() as u64 + 1; // Make space for `0` terminator.
+ let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
let this = self.eval_context_mut();
let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
GetEntropy => {
let ptr = this.read_scalar(args[0])?.not_undef()?;
let len = this.read_scalar(args[1])?.to_machine_usize(this)?;
- this.gen_random(ptr, len as usize)?;
+ this.gen_random(ptr, len)?;
this.write_null(dest)?;
}
}
use std::ffi::{OsString, OsStr};
use std::env;
+use std::convert::TryFrom;
use crate::stacked_borrows::Tag;
use crate::rustc_target::abi::LayoutOf;
Ok(match this.machine.env_vars.map.get(name) {
// The offset is used to strip the "{name}=" part of the string.
Some(var_ptr) => {
- Scalar::from(var_ptr.offset(Size::from_bytes(name.len() as u64 + 1), this)?)
+ Scalar::from(var_ptr.offset(Size::from_bytes(u64::try_from(name.len()).unwrap().checked_add(1).unwrap()), this)?)
}
None => Scalar::ptr_null(&*this.tcx),
})
// Make an array with all these pointers inside Miri.
let tcx = this.tcx;
let vars_layout =
- this.layout_of(tcx.mk_array(tcx.types.usize, vars.len() as u64))?;
+ this.layout_of(tcx.mk_array(tcx.types.usize, u64::try_from(vars.len()).unwrap()))?;
let vars_place = this.allocate(vars_layout, MiriMemoryKind::Machine.into());
for (idx, var) in vars.into_iter().enumerate() {
- let place = this.mplace_field(vars_place, idx as u64)?;
+ let place = this.mplace_field(vars_place, u64::try_from(idx).unwrap())?;
this.write_scalar(var, place.into())?;
}
this.write_scalar(
mod windows;
mod posix;
-use std::{convert::TryInto, iter};
+use std::{convert::{TryInto, TryFrom}, iter};
use rustc_hir::def_id::DefId;
use rustc::mir;
MiriMemoryKind::Rust.into(),
);
// We just allocated this, the access is definitely in-bounds.
- this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(size as usize)).unwrap();
+ this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap();
this.write_scalar(ptr, dest)?;
}
"__rust_dealloc" => {
"strlen" => {
let ptr = this.read_scalar(args[0])?.not_undef()?;
let n = this.memory.read_c_str(ptr)?.len();
- this.write_scalar(Scalar::from_uint(n as u64, dest.layout.size), dest)?;
+ this.write_scalar(Scalar::from_uint(u64::try_from(n).unwrap(), dest.layout.size), dest)?;
}
// math functions
// Saturating cast to i16. Even those are outside the valid exponent range to
// `scalbn` below will do its over/underflow handling.
- let exp = if exp > i16::MAX as i32 {
+ let exp = if exp > i32::from(i16::MAX) {
i16::MAX
- } else if exp < i16::MIN as i32 {
+ } else if exp < i32::from(i16::MIN) {
i16::MIN
} else {
exp.try_into().unwrap()
mod linux;
mod macos;
+use std::convert::TryFrom;
+
use crate::*;
use rustc::mir;
use rustc::ty::layout::{Align, LayoutOf, Size};
io::stderr().write(buf_cont)
};
match res {
- Ok(n) => n as i64,
+ Ok(n) => i64::try_from(n).unwrap(),
Err(_) => -1,
}
} else {
// neither of which have any effect on our current PRNG.
let _flags = this.read_scalar(args[2])?.to_i32()?;
- this.gen_random(ptr, len as usize)?;
+ this.gen_random(ptr, len)?;
this.write_scalar(Scalar::from_uint(len, dest.layout.size), dest)?;
Ok(())
}
"SecRandomCopyBytes" => {
let len = this.read_scalar(args[1])?.to_machine_usize(this)?;
let ptr = this.read_scalar(args[2])?.not_undef()?;
- this.gen_random(ptr, len as usize)?;
+ this.gen_random(ptr, len)?;
this.write_null(dest)?;
}
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
}
"TlsGetValue" => {
- let key = this.read_scalar(args[0])?.to_u32()? as u128;
+ let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
let ptr = this.machine.tls.load_tls(key, tcx)?;
this.write_scalar(ptr, dest)?;
}
"TlsSetValue" => {
- let key = this.read_scalar(args[0])?.to_u32()? as u128;
+ let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
let new_ptr = this.read_scalar(args[1])?.not_undef()?;
this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
"SystemFunction036" => {
let ptr = this.read_scalar(args[0])?.not_undef()?;
let len = this.read_scalar(args[1])?.to_u32()?;
- this.gen_random(ptr, len as usize)?;
+ this.gen_random(ptr, len.into())?;
this.write_scalar(Scalar::from_bool(true), dest)?;
}
// We don't support threading.
use crate::stacked_borrows::Tag;
use crate::*;
-use helpers::immty_from_uint_checked;
+use helpers::{immty_from_int_checked, immty_from_uint_checked};
use shims::time::system_time_to_duration;
#[derive(Debug)]
let new_fd = candidate_new_fd.unwrap_or_else(|| {
// find_map ran out of BTreeMap entries before finding a free fd, use one plus the
// maximum fd in the map
- self.handles.last_entry().map(|entry| entry.key() + 1).unwrap_or(min_fd)
+ self.handles.last_entry().map(|entry| entry.key().checked_add(1).unwrap()).unwrap_or(min_fd)
});
self.handles.insert(new_fd, file_handle).unwrap_none();
match file_type {
Ok(file_type) => {
if file_type.is_dir() {
- Ok(this.eval_libc("DT_DIR")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_DIR")?.to_u8()?.into())
} else if file_type.is_file() {
- Ok(this.eval_libc("DT_REG")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_REG")?.to_u8()?.into())
} else if file_type.is_symlink() {
- Ok(this.eval_libc("DT_LNK")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_LNK")?.to_u8()?.into())
} else {
// Certain file types are only supported when the host is a Unix system.
// (i.e. devices and sockets) If it is, check those cases, if not, fall back to
{
use std::os::unix::fs::FileTypeExt;
if file_type.is_block_device() {
- Ok(this.eval_libc("DT_BLK")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_BLK")?.to_u8()?.into())
} else if file_type.is_char_device() {
- Ok(this.eval_libc("DT_CHR")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_CHR")?.to_u8()?.into())
} else if file_type.is_fifo() {
- Ok(this.eval_libc("DT_FIFO")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_FIFO")?.to_u8()?.into())
} else if file_type.is_socket() {
- Ok(this.eval_libc("DT_SOCK")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_SOCK")?.to_u8()?.into())
} else {
- Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
}
}
#[cfg(not(unix))]
- Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()? as i32)
+ Ok(this.eval_libc("DT_UNKNOWN")?.to_u8()?.into())
}
}
Err(e) => return match e.raw_os_error() {
let whence = this.read_scalar(whence_op)?.to_i32()?;
let seek_from = if whence == this.eval_libc_i32("SEEK_SET")? {
- SeekFrom::Start(offset as u64)
+ SeekFrom::Start(u64::try_from(offset).unwrap())
} else if whence == this.eval_libc_i32("SEEK_CUR")? {
SeekFrom::Current(offset)
} else if whence == this.eval_libc_i32("SEEK_END")? {
};
if let Some(FileHandle { file, writable: _ }) = this.machine.file_handler.handles.get_mut(&fd) {
- let result = file.seek(seek_from).map(|offset| offset as i64);
+ let result = file.seek(seek_from).map(|offset| i64::try_from(offset).unwrap());
this.try_unwrap_io_result(result)
} else {
this.handle_not_found()
this.check_no_isolation("mkdir")?;
let _mode = if this.tcx.sess.target.target.target_os.as_str() == "macos" {
- this.read_scalar(mode_op)?.not_undef()?.to_u16()? as u32
+ u32::from(this.read_scalar(mode_op)?.not_undef()?.to_u16()?)
} else {
this.read_scalar(mode_op)?.to_u32()?
};
#[cfg(not(unix))]
let ino = 0u64;
- let file_type = this.file_type_to_d_type(dir_entry.file_type())? as u128;
+ let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
let imms = [
immty_from_uint_checked(ino, ino64_t_layout)?, // d_ino
immty_from_uint_checked(0u128, off64_t_layout)?, // d_off
immty_from_uint_checked(0u128, c_ushort_layout)?, // d_reclen
- immty_from_uint_checked(file_type, c_uchar_layout)?, // d_type
+ immty_from_int_checked(file_type, c_uchar_layout)?, // d_type
];
this.write_packed_immediates(entry_place, &imms)?;
#[cfg(not(unix))]
let ino = 0u64;
- let file_type = this.file_type_to_d_type(dir_entry.file_type())? as u128;
+ let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
let imms = [
immty_from_uint_checked(ino, ino_t_layout)?, // d_ino
immty_from_uint_checked(0u128, off_t_layout)?, // d_seekoff
immty_from_uint_checked(0u128, c_ushort_layout)?, // d_reclen
immty_from_uint_checked(file_name_len, c_ushort_layout)?, // d_namlen
- immty_from_uint_checked(file_type, c_uchar_layout)?, // d_type
+ immty_from_int_checked(file_type, c_uchar_layout)?, // d_type
];
this.write_packed_immediates(entry_place, &imms)?;
use std::iter;
+use std::convert::TryFrom;
use rustc::mir;
use rustc::mir::interpret::{InterpResult, PointerArithmetic};
let ptr = this.read_scalar(args[0])?.not_undef()?;
let pointee_ty = substs.type_at(0);
- let pointee_size = this.layout_of(pointee_ty)?.size.bytes() as i64;
+ let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap();
let offset = offset.overflowing_mul(pointee_size).0;
let result_ptr = ptr.ptr_wrapping_signed_offset(offset, this);
this.write_scalar(result_ptr, dest)?;
let count = this.read_scalar(args[2])?.to_machine_usize(this)?;
let elem_align = elem_layout.align.abi;
- let size = Size::from_bytes(count * elem_size);
+ let size = Size::from_bytes(count) * elem_size;
let src = this.read_scalar(args[0])?.not_undef()?;
let src = this.memory.check_ptr_access(src, size, elem_align)?;
let dest = this.read_scalar(args[1])?.not_undef()?;
let layout = this.layout_of(ty)?;
let align = layout.align.pref.bytes();
let ptr_size = this.pointer_size();
- let align_val = Scalar::from_uint(align as u128, ptr_size);
+ let align_val = Scalar::from_uint(align, ptr_size);
this.write_scalar(align_val, dest)?;
}
.size_and_align_of_mplace(mplace)?
.expect("size_of_val called on extern type");
let ptr_size = this.pointer_size();
- this.write_scalar(Scalar::from_uint(size.bytes() as u128, ptr_size), dest)?;
+ this.write_scalar(Scalar::from_uint(size.bytes(), ptr_size), dest)?;
}
#[rustfmt::skip]
pub mod time;
pub mod tls;
-use crate::*;
+use std::convert::TryFrom;
+
use rustc::{mir, ty};
+use crate::*;
+
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
fn find_mir_or_eval_fn(
let (dest, ret) = ret.unwrap();
let req_align = this
- .force_bits(this.read_scalar(align_op)?.not_undef()?, this.pointer_size())?
- as usize;
+ .force_bits(this.read_scalar(align_op)?.not_undef()?, this.pointer_size())?;
// Stop if the alignment is not a power of two.
if !req_align.is_power_of_two() {
if let Ok(ptr) = this.force_ptr(ptr_scalar) {
// Only do anything if we can identify the allocation this goes to.
let cur_align =
- this.memory.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)?.1.bytes()
- as usize;
- if cur_align >= req_align {
+ this.memory.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead)?.1.bytes();
+ if u128::from(cur_align) >= req_align {
// If the allocation alignment is at least the required alignment we use the
- // libcore implementation
- result = (this.force_bits(ptr_scalar, this.pointer_size())? as *const i8).align_offset(req_align) as u128;
+ // libcore implementation.
+ // FIXME: is this correct in case of truncation?
+ result = u128::try_from(
+ (this.force_bits(ptr_scalar, this.pointer_size())? as *const i8)
+ .align_offset(usize::try_from(req_align).unwrap())
+ ).unwrap();
}
}
let tp = this.deref_operand(tp_op)?;
let duration = get_time()?;
- let tv_sec = duration.as_secs() as i128;
- let tv_nsec = duration.subsec_nanos() as i128;
+ let tv_sec = duration.as_secs();
+ let tv_nsec = duration.subsec_nanos();
let imms = [
immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,
let tv = this.deref_operand(tv_op)?;
let duration = get_time()?;
- let tv_sec = duration.as_secs() as i128;
- let tv_usec = duration.subsec_micros() as i128;
+ let tv_sec = duration.as_secs();
+ let tv_usec = duration.subsec_micros();
let imms = [
immty_from_int_checked(tv_sec, this.libc_ty_layout("time_t")?)?,