]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/miri/src/shims/unix/fs.rs
make flag checks reobust against multi-bit flags
[rust.git] / src / tools / miri / src / shims / unix / fs.rs
index b152082b4deb80f21f22538cfcc4ff07bb74ef9e..0a26657f57c85cc921db96efbedecdf1fe03842f 100644 (file)
@@ -11,7 +11,6 @@
 use log::trace;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::ty::{self, layout::LayoutOf};
 use rustc_target::abi::{Align, Size};
 
 use crate::shims::os_str::bytes_to_os_str;
@@ -279,7 +278,7 @@ pub struct FileHandler {
 }
 
 impl VisitTags for FileHandler {
-    fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) {
+    fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
         // All our FileDescriptor do not have any tags.
     }
 }
@@ -491,7 +490,7 @@ fn default() -> DirHandler {
 }
 
 impl VisitTags for DirHandler {
-    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+    fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
         let DirHandler { streams, next_id: _ } = self;
 
         for dir in streams.values() {
@@ -563,17 +562,17 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
         let mut mirror = access_mode;
 
         let o_append = this.eval_libc_i32("O_APPEND")?;
-        if flag & o_append != 0 {
+        if flag & o_append == o_append {
             options.append(true);
             mirror |= o_append;
         }
         let o_trunc = this.eval_libc_i32("O_TRUNC")?;
-        if flag & o_trunc != 0 {
+        if flag & o_trunc == o_trunc {
             options.truncate(true);
             mirror |= o_trunc;
         }
         let o_creat = this.eval_libc_i32("O_CREAT")?;
-        if flag & o_creat != 0 {
+        if flag & o_creat == o_creat {
             // Get the mode.  On macOS, the argument type `mode_t` is actually `u16`, but
             // C integer promotion rules mean that on the ABI level, it gets passed as `u32`
             // (see https://github.com/rust-lang/rust/issues/71915).
@@ -593,7 +592,7 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
             mirror |= o_creat;
 
             let o_excl = this.eval_libc_i32("O_EXCL")?;
-            if flag & o_excl != 0 {
+            if flag & o_excl == o_excl {
                 mirror |= o_excl;
                 options.create_new(true);
             } else {
@@ -601,11 +600,20 @@ fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
             }
         }
         let o_cloexec = this.eval_libc_i32("O_CLOEXEC")?;
-        if flag & o_cloexec != 0 {
+        if flag & o_cloexec == o_cloexec {
             // We do not need to do anything for this flag because `std` already sets it.
             // (Technically we do not support *not* setting this flag, but we ignore that.)
             mirror |= o_cloexec;
         }
+        if this.tcx.sess.target.os == "linux" {
+            let o_tmpfile = this.eval_libc_i32("O_TMPFILE")?;
+            if flag & o_tmpfile == o_tmpfile {
+                // if the flag contains `O_TMPFILE` then we return a graceful error
+                let eopnotsupp = this.eval_libc("EOPNOTSUPP")?;
+                this.set_last_error(eopnotsupp)?;
+                return Ok(-1);
+            }
+        }
         // If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`,
         // then we throw an error.
         if flag != mirror {
@@ -1006,18 +1014,14 @@ fn linux_statx(
         // as `isize`s instead of having the proper types. Thus, we have to recover the layout of
         // `statxbuf_op` by using the `libc::statx` struct type.
         let statxbuf = {
-            // FIXME: This long path is required because `libc::statx` is an struct and also a
-            // function and `resolve_path` is returning the latter.
-            let statx_ty = this
-                .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"])
-                .ty(*this.tcx, ty::ParamEnv::reveal_all());
-            let statx_layout = this.layout_of(statx_ty)?;
+            let statx_layout = this.libc_ty_layout("statx")?;
             MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout)
         };
 
         let path = this.read_path_from_c_str(pathname_ptr)?.into_owned();
         // See <https://github.com/rust-lang/rust/pull/79196> for a discussion of argument sizes.
-        let empty_path_flag = flags & this.eval_libc("AT_EMPTY_PATH")?.to_i32()? != 0;
+        let at_ampty_path = this.eval_libc_i32("AT_EMPTY_PATH")?;
+        let empty_path_flag = flags & at_ampty_path == at_ampty_path;
         // We only support:
         // * interpreting `path` as an absolute directory,
         // * interpreting `path` as a path relative to `dirfd` when the latter is `AT_FDCWD`, or
@@ -1917,8 +1921,8 @@ struct FileMetadata {
 }
 
 impl FileMetadata {
-    fn from_path<'tcx, 'mir>(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+    fn from_path<'tcx>(
+        ecx: &mut MiriInterpCx<'_, 'tcx>,
         path: &Path,
         follow_symlink: bool,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
@@ -1928,8 +1932,8 @@ fn from_path<'tcx, 'mir>(
         FileMetadata::from_meta(ecx, metadata)
     }
 
-    fn from_fd<'tcx, 'mir>(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+    fn from_fd<'tcx>(
+        ecx: &mut MiriInterpCx<'_, 'tcx>,
         fd: i32,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let option = ecx.machine.file_handler.handles.get(&fd);
@@ -1942,8 +1946,8 @@ fn from_fd<'tcx, 'mir>(
         FileMetadata::from_meta(ecx, metadata)
     }
 
-    fn from_meta<'tcx, 'mir>(
-        ecx: &mut MiriInterpCx<'mir, 'tcx>,
+    fn from_meta<'tcx>(
+        ecx: &mut MiriInterpCx<'_, 'tcx>,
         metadata: Result<std::fs::Metadata, std::io::Error>,
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let metadata = match metadata {