From 494d23c12dd131cbeb5d5bf34e1509f7e87668a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 May 2022 15:44:27 +0200 Subject: [PATCH] enable number validity checking and ptr::invalid checking by default --- README.md | 14 +++++--- src/bin/miri.rs | 12 +++++-- src/eval.rs | 9 +++-- src/intptrcast.rs | 19 ++++------ src/machine.rs | 17 ++++++--- src/shims/posix/sync.rs | 3 +- .../provenance/ptr_int_unexposed.rs | 2 +- tests/compile-fail/provenance/ptr_invalid.rs | 9 +++++ .../stacked_borrows/illegal_read3.rs | 1 + tests/compile-fail/transmute-pair-uninit.rs | 1 + tests/compile-fail/uninit_byte_read.rs | 1 + .../invalid_enum_tag_256variants_uninit.rs | 1 + .../validity/ptr_integer_array_transmute.rs | 2 -- .../validity/ptr_integer_transmute.rs | 2 -- tests/compile-fail/validity/uninit_float.rs | 2 -- tests/compile-fail/validity/uninit_integer.rs | 2 -- .../validity/uninit_integer_signed.rs | 2 -- tests/run-pass/bitop-beyond-alignment.rs | 36 ------------------- .../run-pass/concurrency/libc_pthread_cond.rs | 2 +- tests/run-pass/intptrcast.rs | 2 ++ tests/run-pass/libc.rs | 10 +++--- tests/run-pass/move-uninit-primval.rs | 1 + tests/run-pass/partially-uninit.rs | 2 -- tests/run-pass/ptr_offset.rs | 4 ++- tests/run-pass/tag-align-dyn-u64.rs | 3 +- tests/run-pass/transmute_fat.rs | 5 +-- tests/run-pass/uninit_number_ignored.rs | 2 +- 27 files changed, 76 insertions(+), 90 deletions(-) create mode 100644 tests/compile-fail/provenance/ptr_invalid.rs delete mode 100644 tests/run-pass/bitop-beyond-alignment.rs diff --git a/README.md b/README.md index 0f6c5007ba..07c5abc4b5 100644 --- a/README.md +++ b/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 means a guarantee that it is UB-free when these questions get answered. - In particular, Miri does currently not check that integers/floats are - initialized or that references point to valid data. + In particular, Miri does currently 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. @@ -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 to Miri failing to detect cases of undefined behavior in a program. -* `-Zmiri-check-number-validity` enables checking of integer and float validity - (e.g., they must be initialized and not carry pointer provenance) as part of - enforcing validity invariants. This has no effect when +* `-Zmiri-allow-uninit-numbers` disables the check to ensure that number types (integer and float + types) always hold initialized data. (They must still be initialized when any actual operation, + such as arithmetic, is performed.) Using this flag is **unsound**. This has no effect when `-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 is **unsound**. * `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 784f0da8a3..9c4cd0684c 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -335,7 +335,16 @@ fn main() { miri_config.check_alignment = miri::AlignmentCheck::Symbolic; } "-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" => { miri_config.check_abi = false; @@ -386,7 +395,6 @@ fn main() { "-Zmiri-strict-provenance" => { miri_config.provenance_mode = ProvenanceMode::Strict; miri_config.tag_raw = true; - miri_config.check_number_validity = true; } "-Zmiri-permissive-provenance" => { miri_config.provenance_mode = ProvenanceMode::Permissive; diff --git a/src/eval.rs b/src/eval.rs index 430ff06cf1..7e777c31c8 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -77,8 +77,10 @@ pub struct MiriConfig { pub stacked_borrows: bool, /// Controls alignment checking. pub check_alignment: AlignmentCheck, - /// Controls integer and float validity (e.g., initialization) checking. - pub check_number_validity: bool, + /// Controls integer and float validity initialization checking. + pub allow_uninit_numbers: bool, + /// Controls how we treat ptr2int and int2ptr transmutes. + pub allow_ptr_int_transmute: bool, /// Controls function [ABI](Abi) checking. pub check_abi: bool, /// Action for an op requiring communication with the host. @@ -126,7 +128,8 @@ impl Default for MiriConfig { validate: true, stacked_borrows: true, check_alignment: AlignmentCheck::Int, - check_number_validity: false, + allow_uninit_numbers: false, + allow_ptr_int_transmute: false, check_abi: true, isolated_op: IsolatedOp::Reject(RejectOpWith::Abort), ignore_leaks: false, diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 4850945b4e..4a86490ed0 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -118,19 +118,12 @@ impl<'mir, 'tcx> GlobalStateInner { ) -> Pointer> { trace!("Transmuting 0x{:x} to a pointer", addr); - let global_state = ecx.machine.intptrcast.borrow(); - - match global_state.provenance_mode { - ProvenanceMode::Legacy => { - // In legacy mode, we have to support int2ptr transmutes, - // so just pretend they do the same thing as a cast. - 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)) - } + if ecx.machine.allow_ptr_int_transmute { + // When we allow transmutes, treat them like casts. + Self::ptr_from_addr_cast(ecx, addr) + } else { + // We consider transmuted pointers to be "invalid" (`None` provenance). + Pointer::new(None, Size::from_bytes(addr)) } } diff --git a/src/machine.rs b/src/machine.rs index 0972699e72..0b9b133e3a 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -255,13 +255,19 @@ pub struct Evaluator<'mir, 'tcx> { /// Whether to enforce the validity invariant. pub(crate) validate: bool, - /// Whether to enforce validity (e.g., initialization) of integers and floats. - pub(crate) enforce_number_validity: bool, + /// Whether to allow uninitialized numbers (integers and floats). + 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. pub(crate) enforce_abi: bool, + /// The table of file descriptors. pub(crate) file_handler: shims::posix::FileHandler, + /// The table of directory descriptors. pub(crate) dir_handler: shims::posix::DirHandler, /// 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(), isolated_op: config.isolated_op, 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, file_handler: FileHandler::new(config.mute_stdout_stderr), dir_handler: Default::default(), @@ -493,12 +500,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { #[inline(always)] fn enforce_number_init(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool { - ecx.machine.enforce_number_validity + !ecx.machine.allow_uninit_numbers } #[inline(always)] fn enforce_number_no_provenance(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool { - ecx.machine.enforce_number_validity + !ecx.machine.allow_ptr_int_transmute } #[inline(always)] diff --git a/src/shims/posix/sync.rs b/src/shims/posix/sync.rs index 1b6112a331..f56a309bf0 100644 --- a/src/shims/posix/sync.rs +++ b/src/shims/posix/sync.rs @@ -405,8 +405,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // To catch double-destroys, we de-initialize the mutexattr. // 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 - // -Zmiri-check-number-validity complains + // code is *likely* sound, even assuming uninit numbers are UB, but Miri complains. // // let mut x: MaybeUninit = MaybeUninit::zeroed(); // libc::pthread_mutexattr_init(x.as_mut_ptr()); diff --git a/tests/compile-fail/provenance/ptr_int_unexposed.rs b/tests/compile-fail/provenance/ptr_int_unexposed.rs index 2aecb68b8b..8a336e43ba 100644 --- a/tests/compile-fail/provenance/ptr_int_unexposed.rs +++ b/tests/compile-fail/provenance/ptr_int_unexposed.rs @@ -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() { let x: i32 = 3; diff --git a/tests/compile-fail/provenance/ptr_invalid.rs b/tests/compile-fail/provenance/ptr_invalid.rs new file mode 100644 index 0000000000..f4f3ed5afa --- /dev/null +++ b/tests/compile-fail/provenance/ptr_invalid.rs @@ -0,0 +1,9 @@ +#![feature(strict_provenance)] + +// Ensure that a `ptr::invalid` ptr is truly invalid. +fn main() { + let x = 42; + let xptr = &x as *const i32; + let xptr_invalid = std::ptr::invalid::(xptr.expose_addr()); + let _val = unsafe { *xptr_invalid }; //~ ERROR is not a valid pointer +} diff --git a/tests/compile-fail/stacked_borrows/illegal_read3.rs b/tests/compile-fail/stacked_borrows/illegal_read3.rs index 09fd5d534c..672c200861 100644 --- a/tests/compile-fail/stacked_borrows/illegal_read3.rs +++ b/tests/compile-fail/stacked_borrows/illegal_read3.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmiri-allow-ptr-int-transmute // A callee may not read the destination of our `&mut` without us noticing. // 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! diff --git a/tests/compile-fail/transmute-pair-uninit.rs b/tests/compile-fail/transmute-pair-uninit.rs index 42aa7a9692..18c80ac42a 100644 --- a/tests/compile-fail/transmute-pair-uninit.rs +++ b/tests/compile-fail/transmute-pair-uninit.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmiri-allow-uninit-numbers #![feature(core_intrinsics)] use std::mem; diff --git a/tests/compile-fail/uninit_byte_read.rs b/tests/compile-fail/uninit_byte_read.rs index 36c14137bd..9a1f8df94d 100644 --- a/tests/compile-fail/uninit_byte_read.rs +++ b/tests/compile-fail/uninit_byte_read.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmiri-allow-uninit-numbers fn main() { let v: Vec = Vec::with_capacity(10); let undef = unsafe { *v.get_unchecked(5) }; diff --git a/tests/compile-fail/validity/invalid_enum_tag_256variants_uninit.rs b/tests/compile-fail/validity/invalid_enum_tag_256variants_uninit.rs index ccf97b416c..c36685ab2f 100644 --- a/tests/compile-fail/validity/invalid_enum_tag_256variants_uninit.rs +++ b/tests/compile-fail/validity/invalid_enum_tag_256variants_uninit.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmiri-allow-uninit-numbers #![allow(unused, deprecated, invalid_value)] #[derive(Copy, Clone)] diff --git a/tests/compile-fail/validity/ptr_integer_array_transmute.rs b/tests/compile-fail/validity/ptr_integer_array_transmute.rs index 7a1ae2f3c9..92c635ff22 100644 --- a/tests/compile-fail/validity/ptr_integer_array_transmute.rs +++ b/tests/compile-fail/validity/ptr_integer_array_transmute.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zmiri-check-number-validity - fn main() { let r = &mut 42; let _i: [usize; 1] = unsafe { std::mem::transmute(r) }; //~ ERROR encountered a pointer, but expected plain (non-pointer) bytes diff --git a/tests/compile-fail/validity/ptr_integer_transmute.rs b/tests/compile-fail/validity/ptr_integer_transmute.rs index bb9e8e1e22..b23ccbbb1b 100644 --- a/tests/compile-fail/validity/ptr_integer_transmute.rs +++ b/tests/compile-fail/validity/ptr_integer_transmute.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zmiri-check-number-validity - fn main() { let r = &mut 42; let _i: usize = unsafe { std::mem::transmute(r) }; //~ ERROR expected plain (non-pointer) bytes diff --git a/tests/compile-fail/validity/uninit_float.rs b/tests/compile-fail/validity/uninit_float.rs index 1cb687f9b0..e79cbb45f9 100644 --- a/tests/compile-fail/validity/uninit_float.rs +++ b/tests/compile-fail/validity/uninit_float.rs @@ -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. fn main() { diff --git a/tests/compile-fail/validity/uninit_integer.rs b/tests/compile-fail/validity/uninit_integer.rs index c700f1f46d..bfa25d6ef3 100644 --- a/tests/compile-fail/validity/uninit_integer.rs +++ b/tests/compile-fail/validity/uninit_integer.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zmiri-check-number-validity - // This test is from https://github.com/rust-lang/miri/issues/1340#issue-600900312. fn main() { diff --git a/tests/compile-fail/validity/uninit_integer_signed.rs b/tests/compile-fail/validity/uninit_integer_signed.rs index 28bca0b19a..1764120805 100644 --- a/tests/compile-fail/validity/uninit_integer_signed.rs +++ b/tests/compile-fail/validity/uninit_integer_signed.rs @@ -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. fn main() { diff --git a/tests/run-pass/bitop-beyond-alignment.rs b/tests/run-pass/bitop-beyond-alignment.rs deleted file mode 100644 index e540a2a4b7..0000000000 --- a/tests/run-pass/bitop-beyond-alignment.rs +++ /dev/null @@ -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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::mem; - -enum Tag { - Tag2(A) -} - -#[allow(dead_code)] -struct Rec { - c8: u8, - t: Tag -} - -fn mk_rec() -> Rec { - return Rec { c8:0, t:Tag::Tag2(0) }; -} - -fn is_u64_aligned(u: &Tag) -> bool { - let p: usize = unsafe { mem::transmute(u) }; - let u64_align = std::mem::align_of::(); - 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) -} diff --git a/tests/run-pass/concurrency/libc_pthread_cond.rs b/tests/run-pass/concurrency/libc_pthread_cond.rs index 0e09ec9126..5c34dc82e0 100644 --- a/tests/run-pass/concurrency/libc_pthread_cond.rs +++ b/tests/run-pass/concurrency/libc_pthread_cond.rs @@ -1,6 +1,6 @@ // ignore-windows: No libc on Windows // ignore-macos: 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)] diff --git a/tests/run-pass/intptrcast.rs b/tests/run-pass/intptrcast.rs index 6e72d30d41..573bdbae70 100644 --- a/tests/run-pass/intptrcast.rs +++ b/tests/run-pass/intptrcast.rs @@ -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 fn transmute_ptr_to_int(x: *const T) -> usize { unsafe { std::mem::transmute(x) } diff --git a/tests/run-pass/libc.rs b/tests/run-pass/libc.rs index ab9a690fe1..fd3625639b 100644 --- a/tests/run-pass/libc.rs +++ b/tests/run-pass/libc.rs @@ -197,17 +197,17 @@ fn test_prctl_thread_name() { use libc::c_long; unsafe { 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"\0", &buf); 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]; - 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); 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]; - 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); } } diff --git a/tests/run-pass/move-uninit-primval.rs b/tests/run-pass/move-uninit-primval.rs index b8bd869b48..0edc3c9e6c 100644 --- a/tests/run-pass/move-uninit-primval.rs +++ b/tests/run-pass/move-uninit-primval.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmiri-allow-uninit-numbers #![allow(deprecated)] struct Foo { diff --git a/tests/run-pass/partially-uninit.rs b/tests/run-pass/partially-uninit.rs index 1de5308428..5ee9abbcb9 100644 --- a/tests/run-pass/partially-uninit.rs +++ b/tests/run-pass/partially-uninit.rs @@ -1,5 +1,3 @@ -// compile-flags: -Zmiri-check-number-validity - use std::mem::{self, MaybeUninit}; #[repr(C)] diff --git a/tests/run-pass/ptr_offset.rs b/tests/run-pass/ptr_offset.rs index 6af3e28854..4c6341813f 100644 --- a/tests/run-pass/ptr_offset.rs +++ b/tests/run-pass/ptr_offset.rs @@ -61,7 +61,9 @@ fn ptr_offset() { unsafe { let p = f as fn() -> i32 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); } } diff --git a/tests/run-pass/tag-align-dyn-u64.rs b/tests/run-pass/tag-align-dyn-u64.rs index 8a97758fbb..460c2b2559 100644 --- a/tests/run-pass/tag-align-dyn-u64.rs +++ b/tests/run-pass/tag-align-dyn-u64.rs @@ -25,7 +25,8 @@ fn mk_rec() -> Rec { } fn is_u64_aligned(u: &Tag) -> 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::(); return (p & (u64_align - 1)) == 0; } diff --git a/tests/run-pass/transmute_fat.rs b/tests/run-pass/transmute_fat.rs index 238122de8d..8a6e15031c 100644 --- a/tests/run-pass/transmute_fat.rs +++ b/tests/run-pass/transmute_fat.rs @@ -1,5 +1,5 @@ // 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() { // If we are careful, we can exploit data layout... @@ -7,7 +7,8 @@ fn main() { std::mem::transmute::<&[u8], [usize; 2]>(&[42]) }; 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 assert_eq!(unsafe { *ptr.offset(-1) }, 42); } diff --git a/tests/run-pass/uninit_number_ignored.rs b/tests/run-pass/uninit_number_ignored.rs index 77d6af6e99..13aac61ba8 100644 --- a/tests/run-pass/uninit_number_ignored.rs +++ b/tests/run-pass/uninit_number_ignored.rs @@ -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 passes because -Zmiri-check-number-validity is not passed. fn main() { let _val1 = unsafe { std::mem::MaybeUninit::::uninit().assume_init() };