Unify readdir shim across Unix targets and add test

This commit is contained in:
Islam-Imad 2026-01-20 13:54:49 +02:00 committed by Ralf Jung
parent 3159e8053a
commit adeb4df788
5 changed files with 47 additions and 14 deletions

View file

@ -39,12 +39,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
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(

View file

@ -382,6 +382,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let result = this.closedir(dirp)?;
this.write_scalar(result, dest)?;
}
"readdir" => {
let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.readdir64("dirent", dirp)?;
this.write_scalar(result, dest)?;
}
"lseek" => {
// FIXME: This does not have a direct test (#3179).
let [fd, offset, whence] = this.check_shim_sig(

View file

@ -155,8 +155,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let result = this.fstat(fd, buf)?;
this.write_scalar(result, dest)?;
}
"readdir" | "readdir@FBSD_1.0" => {
// FIXME: This does not have a direct test (#3179).
"readdir@FBSD_1.0" => {
let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.readdir64("dirent", dirp)?;
this.write_scalar(result, dest)?;

View file

@ -102,12 +102,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
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)?;
}
// Sockets and pipes
"__xnet_socketpair" => {

View file

@ -49,6 +49,7 @@ fn main() {
#[cfg(target_os = "macos")]
test_ioctl();
test_opendir_closedir();
test_readdir();
}
fn test_file_open_unix_allow_two_args() {
@ -609,3 +610,43 @@ fn test_opendir_closedir() {
assert_eq!(e.kind(), ErrorKind::NotADirectory);
remove_file(&file_path).unwrap();
}
fn test_readdir() {
use std::fs::{create_dir, remove_dir};
let dir_path = utils::prepare_dir("miri_test_libc_readdir");
create_dir(&dir_path).ok();
// Create test files
let file1 = dir_path.join("file1.txt");
let file2 = dir_path.join("file2.txt");
std::fs::write(&file1, b"content1").unwrap();
std::fs::write(&file2, b"content2").unwrap();
let c_path = CString::new(dir_path.as_os_str().as_bytes()).unwrap();
unsafe {
let dirp = libc::opendir(c_path.as_ptr()); // DIR *opendir(const char *name);
assert!(!dirp.is_null());
let mut entries = Vec::new();
loop {
let entry_ptr = libc::readdir(dirp);
if entry_ptr.is_null() {
break;
}
let name_ptr = std::ptr::addr_of!((*entry_ptr).d_name) as *const libc::c_char;
let name = CStr::from_ptr(name_ptr);
let name_str = name.to_string_lossy();
if name_str != "." && name_str != ".." {
entries.push(name_str.into_owned());
}
}
assert_eq!(libc::closedir(dirp), 0);
entries.sort();
assert_eq!(entries, vec!["file1.txt", "file2.txt"]);
}
remove_file(&file1).unwrap();
remove_file(&file2).unwrap();
remove_dir(&dir_path).unwrap();
}