提交 4a0402cd 编写于 作者: B bors

Auto merge of #114932 - RalfJung:miri, r=RalfJung

update Miri

r? `@ghost`
......@@ -53,7 +53,7 @@ behavior** in your program, and cannot run all programs:
positives here, so if your program runs fine in Miri right now that is by no
means a guarantee that it is UB-free when these questions get answered.
In particular, Miri does currently not check that references point to valid data.
In particular, Miri does not check that references point to valid data.
* If the program relies on unspecified details of how data is laid out, it will
still run fine in Miri -- but might break (including causing UB) on different
compiler versions or different platforms.
......
9fa6bdd764a1f7bdf69eccceeace6d13f38cb2e1
656ee47db32e882fb02913f6204e09cc7a41a50e
......@@ -304,11 +304,21 @@ pub fn report_error<'tcx, 'mir>(
(None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
(None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
],
UndefinedBehavior(_) =>
vec![
UndefinedBehavior(info) => {
let mut helps = vec![
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
],
];
if let UndefinedBehaviorInfo::PointerUseAfterFree(alloc_id, _) | UndefinedBehaviorInfo::PointerOutOfBounds { alloc_id, .. } = info {
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
}
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
}
}
helps
}
InvalidProgram(
InvalidProgramInfo::AlreadyReported(_)
) => {
......
......@@ -13,11 +13,11 @@
use rustc_middle::mir;
use rustc_middle::ty::{
self,
layout::{LayoutOf, TyAndLayout},
List, TyCtxt,
layout::{IntegerExt as _, LayoutOf, TyAndLayout},
List, Ty, TyCtxt,
};
use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants};
use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants};
use rustc_target::spec::abi::Abi;
use rand::RngCore;
......@@ -1011,6 +1011,65 @@ fn item_link_name(&self, def_id: DefId) -> Symbol {
None => tcx.item_name(def_id),
}
}
/// Converts `f` to integer type `dest_ty` after rounding with mode `round`.
/// Returns `None` if `f` is NaN or out of range.
fn float_to_int_checked<F>(
&self,
f: F,
dest_ty: Ty<'tcx>,
round: rustc_apfloat::Round,
) -> Option<Scalar<Provenance>>
where
F: rustc_apfloat::Float + Into<Scalar<Provenance>>,
{
let this = self.eval_context_ref();
match dest_ty.kind() {
// Unsigned
ty::Uint(t) => {
let size = Integer::from_uint_ty(this, *t).size();
let res = f.to_u128_r(size.bits_usize(), round, &mut false);
if res.status.intersects(
rustc_apfloat::Status::INVALID_OP
| rustc_apfloat::Status::OVERFLOW
| rustc_apfloat::Status::UNDERFLOW,
) {
// Floating point value is NaN (flagged with INVALID_OP) or outside the range
// of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
None
} else {
// Floating point value can be represented by the integer type after rounding.
// The INEXACT flag is ignored on purpose to allow rounding.
Some(Scalar::from_uint(res.value, size))
}
}
// Signed
ty::Int(t) => {
let size = Integer::from_int_ty(this, *t).size();
let res = f.to_i128_r(size.bits_usize(), round, &mut false);
if res.status.intersects(
rustc_apfloat::Status::INVALID_OP
| rustc_apfloat::Status::OVERFLOW
| rustc_apfloat::Status::UNDERFLOW,
) {
// Floating point value is NaN (flagged with INVALID_OP) or outside the range
// of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
None
} else {
// Floating point value can be represented by the integer type after rounding.
// The INEXACT flag is ignored on purpose to allow rounding.
Some(Scalar::from_int(res.value, size))
}
}
// Nothing else
_ =>
span_bug!(
this.cur_span(),
"attempted float-to-int conversion with non-int output type {dest_ty:?}"
),
}
}
}
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
......
......@@ -25,7 +25,7 @@
},
};
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Symbol;
use rustc_span::{Span, SpanData, Symbol};
use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi;
......@@ -135,6 +135,19 @@ fn may_leak(self) -> bool {
}
}
impl MiriMemoryKind {
/// Whether we have a useful allocation span for an allocation of this kind.
fn should_save_allocation_span(self) -> bool {
use self::MiriMemoryKind::*;
match self {
// Heap allocations are fine since the `Allocation` is created immediately.
Rust | Miri | C | WinHeap | Mmap => true,
// Everything else is unclear, let's not show potentially confusing spans.
Machine | Global | ExternStatic | Tls | Runtime => false,
}
}
}
impl fmt::Display for MiriMemoryKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use self::MiriMemoryKind::*;
......@@ -497,6 +510,10 @@ pub struct MiriMachine<'mir, 'tcx> {
/// Whether to collect a backtrace when each allocation is created, just in case it leaks.
pub(crate) collect_leak_backtraces: bool,
/// The spans we will use to report where an allocation was created and deallocated in
/// diagnostics.
pub(crate) allocation_spans: RefCell<FxHashMap<AllocId, (Span, Option<Span>)>>,
}
impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
......@@ -621,6 +638,7 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
stack_addr,
stack_size,
collect_leak_backtraces: config.collect_leak_backtraces,
allocation_spans: RefCell::new(FxHashMap::default()),
}
}
......@@ -742,6 +760,21 @@ pub(crate) fn round_up_to_multiple_of_page_size(&self, length: u64) -> Option<u6
pub(crate) fn page_align(&self) -> Align {
Align::from_bytes(self.page_size).unwrap()
}
pub(crate) fn allocated_span(&self, alloc_id: AllocId) -> Option<SpanData> {
self.allocation_spans
.borrow()
.get(&alloc_id)
.map(|(allocated, _deallocated)| allocated.data())
}
pub(crate) fn deallocated_span(&self, alloc_id: AllocId) -> Option<SpanData> {
self.allocation_spans
.borrow()
.get(&alloc_id)
.and_then(|(_allocated, deallocated)| *deallocated)
.map(Span::data)
}
}
impl VisitTags for MiriMachine<'_, '_> {
......@@ -791,6 +824,7 @@ fn visit_tags(&self, visit: &mut dyn FnMut(BorTag)) {
stack_addr: _,
stack_size: _,
collect_leak_backtraces: _,
allocation_spans: _,
} = self;
threads.visit_tags(visit);
......@@ -1051,6 +1085,14 @@ fn adjust_allocation<'b>(
},
|ptr| ecx.global_base_pointer(ptr),
)?;
if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) {
ecx.machine
.allocation_spans
.borrow_mut()
.insert(id, (ecx.machine.current_span(), None));
}
Ok(Cow::Owned(alloc))
}
......@@ -1181,6 +1223,10 @@ fn before_memory_deallocation(
if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker {
borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, range, machine)?;
}
if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id)
{
*deallocated_at = Some(machine.current_span());
}
Ok(())
}
......
......@@ -27,35 +27,27 @@ impl<T> RangeMap<T> {
#[inline(always)]
pub fn new(size: Size, init: T) -> RangeMap<T> {
let size = size.bytes();
let mut map = RangeMap { v: Vec::new() };
if size > 0 {
map.v.push(Elem { range: 0..size, data: init });
}
map
let v = if size > 0 { vec![Elem { range: 0..size, data: init }] } else { Vec::new() };
RangeMap { v }
}
/// Finds the index containing the given offset.
fn find_offset(&self, offset: u64) -> usize {
// We do a binary search.
let mut left = 0usize; // inclusive
let mut right = self.v.len(); // exclusive
loop {
debug_assert!(left < right, "find_offset: offset {offset} is out-of-bounds");
let candidate = left.checked_add(right).unwrap() / 2;
let elem = &self.v[candidate];
if offset < elem.range.start {
// We are too far right (offset is further left).
debug_assert!(candidate < right); // we are making progress
right = candidate;
} else if offset >= elem.range.end {
// We are too far left (offset is further right).
debug_assert!(candidate >= left); // we are making progress
left = candidate + 1;
} else {
// This is it!
return candidate;
}
}
self.v
.binary_search_by(|elem| -> std::cmp::Ordering {
if offset < elem.range.start {
// We are too far right (offset is further left).
// (`Greater` means that `elem` is greater than the desired target.)
std::cmp::Ordering::Greater
} else if offset >= elem.range.end {
// We are too far left (offset is further right).
std::cmp::Ordering::Less
} else {
// This is it!
std::cmp::Ordering::Equal
}
})
.unwrap()
}
/// Provides read-only iteration over everything in the given range. This does
......
......@@ -690,6 +690,10 @@ fn emulate_foreign_item_by_name(
let right = this.read_pointer(right)?;
let n = Size::from_bytes(this.read_target_usize(n)?);
// C requires that this must always be a valid pointer (C18 §7.1.4).
this.ptr_get_alloc_id(left)?;
this.ptr_get_alloc_id(right)?;
let result = {
let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?;
let right_bytes = this.read_bytes_ptr_strip_provenance(right, n)?;
......@@ -714,6 +718,9 @@ fn emulate_foreign_item_by_name(
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
let val = val as u8;
// C requires that this must always be a valid pointer (C18 §7.1.4).
this.ptr_get_alloc_id(ptr)?;
if let Some(idx) = this
.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
.iter()
......@@ -738,6 +745,9 @@ fn emulate_foreign_item_by_name(
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
let val = val as u8;
// C requires that this must always be a valid pointer (C18 §7.1.4).
this.ptr_get_alloc_id(ptr)?;
let idx = this
.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
.iter()
......@@ -752,6 +762,7 @@ fn emulate_foreign_item_by_name(
"strlen" => {
let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_c_str(ptr)?.len();
this.write_scalar(
Scalar::from_target_usize(u64::try_from(n).unwrap(), this),
......@@ -791,6 +802,7 @@ fn emulate_foreign_item_by_name(
// pointer provenance is preserved by this implementation of `strcpy`.
// That is probably overly cautious, but there also is no fundamental
// reason to have `strcpy` destroy pointer provenance.
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_c_str(ptr_src)?.len().checked_add(1).unwrap();
this.mem_copy(
ptr_src,
......@@ -942,6 +954,7 @@ fn emulate_foreign_item_by_name(
this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
}
// LLVM intrinsics
"llvm.prefetch" => {
let [p, rw, loc, ty] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
......@@ -968,8 +981,6 @@ fn emulate_foreign_item_by_name(
throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty);
}
}
// Architecture-specific shims
"llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
// Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
......
......@@ -6,12 +6,12 @@
use log::trace;
use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::{IntegerExt, LayoutOf};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::{
mir,
ty::{self, FloatTy, Ty},
ty::{self, FloatTy},
};
use rustc_target::abi::{Integer, Size};
use rustc_target::abi::Size;
use crate::*;
use atomic::EvalContextExt as _;
......@@ -356,10 +356,28 @@ fn emulate_intrinsic_by_name(
let val = this.read_immediate(val)?;
let res = match val.layout.ty.kind() {
ty::Float(FloatTy::F32) =>
this.float_to_int_unchecked(val.to_scalar().to_f32()?, dest.layout.ty)?,
ty::Float(FloatTy::F64) =>
this.float_to_int_unchecked(val.to_scalar().to_f64()?, dest.layout.ty)?,
ty::Float(FloatTy::F32) => {
let f = val.to_scalar().to_f32()?;
this
.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
.ok_or_else(|| {
err_ub_format!(
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
dest.layout.ty
)
})?
}
ty::Float(FloatTy::F64) => {
let f = val.to_scalar().to_f64()?;
this
.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
.ok_or_else(|| {
err_ub_format!(
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
dest.layout.ty
)
})?
}
_ =>
span_bug!(
this.cur_span(),
......@@ -383,57 +401,4 @@ fn emulate_intrinsic_by_name(
Ok(())
}
fn float_to_int_unchecked<F>(
&self,
f: F,
dest_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Scalar<Provenance>>
where
F: Float + Into<Scalar<Provenance>>,
{
let this = self.eval_context_ref();
// Step 1: cut off the fractional part of `f`. The result of this is
// guaranteed to be precisely representable in IEEE floats.
let f = f.round_to_integral(Round::TowardZero).value;
// Step 2: Cast the truncated float to the target integer type and see if we lose any information in this step.
Ok(match dest_ty.kind() {
// Unsigned
ty::Uint(t) => {
let size = Integer::from_uint_ty(this, *t).size();
let res = f.to_u128(size.bits_usize());
if res.status.is_empty() {
// No status flags means there was no further rounding or other loss of precision.
Scalar::from_uint(res.value, size)
} else {
// `f` was not representable in this integer type.
throw_ub_format!(
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{dest_ty:?}`",
);
}
}
// Signed
ty::Int(t) => {
let size = Integer::from_int_ty(this, *t).size();
let res = f.to_i128(size.bits_usize());
if res.status.is_empty() {
// No status flags means there was no further rounding or other loss of precision.
Scalar::from_int(res.value, size)
} else {
// `f` was not representable in this integer type.
throw_ub_format!(
"`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{dest_ty:?}`",
);
}
}
// Nothing else
_ =>
span_bug!(
this.cur_span(),
"`float_to_int_unchecked` called with non-int output type {dest_ty:?}"
),
})
}
}
use rustc_apfloat::Float;
use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::{mir, ty, ty::FloatTy};
use rustc_target::abi::{Endian, HasDataLayout, Size};
......@@ -420,7 +420,6 @@ enum Op {
}
}
}
#[rustfmt::skip]
"cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
let [op] = check_arg_count(args)?;
let (op, op_len) = this.operand_to_simd(op)?;
......@@ -440,7 +439,8 @@ enum Op {
let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
// Int-to-(int|float): always safe
(ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
(ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_))
if safe_cast || unsafe_cast =>
this.int_to_int_or_float(&op, dest.layout.ty)?,
// Float-to-float: always safe
(ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
......@@ -449,21 +449,36 @@ enum Op {
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
this.float_to_float_or_int(&op, dest.layout.ty)?,
// Float-to-int in unchecked mode
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
// Ptr-to-ptr cast
(ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
this.ptr_to_ptr(&op, dest.layout.ty)?
}
// Ptr/Int casts
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
this.pointer_expose_address_cast(&op, dest.layout.ty)?
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
let f = op.to_scalar().to_f32()?;
this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
.ok_or_else(|| {
err_ub_format!(
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
dest.layout.ty
)
})?
.into()
}
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
let f = op.to_scalar().to_f64()?;
this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
.ok_or_else(|| {
err_ub_format!(
"`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
dest.layout.ty
)
})?
.into()
}
// Ptr-to-ptr cast
(ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast =>
this.ptr_to_ptr(&op, dest.layout.ty)?,
// Ptr/Int casts
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast =>
this.pointer_expose_address_cast(&op, dest.layout.ty)?,
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast =>
this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?,
// Error otherwise
_ =>
throw_unsup_format!(
......
......@@ -195,24 +195,12 @@ fn emulate_x86_sse_intrinsic(
_ => unreachable!(),
};
let mut exact = false;
let cvt = op.to_i128_r(32, rnd, &mut exact);
let res = if cvt.status.intersects(
rustc_apfloat::Status::INVALID_OP
| rustc_apfloat::Status::OVERFLOW
| rustc_apfloat::Status::UNDERFLOW,
) {
// Input is NaN (flagged with INVALID_OP) or does not fit
// in an i32 (flagged with OVERFLOW or UNDERFLOW), fallback
// to minimum acording to SSE semantics. The INEXACT flag
// is ignored on purpose because rounding can happen during
// float-to-int conversion.
i32::MIN
} else {
i32::try_from(cvt.value).unwrap()
};
let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| {
// Fallback to minimum acording to SSE semantics.
Scalar::from_i32(i32::MIN)
});
this.write_scalar(Scalar::from_i32(res), dest)?;
this.write_scalar(res, dest)?;
}
// Use to implement _mm_cvtss_si64 and _mm_cvttss_si64.
// Converts the first component of `op` from f32 to i64.
......@@ -232,24 +220,12 @@ fn emulate_x86_sse_intrinsic(
_ => unreachable!(),
};
let mut exact = false;
let cvt = op.to_i128_r(64, rnd, &mut exact);
let res = if cvt.status.intersects(
rustc_apfloat::Status::INVALID_OP
| rustc_apfloat::Status::OVERFLOW
| rustc_apfloat::Status::UNDERFLOW,
) {
// Input is NaN (flagged with INVALID_OP) or does not fit
// in an i64 (flagged with OVERFLOW or UNDERFLOW), fallback
// to minimum acording to SSE semantics. The INEXACT flag
// is ignored on purpose because rounding can happen during
// float-to-int conversion.
i64::MIN
} else {
i64::try_from(cvt.value).unwrap()
};
let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| {
// Fallback to minimum acording to SSE semantics.
Scalar::from_i64(i64::MIN)
});
this.write_scalar(Scalar::from_i64(res), dest)?;
this.write_scalar(res, dest)?;
}
// Used to implement the _mm_cvtsi32_ss function.
// Converts `right` from i32 to f32. Returns a SIMD vector with
......
......@@ -6,7 +6,17 @@ LL | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/deallocate-twice.rs:LL:CC
|
LL | let x = alloc(Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/deallocate-twice.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
note: inside `main`
--> $DIR/deallocate-twice.rs:LL:CC
......
......@@ -6,7 +6,17 @@ LL | let _z = *x;
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/reallocate-change-alloc.rs:LL:CC
|
LL | let x = alloc(Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/reallocate-change-alloc.rs:LL:CC
|
LL | let _y = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/reallocate-change-alloc.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/reallocate-dangling.rs:LL:CC
|
LL | let x = alloc(Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/reallocate-dangling.rs:LL:CC
|
LL | dealloc(x, Layout::from_size_align_unchecked(1, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
note: inside `main`
--> $DIR/reallocate-dangling.rs:LL:CC
......
......@@ -6,7 +6,12 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/issue-miri-1050-1.rs:LL:CC
|
LL | let ptr = Box::into_raw(Box::new(0u16));
| ^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
note: inside `main`
......
......@@ -6,7 +6,12 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/issue-miri-1050-1.rs:LL:CC
|
LL | let ptr = Box::into_raw(Box::new(0u16));
| ^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
= note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
note: inside `main`
......
......@@ -6,7 +6,17 @@ LL | let x = unsafe { ptr::addr_of!(*p) };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_addr_of.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_addr_of.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
= note: this error originates in the macro `ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info)
......
......@@ -6,7 +6,17 @@ LL | let x = unsafe { *p };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_deref.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_deref.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_deref.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | let x = unsafe { p.offset(42) };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_offset.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_offset.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_offset.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | let _ = *p;
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_pointer_project_underscore.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_pointer_project_underscore.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | let _x = unsafe { *p };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dangling_zst_deref.rs:LL:CC
|
LL | let b = Box::new(42);
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dangling_zst_deref.rs:LL:CC
|
LL | };
| ^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/dangling_zst_deref.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,8 +6,14 @@ LL | let x = unsafe { *v.as_ptr().wrapping_offset(5) };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/out_of_bounds_read1.rs:LL:CC
|
LL | let v: Vec<u8> = vec![1, 2];
| ^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/out_of_bounds_read1.rs:LL:CC
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,8 +6,14 @@ LL | let x = unsafe { *v.as_ptr().wrapping_offset(5) };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/out_of_bounds_read2.rs:LL:CC
|
LL | let v: Vec<u8> = vec![1, 2];
| ^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/out_of_bounds_read2.rs:LL:CC
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,21 @@ LL | *ptr.0
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dealloc_read_race2.rs:LL:CC
|
LL | let pointer: *mut usize = Box::into_raw(Box::new(0usize));
| ^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dealloc_read_race2.rs:LL:CC
|
LL | / __rust_dealloc(
LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | )
| |_____________^
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_read_race2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,21 @@ LL | *ptr.0 = 2;
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/dealloc_write_race2.rs:LL:CC
|
LL | let pointer: *mut usize = Box::into_raw(Box::new(0usize));
| ^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/dealloc_write_race2.rs:LL:CC
|
LL | / __rust_dealloc(
LL | | ptr.0 as *mut _,
LL | | std::mem::size_of::<usize>(),
LL | | std::mem::align_of::<usize>(),
LL | | );
| |_____________^
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/dealloc_write_race2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | *num += 1;
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/generator-pinned-moved.rs:LL:CC
|
LL | let mut generator_iterator = Box::new(GeneratorIteratorAdapter(firstn()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/generator-pinned-moved.rs:LL:CC
|
LL | }; // *deallocate* generator_iterator
| ^
= note: BACKTRACE (of the first span):
= note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next`
--> $DIR/generator-pinned-moved.rs:LL:CC
......
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u128`
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
--> $DIR/float_to_int_64_neg.rs:LL:CC
|
LL | float_to_int_unchecked::<f64, u128>(-1.0000000000001f64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u128`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
......
......@@ -6,7 +6,12 @@ LL | let _x = unsafe { x.offset(0) }; // UB despite offset 0, the pointer is
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/ptr_offset_ptr_plus_0.rs:LL:CC
|
LL | let x = Box::into_raw(Box::new(0u32));
| ^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/ptr_offset_ptr_plus_0.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
--> $DIR/simd-float-to-int.rs:LL:CC
|
LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
......
......@@ -11,8 +11,14 @@ LL | | );
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/simd-scatter.rs:LL:CC
|
LL | let mut vec: Vec<i8> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/simd-scatter.rs:LL:CC
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) });
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/rc_as_ptr.rs:LL:CC
|
LL | let strong = Rc::new(Box::new(42));
| ^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/rc_as_ptr.rs:LL:CC
|
LL | drop(strong);
| ^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
......
error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
--> $DIR/memchr_null.rs:LL:CC
|
LL | libc::memchr(ptr::null(), 0, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
......
error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
--> $DIR/memcmp_null.rs:LL:CC
|
LL | libc::memcmp(ptr::null(), ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
......
//@ignore-target-windows: No libc on Windows
//@compile-flags: -Zmiri-permissive-provenance
// C says that passing "invalid" pointers is UB for all string functions.
// It is unclear whether `(int*)42` is "invalid", but there is no actually
// a `char` living at that address, so arguably it cannot be a valid pointer.
// Hence this is UB.
fn main() {
let ptr = 42 as *const u8;
unsafe {
libc::memcmp(ptr.cast(), ptr.cast(), 0); //~ERROR: dangling
}
}
error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
--> $DIR/memcmp_zero.rs:LL:CC
|
LL | libc::memcmp(ptr.cast(), ptr.cast(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at $DIR/memcmp_zero.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error
error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
--> $DIR/memrchr_null.rs:LL:CC
|
LL | libc::memrchr(ptr::null(), 0, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
......
......@@ -21,7 +21,24 @@ LL | let _x = *(ptr as *mut u8);
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/mmap_use_after_munmap.rs:LL:CC
|
LL | let ptr = libc::mmap(
| ___________________^
LL | | std::ptr::null_mut(),
LL | | 4096,
LL | | libc::PROT_READ | libc::PROT_WRITE,
... |
LL | | 0,
LL | | );
| |_________^
help: ALLOC was deallocated here:
--> $DIR/mmap_use_after_munmap.rs:LL:CC
|
LL | libc::munmap(ptr, 4096);
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,17 @@ LL | unsafe { *x = zst_val };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/zst2.rs:LL:CC
|
LL | let mut x_box = Box::new(1u8);
| ^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/zst2.rs:LL:CC
|
LL | drop(x_box);
| ^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/zst2.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
......@@ -6,7 +6,12 @@ LL | unsafe { *(x as *mut [u8; 0]) = zst_val };
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
help: ALLOC was allocated here:
--> $DIR/zst3.rs:LL:CC
|
LL | let mut x_box = Box::new(1u8);
| ^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/zst3.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册