Skip to content

Commit 6a2776e

Browse files
committed
Auto merge of #983 - christianpoveda:fs-shims-tweaks, r=RalfJung
Various fixes to the file related shims Hi @RalfJung, I'll be working incrementally over your comments for the new `fs` shims module here.
2 parents e10d9d3 + 003b257 commit 6a2776e

File tree

8 files changed

+42
-31
lines changed

8 files changed

+42
-31
lines changed

src/helpers.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
291291
}
292292
}
293293
}
294+
295+
/// Helper function to get a `libc` constant as a `Scalar`.
296+
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
297+
self.eval_context_mut()
298+
.eval_path_scalar(&["libc", name])?
299+
.ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
300+
.not_undef()
301+
}
302+
303+
/// Helper function to get a `libc` constant as an `i32`.
304+
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
305+
self.eval_libc(name)?.to_i32()
306+
}
294307
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
3434
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
3535
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
3636
pub use crate::shims::env::{EnvVars, EvalContextExt as EnvEvalContextExt};
37-
pub use crate::shims::io::{FileHandler, EvalContextExt as FileEvalContextExt};
37+
pub use crate::shims::fs::{FileHandler, EvalContextExt as FileEvalContextExt};
3838
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
3939
pub use crate::range_map::RangeMap;
4040
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};

src/shims/env.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
127127
let tcx = &{ this.tcx.tcx };
128128

129129
let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
130-
let size = this.read_scalar(size_op)?.to_usize(&*this.tcx)?;
130+
let size = this.read_scalar(size_op)?.to_usize(&*tcx)?;
131131
// If we cannot get the current directory, we return null
132132
match env::current_dir() {
133133
Ok(cwd) => {
134134
// It is not clear what happens with non-utf8 paths here
135135
let mut bytes = cwd.display().to_string().into_bytes();
136-
// If the buffer is smaller or equal than the path, we return null.
136+
// If `size` is smaller or equal than the `bytes.len()`, writing `bytes` plus the
137+
// required null terminator to memory using the `buf` pointer would cause an
138+
// overflow. The desired behavior in this case is to return null.
137139
if (bytes.len() as u64) < size {
138140
// We add a `/0` terminator
139141
bytes.push(0);
140-
// This is ok because the buffer is larger than the path with the null terminator.
142+
// This is ok because the buffer was strictly larger than `bytes`, so after
143+
// adding the null terminator, the buffer size is larger or equal to
144+
// `bytes.len()`, meaning that `bytes` actually fit inside tbe buffer.
141145
this.memory_mut()
142146
.get_mut(buf.alloc_id)?
143147
.write_bytes(tcx, buf, &bytes)?;
@@ -148,7 +152,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
148152
}
149153
Err(e) => this.consume_io_error(e)?,
150154
}
151-
Ok(Scalar::ptr_null(&*this.tcx))
155+
Ok(Scalar::ptr_null(&*tcx))
152156
}
153157

154158
fn chdir(&mut self, path_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {

src/shims/foreign_items.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -981,17 +981,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
981981
return Ok(None);
982982
}
983983

984-
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
985-
self.eval_context_mut()
986-
.eval_path_scalar(&["libc", name])?
987-
.ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name).into())
988-
.and_then(|scalar| scalar.not_undef())
989-
}
990-
991-
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
992-
self.eval_libc(name).and_then(|scalar| scalar.to_i32())
993-
}
994-
995984
fn set_last_error(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx> {
996985
let this = self.eval_context_mut();
997986
let tcx = &{ this.tcx.tcx };

src/shims/io.rs renamed to src/shims/fs.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
107107
if let Some(FileHandle { flag: old_flag, .. }) =
108108
this.machine.file_handler.handles.get_mut(&fd)
109109
{
110+
// Check that the only difference between the old flag and the current flag is
111+
// exactly the `FD_CLOEXEC` value.
110112
if flag ^ *old_flag == fd_cloexec {
111113
*old_flag = flag;
112114
} else {

src/shims/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pub mod env;
33
pub mod foreign_items;
44
pub mod intrinsics;
55
pub mod tls;
6-
pub mod io;
6+
pub mod fs;
77

88
use rustc::{mir, ty};
99

tests/run-pass/change_current_dir.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

tests/run-pass/current_dir.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// ignore-windows: TODO the windows hook is not done yet
2+
// compile-flags: -Zmiri-disable-isolation
3+
use std::env;
4+
use std::path::Path;
5+
6+
fn main() {
7+
// Test that `getcwd` is available
8+
let cwd = env::current_dir().unwrap();
9+
// Test that changing dir to `..` actually sets the current directory to the parent of `cwd`.
10+
// The only exception here is if `cwd` is the root directory, then changing directory must
11+
// keep the current directory equal to `cwd`.
12+
let parent = cwd.parent().unwrap_or(&cwd);
13+
// Test that `chdir` is available
14+
assert!(env::set_current_dir(&Path::new("..")).is_ok());
15+
// Test that `..` goes to the parent directory
16+
assert_eq!(env::current_dir().unwrap(), parent);
17+
}

0 commit comments

Comments
 (0)