Skip to content

Commit 4ac9138

Browse files
committed
route all path reading/writing through central read/write methods
1 parent 3517ce6 commit 4ac9138

File tree

3 files changed

+46
-24
lines changed

3 files changed

+46
-24
lines changed

src/helpers.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::ffi::{OsStr, OsString};
2+
use std::path::Path;
23
use std::{iter, mem};
34
use std::convert::TryFrom;
5+
use std::borrow::Cow;
46

57
use rustc::mir;
68
use rustc::ty::{
@@ -491,6 +493,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
491493
bytes_to_os_str(bytes)
492494
}
493495

496+
/// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
497+
fn read_path_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, Cow<'a, Path>>
498+
where
499+
'tcx: 'a,
500+
'mir: 'a,
501+
{
502+
let os_str = self.read_os_str_from_c_str(scalar)?;
503+
Ok(Cow::Borrowed(Path::new(os_str)))
504+
}
505+
494506
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
495507
/// which is what the Windows APIs usually handle.
496508
fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString>
@@ -513,7 +525,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
513525
u16vec_to_osstring(u16_vec)
514526
}
515527

516-
517528
/// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
518529
/// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
519530
/// to write if `size` is not large enough to fit the contents of `os_string` plus a null
@@ -553,6 +564,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
553564
Ok((true, string_length))
554565
}
555566

567+
/// Write a Path to the machine memory, adjusting path separators if needed.
568+
fn write_path_to_c_str(
569+
&mut self,
570+
path: &Path,
571+
scalar: Scalar<Tag>,
572+
size: u64,
573+
) -> InterpResult<'tcx, (bool, u64)> {
574+
let os_str = path.as_os_str();
575+
self.write_os_str_to_c_str(os_str, scalar, size)
576+
}
577+
556578
/// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
557579
/// the Windows APIs usually handle. This function returns `Ok((false, length))` without trying
558580
/// to write if `size` is not large enough to fit the contents of `os_string` plus a null

src/shims/env.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
134134
// If we cannot get the current directory, we return null
135135
match env::current_dir() {
136136
Ok(cwd) => {
137-
if this.write_os_str_to_c_str(&OsString::from(cwd), buf, size)?.0 {
137+
if this.write_path_to_c_str(&cwd, buf, size)?.0 {
138138
return Ok(buf);
139139
}
140140
let erange = this.eval_libc("ERANGE")?;
@@ -150,7 +150,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
150150

151151
this.check_no_isolation("chdir")?;
152152

153-
let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
153+
let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
154154

155155
match env::set_current_dir(path) {
156156
Ok(()) => Ok(0),

src/shims/fs.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::BTreeMap;
22
use std::convert::{TryFrom, TryInto};
33
use std::fs::{read_dir, remove_dir, remove_file, rename, DirBuilder, File, FileType, OpenOptions, ReadDir};
44
use std::io::{Read, Seek, SeekFrom, Write};
5-
use std::path::PathBuf;
5+
use std::path::Path;
66
use std::time::SystemTime;
77

88
use rustc_data_structures::fx::FxHashMap;
@@ -79,9 +79,9 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '
7979
let this = self.eval_context_mut();
8080

8181
let path_scalar = this.read_scalar(path_op)?.not_undef()?;
82-
let path: PathBuf = this.read_os_str_from_c_str(path_scalar)?.into();
82+
let path = this.read_path_from_c_str(path_scalar)?.into_owned();
8383

84-
let metadata = match FileMetadata::from_path(this, path, follow_symlink)? {
84+
let metadata = match FileMetadata::from_path(this, &path, follow_symlink)? {
8585
Some(metadata) => metadata,
8686
None => return Ok(-1),
8787
};
@@ -303,7 +303,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
303303
throw_unsup_format!("unsupported flags {:#x}", flag & !mirror);
304304
}
305305

306-
let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
306+
let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
307307

308308
let fd = options.open(&path).map(|file| {
309309
let fh = &mut this.machine.file_handler;
@@ -524,10 +524,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
524524

525525
this.check_no_isolation("unlink")?;
526526

527-
let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
527+
let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
528528

529529
let result = remove_file(path).map(|_| 0);
530-
531530
this.try_unwrap_io_result(result)
532531
}
533532

@@ -537,12 +536,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
537536
linkpath_op: OpTy<'tcx, Tag>
538537
) -> InterpResult<'tcx, i32> {
539538
#[cfg(target_family = "unix")]
540-
fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
539+
fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
541540
std::os::unix::fs::symlink(src, dst)
542541
}
543542

544543
#[cfg(target_family = "windows")]
545-
fn create_link(src: PathBuf, dst: PathBuf) -> std::io::Result<()> {
544+
fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
546545
use std::os::windows::fs;
547546
if src.is_dir() {
548547
fs::symlink_dir(src, dst)
@@ -555,10 +554,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
555554

556555
this.check_no_isolation("symlink")?;
557556

558-
let target = this.read_os_str_from_c_str(this.read_scalar(target_op)?.not_undef()?)?.into();
559-
let linkpath = this.read_os_str_from_c_str(this.read_scalar(linkpath_op)?.not_undef()?)?.into();
557+
let target = this.read_path_from_c_str(this.read_scalar(target_op)?.not_undef()?)?;
558+
let linkpath = this.read_path_from_c_str(this.read_scalar(linkpath_op)?.not_undef()?)?;
560559

561-
this.try_unwrap_io_result(create_link(target, linkpath).map(|_| 0))
560+
let result = create_link(&target, &linkpath).map(|_| 0);
561+
this.try_unwrap_io_result(result)
562562
}
563563

564564
fn macos_stat(
@@ -644,7 +644,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
644644
this.ref_to_mplace(statxbuf_imm)?
645645
};
646646

647-
let path: PathBuf = this.read_os_str_from_c_str(pathname_scalar)?.into();
647+
let path = this.read_path_from_c_str(pathname_scalar)?.into_owned();
648648
// `flags` should be a `c_int` but the `syscall` function provides an `isize`.
649649
let flags: i32 =
650650
this.read_scalar(flags_op)?.to_machine_isize(&*this.tcx)?.try_into().map_err(|e| {
@@ -691,7 +691,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
691691
let metadata = if path.as_os_str().is_empty() && empty_path_flag {
692692
FileMetadata::from_fd(this, dirfd)?
693693
} else {
694-
FileMetadata::from_path(this, path, follow_symlink)?
694+
FileMetadata::from_path(this, &path, follow_symlink)?
695695
};
696696
let metadata = match metadata {
697697
Some(metadata) => metadata,
@@ -785,8 +785,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
785785
return Ok(-1);
786786
}
787787

788-
let oldpath = this.read_os_str_from_c_str(oldpath_scalar)?;
789-
let newpath = this.read_os_str_from_c_str(newpath_scalar)?;
788+
let oldpath = this.read_path_from_c_str(oldpath_scalar)?;
789+
let newpath = this.read_path_from_c_str(newpath_scalar)?;
790790

791791
let result = rename(oldpath, newpath).map(|_| 0);
792792

@@ -808,7 +808,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
808808
this.read_scalar(mode_op)?.to_u32()?
809809
};
810810

811-
let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
811+
let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
812812

813813
let mut builder = DirBuilder::new();
814814

@@ -833,7 +833,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
833833

834834
this.check_no_isolation("rmdir")?;
835835

836-
let path = this.read_os_str_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
836+
let path = this.read_path_from_c_str(this.read_scalar(path_op)?.not_undef()?)?;
837837

838838
let result = remove_dir(path).map(|_| 0i32);
839839

@@ -845,7 +845,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
845845

846846
this.check_no_isolation("opendir")?;
847847

848-
let name = this.read_os_str_from_c_str(this.read_scalar(name_op)?.not_undef()?)?;
848+
let name = this.read_path_from_c_str(this.read_scalar(name_op)?.not_undef()?)?;
849849

850850
let result = read_dir(name);
851851

@@ -899,7 +899,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
899899
let entry_place = this.deref_operand(entry_op)?;
900900
let name_place = this.mplace_field(entry_place, 4)?;
901901

902-
let file_name = dir_entry.file_name();
902+
let file_name = dir_entry.file_name(); // not a Path as there are no separators!
903903
let (name_fits, _) = this.write_os_str_to_c_str(
904904
&file_name,
905905
name_place.ptr,
@@ -987,7 +987,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
987987
let entry_place = this.deref_operand(entry_op)?;
988988
let name_place = this.mplace_field(entry_place, 5)?;
989989

990-
let file_name = dir_entry.file_name();
990+
let file_name = dir_entry.file_name(); // not a Path as there are no separators!
991991
let (name_fits, file_name_len) = this.write_os_str_to_c_str(
992992
&file_name,
993993
name_place.ptr,
@@ -1082,7 +1082,7 @@ struct FileMetadata {
10821082
impl FileMetadata {
10831083
fn from_path<'tcx, 'mir>(
10841084
ecx: &mut MiriEvalContext<'mir, 'tcx>,
1085-
path: PathBuf,
1085+
path: &Path,
10861086
follow_symlink: bool
10871087
) -> InterpResult<'tcx, Option<FileMetadata>> {
10881088
let metadata = if follow_symlink {

0 commit comments

Comments
 (0)