Merge pull request #4054 from devnexen/strerror_r_chg

follow-up on #4052, making a miri evaluation context fn for strerror_r.
This commit is contained in:
Ralf Jung 2024-11-24 09:57:49 +00:00 committed by GitHub
commit a221d506bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 62 additions and 50 deletions

View file

@ -2,7 +2,6 @@ use rustc_abi::ExternAbi;
use rustc_span::Symbol;
use crate::shims::unix::android::thread::prctl;
use crate::shims::unix::foreign_items::EvalContextExt as _;
use crate::shims::unix::linux::syscall::syscall;
use crate::*;
@ -21,14 +20,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut();
match link_name.as_str() {
// Querying system information
"sysconf" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
// Miscellaneous
"__errno" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;

View file

@ -68,6 +68,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
throw_unsup_format!("unimplemented sysconf name: {}", name)
}
fn strerror_r(
&mut self,
errnum: &OpTy<'tcx>,
buf: &OpTy<'tcx>,
buflen: &OpTy<'tcx>,
) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let errnum = this.read_scalar(errnum)?;
let buf = this.read_pointer(buf)?;
let buflen = this.read_target_usize(buflen)?;
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)?;
if complete {
interp_ok(Scalar::from_i32(0))
} else {
interp_ok(Scalar::from_i32(this.eval_libc_i32("ERANGE")))
}
}
fn emulate_foreign_item_inner(
&mut self,
link_name: Symbol,
@ -113,6 +137,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"sysconf" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
// File descriptors
"read" => {
let [fd, buf, count] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
@ -724,21 +755,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// We do not support forking, so there is nothing to do here.
this.write_null(dest)?;
}
"strerror_r" | "__xpg_strerror_r" => {
let [errnum, buf, buflen] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let errnum = this.read_scalar(errnum)?;
let buf = this.read_pointer(buf)?;
let buflen = this.read_target_usize(buflen)?;
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)?;
}
"getentropy" => {
// This function is non-standard but exists with the same signature and behavior on
// Linux, macOS, FreeBSD and Solaris/Illumos.
@ -766,6 +782,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_null(dest)?;
}
}
"strerror_r" => {
let [errnum, buf, buflen] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?;
}
"getrandom" => {
// This function is non-standard but exists with the same signature and behavior on
// Linux, FreeBSD and Solaris/Illumos.

View file

@ -1,7 +1,6 @@
use rustc_abi::ExternAbi;
use rustc_span::Symbol;
use crate::shims::unix::foreign_items::EvalContextExt as _;
use crate::shims::unix::*;
use crate::*;
@ -76,14 +75,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
// Querying system information
"sysconf" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
// Miscellaneous
"__error" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;

View file

@ -125,14 +125,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
// Querying system information
"sysconf" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
// Dynamically invoked syscalls
"syscall" => {
syscall(this, link_name, abi, args, dest)?;
@ -152,6 +144,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let ptr = this.mremap(old_address, old_size, new_size, flags)?;
this.write_scalar(ptr, dest)?;
}
"__xpg_strerror_r" => {
let [errnum, buf, buflen] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?;
}
"__errno_location" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let errno_place = this.last_error_place()?;

View file

@ -2,7 +2,6 @@ use rustc_abi::ExternAbi;
use rustc_span::Symbol;
use super::sync::EvalContextExt as _;
use crate::shims::unix::foreign_items::EvalContextExt as _;
use crate::shims::unix::*;
use crate::*;
@ -168,13 +167,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(stack_size, dest)?;
}
"sysconf" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
// Threading
"pthread_setname_np" => {
let [name] =

View file

@ -113,7 +113,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_null(dest)?;
}
"sysconf" | "__sysconf_xpg7" => {
"__sysconf_xpg7" => {
let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?;
let result = this.sysconf(val)?;

View file

@ -0,0 +1,16 @@
//@ignore-target: windows # Supported only on unixes
fn main() {
unsafe {
let mut buf = vec![0u8; 32];
assert_eq!(libc::strerror_r(libc::EPERM, buf.as_mut_ptr().cast(), buf.len()), 0);
let mut buf2 = vec![0u8; 64];
assert_eq!(libc::strerror_r(-1i32, buf2.as_mut_ptr().cast(), buf2.len()), 0);
// This buffer is deliberately too small so this triggers ERANGE.
let mut buf3 = vec![0u8; 2];
assert_eq!(
libc::strerror_r(libc::E2BIG, buf3.as_mut_ptr().cast(), buf3.len()),
libc::ERANGE
);
}
}