Skip to content

Commit 840c2a2

Browse files
author
Ellen Arteca
committed
merge in changes from upstream master
2 parents ec96dff + 0a0a15a commit 840c2a2

File tree

17 files changed

+157
-99
lines changed

17 files changed

+157
-99
lines changed

miri

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ find_sysroot() {
138138
# Run command.
139139
case "$COMMAND" in
140140
install)
141-
# "--locked" to respect the Cargo.lock file if it exists,
141+
# "--locked" to respect the Cargo.lock file if it exists.
142142
$CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR" --force --locked "$@"
143143
$CARGO install $CARGO_EXTRA_FLAGS --path "$MIRIDIR"/cargo-miri --force --locked "$@"
144144
;;

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6077b7cda466afa2b75a62b232ab46dbeb148bcb
1+
db41351753df840773ca628d8daa040e95d00eef

src/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
631631

632632
// Ensure that the access is within bounds.
633633
assert!(op_place.layout.size >= offset + layout.size);
634-
let value_place = op_place.offset(offset, MemPlaceMeta::None, layout, this)?;
634+
let value_place = op_place.offset(offset, layout, this)?;
635635
Ok(value_place)
636636
}
637637

src/shims/backtrace.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
104104
for (i, ptr) in ptrs.into_iter().enumerate() {
105105
let offset = ptr_layout.size * i.try_into().unwrap();
106106

107-
let op_place =
108-
buf_place.offset(offset, MemPlaceMeta::None, ptr_layout, this)?;
107+
let op_place = buf_place.offset(offset, ptr_layout, this)?;
109108

110109
this.write_pointer(ptr, &op_place.into())?;
111110
}

src/shims/unix/foreign_items.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -440,12 +440,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
440440
// Miscellaneous
441441
"isatty" => {
442442
let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
443-
this.read_scalar(fd)?.to_i32()?;
444-
// "returns 1 if fd is an open file descriptor referring to a terminal; otherwise 0 is returned, and errno is set to indicate the error"
445-
// FIXME: we just say nothing is a terminal.
446-
let enotty = this.eval_libc("ENOTTY")?;
447-
this.set_last_error(enotty)?;
448-
this.write_null(dest)?;
443+
let result = this.isatty(fd)?;
444+
this.write_scalar(Scalar::from_i32(result), dest)?;
449445
}
450446
"pthread_atfork" => {
451447
let [prepare, parent, child] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;

src/shims/unix/fs.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ trait FileDescriptor: std::fmt::Debug {
5050
) -> InterpResult<'tcx, io::Result<i32>>;
5151

5252
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>>;
53+
54+
#[cfg(unix)]
55+
fn as_unix_host_fd(&self) -> Option<i32>;
5356
}
5457

5558
impl FileDescriptor for FileHandle {
@@ -114,6 +117,12 @@ impl FileDescriptor for FileHandle {
114117
let duplicated = self.file.try_clone()?;
115118
Ok(Box::new(FileHandle { file: duplicated, writable: self.writable }))
116119
}
120+
121+
#[cfg(unix)]
122+
fn as_unix_host_fd(&self) -> Option<i32> {
123+
use std::os::unix::io::AsRawFd;
124+
Some(self.file.as_raw_fd())
125+
}
117126
}
118127

119128
impl FileDescriptor for io::Stdin {
@@ -159,6 +168,11 @@ impl FileDescriptor for io::Stdin {
159168
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
160169
Ok(Box::new(io::stdin()))
161170
}
171+
172+
#[cfg(unix)]
173+
fn as_unix_host_fd(&self) -> Option<i32> {
174+
Some(libc::STDIN_FILENO)
175+
}
162176
}
163177

164178
impl FileDescriptor for io::Stdout {
@@ -209,6 +223,11 @@ impl FileDescriptor for io::Stdout {
209223
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
210224
Ok(Box::new(io::stdout()))
211225
}
226+
227+
#[cfg(unix)]
228+
fn as_unix_host_fd(&self) -> Option<i32> {
229+
Some(libc::STDOUT_FILENO)
230+
}
212231
}
213232

214233
impl FileDescriptor for io::Stderr {
@@ -252,6 +271,11 @@ impl FileDescriptor for io::Stderr {
252271
fn dup(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
253272
Ok(Box::new(io::stderr()))
254273
}
274+
275+
#[cfg(unix)]
276+
fn as_unix_host_fd(&self) -> Option<i32> {
277+
Some(libc::STDERR_FILENO)
278+
}
255279
}
256280

257281
#[derive(Debug)]
@@ -297,6 +321,11 @@ impl FileDescriptor for DummyOutput {
297321
fn dup<'tcx>(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
298322
Ok(Box::new(DummyOutput))
299323
}
324+
325+
#[cfg(unix)]
326+
fn as_unix_host_fd(&self) -> Option<i32> {
327+
None
328+
}
300329
}
301330

302331
#[derive(Debug)]
@@ -1660,6 +1689,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
16601689
}
16611690
}
16621691
}
1692+
1693+
#[cfg_attr(not(unix), allow(unused))]
1694+
fn isatty(&mut self, miri_fd: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
1695+
let this = self.eval_context_mut();
1696+
#[cfg(unix)]
1697+
if matches!(this.machine.isolated_op, IsolatedOp::Allow) {
1698+
let miri_fd = this.read_scalar(miri_fd)?.to_i32()?;
1699+
if let Some(host_fd) =
1700+
this.machine.file_handler.handles.get(&miri_fd).and_then(|fd| fd.as_unix_host_fd())
1701+
{
1702+
// "returns 1 if fd is an open file descriptor referring to a terminal;
1703+
// otherwise 0 is returned, and errno is set to indicate the error"
1704+
// SAFETY: isatty has no preconditions
1705+
let is_tty = unsafe { libc::isatty(host_fd) };
1706+
if is_tty == 0 {
1707+
let errno = std::io::Error::last_os_error()
1708+
.raw_os_error()
1709+
.map(Scalar::from_i32)
1710+
.unwrap();
1711+
this.set_last_error(errno)?;
1712+
}
1713+
return Ok(is_tty);
1714+
}
1715+
}
1716+
// We are attemping to use a Unix interface on a non-Unix platform, or we are on a Unix
1717+
// platform and the passed file descriptor is not open, or isolation is enabled
1718+
// FIXME: It should be possible to emulate this at least on Windows by using
1719+
// GetConsoleMode.
1720+
let enotty = this.eval_libc("ENOTTY")?;
1721+
this.set_last_error(enotty)?;
1722+
Ok(0)
1723+
}
16631724
}
16641725

16651726
/// Extracts the number of seconds and nanoseconds elapsed between `time` and the unix epoch when

src/shims/windows/foreign_items.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
152152
.collect();
153153

154154
// Set page size.
155-
let page_size = system_info.offset(
156-
field_offsets[2],
157-
MemPlaceMeta::None,
158-
dword_layout,
159-
&this.tcx,
160-
)?;
155+
let page_size = system_info.offset(field_offsets[2], dword_layout, &this.tcx)?;
161156
this.write_scalar(
162157
Scalar::from_int(PAGE_SIZE, dword_layout.size),
163158
&page_size.into(),
164159
)?;
165160
// Set number of processors.
166-
let num_cpus = system_info.offset(
167-
field_offsets[6],
168-
MemPlaceMeta::None,
169-
dword_layout,
170-
&this.tcx,
171-
)?;
161+
let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?;
172162
this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?;
173163
}
174164

src/stacked_borrows/mod.rs

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,10 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
10211021
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
10221022
fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
10231023
let this = self.eval_context_mut();
1024+
let retag_fields = this.machine.stacked_borrows.as_mut().unwrap().get_mut().retag_fields;
1025+
let mut visitor = RetagVisitor { ecx: this, kind, retag_fields };
1026+
return visitor.visit_value(place);
1027+
10241028
// Determine mutability and whether to add a protector.
10251029
// Cannot use `builtin_deref` because that reports *immutable* for `Box`,
10261030
// making it useless.
@@ -1037,90 +1041,67 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
10371041
// Raw pointers need to be enabled.
10381042
ty::RawPtr(tym) if kind == RetagKind::Raw =>
10391043
Some((RefKind::Raw { mutable: tym.mutbl == Mutability::Mut }, false)),
1040-
// Boxes are handled separately due to that allocator situation.
1044+
// Boxes are handled separately due to that allocator situation,
1045+
// see the visitor below.
10411046
_ => None,
10421047
}
10431048
}
10441049

1045-
// We need a visitor to visit all references. However, that requires
1046-
// a `MPlaceTy` (or `OpTy`), so we have a fast path for reference types that
1047-
// avoids allocating.
1048-
1049-
if let Some((ref_kind, protector)) = qualify(place.layout.ty, kind) {
1050-
// Fast path.
1051-
let val = this.read_immediate(&this.place_to_op(place)?)?;
1052-
let val = this.retag_reference(&val, ref_kind, protector)?;
1053-
this.write_immediate(*val, place)?;
1054-
return Ok(());
1055-
}
1056-
1057-
// If we don't want to recurse, we are already done.
1058-
// EXCEPT if this is a `Box`, then we have to recurse because allocators.
1059-
// (Yes this means we technically also recursively retag the allocator itself even if field
1060-
// retagging is not enabled. *shrug*)
1061-
if !this.machine.stacked_borrows.as_mut().unwrap().get_mut().retag_fields
1062-
&& !place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box())
1063-
{
1064-
return Ok(());
1065-
}
1066-
1067-
// Skip some types that have no further structure we might care about.
1068-
if matches!(
1069-
place.layout.ty.kind(),
1070-
ty::RawPtr(..)
1071-
| ty::Ref(..)
1072-
| ty::Int(..)
1073-
| ty::Uint(..)
1074-
| ty::Float(..)
1075-
| ty::Bool
1076-
| ty::Char
1077-
) {
1078-
return Ok(());
1079-
}
1080-
// Now go visit this thing.
1081-
let place = this.force_allocation(place)?;
1082-
1083-
let mut visitor = RetagVisitor { ecx: this, kind };
1084-
return visitor.visit_value(&place);
1085-
10861050
// The actual visitor.
10871051
struct RetagVisitor<'ecx, 'mir, 'tcx> {
10881052
ecx: &'ecx mut MiriEvalContext<'mir, 'tcx>,
10891053
kind: RetagKind,
1054+
retag_fields: bool,
1055+
}
1056+
impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
1057+
#[inline(always)] // yes this helps in our benchmarks
1058+
fn retag_place(
1059+
&mut self,
1060+
place: &PlaceTy<'tcx, Tag>,
1061+
ref_kind: RefKind,
1062+
protector: bool,
1063+
) -> InterpResult<'tcx> {
1064+
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
1065+
let val = self.ecx.retag_reference(&val, ref_kind, protector)?;
1066+
self.ecx.write_immediate(*val, place)?;
1067+
Ok(())
1068+
}
10901069
}
10911070
impl<'ecx, 'mir, 'tcx> MutValueVisitor<'mir, 'tcx, Evaluator<'mir, 'tcx>>
10921071
for RetagVisitor<'ecx, 'mir, 'tcx>
10931072
{
1094-
type V = MPlaceTy<'tcx, Tag>;
1073+
type V = PlaceTy<'tcx, Tag>;
10951074

10961075
#[inline(always)]
10971076
fn ecx(&mut self) -> &mut MiriEvalContext<'mir, 'tcx> {
10981077
self.ecx
10991078
}
11001079

1101-
fn visit_box(&mut self, place: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
1080+
fn visit_box(&mut self, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
11021081
// Boxes do not get a protector: protectors reflect that references outlive the call
11031082
// they were passed in to; that's just not the case for boxes.
1104-
let (ref_kind, protector) = (RefKind::Unique { two_phase: false }, false);
1105-
1106-
let val = self.ecx.read_immediate(&place.into())?;
1107-
let val = self.ecx.retag_reference(&val, ref_kind, protector)?;
1108-
self.ecx.write_immediate(*val, &place.into())?;
1109-
Ok(())
1083+
self.retag_place(
1084+
place,
1085+
RefKind::Unique { two_phase: false },
1086+
/*protector*/ false,
1087+
)
11101088
}
11111089

1112-
fn visit_value(&mut self, place: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
1090+
fn visit_value(&mut self, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
11131091
if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) {
1114-
let val = self.ecx.read_immediate(&place.into())?;
1115-
let val = self.ecx.retag_reference(&val, ref_kind, protector)?;
1116-
self.ecx.write_immediate(*val, &place.into())?;
1092+
self.retag_place(place, ref_kind, protector)?;
11171093
} else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
11181094
// Wide raw pointers *do* have fields and their types are strange.
11191095
// vtables have a type like `&[*const (); 3]` or so!
11201096
// Do *not* recurse into them.
1121-
// (No need to worry about wide references or boxes, those always "qualify".)
1122-
} else {
1123-
// Maybe we need to go deeper.
1097+
// (No need to worry about wide references, those always "qualify". And Boxes
1098+
// are handles specially by the visitor anyway.)
1099+
} else if self.retag_fields
1100+
|| place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box())
1101+
{
1102+
// Recurse deeper. Need to always recurse for `Box` to even hit `visit_box`.
1103+
// (Yes this means we technically also recursively retag the allocator itself
1104+
// even if field retagging is not enabled. *shrug*)
11241105
self.walk_value(place)?;
11251106
}
11261107
Ok(())

tests/compiletest.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ fn run_tests(mode: Mode, path: &str, target: Option<String>) -> Result<()> {
1919
// Less aggressive warnings to make the rustc toolstate management less painful.
2020
// (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
2121
flags.push("-Astable-features".to_owned());
22+
flags.push("-Aunused".to_owned());
2223
} else {
2324
flags.push("-Dwarnings".to_owned());
24-
flags.push("-Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
25+
flags.push("-Dunused".to_owned());
2526
}
2627
if let Ok(sysroot) = env::var("MIRI_SYSROOT") {
2728
flags.push("--sysroot".to_string());

tests/fail/stacked_borrows/issue-miri-1050-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
fn main() {
44
unsafe {
55
let ptr = Box::into_raw(Box::new(0u16));
6-
Box::from_raw(ptr as *mut u32);
6+
drop(Box::from_raw(ptr as *mut u32));
77
}
88
}

0 commit comments

Comments
 (0)