Auto merge of #2465 - RalfJung:strerror_r, r=RalfJung
avoid strerror_r failure on unknown errnum This is an informative function anyway, so as fallback just return a string with the raw errnum. Avoids panics / interpreter aborts in std on unknown errnum in from_raw_os_error.
This commit is contained in:
commit
74c5f1b468
@ -609,20 +609,23 @@ fn io_error_to_errnum(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The inverse of `io_error_to_errnum`.
|
/// The inverse of `io_error_to_errnum`.
|
||||||
fn errnum_to_io_error(
|
#[allow(clippy::needless_return)]
|
||||||
|
fn try_errnum_to_io_error(
|
||||||
&self,
|
&self,
|
||||||
errnum: Scalar<Provenance>,
|
errnum: Scalar<Provenance>,
|
||||||
) -> InterpResult<'tcx, std::io::ErrorKind> {
|
) -> InterpResult<'tcx, Option<std::io::ErrorKind>> {
|
||||||
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") {
|
||||||
let errnum = errnum.to_i32()?;
|
let errnum = errnum.to_i32()?;
|
||||||
for &(name, kind) in UNIX_IO_ERROR_TABLE {
|
for &(name, kind) in UNIX_IO_ERROR_TABLE {
|
||||||
if errnum == this.eval_libc_i32(name)? {
|
if errnum == this.eval_libc_i32(name)? {
|
||||||
return Ok(kind);
|
return Ok(Some(kind));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw_unsup_format!("raw errnum {:?} cannot be translated into io::Error", errnum)
|
// Our table is as complete as the mapping in std, so we are okay with saying "that's a
|
||||||
|
// strange one" here.
|
||||||
|
return Ok(None);
|
||||||
} else {
|
} else {
|
||||||
throw_unsup_format!(
|
throw_unsup_format!(
|
||||||
"converting errnum into io::Error is unsupported for OS {}",
|
"converting errnum into io::Error is unsupported for OS {}",
|
||||||
|
@ -465,8 +465,11 @@ fn emulate_foreign_item_by_name(
|
|||||||
let buf = this.read_pointer(buf)?;
|
let buf = this.read_pointer(buf)?;
|
||||||
let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
|
let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
|
||||||
|
|
||||||
let error = this.errnum_to_io_error(errnum)?;
|
let error = this.try_errnum_to_io_error(errnum)?;
|
||||||
let formatted = error.to_string();
|
let formatted = match error {
|
||||||
|
Some(err) => format!("{err}"),
|
||||||
|
None => format!("<unknown errnum in strerror_r: {errnum}>"),
|
||||||
|
};
|
||||||
let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
|
let (complete, _) = this.write_os_str_to_c_str(OsStr::new(&formatted), buf, buflen)?;
|
||||||
let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
|
let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
|
||||||
this.write_int(ret, dest)?;
|
this.write_int(ret, dest)?;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
#![feature(io_error_more)]
|
#![feature(io_error_more)]
|
||||||
|
#![feature(io_error_uncategorized)]
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs::{
|
use std::fs::{
|
||||||
@ -26,6 +27,7 @@ fn main() {
|
|||||||
test_directory();
|
test_directory();
|
||||||
test_canonicalize();
|
test_canonicalize();
|
||||||
test_dup_stdout_stderr();
|
test_dup_stdout_stderr();
|
||||||
|
test_from_raw_os_error();
|
||||||
|
|
||||||
// These all require unix, if the test is changed to no longer `ignore-windows`, move these to a unix test
|
// These all require unix, if the test is changed to no longer `ignore-windows`, move these to a unix test
|
||||||
test_file_open_unix_allow_two_args();
|
test_file_open_unix_allow_two_args();
|
||||||
@ -434,3 +436,11 @@ fn test_dup_stdout_stderr() {
|
|||||||
libc::write(new_stderr, bytes.as_ptr() as *const libc::c_void, bytes.len());
|
libc::write(new_stderr, bytes.as_ptr() as *const libc::c_void, bytes.len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_from_raw_os_error() {
|
||||||
|
let code = 6; // not a code that std or Miri know
|
||||||
|
let error = Error::from_raw_os_error(code);
|
||||||
|
assert!(matches!(error.kind(), ErrorKind::Uncategorized));
|
||||||
|
// Make sure we can also format this.
|
||||||
|
format!("{error:?}");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user