Skip to content

Conversation

@hulxv
Copy link
Contributor

@hulxv hulxv commented Nov 21, 2025

Close #4684

@rustbot
Copy link
Collaborator

rustbot commented Nov 21, 2025

Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two.
Please remember to not force-push to the PR branch except when you need to rebase due to a conflict or when the reviewer asks you for it.

@rustbot rustbot added the S-waiting-on-review Status: Waiting for a review to complete label Nov 21, 2025
@hulxv hulxv force-pushed the feat/support-fstat-in-linux branch from e009ee2 to 8731b63 Compare November 21, 2025 14:40
Copy link
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! However, there are some things missing.

View changes since this review

Comment on lines +56 to +60
"fstat" => {
let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
let result = this.fstat(fd, buf)?;
this.write_scalar(result, dest)?;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in the issue, this should be moved into src/shims/unix/foreign_items.rs, and then the corresponding blocks in the other unixes can be removed. (Some of them also make the function available under other names; those cannot be removed.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to remove them from other unixes but it seems all of them are under different names

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add fstat64 here as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't yet add fstat64 here. What was your plan?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, if we are fstat64 we should probably use the stat64 type, not the stat type... but somehow this worked before? Not entirely sure what is happening. This might be related to the freebsd test failure.

@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels Nov 23, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 23, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@hulxv hulxv requested a review from RalfJung November 24, 2025 22:16
@RalfJung
Copy link
Member

Please use @rustbot ready when the PR is ready for review again.

However, it seems like there are some CI failures that need to be dealt with before this is ready?

refactor: rename `macos_fbsd_solarish_write_stat_buf` to `write_stat_buf`

refactor: rename `macos_fbsd_solarish_fstat` to `fstat`

feat: support `fstat` in linux

test: testing support of `fstat` in linux

fix: missed add `Os::Linux` for supported OSs in `fstat`

feat: add nanosecond fields to file metadata in `EvalContextExtPrivate`

add `fstat` to foreign items in unix

enhance test of `fstat`

fix the test
@hulxv hulxv force-pushed the feat/support-fstat-in-linux branch from 620531b to d2ded9c Compare November 25, 2025 21:21
@hulxv
Copy link
Contributor Author

hulxv commented Nov 25, 2025

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Waiting for a review to complete and removed S-waiting-on-author Status: Waiting for the PR author to address review comments labels Nov 25, 2025
@hulxv
Copy link
Contributor Author

hulxv commented Nov 25, 2025

for some reason, it fails on aarch64 only

  full stderr:
  hello dup fd
  error: Undefined Behavior: memory access failed: attempting to access 8 bytes, but got alloc23440+0x78 which is at or beyond the end of the allocation of size 120 bytes
    --> tests/pass-dep/libc/libc-fs.rs:465:24
     |
  LL |     let res = unsafe { libc::fstat(fd, &mut stat) };
     |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
     |
     = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
     = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
  help: alloc23440 was allocated here:
    --> tests/pass-dep/libc/libc-fs.rs:464:9
     |
  LL |     let mut stat: libc::stat = unsafe { MaybeUninit::zeroed().assume_init() };
     |         ^^^^^^^^
     = note: BACKTRACE (of the first span):
     = note: inside `test_fstat` at tests/pass-dep/libc/libc-fs.rs:465:24: 465:50
  note: inside `main`
    --> tests/pass-dep/libc/libc-fs.rs:45:5
     |
  LL |     test_fstat();
     |     ^^^^^^^^^^^^
  
  note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
  
  error: aborting due to 1 previous error
  
  
  full stdout:
  hello dup fd

maybe the problem comes from libc itself in aarch64? It's 128 bits, but it allocates 120. I think it's related to the size of libc::stat. Maybe the problem is related to the padding size on aarch64. We can do something like that:

#[repr(C)]
struct SafeStat {
    stat: libc::stat,
    _pad: [u64; 16],
}
let mut safe_stat: SafeStat = unsafe { MaybeUninit::zeroed().assume_init() };
let stat_ptr = &mut safe_stat as *mut SafeStat as *mut libc::stat;

let res = unsafe { libc::fstat(fd, stat_ptr) };

what do you think?

@hulxv hulxv requested a review from RalfJung November 25, 2025 22:15
@RalfJung
Copy link
Member

RalfJung commented Nov 25, 2025

Note that the target it failed on is x86_64-unknown-freebsd. So you are looking at the wrong target.

We definitely should not do anything like that in the test. If a test fails, usually that means you have to fix the code, not the test.

let result = this.macos_fbsd_solarish_lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"fstat" | "fstat64" => {
Copy link
Member

@RalfJung RalfJung Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I have already said twice, this match arm should be removed now. Please make sure you understand my comments before marking the PR as ready, and ask if anything is unclear. Do not just guess and update the PR. Only mark it as ready once you are confident everything is ready. It's a lot of extra work for me if I have to keep re-checking and repeating everything I already said.

("st_mtime", modified_sec.into()),
("st_mtime_nsec", modified_nsec.into()),
("st_ctime", 0),
("st_ctime_nsec", 0),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are now writing these fields twice on macos and freebsd.

@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels Nov 26, 2025
let result = this.macos_fbsd_solarish_lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"fstat" | "fstat@FBSD_1.0" => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"fstat" | "fstat@FBSD_1.0" => {
"fstat@FBSD_1.0" => {

As elsewhere, the "fstat" case should be removed here, since it is already handled in the "unix" handler now.

@RalfJung
Copy link
Member

I looked into the BSD issue. Apparently on BSD there is libc::unix::bsd::freebsdlike::freebsd::freebsd12::stat and libc::stat and those are not the same type. Great. Who on Earth screwed that up?!??

The fix for us is fairly simple though -- we just trust the type signature used by the program, since double-checking it is apparently impractically difficult:

diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs
index 16214d7ef..c33100b24 100644
--- a/src/shims/unix/fs.rs
+++ b/src/shims/unix/fs.rs
@@ -130,7 +130,11 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> {
         let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0));
         let mode = metadata.mode.to_uint(this.libc_ty_layout("mode_t").size)?;
 
-        let buf = this.deref_pointer_as(buf_op, this.libc_ty_layout("stat"))?;
+        // We do *not* use `deref_pointer_as` here since determining the right pointee type
+        // is highly non-trivial: it depends on which exact alias of the function was invoked
+        // (e.g. `fstat` vs `fstat64`), and then on FreeBSD it also depends on the ABI level
+        // which can be different between the libc used by std and the libc used by everyone else.
+        let buf = this.deref_pointer(buf_op)?;
         this.write_int_fields_named(
             &[
                 ("st_dev", metadata.dev.into()),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: Waiting for the PR author to address review comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support "fstat" on Linux

3 participants