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`.
|
||||
fn errnum_to_io_error(
|
||||
#[allow(clippy::needless_return)]
|
||||
fn try_errnum_to_io_error(
|
||||
&self,
|
||||
errnum: Scalar<Provenance>,
|
||||
) -> InterpResult<'tcx, std::io::ErrorKind> {
|
||||
) -> InterpResult<'tcx, Option<std::io::ErrorKind>> {
|
||||
let this = self.eval_context_ref();
|
||||
let target = &this.tcx.sess.target;
|
||||
if target.families.iter().any(|f| f == "unix") {
|
||||
let errnum = errnum.to_i32()?;
|
||||
for &(name, kind) in UNIX_IO_ERROR_TABLE {
|
||||
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 {
|
||||
throw_unsup_format!(
|
||||
"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 buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
|
||||
|
||||
let error = this.errnum_to_io_error(errnum)?;
|
||||
let formatted = error.to_string();
|
||||
let error = this.try_errnum_to_io_error(errnum)?;
|
||||
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 ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
|
||||
this.write_int(ret, dest)?;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(io_error_more)]
|
||||
#![feature(io_error_uncategorized)]
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fs::{
|
||||
@ -26,6 +27,7 @@ fn main() {
|
||||
test_directory();
|
||||
test_canonicalize();
|
||||
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
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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