Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
fd1a753
Refactor CPU affinity tests to use errno_check for error handling
hulxv Dec 17, 2025
d5d605a
Refactor libc time tests to use errno_check for error handling
hulxv Dec 17, 2025
cecc26b
Refactor libc-fs-symlink tests to use errno_result
hulxv Jan 2, 2026
c5f6783
Convert Windows to use check_shim_sig instead of check_shim_sig_lenient
CraftSpider Dec 19, 2025
00693a8
tweak shim_sig
RalfJung Jan 5, 2026
078712b
Merge pull request #4779 from CraftSpider/windows-shim-sig
RalfJung Jan 5, 2026
6750919
add `pmaddwd` shim
folkertdev Jan 7, 2026
fb9b6bd
Refactor socketpair tests to use utility functions for reading and wr…
hulxv Dec 17, 2025
ffaf76a
Refactor epoll tests to use errno_result and improve notification checks
hulxv Dec 17, 2025
7dc7942
Merge pull request #4808 from folkertdev/pmaddwd
RalfJung Jan 8, 2026
1caf7b2
Add miri specific shims for managing threads in no_std projects
loftyinclination Jan 10, 2026
fab0a65
Merge pull request #4807 from loftyinclination/master
RalfJung Jan 10, 2026
bd31b9d
use io::Result for read/write helpers, and add read_until_eof_into_slice
RalfJung Jan 10, 2026
ded9a2b
Merge pull request #4770 from hulxv/refactor/simplify-libc-tests/libc…
RalfJung Jan 10, 2026
03ad5b0
readme: clarify 'single-threaded interpreter'
RalfJung Jan 10, 2026
7a1b8bf
Merge pull request #4771 from hulxv/refactor/simplify-libc-tests/libc…
RalfJung Jan 10, 2026
8029c44
Merge pull request #4773 from hulxv/refactor/simplify-libc-tests/libc…
RalfJung Jan 10, 2026
decd472
Merge pull request #4811 from RalfJung/readme
RalfJung Jan 10, 2026
199aa68
Prepare for merging from rust-lang/rust
Jan 12, 2026
e7b0b35
Merge ref '44a5b55557c2' from rust-lang/rust
Jan 12, 2026
41939ae
test closing std streams separately, and in two configurations
RalfJung Jan 12, 2026
c947436
Merge pull request #4814 from rust-lang/rustup-2026-01-12
RalfJung Jan 12, 2026
d59c47c
Prepare for merging from rust-lang/rust
Jan 15, 2026
c15cdfb
Merge ref 'b6fdaf2a1573' from rust-lang/rust
Jan 15, 2026
b184dd9
Merge pull request #4815 from rust-lang/rustup-2026-01-15
RalfJung Jan 15, 2026
2ef85d7
use epoll_ctl_add more often
RalfJung Jan 18, 2026
255b483
Merge pull request #4772 from hulxv/refactor/simplify-libc-tests/libc…
RalfJung Jan 18, 2026
c367dfd
shims: add FIXME for missing direct tests
RalfJung Jan 18, 2026
bf8091e
Merge pull request #4817 from RalfJung/missing-tests
RalfJung Jan 18, 2026
43fb39f
Add avx512 `pack*` family of instructions
ChillFish8 Jan 11, 2026
41204bf
Merge pull request #4800 from hulxv/refactor/simplify-libc-tests/libc…
RalfJung Jan 18, 2026
e582ac3
Merge pull request #4813 from ChillFish8/avx512/add-pack-instructions
RalfJung Jan 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/tools/miri/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ and macOS targets are usually on par. Windows is supported less well.

### Running tests in parallel

Though it implements Rust threading, Miri itself is a single-threaded interpreter.
Though it implements Rust threading, Miri itself is a single-threaded interpreter
(it works like a multi-threaded OS on a single-core CPU).
This means that when running `cargo miri test`, you will probably see a dramatic
increase in the amount of time it takes to run your whole test suite due to the
inherent interpreter slowdown and a loss of parallelism.
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f57b9e6f565a1847e83a63f3e90faa3870536c1f
b6fdaf2a15736cbccf248b532f48e33179614d40
2 changes: 1 addition & 1 deletion src/tools/miri/src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ fn main() {
if !miri_config.native_lib.is_empty() && miri_config.provenance_mode == ProvenanceMode::Strict {
fatal_error!("strict provenance is not compatible with calling native functions");
}
// Native calls and many-seeds are an "intersting" combination.
// Native calls and many-seeds are an "interesting" combination.
if !miri_config.native_lib.is_empty() && many_seeds.is_some() {
eprintln!(
"warning: `-Zmiri-many-seeds` runs multiple instances of the program in the same address space, \
Expand Down
36 changes: 35 additions & 1 deletion src/tools/miri/src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry;
use std::io::Write;
use std::path::Path;

use rustc_abi::{Align, CanonAbi, Size};
use rustc_abi::{Align, CanonAbi, ExternAbi, Size};
use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE;
use rustc_data_structures::either::Either;
use rustc_hir::attrs::Linkage;
Expand Down Expand Up @@ -435,6 +435,40 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Return value: 0 on success, otherwise the size it would have needed.
this.write_int(if success { 0 } else { needed_size }, dest)?;
}
"miri_thread_spawn" => {
// FIXME: `check_shim_sig` does not work with function pointers.
let [start_routine, func_arg] =
this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
let start_routine = this.read_pointer(start_routine)?;
let func_arg = this.read_immediate(func_arg)?;

this.start_regular_thread(
Some(dest.clone()),
start_routine,
ExternAbi::Rust,
func_arg,
this.machine.layouts.unit,
)?;
}
"miri_thread_join" => {
let [thread_id] = this.check_shim_sig(
shim_sig!(extern "Rust" fn(usize) -> bool),
link_name,
abi,
args,
)?;

let thread = this.read_target_usize(thread_id)?;
if let Ok(thread) = this.thread_id_try_from(thread) {
this.join_thread_exclusive(
thread,
/* success_retval */ Scalar::from_bool(true),
dest,
)?;
} else {
this.write_scalar(Scalar::from_bool(false), dest)?;
}
}
// Hint that a loop is spinning indefinitely.
"miri_spin_loop" => {
let [] = this.check_shim_sig_lenient(abi, CanonAbi::Rust, link_name, args)?;
Expand Down
17 changes: 14 additions & 3 deletions src/tools/miri/src/shims/sig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@ pub struct ShimSig<'tcx, const ARGS: usize> {

/// Construct a `ShimSig` with convenient syntax:
/// ```rust,ignore
/// shim_sig!(this, extern "C" fn (*const T, i32) -> usize)
/// shim_sig!(extern "C" fn (*const T, i32) -> usize)
/// ```
///
/// The following types are supported:
/// - primitive integer types
/// - `()`
/// - (thin) raw pointers, written `*const _` and `*mut _` since the pointee type is irrelevant
/// - `$crate::$mod::...::$ty` for a type from the given crate (most commonly that is `libc`)
/// - `winapi::$ty` for a type from `std::sys::pal::windows::c`
#[macro_export]
macro_rules! shim_sig {
(extern $abi:literal fn($($arg:ty),*) -> $ret:ty) => {
(extern $abi:literal fn($($arg:ty),* $(,)?) -> $ret:ty) => {
|this| $crate::shims::sig::ShimSig {
abi: std::str::FromStr::from_str($abi).expect("incorrect abi specified"),
args: [$(shim_sig_arg!(this, $arg)),*],
Expand Down Expand Up @@ -50,9 +57,13 @@ macro_rules! shim_sig_arg {
"u128" => $this.tcx.types.u128,
"usize" => $this.tcx.types.usize,
"()" => $this.tcx.types.unit,
"bool" => $this.tcx.types.bool,
"*const _" => $this.machine.layouts.const_raw_ptr.ty,
"*mut _" => $this.machine.layouts.mut_raw_ptr.ty,
ty if let Some(libc_ty) = ty.strip_prefix("libc::") => $this.libc_ty_layout(libc_ty).ty,
ty if let Some(win_ty) = ty.strip_prefix("winapi::") =>
$this.windows_ty_layout(win_ty).ty,
ty if ty.contains("::") =>
helpers::path_ty_layout($this, &ty.split("::").collect::<Vec<_>>()).ty,
ty => panic!("unsupported signature type {ty:?}"),
}
}};
Expand Down
6 changes: 6 additions & 0 deletions src/tools/miri/src/shims/unix/android/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
match link_name.as_str() {
// File related shims
"stat" => {
// FIXME: This does not have a direct test (#3179).
let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.stat(path, buf)?;
this.write_scalar(result, dest)?;
}
"lstat" => {
// FIXME: This does not have a direct test (#3179).
let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"readdir" => {
// FIXME: This does not have a direct test (#3179).
let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.readdir64("dirent", dirp)?;
this.write_scalar(result, dest)?;
}
"pread64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, count, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off64_t) -> isize),
link_name,
Expand All @@ -56,6 +60,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.read(fd, buf, count, Some(offset), dest)?;
}
"pwrite64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, n, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *const _, usize, libc::off64_t) -> isize),
link_name,
Expand All @@ -70,6 +75,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, Some(offset), dest)?;
}
"lseek64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, offset, whence] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, libc::off64_t, i32) -> libc::off64_t),
link_name,
Expand Down
19 changes: 19 additions & 0 deletions src/tools/miri/src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"getcwd" => {
// FIXME: This does not have a direct test (#3179).
let [buf, size] = this.check_shim_sig(
shim_sig!(extern "C" fn(*mut _, usize) -> *mut _),
link_name,
Expand All @@ -153,6 +154,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_pointer(result, dest)?;
}
"chdir" => {
// FIXME: This does not have a direct test (#3179).
let [path] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _) -> i32),
link_name,
Expand Down Expand Up @@ -209,6 +211,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, None, dest)?;
}
"pread" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, count, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off_t) -> isize),
link_name,
Expand All @@ -222,6 +225,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.read(fd, buf, count, Some(offset), dest)?;
}
"pwrite" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, n, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *const _, usize, libc::off_t) -> isize),
link_name,
Expand Down Expand Up @@ -299,6 +303,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"unlink" => {
// FIXME: This does not have a direct test (#3179).
let [path] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _) -> i32),
link_name,
Expand All @@ -309,6 +314,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"symlink" => {
// FIXME: This does not have a direct test (#3179).
let [target, linkpath] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _, *const _) -> i32),
link_name,
Expand All @@ -324,6 +330,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"rename" => {
// FIXME: This does not have a direct test (#3179).
let [oldpath, newpath] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _, *const _) -> i32),
link_name,
Expand All @@ -334,6 +341,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"mkdir" => {
// FIXME: This does not have a direct test (#3179).
let [path, mode] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _, libc::mode_t) -> i32),
link_name,
Expand All @@ -344,6 +352,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"rmdir" => {
// FIXME: This does not have a direct test (#3179).
let [path] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _) -> i32),
link_name,
Expand All @@ -354,6 +363,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"opendir" => {
// FIXME: This does not have a direct test (#3179).
let [name] = this.check_shim_sig(
shim_sig!(extern "C" fn(*const _) -> *mut _),
link_name,
Expand All @@ -364,6 +374,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"closedir" => {
// FIXME: This does not have a direct test (#3179).
let [dirp] = this.check_shim_sig(
shim_sig!(extern "C" fn(*mut _) -> i32),
link_name,
Expand All @@ -374,6 +385,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"lseek" => {
// FIXME: This does not have a direct test (#3179).
let [fd, offset, whence] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, libc::off_t, i32) -> libc::off_t),
link_name,
Expand All @@ -398,6 +410,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"fsync" => {
// FIXME: This does not have a direct test (#3179).
let [fd] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32) -> i32),
link_name,
Expand All @@ -408,6 +421,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"fdatasync" => {
// FIXME: This does not have a direct test (#3179).
let [fd] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32) -> i32),
link_name,
Expand Down Expand Up @@ -659,20 +673,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_null(dest)?;
}
"pthread_key_delete" => {
// FIXME: This does not have a direct test (#3179).
let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
this.machine.tls.delete_tls_key(key)?;
// Return success (0)
this.write_null(dest)?;
}
"pthread_getspecific" => {
// FIXME: This does not have a direct test (#3179).
let [key] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
let active_thread = this.active_thread();
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
this.write_scalar(ptr, dest)?;
}
"pthread_setspecific" => {
// FIXME: This does not have a direct test (#3179).
let [key, new_ptr] =
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
Expand Down Expand Up @@ -833,6 +850,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(res, dest)?;
}
"sched_yield" => {
// FIXME: This does not have a direct test (#3179).
let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
this.sched_yield()?;
this.write_null(dest)?;
Expand Down Expand Up @@ -941,6 +959,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"pthread_atfork" => {
// FIXME: This does not have a direct test (#3179).
let [prepare, parent, child] =
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
this.read_pointer(prepare)?;
Expand Down
3 changes: 3 additions & 0 deletions src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// For those, we both intercept `func` and `call@FBSD_1.0` symbols cases
// since freebsd 12 the former form can be expected.
"stat" | "stat@FBSD_1.0" => {
// FIXME: This does not have a direct test (#3179).
let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.stat(path, buf)?;
this.write_scalar(result, dest)?;
}
"lstat" | "lstat@FBSD_1.0" => {
// FIXME: This does not have a direct test (#3179).
let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.lstat(path, buf)?;
this.write_scalar(result, dest)?;
Expand All @@ -154,6 +156,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"readdir" | "readdir@FBSD_1.0" => {
// FIXME: This does not have a direct test (#3179).
let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.readdir64("dirent", dirp)?;
this.write_scalar(result, dest)?;
Expand Down
5 changes: 5 additions & 0 deletions src/tools/miri/src/shims/unix/linux/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"pread64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, count, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off64_t) -> isize),
link_name,
Expand All @@ -58,6 +59,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.read(fd, buf, count, Some(offset), dest)?;
}
"pwrite64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, buf, n, offset] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, *const _, usize, libc::off64_t) -> isize),
link_name,
Expand All @@ -72,6 +74,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, Some(offset), dest)?;
}
"lseek64" => {
// FIXME: This does not have a direct test (#3179).
let [fd, offset, whence] = this.check_shim_sig(
shim_sig!(extern "C" fn(i32, libc::off64_t, i32) -> libc::off64_t),
link_name,
Expand Down Expand Up @@ -111,6 +114,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"readdir64" => {
// FIXME: This does not have a direct test (#3179).
let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.readdir64("dirent64", dirp)?;
this.write_scalar(result, dest)?;
Expand All @@ -122,6 +126,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?;
}
"statx" => {
// FIXME: This does not have a direct test (#3179).
let [dirfd, pathname, flags, mask, statxbuf] =
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
Expand Down
Loading
Loading