Fix merge conflicts
This commit is contained in:
commit
72bd25de83
13 changed files with 116 additions and 112 deletions
2
miri
2
miri
|
|
@ -54,7 +54,7 @@ build_sysroot() {
|
|||
# Build once, for the user to see.
|
||||
cargo run $CARGO_BUILD_FLAGS --bin cargo-miri -- miri setup "$@"
|
||||
# Call again, to just set env var.
|
||||
eval $(cargo run $CARGO_BUILD_FLAGS -q --bin cargo-miri -- miri setup --env "$@")
|
||||
export MIRI_SYSROOT="$(cargo run $CARGO_BUILD_FLAGS -q --bin cargo-miri -- miri setup --print-sysroot "$@")"
|
||||
}
|
||||
|
||||
# Prepare and set MIRI_SYSROOT. Respects `MIRI_TEST_TARGET` and takes into account
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f
|
||||
7979016aff545f7b41cc517031026020b340989d
|
||||
|
|
|
|||
|
|
@ -259,6 +259,10 @@ fn setup(ask_user: bool) {
|
|||
|
||||
// First, we need xargo.
|
||||
if xargo_version().map_or(true, |v| v < (0, 3, 16)) {
|
||||
if std::env::var("XARGO").is_ok() {
|
||||
// The user manually gave us a xargo binary; don't do anything automatically.
|
||||
show_error(format!("Your xargo is too old; please upgrade to the latest version"))
|
||||
}
|
||||
let mut cmd = cargo();
|
||||
cmd.args(&["install", "xargo", "-f"]);
|
||||
ask_to_run(cmd, ask_user, "install a recent enough xargo");
|
||||
|
|
@ -310,7 +314,7 @@ path = "lib.rs"
|
|||
File::create(dir.join("lib.rs")).unwrap();
|
||||
// Prepare xargo invocation.
|
||||
let target = get_arg_flag_value("--target");
|
||||
let print_env = !ask_user && has_arg_flag("--env"); // whether we just print the necessary environment variable
|
||||
let print_sysroot = !ask_user && has_arg_flag("--print-sysroot"); // whether we just print the sysroot path
|
||||
let mut command = xargo();
|
||||
command.arg("build").arg("-q");
|
||||
command.current_dir(&dir);
|
||||
|
|
@ -339,13 +343,9 @@ path = "lib.rs"
|
|||
};
|
||||
let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) };
|
||||
std::env::set_var("MIRI_SYSROOT", &sysroot); // pass the env var to the processes we spawn, which will turn it into "--sysroot" flags
|
||||
if print_env {
|
||||
// Escape an arbitrary string for the shell: by wrapping it in `'`, the only special
|
||||
// character we have to worry about is `'` itself. Everything else is taken literally
|
||||
// in these strings. `'` is encoded as `'"'"'`: the outer `'` end and being a
|
||||
// `'`-quoted string, respectively; the `"'"` in the middle represents a single `'`.
|
||||
// (We could use `'\''` instead of `'"'"'` if we wanted but let's avoid backslashes.)
|
||||
println!("MIRI_SYSROOT='{}'", sysroot.display().to_string().replace('\'', r#"'"'"'"#));
|
||||
if print_sysroot {
|
||||
// Print just the sysroot and nothing else; this way we do not need any escaping.
|
||||
println!("{}", sysroot.display());
|
||||
} else if !ask_user {
|
||||
println!("A libstd for Miri is now available in `{}`.", sysroot.display());
|
||||
}
|
||||
|
|
|
|||
10
src/eval.rs
10
src/eval.rs
|
|
@ -162,7 +162,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
|||
MiriMemoryKind::Env.into(),
|
||||
);
|
||||
ecx.machine.cmd_line = Some(cmd_ptr);
|
||||
// Store the UTF-16 string.
|
||||
// Store the UTF-16 string. We just allocated so we know the bounds are fine.
|
||||
let char_size = Size::from_bytes(2);
|
||||
let cmd_alloc = ecx.memory.get_mut(cmd_ptr.alloc_id)?;
|
||||
let mut cur_ptr = cmd_ptr;
|
||||
|
|
@ -177,17 +177,13 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
|||
}
|
||||
}
|
||||
|
||||
assert!(
|
||||
args.next().is_none(),
|
||||
"start lang item has more arguments than expected"
|
||||
);
|
||||
args.next().expect_none("start lang item has more arguments than expected");
|
||||
|
||||
// Set the last_error to 0
|
||||
let errno_layout = ecx.layout_of(ecx.tcx.types.u32)?;
|
||||
let errno_place = ecx.allocate(errno_layout, MiriMemoryKind::Static.into());
|
||||
ecx.write_scalar(Scalar::from_u32(0), errno_place.into())?;
|
||||
let errno_ptr = ecx.check_mplace_access(errno_place.into(), Some(Size::from_bits(32)))?;
|
||||
ecx.machine.last_error = errno_ptr;
|
||||
ecx.machine.last_error = Some(errno_place);
|
||||
|
||||
Ok(ecx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
}
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Don't forget the bounds check.
|
||||
let ptr = this.memory.check_ptr_access(
|
||||
ptr,
|
||||
Size::from_bytes(len as u64),
|
||||
|
|
@ -346,6 +347,70 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the last error variable.
|
||||
fn set_last_error(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_place = this.machine.last_error.unwrap();
|
||||
this.write_scalar(scalar, errno_place.into())
|
||||
}
|
||||
|
||||
/// Gets the last error variable.
|
||||
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_place = this.machine.last_error.unwrap();
|
||||
this.read_scalar(errno_place.into())?.not_undef()
|
||||
}
|
||||
|
||||
/// Sets the last OS error using a `std::io::Error`. This function tries to produce the most
|
||||
/// similar OS error from the `std::io::ErrorKind` and sets it as the last OS error.
|
||||
fn set_last_error_from_io_error(&mut self, e: std::io::Error) -> InterpResult<'tcx> {
|
||||
use std::io::ErrorKind::*;
|
||||
let this = self.eval_context_mut();
|
||||
let target = &this.tcx.tcx.sess.target.target;
|
||||
let last_error = if target.options.target_family == Some("unix".to_owned()) {
|
||||
this.eval_libc(match e.kind() {
|
||||
ConnectionRefused => "ECONNREFUSED",
|
||||
ConnectionReset => "ECONNRESET",
|
||||
PermissionDenied => "EPERM",
|
||||
BrokenPipe => "EPIPE",
|
||||
NotConnected => "ENOTCONN",
|
||||
ConnectionAborted => "ECONNABORTED",
|
||||
AddrNotAvailable => "EADDRNOTAVAIL",
|
||||
AddrInUse => "EADDRINUSE",
|
||||
NotFound => "ENOENT",
|
||||
Interrupted => "EINTR",
|
||||
InvalidInput => "EINVAL",
|
||||
TimedOut => "ETIMEDOUT",
|
||||
AlreadyExists => "EEXIST",
|
||||
WouldBlock => "EWOULDBLOCK",
|
||||
_ => throw_unsup_format!("The {} error cannot be transformed into a raw os error", e)
|
||||
})?
|
||||
} else {
|
||||
// FIXME: we have to implement the windows' equivalent of this.
|
||||
throw_unsup_format!("Setting the last OS error from an io::Error is unsupported for {}.", target.target_os)
|
||||
};
|
||||
this.set_last_error(last_error)
|
||||
}
|
||||
|
||||
/// Helper function that consumes an `std::io::Result<T>` and returns an
|
||||
/// `InterpResult<'tcx,T>::Ok` instead. In case the result is an error, this function returns
|
||||
/// `Ok(-1)` and sets the last OS error accordingly.
|
||||
///
|
||||
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
|
||||
/// functions return different integer types (like `read`, that returns an `i64`)
|
||||
fn try_unwrap_io_result<T: From<i32>>(
|
||||
&mut self,
|
||||
result: std::io::Result<T>,
|
||||
) -> InterpResult<'tcx, T> {
|
||||
match result {
|
||||
Ok(ok) => Ok(ok),
|
||||
Err(e) => {
|
||||
self.eval_context_mut().set_last_error_from_io_error(e)?;
|
||||
Ok((-1).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
|
||||
/// the Unix APIs usually handle.
|
||||
fn read_os_string_from_c_string(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(option_expect_none, option_unwrap_none)]
|
||||
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![allow(clippy::cast_lossless)]
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ pub struct Evaluator<'tcx> {
|
|||
pub(crate) argv: Option<Pointer<Tag>>,
|
||||
pub(crate) cmd_line: Option<Pointer<Tag>>,
|
||||
|
||||
/// Last OS error.
|
||||
pub(crate) last_error: Option<Pointer<Tag>>,
|
||||
/// Last OS error location in memory. It is a 32-bit integer.
|
||||
pub(crate) last_error: Option<MPlaceTy<'tcx, Tag>>,
|
||||
|
||||
/// TLS state.
|
||||
pub(crate) tls: TlsData<'tcx>,
|
||||
|
|
@ -244,10 +244,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
|||
ecx.write_scalar(Scalar::from_uint(align, arg.layout.size), arg)?;
|
||||
|
||||
// No more arguments.
|
||||
assert!(
|
||||
args.next().is_none(),
|
||||
"`exchange_malloc` lang item has more arguments than expected"
|
||||
);
|
||||
args.next().expect_none("`exchange_malloc` lang item has more arguments than expected");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
let erange = this.eval_libc("ERANGE")?;
|
||||
this.set_last_error(erange)?;
|
||||
}
|
||||
Err(e) => this.consume_io_error(e)?,
|
||||
Err(e) => this.set_last_error_from_io_error(e)?,
|
||||
}
|
||||
Ok(Scalar::ptr_null(&*this.tcx))
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
match env::set_current_dir(path) {
|
||||
Ok(()) => Ok(0),
|
||||
Err(e) => {
|
||||
this.consume_io_error(e)?;
|
||||
this.set_last_error_from_io_error(e)?;
|
||||
Ok(-1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
.memory
|
||||
.allocate(Size::from_bytes(size), align, kind.into());
|
||||
if zero_init {
|
||||
// We just allocated this, the access cannot fail
|
||||
// We just allocated this, the access is definitely in-bounds.
|
||||
this.memory
|
||||
.get_mut(ptr.alloc_id)
|
||||
.unwrap()
|
||||
|
|
@ -227,7 +227,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
Align::from_bytes(align).unwrap(),
|
||||
MiriMemoryKind::Rust.into(),
|
||||
);
|
||||
// We just allocated this, the access cannot fail
|
||||
// We just allocated this, the access is definitely in-bounds.
|
||||
this.memory
|
||||
.get_mut(ptr.alloc_id)
|
||||
.unwrap()
|
||||
|
|
@ -349,10 +349,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
let arg_dest = this.local_place(arg_local)?;
|
||||
this.write_scalar(data, arg_dest)?;
|
||||
|
||||
assert!(
|
||||
args.next().is_none(),
|
||||
"__rust_maybe_catch_panic argument has more arguments than expected"
|
||||
);
|
||||
args.next().expect_none("__rust_maybe_catch_panic argument has more arguments than expected");
|
||||
|
||||
// We ourselves will return `0`, eventually (because we will not return if we paniced).
|
||||
this.write_null(dest)?;
|
||||
|
|
@ -417,8 +414,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
}
|
||||
|
||||
"__errno_location" | "__error" => {
|
||||
let errno_scalar: Scalar<Tag> = this.machine.last_error.unwrap().into();
|
||||
this.write_scalar(errno_scalar, dest)?;
|
||||
let errno_place = this.machine.last_error.unwrap();
|
||||
this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?;
|
||||
}
|
||||
|
||||
"getenv" => {
|
||||
|
|
@ -643,7 +640,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
|
||||
// Hook pthread calls that go to the thread-local storage memory subsystem.
|
||||
"pthread_key_create" => {
|
||||
let key_ptr = this.read_scalar(args[0])?.not_undef()?;
|
||||
let key_place = this.deref_operand(args[0])?;
|
||||
|
||||
// Extract the function type out of the signature (that seems easier than constructing it ourselves).
|
||||
let dtor = match this.test_null(this.read_scalar(args[1])?.not_undef()?)? {
|
||||
|
|
@ -668,16 +665,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
throw_unsup!(OutOfTls);
|
||||
}
|
||||
|
||||
let key_ptr = this
|
||||
.memory
|
||||
.check_ptr_access(key_ptr, key_layout.size, key_layout.align.abi)?
|
||||
.expect("cannot be a ZST");
|
||||
this.memory.get_mut(key_ptr.alloc_id)?.write_scalar(
|
||||
tcx,
|
||||
key_ptr,
|
||||
Scalar::from_uint(key, key_layout.size).into(),
|
||||
key_layout.size,
|
||||
)?;
|
||||
this.write_scalar(Scalar::from_uint(key, key_layout.size), key_place.into())?;
|
||||
|
||||
// Return success (`0`).
|
||||
this.write_null(dest)?;
|
||||
|
|
@ -856,6 +844,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
let system_info_ptr = this
|
||||
.check_mplace_access(system_info, None)?
|
||||
.expect("cannot be a ZST");
|
||||
// We rely on `deref_operand` doing bounds checks for us.
|
||||
// Initialize with `0`.
|
||||
this.memory
|
||||
.get_mut(system_info_ptr.alloc_id)?
|
||||
|
|
@ -988,33 +977,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
}
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
fn set_last_error(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_ptr = this.machine.last_error.unwrap();
|
||||
this.memory.get_mut(errno_ptr.alloc_id)?.write_scalar(
|
||||
&*this.tcx,
|
||||
errno_ptr,
|
||||
scalar.into(),
|
||||
Size::from_bits(32),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_ptr = this.machine.last_error.unwrap();
|
||||
this.memory
|
||||
.get(errno_ptr.alloc_id)?
|
||||
.read_scalar(&*this.tcx, errno_ptr, Size::from_bits(32))?
|
||||
.not_undef()
|
||||
}
|
||||
|
||||
fn consume_io_error(&mut self, e: std::io::Error) -> InterpResult<'tcx> {
|
||||
self.eval_context_mut().set_last_error(Scalar::from_int(
|
||||
e.raw_os_error().unwrap(),
|
||||
Size::from_bits(32),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Shims the linux 'getrandom()' syscall.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use rustc::ty::layout::Size;
|
|||
use crate::stacked_borrows::Tag;
|
||||
use crate::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileHandle {
|
||||
file: File,
|
||||
}
|
||||
|
|
@ -20,7 +21,7 @@ impl Default for FileHandler {
|
|||
fn default() -> Self {
|
||||
FileHandler {
|
||||
handles: Default::default(),
|
||||
// 0, 1 and 2 are reserved for stdin, stdout and stderr
|
||||
// 0, 1 and 2 are reserved for stdin, stdout and stderr.
|
||||
low: 3,
|
||||
}
|
||||
}
|
||||
|
|
@ -99,11 +100,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
let fd = options.open(path).map(|file| {
|
||||
let mut fh = &mut this.machine.file_handler;
|
||||
fh.low += 1;
|
||||
fh.handles.insert(fh.low, FileHandle { file });
|
||||
fh.handles.insert(fh.low, FileHandle { file }).unwrap_none();
|
||||
fh.low
|
||||
});
|
||||
|
||||
this.consume_result(fd)
|
||||
this.try_unwrap_io_result(fd)
|
||||
}
|
||||
|
||||
fn fcntl(
|
||||
|
|
@ -118,7 +119,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
|
||||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
let cmd = this.read_scalar(cmd_op)?.to_i32()?;
|
||||
// We only support getting the flags for a descriptor
|
||||
// We only support getting the flags for a descriptor.
|
||||
if cmd == this.eval_libc_i32("F_GETFD")? {
|
||||
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
|
||||
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
|
||||
|
|
@ -139,7 +140,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
|
||||
this.remove_handle_and(fd, |handle, this| {
|
||||
this.consume_result(handle.file.sync_all().map(|_| 0i32))
|
||||
this.try_unwrap_io_result(handle.file.sync_all().map(|_| 0i32))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -154,25 +155,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
this.check_no_isolation("read")?;
|
||||
|
||||
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
|
||||
// Reading zero bytes should not change `buf`
|
||||
// Reading zero bytes should not change `buf`.
|
||||
if count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
let buf_scalar = this.read_scalar(buf_op)?.not_undef()?;
|
||||
|
||||
// Remove the file handle to avoid borrowing issues
|
||||
// Remove the file handle to avoid borrowing issues.
|
||||
this.remove_handle_and(fd, |mut handle, this| {
|
||||
// Don't use `?` to avoid returning before reinserting the handle
|
||||
// Don't use `?` to avoid returning before reinserting the handle.
|
||||
let bytes = this.force_ptr(buf_scalar).and_then(|buf| {
|
||||
this.memory
|
||||
.get_mut(buf.alloc_id)?
|
||||
.get_bytes_mut(&*this.tcx, buf, Size::from_bytes(count))
|
||||
.map(|buffer| handle.file.read(buffer))
|
||||
});
|
||||
// Reinsert the file handle
|
||||
this.machine.file_handler.handles.insert(fd, handle);
|
||||
this.consume_result(bytes?.map(|bytes| bytes as i64))
|
||||
this.machine.file_handler.handles.insert(fd, handle).unwrap_none();
|
||||
this.try_unwrap_io_result(bytes?.map(|bytes| bytes as i64))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
this.check_no_isolation("write")?;
|
||||
|
||||
let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;
|
||||
// Writing zero bytes should not change `buf`
|
||||
// Writing zero bytes should not change `buf`.
|
||||
if count == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
|
@ -200,8 +200,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
.get_bytes(&*this.tcx, buf, Size::from_bytes(count))
|
||||
.map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
|
||||
});
|
||||
this.machine.file_handler.handles.insert(fd, handle);
|
||||
this.consume_result(bytes?)
|
||||
this.machine.file_handler.handles.insert(fd, handle).unwrap_none();
|
||||
this.try_unwrap_io_result(bytes?)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
|
||||
let result = remove_file(path).map(|_| 0);
|
||||
|
||||
this.consume_result(result)
|
||||
this.try_unwrap_io_result(result)
|
||||
}
|
||||
|
||||
/// Helper function that gets a `FileHandle` immutable reference and allows to manipulate it
|
||||
|
|
@ -224,7 +224,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
/// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
|
||||
///
|
||||
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
|
||||
/// functions return different integer types (like `read`, that returns an `i64`)
|
||||
/// functions return different integer types (like `read`, that returns an `i64`).
|
||||
fn get_handle_and<F, T: From<i32>>(&mut self, fd: i32, f: F) -> InterpResult<'tcx, T>
|
||||
where
|
||||
F: Fn(&FileHandle) -> InterpResult<'tcx, T>,
|
||||
|
|
@ -248,7 +248,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
/// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
|
||||
///
|
||||
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
|
||||
/// functions return different integer types (like `read`, that returns an `i64`)
|
||||
/// functions return different integer types (like `read`, that returns an `i64`).
|
||||
fn remove_handle_and<F, T: From<i32>>(&mut self, fd: i32, mut f: F) -> InterpResult<'tcx, T>
|
||||
where
|
||||
F: FnMut(FileHandle, &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, T>,
|
||||
|
|
@ -262,23 +262,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
Ok((-1).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that consumes an `std::io::Result<T>` and returns an
|
||||
/// `InterpResult<'tcx,T>::Ok` instead. It is expected that the result can be converted to an
|
||||
/// OS error using `std::io::Error::raw_os_error`.
|
||||
///
|
||||
/// This function uses `T: From<i32>` instead of `i32` directly because some IO related
|
||||
/// functions return different integer types (like `read`, that returns an `i64`)
|
||||
fn consume_result<T: From<i32>>(
|
||||
&mut self,
|
||||
result: std::io::Result<T>,
|
||||
) -> InterpResult<'tcx, T> {
|
||||
match result {
|
||||
Ok(ok) => Ok(ok),
|
||||
Err(e) => {
|
||||
self.eval_context_mut().consume_io_error(e)?;
|
||||
Ok((-1).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,9 +356,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
_ => {
|
||||
// Do it in memory
|
||||
let mplace = this.force_allocation(dest)?;
|
||||
assert!(mplace.meta.is_none());
|
||||
mplace.meta.unwrap_none();
|
||||
// not a zst, must be valid pointer
|
||||
let ptr = mplace.ptr.to_ptr()?;
|
||||
// we know the return place is in-bounds
|
||||
this.memory.get_mut(ptr.alloc_id)?.write_repeat(tcx, ptr, 0, dest.layout.size)?;
|
||||
}
|
||||
}
|
||||
|
|
@ -546,8 +547,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||
_ => {
|
||||
// Do it in memory
|
||||
let mplace = this.force_allocation(dest)?;
|
||||
assert!(mplace.meta.is_none());
|
||||
mplace.meta.unwrap_none();
|
||||
let ptr = mplace.ptr.to_ptr()?;
|
||||
// We know the return place is in-bounds
|
||||
this.memory
|
||||
.get_mut(ptr.alloc_id)?
|
||||
.mark_definedness(ptr, dest.layout.size, false);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl<'tcx> TlsData<'tcx> {
|
|||
data: None,
|
||||
dtor,
|
||||
},
|
||||
);
|
||||
).unwrap_none();
|
||||
trace!("New TLS key allocated: {} with dtor {:?}", new_key, dtor);
|
||||
new_key
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ impl GlobalState {
|
|||
pub fn new_call(&mut self) -> CallId {
|
||||
let id = self.next_call_id;
|
||||
trace!("new_call: Assigning ID {}", id);
|
||||
self.active_calls.insert(id);
|
||||
assert!(self.active_calls.insert(id));
|
||||
self.next_call_id = NonZeroU64::new(id.get() + 1).unwrap();
|
||||
id
|
||||
}
|
||||
|
|
@ -189,7 +189,7 @@ impl GlobalState {
|
|||
self.base_ptr_ids.get(&id).copied().unwrap_or_else(|| {
|
||||
let tag = Tag::Tagged(self.new_ptr());
|
||||
trace!("New allocation {:?} has base tag {:?}", id, tag);
|
||||
self.base_ptr_ids.insert(id, tag);
|
||||
self.base_ptr_ids.insert(id, tag).unwrap_none();
|
||||
tag
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue