diff options
Diffstat (limited to 'tests/ui/consts')
11 files changed, 203 insertions, 42 deletions
diff --git a/tests/ui/consts/const-eval/heap/ptr_not_made_global.stderr b/tests/ui/consts/const-eval/heap/ptr_not_made_global.stderr index cb2bb1e8cd8..e5b108df298 100644 --- a/tests/ui/consts/const-eval/heap/ptr_not_made_global.stderr +++ b/tests/ui/consts/const-eval/heap/ptr_not_made_global.stderr @@ -4,7 +4,7 @@ error: encountered `const_allocate` pointer in final value that was not made glo LL | const FOO: &i32 = foo(); | ^^^^^^^^^^^^^^^ | - = note: use `const_make_global` to make allocated pointers immutable before returning + = note: use `const_make_global` to turn allocated pointers into immutable globals before returning error: encountered `const_allocate` pointer in final value that was not made global --> $DIR/ptr_not_made_global.rs:12:1 @@ -12,7 +12,7 @@ error: encountered `const_allocate` pointer in final value that was not made glo LL | const FOO_RAW: *const i32 = foo(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: use `const_make_global` to make allocated pointers immutable before returning + = note: use `const_make_global` to turn allocated pointers into immutable globals before returning error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/heap/ptr_not_made_global_mut.stderr b/tests/ui/consts/const-eval/heap/ptr_not_made_global_mut.stderr index 2445ce633d6..2d1993f96d3 100644 --- a/tests/ui/consts/const-eval/heap/ptr_not_made_global_mut.stderr +++ b/tests/ui/consts/const-eval/heap/ptr_not_made_global_mut.stderr @@ -4,7 +4,7 @@ error: encountered `const_allocate` pointer in final value that was not made glo LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ | - = note: use `const_make_global` to make allocated pointers immutable before returning + = note: use `const_make_global` to turn allocated pointers into immutable globals before returning error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs deleted file mode 100644 index bd97bec0f71..00000000000 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Test for the behavior described in <https://github.com/rust-lang/rust/issues/87184>. - -const PARTIAL_OVERWRITE: () = { - let mut p = &42; - unsafe { - let ptr: *mut _ = &mut p; - *(ptr as *mut u8) = 123; //~ ERROR unable to overwrite parts of a pointer - } - let x = *p; -}; - -fn main() {} diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr b/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr deleted file mode 100644 index 6ef1cfd35c8..00000000000 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0080]: unable to overwrite parts of a pointer in memory at ALLOC0 - --> $DIR/partial_ptr_overwrite.rs:7:9 - | -LL | *(ptr as *mut u8) = 123; - | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `PARTIAL_OVERWRITE` failed here - | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/ptr_fragments.rs b/tests/ui/consts/const-eval/ptr_fragments.rs new file mode 100644 index 00000000000..04dcbe55590 --- /dev/null +++ b/tests/ui/consts/const-eval/ptr_fragments.rs @@ -0,0 +1,63 @@ +//! Test that various operations involving pointer fragments work as expected. +//@ run-pass + +use std::mem::{self, MaybeUninit, transmute}; +use std::ptr; + +type Byte = MaybeUninit<u8>; + +const unsafe fn memcpy(dst: *mut Byte, src: *const Byte, n: usize) { + let mut i = 0; + while i < n { + *dst.add(i) = *src.add(i); + i += 1; + } +} + +const _MEMCPY: () = unsafe { + let ptr = &42; + let mut ptr2 = ptr::null::<i32>(); + memcpy(&mut ptr2 as *mut _ as *mut _, &ptr as *const _ as *const _, mem::size_of::<&i32>()); + assert!(*ptr2 == 42); +}; +const _MEMCPY_OFFSET: () = unsafe { + // Same as above, but the pointer has a non-zero offset so not all the data bytes are the same. + let ptr = &(42, 18); + let ptr = &ptr.1; + let mut ptr2 = ptr::null::<i32>(); + memcpy(&mut ptr2 as *mut _ as *mut _, &ptr as *const _ as *const _, mem::size_of::<&i32>()); + assert!(*ptr2 == 18); +}; + +const MEMCPY_RET: MaybeUninit<*const i32> = unsafe { + let ptr = &42; + let mut ptr2 = MaybeUninit::new(ptr::null::<i32>()); + memcpy(&mut ptr2 as *mut _ as *mut _, &ptr as *const _ as *const _, mem::size_of::<&i32>()); + // Return in a MaybeUninit so it does not get treated as a scalar. + ptr2 +}; + +#[allow(dead_code)] +fn reassemble_ptr_fragments_in_static() { + static DATA: i32 = 1i32; + + #[cfg(target_pointer_width = "64")] + struct Thing { + x: MaybeUninit<u32>, + y: MaybeUninit<u32>, + } + #[cfg(target_pointer_width = "32")] + struct Thing { + x: MaybeUninit<u16>, + y: MaybeUninit<u16>, + } + + static X: Thing = unsafe { + let Thing { x, y } = transmute(&raw const DATA); + Thing { x, y } + }; +} + +fn main() { + assert_eq!(unsafe { MEMCPY_RET.assume_init().read() }, 42); +} diff --git a/tests/ui/consts/const-eval/ptr_fragments_in_final.rs b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs new file mode 100644 index 00000000000..e2f3f51b086 --- /dev/null +++ b/tests/ui/consts/const-eval/ptr_fragments_in_final.rs @@ -0,0 +1,25 @@ +//! Test that we properly error when there is a pointer fragment in the final value. + +use std::{mem::{self, MaybeUninit}, ptr}; + +type Byte = MaybeUninit<u8>; + +const unsafe fn memcpy(dst: *mut Byte, src: *const Byte, n: usize) { + let mut i = 0; + while i < n { + dst.add(i).write(src.add(i).read()); + i += 1; + } +} + +const MEMCPY_RET: MaybeUninit<*const i32> = unsafe { //~ERROR: partial pointer in final value + let ptr = &42; + let mut ptr2 = MaybeUninit::new(ptr::null::<i32>()); + memcpy(&mut ptr2 as *mut _ as *mut _, &ptr as *const _ as *const _, mem::size_of::<&i32>() / 2); + // Return in a MaybeUninit so it does not get treated as a scalar. + ptr2 +}; + +fn main() { + assert_eq!(unsafe { MEMCPY_RET.assume_init().read() }, 42); +} diff --git a/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr b/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr new file mode 100644 index 00000000000..628bf2566e5 --- /dev/null +++ b/tests/ui/consts/const-eval/ptr_fragments_in_final.stderr @@ -0,0 +1,10 @@ +error: encountered partial pointer in final value of constant + --> $DIR/ptr_fragments_in_final.rs:15:1 + | +LL | const MEMCPY_RET: MaybeUninit<*const i32> = unsafe { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: while pointers can be broken apart into individual bytes during const-evaluation, only complete pointers (with all their bytes in the right order) are supported in the final value + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const-eval/read_partial_ptr.rs b/tests/ui/consts/const-eval/read_partial_ptr.rs new file mode 100644 index 00000000000..bccef9c0bc6 --- /dev/null +++ b/tests/ui/consts/const-eval/read_partial_ptr.rs @@ -0,0 +1,49 @@ +//! Ensure we error when trying to load from a pointer whose provenance has been messed with. + +const PARTIAL_OVERWRITE: () = { + let mut p = &42; + // Overwrite one byte with a no-provenance value. + unsafe { + let ptr: *mut _ = &mut p; + *(ptr as *mut u8) = 123; + } + let x = *p; //~ ERROR: unable to read parts of a pointer +}; + +const PTR_BYTES_SWAP: () = { + let mut p = &42; + // Swap the first two bytes. + unsafe { + let ptr = &mut p as *mut _ as *mut std::mem::MaybeUninit<u8>; + let byte0 = ptr.read(); + let byte1 = ptr.add(1).read(); + ptr.write(byte1); + ptr.add(1).write(byte0); + } + let x = *p; //~ ERROR: unable to read parts of a pointer +}; + +const PTR_BYTES_REPEAT: () = { + let mut p = &42; + // Duplicate the first byte over the second. + unsafe { + let ptr = &mut p as *mut _ as *mut std::mem::MaybeUninit<u8>; + let byte0 = ptr.read(); + ptr.add(1).write(byte0); + } + let x = *p; //~ ERROR: unable to read parts of a pointer +}; + +const PTR_BYTES_MIX: () = { + let mut p = &42; + let q = &43; + // Overwrite the first byte of p with the first byte of q. + unsafe { + let ptr = &mut p as *mut _ as *mut std::mem::MaybeUninit<u8>; + let qtr = &q as *const _ as *const std::mem::MaybeUninit<u8>; + ptr.write(qtr.read()); + } + let x = *p; //~ ERROR: unable to read parts of a pointer +}; + +fn main() {} diff --git a/tests/ui/consts/const-eval/read_partial_ptr.stderr b/tests/ui/consts/const-eval/read_partial_ptr.stderr new file mode 100644 index 00000000000..196606c77a3 --- /dev/null +++ b/tests/ui/consts/const-eval/read_partial_ptr.stderr @@ -0,0 +1,39 @@ +error[E0080]: unable to read parts of a pointer from memory at ALLOC0 + --> $DIR/read_partial_ptr.rs:10:13 + | +LL | let x = *p; + | ^^ evaluation of `PARTIAL_OVERWRITE` failed here + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: unable to read parts of a pointer from memory at ALLOC1 + --> $DIR/read_partial_ptr.rs:23:13 + | +LL | let x = *p; + | ^^ evaluation of `PTR_BYTES_SWAP` failed here + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: unable to read parts of a pointer from memory at ALLOC2 + --> $DIR/read_partial_ptr.rs:34:13 + | +LL | let x = *p; + | ^^ evaluation of `PTR_BYTES_REPEAT` failed here + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error[E0080]: unable to read parts of a pointer from memory at ALLOC3 + --> $DIR/read_partial_ptr.rs:46:13 + | +LL | let x = *p; + | ^^ evaluation of `PTR_BYTES_MIX` failed here + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/missing_span_in_backtrace.rs b/tests/ui/consts/missing_span_in_backtrace.rs index 4f3f9aa6ada..09a11c75fd7 100644 --- a/tests/ui/consts/missing_span_in_backtrace.rs +++ b/tests/ui/consts/missing_span_in_backtrace.rs @@ -1,3 +1,4 @@ +//! Check what happens when the error occurs inside a std function that we can't print the span of. //@ ignore-backends: gcc //@ compile-flags: -Z ui-testing=no @@ -7,15 +8,15 @@ use std::{ }; const X: () = { - let mut ptr1 = &1; - let mut ptr2 = &2; + let mut x1 = 1; + let mut x2 = 2; // Swap them, bytewise. unsafe { - ptr::swap_nonoverlapping( //~ ERROR unable to copy parts of a pointer - &mut ptr1 as *mut _ as *mut MaybeUninit<u8>, - &mut ptr2 as *mut _ as *mut MaybeUninit<u8>, - mem::size_of::<&i32>(), + ptr::swap_nonoverlapping( //~ ERROR beyond the end of the allocation + &mut x1 as *mut _ as *mut MaybeUninit<u8>, + &mut x2 as *mut _ as *mut MaybeUninit<u8>, + 10, ); } }; diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 0ac1e281107..55dde635828 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -1,15 +1,13 @@ -error[E0080]: unable to copy parts of a pointer from memory at ALLOC0 - --> $DIR/missing_span_in_backtrace.rs:15:9 +error[E0080]: memory access failed: attempting to access 1 byte, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes + --> $DIR/missing_span_in_backtrace.rs:16:9 | -15 | / ptr::swap_nonoverlapping( -16 | | &mut ptr1 as *mut _ as *mut MaybeUninit<u8>, -17 | | &mut ptr2 as *mut _ as *mut MaybeUninit<u8>, -18 | | mem::size_of::<&i32>(), -19 | | ); +16 | / ptr::swap_nonoverlapping( +17 | | &mut x1 as *mut _ as *mut MaybeUninit<u8>, +18 | | &mut x2 as *mut _ as *mut MaybeUninit<u8>, +19 | | 10, +20 | | ); | |_________^ evaluation of `X` failed inside this call | - = help: this code performed an operation that depends on the underlying bytes representing a pointer - = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported note: inside `swap_nonoverlapping::compiletime::<MaybeUninit<u8>>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `std::ptr::swap_nonoverlapping_const::<MaybeUninit<u8>>` |
