]> git.lizzy.rs Git - rust.git/commitdiff
route all path reading/writing through central read/write methods
authorRalf Jung <post@ralfj.de>
Mon, 23 Mar 2020 18:24:16 +0000 (19:24 +0100)
committerRalf Jung <post@ralfj.de>
Tue, 24 Mar 2020 08:11:47 +0000 (09:11 +0100)
src/helpers.rs
src/shims/env.rs
src/shims/fs.rs

index 76c5308cfd35b1ecd20c84ff8c3e42947c540245..d8731b537719b9ce229da2344f10ce669111a214 100644 (file)
@@ -1,6 +1,8 @@
 use std::ffi::{OsStr, OsString};
+use std::path::Path;
 use std::{iter, mem};
 use std::convert::TryFrom;
+use std::borrow::Cow;
 
 use rustc::mir;
 use rustc::ty::{
@@ -491,6 +493,16 @@ fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
         bytes_to_os_str(bytes)
     }
 
+    /// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
+    fn read_path_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, Cow<'a, Path>>
+    where
+        'tcx: 'a,
+        'mir: 'a,
+    {
+        let os_str = self.read_os_str_from_c_str(scalar)?;
+        Ok(Cow::Borrowed(Path::new(os_str)))
+    }
+
     /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
     /// which is what the Windows APIs usually handle.
     fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString>
@@ -513,7 +525,6 @@ pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsS
         u16vec_to_osstring(u16_vec)
     }
 
-
     /// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
     /// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
     /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
@@ -553,6 +564,17 @@ fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]>
         Ok((true, string_length))
     }
 
+    /// Write a Path to the machine memory, adjusting path separators if needed.
+    fn write_path_to_c_str(
+        &mut self,
+        path: &Path,
+        scalar: Scalar<Tag>,
+        size: u64,
+    ) -> InterpResult<'tcx, (bool, u64)> {
+        let os_str = path.as_os_str();
+        self.write_os_str_to_c_str(os_str, scalar, size)
+    }
+
     /// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
     /// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
     /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
index 6b18cd25a1b0f0a74366c088b3c34b0b30c68b4f..192fc0d47abec40eb36a13b6e0f48a00b3e2a718 100644 (file)
@@ -134,7 +134,7 @@ fn getcwd(
         // If we cannot get the current directory, we return null
         match env::current_dir() {
             Ok(cwd) => {
-                if this.write_os_str_to_c_str(&OsString::from(cwd), buf, size)?.0 {
+                if this.write_path_to_c_str(&cwd, buf, size)?.0 {
                     return Ok(buf);
                 }
                 let erange = this.eval_libc("ERANGE")?;
@@ -150,7 +150,7 @@ fn chdir(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
 
         this.check_no_isolation("chdir")?;
 
-        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+        let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
 
         match env::set_current_dir(path) {
             Ok(()) => Ok(0),
index 16d83188dbc276541c49b694102ee2da0bae2a4f..9778775fca641372e88701823301b4fd4e5928b2 100644 (file)
@@ -2,7 +2,7 @@
 use std::convert::{TryFrom, TryInto};
 use std::fs::{read_dir, remove_dir, remove_file, rename, DirBuilder, File, FileType, OpenOptions, ReadDir};
 use std::io::{Read, Seek, SeekFrom, Write};
-use std::path::PathBuf;
+use std::path::Path;
 use std::time::SystemTime;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -79,9 +79,9 @@ fn macos_stat_or_lstat(
         let this = self.eval_context_mut();
 
         let path_scalar = this.read_scalar(path_op)?.not_undef()?;
-        let path: PathBuf = this.read_os_str_from_c_str(path_scalar)?.into();
+        let path = this.read_path_from_c_str(path_scalar)?.into_owned();
 
-        let metadata = match FileMetadata::from_path(this, path, follow_symlink)? {
+        let metadata = match FileMetadata::from_path(this, &path, follow_symlink)? {
             Some(metadata) => metadata,
             None => return Ok(-1),
         };
@@ -303,7 +303,7 @@ fn open(
             throw_unsup_format!("unsupported flags {:#x}", flag & !mirror);
         }
 
-        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+        let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
 
         let fd = options.open(&path).map(|file| {
             let fh = &mut this.machine.file_handler;
@@ -524,10 +524,9 @@ fn unlink(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
 
         this.check_no_isolation("unlink")?;
 
-        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+        let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
 
         let result = remove_file(path).map(|_| 0);
-
         this.try_unwrap_io_result(result)
     }
 
@@ -537,12 +536,12 @@ fn symlink(
         linkpath_op: OpTy<'tcx, Tag>
     ) -> InterpResult<'tcx, i32> {
         #[cfg(target_family = "unix")]
-        fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
+        fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
             std::os::unix::fs::symlink(src, dst)
         }
 
         #[cfg(target_family = "windows")]
-        fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
+        fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
             use std::os::windows::fs;
             if src.is_dir() {
                 fs::symlink_dir(src, dst)
@@ -555,10 +554,11 @@ fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
 
         this.check_no_isolation("symlink")?;
 
-        let target = this.read_os_str_from_c_str(this.read_scalar(target_op)?.not_undef()?)?.into();
-        let linkpath = this.read_os_str_from_c_str(this.read_scalar(linkpath_op)?.not_undef()?)?.into();
+        let target = this.read_path_from_c_str(this.read_scalar(target_op)?.not_undef()?)?;
+        let linkpath = this.read_path_from_c_str(this.read_scalar(linkpath_op)?.not_undef()?)?;
 
-        this.try_unwrap_io_result(create_link(target, linkpath).map(|_| 0))
+        let result = create_link(&target, &linkpath).map(|_| 0);
+        this.try_unwrap_io_result(result)
     }
 
     fn macos_stat(
@@ -644,7 +644,7 @@ fn linux_statx(
             this.ref_to_mplace(statxbuf_imm)?
         };
 
-        let path: PathBuf = this.read_os_str_from_c_str(pathname_scalar)?.into();
+        let path = this.read_path_from_c_str(pathname_scalar)?.into_owned();
         // `flags` should be a `c_int` but the `syscall` function provides an `isize`.
         let flags: i32 =
             this.read_scalar(flags_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
@@ -691,7 +691,7 @@ fn linux_statx(
         let metadata = if path.as_os_str().is_empty() && empty_path_flag {
             FileMetadata::from_fd(this, dirfd)?
         } else {
-            FileMetadata::from_path(this, path, follow_symlink)?
+            FileMetadata::from_path(this, &path, follow_symlink)?
         };
         let metadata = match metadata {
             Some(metadata) => metadata,
@@ -785,8 +785,8 @@ fn rename(
             return Ok(-1);
         }
 
-        let oldpath = this.read_os_str_from_c_str(oldpath_scalar)?;
-        let newpath = this.read_os_str_from_c_str(newpath_scalar)?;
+        let oldpath = this.read_path_from_c_str(oldpath_scalar)?;
+        let newpath = this.read_path_from_c_str(newpath_scalar)?;
 
         let result = rename(oldpath, newpath).map(|_| 0);
 
@@ -808,7 +808,7 @@ fn mkdir(
             this.read_scalar(mode_op)?.to_u32()?
         };
 
-        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+        let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
 
         let mut builder = DirBuilder::new();
 
@@ -833,7 +833,7 @@ fn rmdir(
 
         this.check_no_isolation("rmdir")?;
 
-        let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
+        let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
 
         let result = remove_dir(path).map(|_| 0i32);
 
@@ -845,7 +845,7 @@ fn opendir(&mut self, name_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag
 
         this.check_no_isolation("opendir")?;
 
-        let name = this.read_os_str_from_c_str(this.read_scalar(name_op)?.not_undef()?)?;
+        let name = this.read_path_from_c_str(this.read_scalar(name_op)?.not_undef()?)?;
 
         let result = read_dir(name);
 
@@ -899,7 +899,7 @@ fn linux_readdir64_r(
                 let entry_place = this.deref_operand(entry_op)?;
                 let name_place = this.mplace_field(entry_place, 4)?;
 
-                let file_name = dir_entry.file_name();
+                let file_name = dir_entry.file_name(); // not a Path as there are no separators!
                 let (name_fits, _) = this.write_os_str_to_c_str(
                     &file_name,
                     name_place.ptr,
@@ -987,7 +987,7 @@ fn macos_readdir_r(
                 let entry_place = this.deref_operand(entry_op)?;
                 let name_place = this.mplace_field(entry_place, 5)?;
 
-                let file_name = dir_entry.file_name();
+                let file_name = dir_entry.file_name(); // not a Path as there are no separators!
                 let (name_fits, file_name_len) = this.write_os_str_to_c_str(
                     &file_name,
                     name_place.ptr,
@@ -1082,7 +1082,7 @@ struct FileMetadata {
 impl FileMetadata {
     fn from_path<'tcx, 'mir>(
         ecx: &mut MiriEvalContext<'mir, 'tcx>,
-        path: PathBuf,
+        path: &Path,
         follow_symlink: bool
     ) -> InterpResult<'tcx, Option<FileMetadata>> {
         let metadata = if follow_symlink {