Auto merge of #2151 - RalfJung:numbers, r=oli-obk
enable number validity checking and ptr::invalid checking by default This removes the `-Zmiri-check-number-validity` flag, enabling its effects by default. (We don't error when the flag is passed, for backwards compatibility.) We also enable by default that transmuting an integer to a pointer now creates a pointer with `None` provenance, which is invalid to dereference (and, in the case of a function pointer, invalid to call). I did this together since it is all related to ptr2int/int2ptr transmutation. Two new flags are added to optionally take back these stricter checks: - `-Zmiri-allow-uninit-numbers` makes Miri accept uninit data in integers and floats - `-Zmiri-allow-ptr-int-transmute` makes Miri accept pointers (provenance data) in integers and floats, *and* makes Miri treat int2ptr transmutes as equivalent to a cast. The flag names make sense IMO, but they are somewhat inconsistent with our existing flags since we usually call things `-Zmiri-disable-$CHECK` rather than `-Zmiri-allow-$THING`. But `-Zmiri-disable-uninit-number-check` sounds silly? (Whenever I say "transmute" this includes union and pointer based type punning.) Cc `@saethlin` I hope this won't break everything?^^ I think the most risky part is the int2ptr transmute aspect, in particular around function pointers where no `as` casts are possible. The correct pattern is to first cast to a raw ptr and then transmute that to a fn ptr. We should probably document this better, in the `transmute` documentation and maybe in the documentation for the `fn()` type. I should run this PR against the std test suite before we land it. r? `@oli-obk` - [x] Ensure stdlib docs recommend "usize -> raw ptr -> fn ptr" for int-to-fnptr casts: https://github.com/rust-lang/rust/pull/97321 - [x] Run the stdlib test suite
This commit is contained in:
commit
5832dd1c0c
14
README.md
14
README.md
@ -44,8 +44,7 @@ in your program, and cannot run all programs:
|
|||||||
positives here, so if your program runs fine in Miri right now that is by no
|
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.
|
means a guarantee that it is UB-free when these questions get answered.
|
||||||
|
|
||||||
In particular, Miri does currently not check that integers/floats are
|
In particular, Miri does currently not check that references point to valid data.
|
||||||
initialized or that references point to valid data.
|
|
||||||
* If the program relies on unspecified details of how data is laid out, it will
|
* 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
|
still run fine in Miri -- but might break (including causing UB) on different
|
||||||
compiler versions or different platforms.
|
compiler versions or different platforms.
|
||||||
@ -302,10 +301,15 @@ The remaining flags are for advanced use only, and more likely to change or be r
|
|||||||
Some of these are **unsound**, which means they can lead
|
Some of these are **unsound**, which means they can lead
|
||||||
to Miri failing to detect cases of undefined behavior in a program.
|
to Miri failing to detect cases of undefined behavior in a program.
|
||||||
|
|
||||||
* `-Zmiri-check-number-validity` enables checking of integer and float validity
|
* `-Zmiri-allow-uninit-numbers` disables the check to ensure that number types (integer and float
|
||||||
(e.g., they must be initialized and not carry pointer provenance) as part of
|
types) always hold initialized data. (They must still be initialized when any actual operation,
|
||||||
enforcing validity invariants. This has no effect when
|
such as arithmetic, is performed.) Using this flag is **unsound**. This has no effect when
|
||||||
`-Zmiri-disable-validation` is present.
|
`-Zmiri-disable-validation` is present.
|
||||||
|
* `-Zmiri-allow-ptr-int-transmute` makes Miri more accepting of transmutation between pointers and
|
||||||
|
integers via `mem::transmute` or union/pointer type punning. This has two effects: it disables the
|
||||||
|
check against integers storing a pointer (i.e., data with provenance), thus allowing
|
||||||
|
pointer-to-integer transmutation, and it treats integer-to-pointer transmutation as equivalent to
|
||||||
|
a cast. Using this flag is **unsound**.
|
||||||
* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag
|
* `-Zmiri-disable-abi-check` disables checking [function ABI]. Using this flag
|
||||||
is **unsound**.
|
is **unsound**.
|
||||||
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
|
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
|
||||||
|
@ -335,7 +335,16 @@ fn main() {
|
|||||||
miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
|
miri_config.check_alignment = miri::AlignmentCheck::Symbolic;
|
||||||
}
|
}
|
||||||
"-Zmiri-check-number-validity" => {
|
"-Zmiri-check-number-validity" => {
|
||||||
miri_config.check_number_validity = true;
|
eprintln!(
|
||||||
|
"WARNING: the flag `-Zmiri-check-number-validity` no longer has any effect \
|
||||||
|
since it is now enabled by default"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"-Zmiri-allow-uninit-numbers" => {
|
||||||
|
miri_config.allow_uninit_numbers = true;
|
||||||
|
}
|
||||||
|
"-Zmiri-allow-ptr-int-transmute" => {
|
||||||
|
miri_config.allow_ptr_int_transmute = true;
|
||||||
}
|
}
|
||||||
"-Zmiri-disable-abi-check" => {
|
"-Zmiri-disable-abi-check" => {
|
||||||
miri_config.check_abi = false;
|
miri_config.check_abi = false;
|
||||||
@ -386,7 +395,6 @@ fn main() {
|
|||||||
"-Zmiri-strict-provenance" => {
|
"-Zmiri-strict-provenance" => {
|
||||||
miri_config.provenance_mode = ProvenanceMode::Strict;
|
miri_config.provenance_mode = ProvenanceMode::Strict;
|
||||||
miri_config.tag_raw = true;
|
miri_config.tag_raw = true;
|
||||||
miri_config.check_number_validity = true;
|
|
||||||
}
|
}
|
||||||
"-Zmiri-permissive-provenance" => {
|
"-Zmiri-permissive-provenance" => {
|
||||||
miri_config.provenance_mode = ProvenanceMode::Permissive;
|
miri_config.provenance_mode = ProvenanceMode::Permissive;
|
||||||
|
@ -77,8 +77,10 @@ pub struct MiriConfig {
|
|||||||
pub stacked_borrows: bool,
|
pub stacked_borrows: bool,
|
||||||
/// Controls alignment checking.
|
/// Controls alignment checking.
|
||||||
pub check_alignment: AlignmentCheck,
|
pub check_alignment: AlignmentCheck,
|
||||||
/// Controls integer and float validity (e.g., initialization) checking.
|
/// Controls integer and float validity initialization checking.
|
||||||
pub check_number_validity: bool,
|
pub allow_uninit_numbers: bool,
|
||||||
|
/// Controls how we treat ptr2int and int2ptr transmutes.
|
||||||
|
pub allow_ptr_int_transmute: bool,
|
||||||
/// Controls function [ABI](Abi) checking.
|
/// Controls function [ABI](Abi) checking.
|
||||||
pub check_abi: bool,
|
pub check_abi: bool,
|
||||||
/// Action for an op requiring communication with the host.
|
/// Action for an op requiring communication with the host.
|
||||||
@ -126,7 +128,8 @@ impl Default for MiriConfig {
|
|||||||
validate: true,
|
validate: true,
|
||||||
stacked_borrows: true,
|
stacked_borrows: true,
|
||||||
check_alignment: AlignmentCheck::Int,
|
check_alignment: AlignmentCheck::Int,
|
||||||
check_number_validity: false,
|
allow_uninit_numbers: false,
|
||||||
|
allow_ptr_int_transmute: false,
|
||||||
check_abi: true,
|
check_abi: true,
|
||||||
isolated_op: IsolatedOp::Reject(RejectOpWith::Abort),
|
isolated_op: IsolatedOp::Reject(RejectOpWith::Abort),
|
||||||
ignore_leaks: false,
|
ignore_leaks: false,
|
||||||
|
@ -118,19 +118,12 @@ impl<'mir, 'tcx> GlobalStateInner {
|
|||||||
) -> Pointer<Option<Tag>> {
|
) -> Pointer<Option<Tag>> {
|
||||||
trace!("Transmuting 0x{:x} to a pointer", addr);
|
trace!("Transmuting 0x{:x} to a pointer", addr);
|
||||||
|
|
||||||
let global_state = ecx.machine.intptrcast.borrow();
|
if ecx.machine.allow_ptr_int_transmute {
|
||||||
|
// When we allow transmutes, treat them like casts.
|
||||||
match global_state.provenance_mode {
|
Self::ptr_from_addr_cast(ecx, addr)
|
||||||
ProvenanceMode::Legacy => {
|
} else {
|
||||||
// In legacy mode, we have to support int2ptr transmutes,
|
// We consider transmuted pointers to be "invalid" (`None` provenance).
|
||||||
// so just pretend they do the same thing as a cast.
|
Pointer::new(None, Size::from_bytes(addr))
|
||||||
Self::ptr_from_addr_cast(ecx, addr)
|
|
||||||
}
|
|
||||||
ProvenanceMode::Permissive | ProvenanceMode::Strict => {
|
|
||||||
// Both of these modes consider transmuted pointers to be "invalid" (`None`
|
|
||||||
// provenance).
|
|
||||||
Pointer::new(None, Size::from_bytes(addr))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,13 +255,19 @@ pub struct Evaluator<'mir, 'tcx> {
|
|||||||
/// Whether to enforce the validity invariant.
|
/// Whether to enforce the validity invariant.
|
||||||
pub(crate) validate: bool,
|
pub(crate) validate: bool,
|
||||||
|
|
||||||
/// Whether to enforce validity (e.g., initialization) of integers and floats.
|
/// Whether to allow uninitialized numbers (integers and floats).
|
||||||
pub(crate) enforce_number_validity: bool,
|
pub(crate) allow_uninit_numbers: bool,
|
||||||
|
|
||||||
|
/// Whether to allow ptr2int transmutes, and whether to allow *dereferencing* the result of an
|
||||||
|
/// int2ptr transmute.
|
||||||
|
pub(crate) allow_ptr_int_transmute: bool,
|
||||||
|
|
||||||
/// Whether to enforce [ABI](Abi) of function calls.
|
/// Whether to enforce [ABI](Abi) of function calls.
|
||||||
pub(crate) enforce_abi: bool,
|
pub(crate) enforce_abi: bool,
|
||||||
|
|
||||||
|
/// The table of file descriptors.
|
||||||
pub(crate) file_handler: shims::posix::FileHandler,
|
pub(crate) file_handler: shims::posix::FileHandler,
|
||||||
|
/// The table of directory descriptors.
|
||||||
pub(crate) dir_handler: shims::posix::DirHandler,
|
pub(crate) dir_handler: shims::posix::DirHandler,
|
||||||
|
|
||||||
/// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
|
/// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
|
||||||
@ -351,7 +357,8 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
|
|||||||
tls: TlsData::default(),
|
tls: TlsData::default(),
|
||||||
isolated_op: config.isolated_op,
|
isolated_op: config.isolated_op,
|
||||||
validate: config.validate,
|
validate: config.validate,
|
||||||
enforce_number_validity: config.check_number_validity,
|
allow_uninit_numbers: config.allow_uninit_numbers,
|
||||||
|
allow_ptr_int_transmute: config.allow_ptr_int_transmute,
|
||||||
enforce_abi: config.check_abi,
|
enforce_abi: config.check_abi,
|
||||||
file_handler: FileHandler::new(config.mute_stdout_stderr),
|
file_handler: FileHandler::new(config.mute_stdout_stderr),
|
||||||
dir_handler: Default::default(),
|
dir_handler: Default::default(),
|
||||||
@ -493,12 +500,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn enforce_number_init(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
|
fn enforce_number_init(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
|
||||||
ecx.machine.enforce_number_validity
|
!ecx.machine.allow_uninit_numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn enforce_number_no_provenance(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
|
fn enforce_number_no_provenance(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
|
||||||
ecx.machine.enforce_number_validity
|
!ecx.machine.allow_ptr_int_transmute
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -405,8 +405,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
|||||||
|
|
||||||
// To catch double-destroys, we de-initialize the mutexattr.
|
// To catch double-destroys, we de-initialize the mutexattr.
|
||||||
// This is technically not right and might lead to false positives. For example, the below
|
// This is technically not right and might lead to false positives. For example, the below
|
||||||
// code is *likely* sound, even assuming uninit numbers are UB, but miri with
|
// code is *likely* sound, even assuming uninit numbers are UB, but Miri complains.
|
||||||
// -Zmiri-check-number-validity complains
|
|
||||||
//
|
//
|
||||||
// let mut x: MaybeUninit<libc::pthread_mutexattr_t> = MaybeUninit::zeroed();
|
// let mut x: MaybeUninit<libc::pthread_mutexattr_t> = MaybeUninit::zeroed();
|
||||||
// libc::pthread_mutexattr_init(x.as_mut_ptr());
|
// libc::pthread_mutexattr_init(x.as_mut_ptr());
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// compile-flags: -Zmiri-permissive-provenance -Zmiri-disable-stacked-borrows
|
// compile-flags: -Zmiri-permissive-provenance -Zmiri-disable-stacked-borrows -Zmiri-allow-ptr-int-transmute
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: i32 = 3;
|
let x: i32 = 3;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-permissive-provenance
|
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
// Ensure that a `ptr::invalid` ptr is truly invalid.
|
// Ensure that a `ptr::invalid` ptr is truly invalid.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-ptr-int-transmute
|
||||||
// A callee may not read the destination of our `&mut` without us noticing.
|
// A callee may not read the destination of our `&mut` without us noticing.
|
||||||
// Thise code got carefully checked to not introduce any reborrows
|
// Thise code got carefully checked to not introduce any reborrows
|
||||||
// that are not explicit in the source. Let's hope the compiler does not break this later!
|
// that are not explicit in the source. Let's hope the compiler does not break this later!
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-uninit-numbers
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-uninit-numbers
|
||||||
fn main() {
|
fn main() {
|
||||||
let v: Vec<u8> = Vec::with_capacity(10);
|
let v: Vec<u8> = Vec::with_capacity(10);
|
||||||
let undef = unsafe { *v.get_unchecked(5) };
|
let undef = unsafe { *v.get_unchecked(5) };
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-uninit-numbers
|
||||||
#![allow(unused, deprecated, invalid_value)]
|
#![allow(unused, deprecated, invalid_value)]
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let r = &mut 42;
|
let r = &mut 42;
|
||||||
let _i: [usize; 1] = unsafe { std::mem::transmute(r) }; //~ ERROR encountered a pointer, but expected plain (non-pointer) bytes
|
let _i: [usize; 1] = unsafe { std::mem::transmute(r) }; //~ ERROR encountered a pointer, but expected plain (non-pointer) bytes
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let r = &mut 42;
|
let r = &mut 42;
|
||||||
let _i: usize = unsafe { std::mem::transmute(r) }; //~ ERROR expected plain (non-pointer) bytes
|
let _i: usize = unsafe { std::mem::transmute(r) }; //~ ERROR expected plain (non-pointer) bytes
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
// This test is from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
// This test is from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
enum Tag<A> {
|
|
||||||
Tag2(A)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
struct Rec {
|
|
||||||
c8: u8,
|
|
||||||
t: Tag<u64>
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mk_rec() -> Rec {
|
|
||||||
return Rec { c8:0, t:Tag::Tag2(0) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_u64_aligned(u: &Tag<u64>) -> bool {
|
|
||||||
let p: usize = unsafe { mem::transmute(u) };
|
|
||||||
let u64_align = std::mem::align_of::<u64>();
|
|
||||||
return (p & (u64_align + 1)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let x = mk_rec();
|
|
||||||
is_u64_aligned(&x.t); // the result of this is non-deterministic (even with a fixed seed, results vary between targets)
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
// ignore-windows: No libc on Windows
|
// ignore-windows: No libc on Windows
|
||||||
// ignore-apple: pthread_condattr_setclock is not supported on MacOS.
|
// ignore-apple: pthread_condattr_setclock is not supported on MacOS.
|
||||||
// compile-flags: -Zmiri-disable-isolation -Zmiri-check-number-validity
|
// compile-flags: -Zmiri-disable-isolation
|
||||||
|
|
||||||
#![feature(rustc_private)]
|
#![feature(rustc_private)]
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-ptr-int-transmute
|
||||||
|
|
||||||
// This returns a miri pointer at type usize, if the argument is a proper pointer
|
// This returns a miri pointer at type usize, if the argument is a proper pointer
|
||||||
fn transmute_ptr_to_int<T>(x: *const T) -> usize {
|
fn transmute_ptr_to_int<T>(x: *const T) -> usize {
|
||||||
unsafe { std::mem::transmute(x) }
|
unsafe { std::mem::transmute(x) }
|
||||||
|
@ -197,17 +197,17 @@ fn test_prctl_thread_name() {
|
|||||||
use libc::c_long;
|
use libc::c_long;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut buf = [255; 10];
|
let mut buf = [255; 10];
|
||||||
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr(), 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
||||||
assert_eq!(b"<unnamed>\0", &buf);
|
assert_eq!(b"<unnamed>\0", &buf);
|
||||||
let thread_name = CString::new("hello").expect("CString::new failed");
|
let thread_name = CString::new("hello").expect("CString::new failed");
|
||||||
assert_eq!(libc::prctl(libc::PR_SET_NAME, thread_name.as_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
assert_eq!(libc::prctl(libc::PR_SET_NAME, thread_name.as_ptr(), 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
||||||
let mut buf = [255; 6];
|
let mut buf = [255; 6];
|
||||||
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr(), 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
||||||
assert_eq!(b"hello\0", &buf);
|
assert_eq!(b"hello\0", &buf);
|
||||||
let long_thread_name = CString::new("01234567890123456789").expect("CString::new failed");
|
let long_thread_name = CString::new("01234567890123456789").expect("CString::new failed");
|
||||||
assert_eq!(libc::prctl(libc::PR_SET_NAME, long_thread_name.as_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
assert_eq!(libc::prctl(libc::PR_SET_NAME, long_thread_name.as_ptr(), 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
||||||
let mut buf = [255; 16];
|
let mut buf = [255; 16];
|
||||||
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr() as c_long, 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
assert_eq!(libc::prctl(libc::PR_GET_NAME, buf.as_mut_ptr(), 0 as c_long, 0 as c_long, 0 as c_long), 0);
|
||||||
assert_eq!(b"012345678901234\0", &buf);
|
assert_eq!(b"012345678901234\0", &buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-uninit-numbers
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// compile-flags: -Zmiri-check-number-validity
|
|
||||||
|
|
||||||
use std::mem::{self, MaybeUninit};
|
use std::mem::{self, MaybeUninit};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -61,7 +61,9 @@ fn ptr_offset() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let p = f as fn() -> i32 as usize;
|
let p = f as fn() -> i32 as usize;
|
||||||
let x = (p as *mut u32).offset(0) as usize;
|
let x = (p as *mut u32).offset(0) as usize;
|
||||||
let f: fn() -> i32 = mem::transmute(x);
|
// *cast* to ptr, then transmute to fn ptr.
|
||||||
|
// (transmuting int to [fn]ptr causes trouble.)
|
||||||
|
let f: fn() -> i32 = mem::transmute(x as *const ());
|
||||||
assert_eq!(f(), 42);
|
assert_eq!(f(), 42);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@ fn mk_rec() -> Rec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_u64_aligned(u: &Tag<u64>) -> bool {
|
fn is_u64_aligned(u: &Tag<u64>) -> bool {
|
||||||
let p: usize = unsafe { mem::transmute(u) };
|
let p: *const () = unsafe { mem::transmute(u) };
|
||||||
|
let p = p as usize;
|
||||||
let u64_align = std::mem::align_of::<u64>();
|
let u64_align = std::mem::align_of::<u64>();
|
||||||
return (p & (u64_align - 1)) == 0;
|
return (p & (u64_align - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Stacked Borrows disallows this becuase the reference is never cast to a raw pointer.
|
// Stacked Borrows disallows this becuase the reference is never cast to a raw pointer.
|
||||||
// compile-flags: -Zmiri-disable-stacked-borrows
|
// compile-flags: -Zmiri-disable-stacked-borrows -Zmiri-allow-ptr-int-transmute
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// If we are careful, we can exploit data layout...
|
// If we are careful, we can exploit data layout...
|
||||||
@ -7,7 +7,8 @@ fn main() {
|
|||||||
std::mem::transmute::<&[u8], [usize; 2]>(&[42])
|
std::mem::transmute::<&[u8], [usize; 2]>(&[42])
|
||||||
};
|
};
|
||||||
let ptr = raw[0] + raw[1];
|
let ptr = raw[0] + raw[1];
|
||||||
let ptr = ptr as *const u8;
|
// We transmute both ways, to really test allow-ptr-int-transmute.
|
||||||
|
let ptr: *const u8 = unsafe { std::mem::transmute(ptr) };
|
||||||
// The pointer is one-past-the end, but we decrement it into bounds before using it
|
// The pointer is one-past-the end, but we decrement it into bounds before using it
|
||||||
assert_eq!(unsafe { *ptr.offset(-1) }, 42);
|
assert_eq!(unsafe { *ptr.offset(-1) }, 42);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
// compile-flags: -Zmiri-allow-uninit-numbers
|
||||||
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
// This test is adapted from https://github.com/rust-lang/miri/issues/1340#issue-600900312.
|
||||||
// This test passes because -Zmiri-check-number-validity is not passed.
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _val1 = unsafe { std::mem::MaybeUninit::<usize>::uninit().assume_init() };
|
let _val1 = unsafe { std::mem::MaybeUninit::<usize>::uninit().assume_init() };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user