From 46f6e39ac61241729b81671ed8fb917b8bb2e9e5 Mon Sep 17 00:00:00 2001 From: raffimolero <49224759+raffimolero@users.noreply.github.com> Date: Mon, 12 Dec 2022 12:28:40 +0800 Subject: [PATCH 1/8] add assert messages if chunks/windows are length 0 --- library/core/src/slice/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d9281a9252c08..9e89c9f832fa4 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -893,7 +893,7 @@ impl [T] { #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact(&self, chunk_size: usize) -> ChunksExact<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); ChunksExact::new(self, chunk_size) } @@ -935,7 +935,7 @@ impl [T] { #[stable(feature = "chunks_exact", since = "1.31.0")] #[inline] pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> ChunksExactMut<'_, T> { - assert_ne!(chunk_size, 0); + assert_ne!(chunk_size, 0, "chunks cannot have a size of zero"); ChunksExactMut::new(self, chunk_size) } @@ -1006,7 +1006,7 @@ impl [T] { #[inline] #[must_use] pub fn as_chunks(&self) -> (&[[T; N]], &[T]) { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); let len = self.len() / N; let (multiple_of_n, remainder) = self.split_at(len * N); // SAFETY: We already panicked for zero, and ensured by construction @@ -1037,7 +1037,7 @@ impl [T] { #[inline] #[must_use] pub fn as_rchunks(&self) -> (&[T], &[[T; N]]) { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); let len = self.len() / N; let (remainder, multiple_of_n) = self.split_at(self.len() - len * N); // SAFETY: We already panicked for zero, and ensured by construction @@ -1076,7 +1076,7 @@ impl [T] { #[unstable(feature = "array_chunks", issue = "74985")] #[inline] pub fn array_chunks(&self) -> ArrayChunks<'_, T, N> { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); ArrayChunks::new(self) } @@ -1155,7 +1155,7 @@ impl [T] { #[inline] #[must_use] pub fn as_chunks_mut(&mut self) -> (&mut [[T; N]], &mut [T]) { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); let len = self.len() / N; let (multiple_of_n, remainder) = self.split_at_mut(len * N); // SAFETY: We already panicked for zero, and ensured by construction @@ -1192,7 +1192,7 @@ impl [T] { #[inline] #[must_use] pub fn as_rchunks_mut(&mut self) -> (&mut [T], &mut [[T; N]]) { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); let len = self.len() / N; let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N); // SAFETY: We already panicked for zero, and ensured by construction @@ -1233,7 +1233,7 @@ impl [T] { #[unstable(feature = "array_chunks", issue = "74985")] #[inline] pub fn array_chunks_mut(&mut self) -> ArrayChunksMut<'_, T, N> { - assert_ne!(N, 0); + assert_ne!(N, 0, "chunks cannot have a size of zero"); ArrayChunksMut::new(self) } @@ -1265,7 +1265,7 @@ impl [T] { #[unstable(feature = "array_windows", issue = "75027")] #[inline] pub fn array_windows(&self) -> ArrayWindows<'_, T, N> { - assert_ne!(N, 0); + assert_ne!(N, 0, "windows cannot have a size of zero"); ArrayWindows::new(self) } From 158894464c5e4b143c7b307f932d9eb51afc24ee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 12 Dec 2022 11:10:19 +0100 Subject: [PATCH 2/8] interpret: add read_machine_[ui]size convenience methods --- .../src/interpret/intrinsics.rs | 8 ++--- .../rustc_const_eval/src/interpret/operand.rs | 11 +++++++ .../src/interpret/projection.rs | 4 +-- src/tools/miri/src/eval.rs | 2 +- src/tools/miri/src/shims/env.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 32 +++++++++---------- src/tools/miri/src/shims/intrinsics/mod.rs | 4 +-- src/tools/miri/src/shims/mod.rs | 2 +- .../miri/src/shims/unix/foreign_items.rs | 18 +++++------ src/tools/miri/src/shims/unix/fs.rs | 8 ++--- .../src/shims/unix/linux/foreign_items.rs | 6 ++-- src/tools/miri/src/shims/unix/macos/dlsym.rs | 2 +- .../src/shims/unix/macos/foreign_items.rs | 4 +-- src/tools/miri/src/shims/unix/thread.rs | 4 +-- src/tools/miri/src/shims/windows/dlsym.rs | 4 +-- .../miri/src/shims/windows/foreign_items.rs | 16 +++++----- src/tools/miri/src/shims/windows/sync.rs | 2 +- src/tools/miri/src/shims/windows/thread.rs | 2 +- 18 files changed, 71 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index b9be7fa48000b..7031a0b45d6ec 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -305,7 +305,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::offset => { let ptr = self.read_pointer(&args[0])?; - let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; + let offset_count = self.read_machine_isize(&args[1])?; let pointee_ty = substs.type_at(0); let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; @@ -313,7 +313,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::arith_offset => { let ptr = self.read_pointer(&args[0])?; - let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; + let offset_count = self.read_machine_isize(&args[1])?; let pointee_ty = substs.type_at(0); let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap(); @@ -670,7 +670,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { count: &OpTy<'tcx, >::Provenance>, nonoverlapping: bool, ) -> InterpResult<'tcx> { - let count = self.read_scalar(&count)?.to_machine_usize(self)?; + let count = self.read_machine_usize(&count)?; let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?; let (size, align) = (layout.size, layout.align.abi); // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), @@ -698,7 +698,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let dst = self.read_pointer(&dst)?; let byte = self.read_scalar(&byte)?.to_u8()?; - let count = self.read_scalar(&count)?.to_machine_usize(self)?; + let count = self.read_machine_usize(&count)?; // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 221e359d24ab8..68a3318ab4e0b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -407,6 +407,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(self.read_immediate(op)?.to_scalar()) } + // Pointer-sized reads are fairly common and need target layout access, so we wrap them in + // convenience functions. + /// Read a pointer from a place. pub fn read_pointer( &self, @@ -414,6 +417,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, Pointer>> { self.read_scalar(op)?.to_pointer(self) } + /// Read a pointer-sized unsigned integer from a place. + pub fn read_machine_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> { + self.read_scalar(op)?.to_machine_usize(self) + } + /// Read a pointer-sized signed integer from a place. + pub fn read_machine_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> { + self.read_scalar(op)?.to_machine_isize(self) + } /// Turn the wide MPlace into a string (must already be dereferenced!) pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> { diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index 2ffd73eef3ef8..291464ab58ae2 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -363,7 +363,7 @@ where Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; let n = self.local_to_op(self.frame(), local, Some(layout))?; - let n = self.read_scalar(&n)?.to_machine_usize(self)?; + let n = self.read_machine_usize(&n)?; self.place_index(base, n)? } ConstantIndex { offset, min_length, from_end } => { @@ -392,7 +392,7 @@ where Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; let n = self.local_to_op(self.frame(), local, Some(layout))?; - let n = self.read_scalar(&n)?.to_machine_usize(self)?; + let n = self.read_machine_usize(&n)?; self.operand_index(base, n)? } ConstantIndex { offset, min_length, from_end } => { diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 7b4973f3b9daf..30288e5a999bb 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -233,7 +233,7 @@ impl MainThreadState { this.machine.main_fn_ret_place.unwrap().ptr, this.machine.layouts.isize, ); - let exit_code = this.read_scalar(&ret_place.into())?.to_machine_isize(this)?; + let exit_code = this.read_machine_isize(&ret_place.into())?; // Need to call this ourselves since we are not going to return to the scheduler // loop, and we want the main thread TLS to not show up as memory leaks. this.terminate_active_thread()?; diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 80fb4ff2fe980..218aa89b3f9b0 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -321,7 +321,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("getcwd"); let buf = this.read_pointer(buf_op)?; - let size = this.read_scalar(size_op)?.to_machine_usize(&*this.tcx)?; + let size = this.read_machine_usize(size_op)?; if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`getcwd`", reject_with)?; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 8370e02b588af..b7ed63e17c5b2 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -485,14 +485,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Standard C allocation "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size)?; let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C)?; this.write_pointer(res, dest)?; } "calloc" => { let [items, len] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let items = this.read_scalar(items)?.to_machine_usize(this)?; - let len = this.read_scalar(len)?.to_machine_usize(this)?; + let items = this.read_machine_usize(items)?; + let len = this.read_machine_usize(len)?; let size = items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?; let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?; @@ -506,7 +506,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "realloc" => { let [old_ptr, new_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_ptr = this.read_pointer(old_ptr)?; - let new_size = this.read_scalar(new_size)?.to_machine_usize(this)?; + let new_size = this.read_machine_usize(new_size)?; let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?; this.write_pointer(res, dest)?; } @@ -514,8 +514,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Rust allocation "__rust_alloc" | "miri_alloc" => { let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; - let align = this.read_scalar(align)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size)?; + let align = this.read_machine_usize(align)?; let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { Self::check_alloc_request(size, align)?; @@ -546,8 +546,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "__rust_alloc_zeroed" => { let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; - let align = this.read_scalar(align)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size)?; + let align = this.read_machine_usize(align)?; return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| { Self::check_alloc_request(size, align)?; @@ -566,8 +566,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_dealloc" | "miri_dealloc" => { let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; - let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?; - let align = this.read_scalar(align)?.to_machine_usize(this)?; + let old_size = this.read_machine_usize(old_size)?; + let align = this.read_machine_usize(align)?; let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { let memory_kind = match link_name.as_str() { @@ -596,9 +596,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_realloc" => { let [ptr, old_size, align, new_size] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; - let old_size = this.read_scalar(old_size)?.to_machine_usize(this)?; - let align = this.read_scalar(align)?.to_machine_usize(this)?; - let new_size = this.read_scalar(new_size)?.to_machine_usize(this)?; + let old_size = this.read_machine_usize(old_size)?; + let align = this.read_machine_usize(align)?; + let new_size = this.read_machine_usize(new_size)?; // No need to check old_size; we anyway check that they match the allocation. return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| { @@ -621,7 +621,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [left, right, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let left = this.read_pointer(left)?; let right = this.read_pointer(right)?; - let n = Size::from_bytes(this.read_scalar(n)?.to_machine_usize(this)?); + let n = Size::from_bytes(this.read_machine_usize(n)?); let result = { let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?; @@ -641,7 +641,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; - let num = this.read_scalar(num)?.to_machine_usize(this)?; + let num = this.read_machine_usize(num)?; // The docs say val is "interpreted as unsigned char". #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] let val = val as u8; @@ -664,7 +664,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [ptr, val, num] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; - let num = this.read_scalar(num)?.to_machine_usize(this)?; + let num = this.read_machine_usize(num)?; // The docs say val is "interpreted as unsigned char". #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] let val = val as u8; diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 5ea82adb9c69c..1b97a9d20de0c 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -111,7 +111,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ty_layout = this.layout_of(ty)?; let val_byte = this.read_scalar(val_byte)?.to_u8()?; let ptr = this.read_pointer(ptr)?; - let count = this.read_scalar(count)?.to_machine_usize(this)?; + let count = this.read_machine_usize(count)?; // `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| { @@ -124,7 +124,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [ptr, mask] = check_arg_count(args)?; let ptr = this.read_pointer(ptr)?; - let mask = this.read_scalar(mask)?.to_machine_usize(this)?; + let mask = this.read_machine_usize(mask)?; let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask); diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index b6efad6b5ee08..39db97b72e2ce 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -80,7 +80,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(false); } - let req_align = this.read_scalar(align_op)?.to_machine_usize(this)?; + let req_align = this.read_machine_usize(align_op)?; // Stop if the alignment is not a power of two. if !req_align.is_power_of_two() { diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index d746f9df90ac3..63cc132f3fc93 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -78,7 +78,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [fd, buf, count] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; - let count = this.read_scalar(count)?.to_machine_usize(this)?; + let count = this.read_machine_usize(count)?; let result = this.read(fd, buf, count)?; this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; } @@ -86,7 +86,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; let buf = this.read_pointer(buf)?; - let count = this.read_scalar(n)?.to_machine_usize(this)?; + let count = this.read_machine_usize(n)?; trace!("Called write({:?}, {:?}, {:?})", fd, buf, count); let result = this.write(fd, buf, count)?; // Now, `result` is the value we return back to the program. @@ -157,8 +157,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [fd, offset, len, advice] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(fd)?.to_i32()?; - this.read_scalar(offset)?.to_machine_isize(this)?; - this.read_scalar(len)?.to_machine_isize(this)?; + this.read_machine_isize(offset)?; + this.read_machine_isize(len)?; this.read_scalar(advice)?.to_i32()?; // fadvise is only informational, we can ignore it. this.write_null(dest)?; @@ -191,8 +191,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "posix_memalign" => { let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let ret = this.deref_operand(ret)?; - let align = this.read_scalar(align)?.to_machine_usize(this)?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; + let align = this.read_machine_usize(align)?; + let size = this.read_machine_usize(size)?; // Align must be power of 2, and also at least ptr-sized (POSIX rules). // But failure to adhere to this is not UB, it's an error condition. if !align.is_power_of_two() || align < this.pointer_size().bytes() { @@ -216,7 +216,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Dynamic symbol loading "dlsym" => { let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.read_scalar(handle)?.to_machine_usize(this)?; + this.read_machine_usize(handle)?; let symbol = this.read_pointer(symbol)?; let symbol_name = this.read_c_str(symbol)?; if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? { @@ -472,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [errnum, buf, buflen] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let errnum = this.read_scalar(errnum)?; let buf = this.read_pointer(buf)?; - let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?; + let buflen = this.read_machine_usize(buflen)?; let error = this.try_errnum_to_io_error(errnum)?; let formatted = match error { @@ -565,7 +565,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let uid = this.read_scalar(uid)?.to_u32()?; let pwd = this.deref_operand(pwd)?; let buf = this.read_pointer(buf)?; - let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?; + let buflen = this.read_machine_usize(buflen)?; let result = this.deref_operand(result)?; // Must be for "us". diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 988627db5611c..5af1b354e7bb1 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1293,7 +1293,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("linux", "readdir64"); - let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?; + let dirp = this.read_machine_usize(dirp_op)?; // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { @@ -1385,7 +1385,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("macos", "readdir_r"); - let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?; + let dirp = this.read_machine_usize(dirp_op)?; // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { @@ -1478,7 +1478,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?; + let dirp = this.read_machine_usize(dirp_op)?; // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { @@ -1642,7 +1642,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?; let buf = this.read_pointer(buf_op)?; - let bufsize = this.read_scalar(bufsize_op)?.to_machine_usize(this)?; + let bufsize = this.read_machine_usize(bufsize_op)?; // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 34076e842d55b..acf47fe924803 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -99,7 +99,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "incorrect number of arguments for syscall: got 0, expected at least 1" ); } - match this.read_scalar(&args[0])?.to_machine_usize(this)? { + match this.read_machine_usize(&args[0])? { // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` // is called if a `HashMap` is created the regular way (e.g. HashMap). id if id == sys_getrandom => { @@ -147,7 +147,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [pid, cpusetsize, mask] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(pid)?.to_i32()?; - this.read_scalar(cpusetsize)?.to_machine_usize(this)?; + this.read_machine_usize(cpusetsize)?; this.deref_operand(mask)?; // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`. let einval = this.eval_libc("EINVAL")?; @@ -179,7 +179,7 @@ fn getrandom<'tcx>( dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let ptr = this.read_pointer(ptr)?; - let len = this.read_scalar(len)?.to_machine_usize(this)?; + let len = this.read_machine_usize(len)?; // The only supported flags are GRND_RANDOM and GRND_NONBLOCK, // neither of which have any effect on our current PRNG. diff --git a/src/tools/miri/src/shims/unix/macos/dlsym.rs b/src/tools/miri/src/shims/unix/macos/dlsym.rs index 18804b45efca9..44b9af79005a9 100644 --- a/src/tools/miri/src/shims/unix/macos/dlsym.rs +++ b/src/tools/miri/src/shims/unix/macos/dlsym.rs @@ -39,7 +39,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Dlsym::getentropy => { let [ptr, len] = check_arg_count(args)?; let ptr = this.read_pointer(ptr)?; - let len = this.read_scalar(len)?.to_machine_usize(this)?; + let len = this.read_machine_usize(len)?; this.gen_random(ptr, len)?; this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 221dc39697f90..2554fc7798454 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -161,13 +161,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Querying system information "pthread_get_stackaddr_np" => { let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.read_scalar(thread)?.to_machine_usize(this)?; + this.read_machine_usize(thread)?; let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size()); this.write_scalar(stack_addr, dest)?; } "pthread_get_stacksize_np" => { let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.read_scalar(thread)?.to_machine_usize(this)?; + this.read_machine_usize(thread)?; let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size()); this.write_scalar(stack_size, dest)?; } diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 5b9dc90f0f006..2cb4858fdfdee 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { throw_unsup_format!("Miri supports pthread_join only with retval==NULL"); } - let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?; + let thread_id = this.read_machine_usize(thread)?; this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?; Ok(0) @@ -51,7 +51,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?; + let thread_id = this.read_machine_usize(thread)?; this.detach_thread( thread_id.try_into().expect("thread ID should fit in u32"), /*allow_terminated_joined*/ false, diff --git a/src/tools/miri/src/shims/windows/dlsym.rs b/src/tools/miri/src/shims/windows/dlsym.rs index 4b2a90723c79c..857cf1ae7037b 100644 --- a/src/tools/miri/src/shims/windows/dlsym.rs +++ b/src/tools/miri/src/shims/windows/dlsym.rs @@ -67,10 +67,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { byte_offset, _key, ] = check_arg_count(args)?; - let handle = this.read_scalar(handle)?.to_machine_isize(this)?; + let handle = this.read_machine_isize(handle)?; let buf = this.read_pointer(buf)?; let n = this.read_scalar(n)?.to_u32()?; - let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer + let byte_offset = this.read_machine_usize(byte_offset)?; // is actually a pointer let io_status_block = this.deref_operand(io_status_block)?; if byte_offset != 0 { diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index e16749c986b16..656f1a4ae7223 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -73,9 +73,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "HeapAlloc" => { let [handle, flags, size] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(handle)?.to_machine_isize(this)?; + this.read_machine_isize(handle)?; let flags = this.read_scalar(flags)?.to_u32()?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size)?; let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?; this.write_pointer(res, dest)?; @@ -83,7 +83,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "HeapFree" => { let [handle, flags, ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(handle)?.to_machine_isize(this)?; + this.read_machine_isize(handle)?; this.read_scalar(flags)?.to_u32()?; let ptr = this.read_pointer(ptr)?; this.free(ptr, MiriMemoryKind::WinHeap)?; @@ -92,10 +92,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "HeapReAlloc" => { let [handle, flags, ptr, size] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(handle)?.to_machine_isize(this)?; + this.read_machine_isize(handle)?; this.read_scalar(flags)?.to_u32()?; let ptr = this.read_pointer(ptr)?; - let size = this.read_scalar(size)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size)?; let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?; this.write_pointer(res, dest)?; } @@ -298,7 +298,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { #[allow(non_snake_case)] let [hModule, lpProcName] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(hModule)?.to_machine_isize(this)?; + this.read_machine_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? { let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym)); @@ -356,7 +356,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // `term` needs this, so we fake it. let [console, buffer_info] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(console)?.to_machine_isize(this)?; + this.read_machine_isize(console)?; this.deref_operand(buffer_info)?; // Indicate an error. // FIXME: we should set last_error, but to what? @@ -432,7 +432,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "GetConsoleMode" if this.frame_in_std() => { let [console, mode] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - this.read_scalar(console)?.to_machine_isize(this)?; + this.read_machine_isize(console)?; this.deref_operand(mode)?; // Indicate an error. this.write_null(dest)?; diff --git a/src/tools/miri/src/shims/windows/sync.rs b/src/tools/miri/src/shims/windows/sync.rs index 6b043c6d2c9e1..7892f35f7b05c 100644 --- a/src/tools/miri/src/shims/windows/sync.rs +++ b/src/tools/miri/src/shims/windows/sync.rs @@ -273,7 +273,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let ptr = this.read_pointer(ptr_op)?; let compare = this.read_pointer(compare_op)?; - let size = this.read_scalar(size_op)?.to_machine_usize(this)?; + let size = this.read_machine_usize(size_op)?; let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?; let thread = this.get_active_thread(); diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index 25a5194caa096..1dbc848b03055 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let security = this.read_pointer(security_op)?; // stacksize is ignored, but still needs to be a valid usize - this.read_scalar(stacksize_op)?.to_machine_usize(this)?; + this.read_machine_usize(stacksize_op)?; let start_routine = this.read_pointer(start_op)?; let func_arg = this.read_immediate(arg_op)?; let flags = this.read_scalar(flags_op)?.to_u32()?; From 7f9438910c2c86813b597dfc518990198691d170 Mon Sep 17 00:00:00 2001 From: Stefano Zacchiroli Date: Sat, 17 Dec 2022 12:20:56 +0100 Subject: [PATCH 3/8] str.lines() docstring: clarify that line endings are not returned Previously, the str.lines() docstring stated that lines are split at line endings, but not whether those were returned or not. This new version of the docstring states this explicitly, avoiding the need of getting to doctests to get an answer to this FAQ. --- library/core/src/str/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 45fd2caae52f4..863ded5e5ec03 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -970,8 +970,10 @@ impl str { /// An iterator over the lines of a string, as string slices. /// - /// Lines are ended with either a newline (`\n`) or a carriage return with - /// a line feed (`\r\n`). + /// Lines are split at line endings that are either newlines (`\n`) or + /// sequences of a carriage return followed by a line feed (`\r\n`). + /// + /// Line terminators are not included in the lines returned by the iterator. /// /// The final line ending is optional. A string that ends with a final line /// ending will return the same lines as an otherwise identical string From f5e776c3f7afc2020d9828b593bac9db27290376 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Tue, 20 Dec 2022 14:51:24 -0800 Subject: [PATCH 4/8] Refer to "Waker" rather than "RawWaker" in `drop` comment --- library/core/src/task/wake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 0cff972df3a5a..1b7578376b42b 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -104,7 +104,7 @@ pub struct RawWakerVTable { /// pointer. wake_by_ref: unsafe fn(*const ()), - /// This function gets called when a [`RawWaker`] gets dropped. + /// This function gets called when a [`Waker`] gets dropped. /// /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and @@ -151,7 +151,7 @@ impl RawWakerVTable { /// /// # `drop` /// - /// This function gets called when a [`RawWaker`] gets dropped. + /// This function gets called when a [`Waker`] gets dropped. /// /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and From 5538c92837ef66369ea80faf0badd1c85f1512c9 Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Wed, 21 Dec 2022 15:34:21 +0900 Subject: [PATCH 5/8] Fix typo in reading_half_a_pointer.rs gurantee -> guarantee --- src/tools/miri/tests/fail/reading_half_a_pointer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.rs b/src/tools/miri/tests/fail/reading_half_a_pointer.rs index 2d66913262476..7dd98eab78526 100644 --- a/src/tools/miri/tests/fail/reading_half_a_pointer.rs +++ b/src/tools/miri/tests/fail/reading_half_a_pointer.rs @@ -7,7 +7,7 @@ struct Data { ptr: &'static i32, } -// But we need to gurantee some alignment +// But we need to guarantee some alignment struct Wrapper { align: u64, data: Data, From 32a31d8acaf8521712a49f53feabd7d98844ef73 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 21 Dec 2022 21:10:30 +0900 Subject: [PATCH 6/8] Add regression test for #96530 Signed-off-by: Yuki Okushi --- src/test/ui/typeck/issue-96530.rs | 20 ++++++++++++++++++++ src/test/ui/typeck/issue-96530.stderr | 9 +++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/typeck/issue-96530.rs create mode 100644 src/test/ui/typeck/issue-96530.stderr diff --git a/src/test/ui/typeck/issue-96530.rs b/src/test/ui/typeck/issue-96530.rs new file mode 100644 index 0000000000000..4ab93ab4938f4 --- /dev/null +++ b/src/test/ui/typeck/issue-96530.rs @@ -0,0 +1,20 @@ +struct Person { + first_name: String, + age: u32, +} + +fn first_woman(man: &Person) -> Person { + Person { + first_name: "Eve".to_string(), + ..man.clone() //~ ERROR: mismatched types + } +} + +fn main() { + let adam = Person { + first_name: "Adam".to_string(), + age: 0, + }; + + let eve = first_woman(&adam); +} diff --git a/src/test/ui/typeck/issue-96530.stderr b/src/test/ui/typeck/issue-96530.stderr new file mode 100644 index 0000000000000..4b4568b1de9b2 --- /dev/null +++ b/src/test/ui/typeck/issue-96530.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-96530.rs:9:11 + | +LL | ..man.clone() + | ^^^^^^^^^^^ expected struct `Person`, found `&Person` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 30fbfd5f05108d12f08711024db699e1b0632508 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Wed, 21 Dec 2022 17:27:45 +0100 Subject: [PATCH 7/8] Sort lint_groups in no_lint_suggestion The no_lint_suggestion routine passes a vector of lint group names to find_best_match_for_name. That routine depends on the sort order of its input vector, which matters in case multiple inputs are at the same Levenshtein distance to the target name. However, no_lint_suggestion currently just passes lint_groups.keys() as input vector - this is sorted in hash value order, which is not guaranteed to be stable, and in fact differs between big- and little-endian host platforms, causing test failures on s390x. To fix this, always sort the lint groups before using their names as input to find_best_match_for_name. In addition, deprecated lint groups should never be suggested, so filter those out. Fixes https://github.com/rust-lang/rust/issues/105379 --- compiler/rustc_lint/src/context.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 0417f375588cc..3c9ad410663f9 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -483,7 +483,16 @@ impl LintStore { return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower))); } // ...if not, search for lints with a similar name - let groups = self.lint_groups.keys().copied().map(Symbol::intern); + // Note: find_best_match_for_name depends on the sort order of its input vector. + // To ensure deterministic output, sort elements of the lint_groups hash map. + // Also, never suggest deprecated lint groups. + let mut groups: Vec<_> = self + .lint_groups + .iter() + .filter_map(|(k, LintGroup { depr, .. })| if depr.is_none() { Some(k) } else { None }) + .collect(); + groups.sort(); + let groups = groups.iter().map(|k| Symbol::intern(k)); let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower())); let names: Vec = groups.chain(lints).collect(); let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None); From 34a4e5cc1219da042697cf3adb984eeec2f8cb80 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 21 Dec 2022 20:21:31 +0100 Subject: [PATCH 8/8] Add comment explaining what the scrape-examples-toggle.goml GUI test is about --- src/test/rustdoc-gui/scrape-examples-toggle.goml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml index ee720afb788fe..a0b696ee3363d 100644 --- a/src/test/rustdoc-gui/scrape-examples-toggle.goml +++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml @@ -1,3 +1,4 @@ +// This tests checks that the "scraped examples" toggle is working as expected. goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" // Clicking "More examples..." will open additional examples