Skip to content

Commit

Permalink
Merge pull request rust-lang#4054 from devnexen/strerror_r_chg
Browse files Browse the repository at this point in the history
follow-up on rust-lang#4052, making a miri evaluation context fn for strerror_r.
  • Loading branch information
RalfJung authored Nov 24, 2024
2 parents 6a4aa9a + bb55f52 commit a221d50
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 50 deletions.
9 changes: 0 additions & 9 deletions src/tools/miri/src/shims/unix/android/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand All @@ -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)?;
Expand Down
54 changes: 39 additions & 15 deletions src/tools/miri/src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)?;
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 0 additions & 9 deletions src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -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::*;

Expand Down Expand Up @@ -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)?;
Expand Down
14 changes: 6 additions & 8 deletions src/tools/miri/src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -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()?;
Expand Down
8 changes: 0 additions & 8 deletions src/tools/miri/src/shims/unix/macos/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down Expand Up @@ -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] =
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/src/shims/unix/solarish/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down
16 changes: 16 additions & 0 deletions src/tools/miri/tests/pass-dep/libc/libc-strerror_r.rs
Original file line number Diff line number Diff line change
@@ -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
);
}
}

0 comments on commit a221d50

Please sign in to comment.