Auto merge of #3589 - RalfJung:io-error, r=RalfJung
io::Error handling: keep around the full io::Error for longer so we can give better errors This should help with the error message in https://github.com/rust-lang/miri/issues/3587.
This commit is contained in:
commit
15305a764d
@ -751,26 +751,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
|
/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
|
||||||
/// as a platform-specific errnum.
|
/// as a platform-specific errnum.
|
||||||
fn io_error_to_errnum(
|
fn io_error_to_errnum(&self, err: std::io::Error) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||||
&self,
|
|
||||||
err_kind: std::io::ErrorKind,
|
|
||||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
|
||||||
let this = self.eval_context_ref();
|
let this = self.eval_context_ref();
|
||||||
let target = &this.tcx.sess.target;
|
let target = &this.tcx.sess.target;
|
||||||
if target.families.iter().any(|f| f == "unix") {
|
if target.families.iter().any(|f| f == "unix") {
|
||||||
for &(name, kind) in UNIX_IO_ERROR_TABLE {
|
for &(name, kind) in UNIX_IO_ERROR_TABLE {
|
||||||
if err_kind == kind {
|
if err.kind() == kind {
|
||||||
return Ok(this.eval_libc(name));
|
return Ok(this.eval_libc(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind)
|
throw_unsup_format!("unsupported io error: {err}")
|
||||||
} else if target.families.iter().any(|f| f == "windows") {
|
} else if target.families.iter().any(|f| f == "windows") {
|
||||||
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
|
for &(name, kind) in WINDOWS_IO_ERROR_TABLE {
|
||||||
if err_kind == kind {
|
if err.kind() == kind {
|
||||||
return Ok(this.eval_windows("c", name));
|
return Ok(this.eval_windows("c", name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw_unsup_format!("io error {:?} cannot be translated into a raw os error", err_kind);
|
throw_unsup_format!("unsupported io error: {err}");
|
||||||
} else {
|
} else {
|
||||||
throw_unsup_format!(
|
throw_unsup_format!(
|
||||||
"converting io::Error into errnum is unsupported for OS {}",
|
"converting io::Error into errnum is unsupported for OS {}",
|
||||||
@ -812,8 +809,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the last OS error using a `std::io::ErrorKind`.
|
/// Sets the last OS error using a `std::io::ErrorKind`.
|
||||||
fn set_last_error_from_io_error(&mut self, err_kind: std::io::ErrorKind) -> InterpResult<'tcx> {
|
fn set_last_error_from_io_error(&mut self, err: std::io::Error) -> InterpResult<'tcx> {
|
||||||
self.set_last_error(self.io_error_to_errnum(err_kind)?)
|
self.set_last_error(self.io_error_to_errnum(err)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function that consumes an `std::io::Result<T>` and returns an
|
/// Helper function that consumes an `std::io::Result<T>` and returns an
|
||||||
@ -829,7 +826,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
match result {
|
match result {
|
||||||
Ok(ok) => Ok(ok),
|
Ok(ok) => Ok(ok),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.eval_context_mut().set_last_error_from_io_error(e.kind())?;
|
self.eval_context_mut().set_last_error_from_io_error(e)?;
|
||||||
Ok((-1).into())
|
Ok((-1).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,7 +228,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`getcwd`", reject_with)?;
|
this.reject_in_isolation("`getcwd`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(Pointer::null());
|
return Ok(Pointer::null());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
let erange = this.eval_libc("ERANGE");
|
let erange = this.eval_libc("ERANGE");
|
||||||
this.set_last_error(erange)?;
|
this.set_last_error(erange)?;
|
||||||
}
|
}
|
||||||
Err(e) => this.set_last_error_from_io_error(e.kind())?,
|
Err(e) => this.set_last_error_from_io_error(e)?,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Pointer::null())
|
Ok(Pointer::null())
|
||||||
@ -255,7 +255,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`chdir`", reject_with)?;
|
this.reject_in_isolation("`chdir`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
|
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
match env::set_current_dir(path) {
|
match env::set_current_dir(path) {
|
||||||
Ok(()) => Ok(0),
|
Ok(()) => Ok(0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(-1)
|
Ok(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`fcntl`", reject_with)?;
|
this.reject_in_isolation("`fcntl`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
Ok(read_bytes)
|
Ok(read_bytes)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(-1)
|
Ok(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`open`", reject_with)?;
|
this.reject_in_isolation("`open`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,7 +434,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`unlink`", reject_with)?;
|
this.reject_in_isolation("`unlink`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +465,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`symlink`", reject_with)?;
|
this.reject_in_isolation("`symlink`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,7 +766,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`rename`", reject_with)?;
|
this.reject_in_isolation("`rename`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,7 +794,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`mkdir`", reject_with)?;
|
this.reject_in_isolation("`mkdir`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,7 +822,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
// Reject if isolation is enabled.
|
// Reject if isolation is enabled.
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`rmdir`", reject_with)?;
|
this.reject_in_isolation("`rmdir`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -859,7 +859,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
Ok(Scalar::from_target_usize(id, this))
|
Ok(Scalar::from_target_usize(id, this))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(Scalar::null_ptr(this))
|
Ok(Scalar::null_ptr(this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,7 +947,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some(Err(e)) => {
|
Some(Err(e)) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1299,7 +1299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
Ok(path_bytes.len().try_into().unwrap())
|
Ok(path_bytes.len().try_into().unwrap())
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(-1)
|
Ok(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1382,7 +1382,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
Ok(Scalar::from_maybe_pointer(dest, this))
|
Ok(Scalar::from_maybe_pointer(dest, this))
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(Scalar::from_target_usize(0, this))
|
Ok(Scalar::from_target_usize(0, this))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1503,7 +1503,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
_ => {
|
_ => {
|
||||||
// "On error, -1 is returned, and errno is set to
|
// "On error, -1 is returned, and errno is set to
|
||||||
// indicate the error"
|
// indicate the error"
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1582,7 +1582,7 @@ impl FileMetadata {
|
|||||||
let metadata = match metadata {
|
let metadata = match metadata {
|
||||||
Ok(metadata) => metadata,
|
Ok(metadata) => metadata,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
ecx.set_last_error_from_io_error(e.kind())?;
|
ecx.set_last_error_from_io_error(e)?;
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -153,7 +153,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`GetCurrentDirectoryW`", reject_with)?;
|
this.reject_in_isolation("`GetCurrentDirectoryW`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
return Ok(Scalar::from_u32(0));
|
return Ok(Scalar::from_u32(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
this.write_path_to_wide_str(&cwd, buf, size)?,
|
this.write_path_to_wide_str(&cwd, buf, size)?,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
Err(e) => this.set_last_error_from_io_error(e.kind())?,
|
Err(e) => this.set_last_error_from_io_error(e)?,
|
||||||
}
|
}
|
||||||
Ok(Scalar::from_u32(0))
|
Ok(Scalar::from_u32(0))
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
|
|
||||||
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
|
||||||
this.reject_in_isolation("`SetCurrentDirectoryW`", reject_with)?;
|
this.reject_in_isolation("`SetCurrentDirectoryW`", reject_with)?;
|
||||||
this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
|
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
|
||||||
|
|
||||||
return Ok(this.eval_windows("c", "FALSE"));
|
return Ok(this.eval_windows("c", "FALSE"));
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
match env::set_current_dir(path) {
|
match env::set_current_dir(path) {
|
||||||
Ok(()) => Ok(this.eval_windows("c", "TRUE")),
|
Ok(()) => Ok(this.eval_windows("c", "TRUE")),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
this.set_last_error_from_io_error(e.kind())?;
|
this.set_last_error_from_io_error(e)?;
|
||||||
Ok(this.eval_windows("c", "FALSE"))
|
Ok(this.eval_windows("c", "FALSE"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||||||
let filename = this.read_path_from_wide_str(filename)?;
|
let filename = this.read_path_from_wide_str(filename)?;
|
||||||
let result = match win_absolute(&filename)? {
|
let result = match win_absolute(&filename)? {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
this.set_last_error_from_io_error(err.kind())?;
|
this.set_last_error_from_io_error(err)?;
|
||||||
Scalar::from_u32(0) // return zero upon failure
|
Scalar::from_u32(0) // return zero upon failure
|
||||||
}
|
}
|
||||||
Ok(abs_filename) => {
|
Ok(abs_filename) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user