mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Add a bunch of tests for #107975
This commit is contained in:
parent
0cd01aac6a
commit
2b089147ab
22
tests/ui/codegen/equal-pointers-unequal/README.md
Normal file
22
tests/ui/codegen/equal-pointers-unequal/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
See https://github.com/rust-lang/rust/issues/107975
|
||||||
|
|
||||||
|
Basically, if you have two pointers with the same address but from two different allocations,
|
||||||
|
the compiler gets confused whether their addresses are equal or not,
|
||||||
|
resulting in some self-contradictory behavior of the compiled code.
|
||||||
|
|
||||||
|
This folder contains some examples.
|
||||||
|
They all boil down to allocating a variable on the stack, taking its address,
|
||||||
|
getting rid of the variable, and then doing it all again.
|
||||||
|
This way we end up with two addresses stored in two `usize`s (`a` and `b`).
|
||||||
|
The addresses are (probably) equal but (definitely) come from two different allocations.
|
||||||
|
Logically, we would expect that exactly one of the following options holds true:
|
||||||
|
1. `a == b`
|
||||||
|
2. `a != b`
|
||||||
|
Sadly, the compiler does not always agree.
|
||||||
|
|
||||||
|
Due to Rust having at least three meaningfully different ways
|
||||||
|
to get a variable's address as an `usize`,
|
||||||
|
each example is provided in three versions, each in the corresponding subfolder:
|
||||||
|
1. `./as-cast/` for `&v as *const _ as usize`,
|
||||||
|
2. `./strict-provenance/` for `addr_of!(v).addr()`,
|
||||||
|
2. `./exposed-provenance/` for `addr_of!(v).expose_provenance()`.
|
21
tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
Normal file
21
tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
22
tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs
Normal file
22
tests/ui/codegen/equal-pointers-unequal/as-cast/function.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
|
||||||
|
|
||||||
|
fn f() -> usize {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = f();
|
||||||
|
let b = f();
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
30
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
Normal file
30
tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
assert_eq!(format!("{}", a == b), "false");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "false");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
}
|
30
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
Normal file
30
tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
assert_eq!(format!("{}", a == b), "true");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "true");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
}
|
20
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
Normal file
20
tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
println!("{a}"); // or b
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
23
tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
Normal file
23
tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b = {
|
||||||
|
let v = 0;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
assert_ne!(a, b);
|
||||||
|
let c = a;
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
|
||||||
|
println!("{a} {b}");
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
|
||||||
|
}
|
63
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
Normal file
63
tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
use std::cell::{Ref, RefCell};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let i: usize = b - a;
|
||||||
|
|
||||||
|
// A surprise tool that will help us later.
|
||||||
|
let arr = [
|
||||||
|
RefCell::new(Some(Box::new(1u8))),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
];
|
||||||
|
|
||||||
|
// `i` is not 0
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
|
||||||
|
// Let's borrow the `i`-th element.
|
||||||
|
// If `i` is out of bounds, indexing will panic.
|
||||||
|
let r: Ref<Option<Box<u8>>> = arr[i].borrow();
|
||||||
|
|
||||||
|
// If we got here, it means `i` was in bounds.
|
||||||
|
// Now, two options are possible:
|
||||||
|
// EITHER `i` is not 0 (as we have asserted above),
|
||||||
|
// so the unwrap will panic, because only the 0-th element is `Some`
|
||||||
|
// OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
|
||||||
|
let r: &Box<u8> = r.as_ref().unwrap();
|
||||||
|
|
||||||
|
// If we got here, it means `i` *was* actually 0.
|
||||||
|
// Let's ignore the fact that the assert has lied
|
||||||
|
// and try to take a mutable reference to the 0-th element.
|
||||||
|
// `borrow_mut` should panic, because we are sill holding on
|
||||||
|
// to a shared `Ref` for the same `RefCell`.
|
||||||
|
*arr[0].borrow_mut() = None;
|
||||||
|
|
||||||
|
// But it doesn't panic!
|
||||||
|
// We have successfully replaced `Some(Box)` with `None`,
|
||||||
|
// while holding a shared reference to it.
|
||||||
|
// No unsafe involved.
|
||||||
|
|
||||||
|
// The `Box` has been deallocated by now, so this is a dangling reference!
|
||||||
|
let r: &u8 = &*r;
|
||||||
|
println!("{:p}", r);
|
||||||
|
|
||||||
|
// The following might segfault. Or it might not.
|
||||||
|
// Depends on the platform semantics
|
||||||
|
// and whatever happened to the pointed-to memory after deallocation.
|
||||||
|
// let u: u8 = *r;
|
||||||
|
// println!("{u}");
|
||||||
|
}
|
28
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
Normal file
28
tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
&v as *const _ as usize
|
||||||
|
};
|
||||||
|
|
||||||
|
// So, are `a` and `b` equal?
|
||||||
|
|
||||||
|
// Let's check their difference.
|
||||||
|
let i: usize = a - b;
|
||||||
|
// It's not zero, which means `a` and `b` are not equal.
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
// But it looks like zero...
|
||||||
|
assert_eq!(i.to_string(), "0");
|
||||||
|
// ...and now it *is* zero?
|
||||||
|
assert_eq!(i, 0);
|
||||||
|
// So `a` and `b` are equal after all?
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn f() -> usize {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = f();
|
||||||
|
let b = f();
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
assert_eq!(format!("{}", a == b), "false");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "false");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
assert_eq!(format!("{}", a == b), "true");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "true");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
println!("{a}"); // or b
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
assert_ne!(a, b);
|
||||||
|
let c = a;
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
|
||||||
|
println!("{a} {b}");
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::{Ref, RefCell},
|
||||||
|
ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let i: usize = b - a;
|
||||||
|
|
||||||
|
// A surprise tool that will help us later.
|
||||||
|
let arr = [
|
||||||
|
RefCell::new(Some(Box::new(1u8))),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
];
|
||||||
|
|
||||||
|
// `i` is not 0
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
|
||||||
|
// Let's borrow the `i`-th element.
|
||||||
|
// If `i` is out of bounds, indexing will panic.
|
||||||
|
let r: Ref<Option<Box<u8>>> = arr[i].borrow();
|
||||||
|
|
||||||
|
// If we got here, it means `i` was in bounds.
|
||||||
|
// Now, two options are possible:
|
||||||
|
// EITHER `i` is not 0 (as we have asserted above),
|
||||||
|
// so the unwrap will panic, because only the 0-th element is `Some`
|
||||||
|
// OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
|
||||||
|
let r: &Box<u8> = r.as_ref().unwrap();
|
||||||
|
|
||||||
|
// If we got here, it means `i` *was* actually 0.
|
||||||
|
// Let's ignore the fact that the assert has lied
|
||||||
|
// and try to take a mutable reference to the 0-th element.
|
||||||
|
// `borrow_mut` should panic, because we are sill holding on
|
||||||
|
// to a shared `Ref` for the same `RefCell`.
|
||||||
|
*arr[0].borrow_mut() = None;
|
||||||
|
|
||||||
|
// But it doesn't panic!
|
||||||
|
// We have successfully replaced `Some(Box)` with `None`,
|
||||||
|
// while holding a shared reference to it.
|
||||||
|
// No unsafe involved.
|
||||||
|
|
||||||
|
// The `Box` has been deallocated by now, so this is a dangling reference!
|
||||||
|
let r: &u8 = &*r;
|
||||||
|
println!("{:p}", r);
|
||||||
|
|
||||||
|
// The following might segfault. Or it might not.
|
||||||
|
// Depends on the platform semantics
|
||||||
|
// and whatever happened to the pointed-to memory after deallocation.
|
||||||
|
// let u: u8 = *r;
|
||||||
|
// println!("{u}");
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
#![feature(exposed_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).expose_provenance()
|
||||||
|
};
|
||||||
|
|
||||||
|
// So, are `a` and `b` equal?
|
||||||
|
|
||||||
|
// Let's check their difference.
|
||||||
|
let i: usize = a - b;
|
||||||
|
// It's not zero, which means `a` and `b` are not equal.
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
// But it looks like zero...
|
||||||
|
assert_eq!(i.to_string(), "0");
|
||||||
|
// ...and now it *is* zero?
|
||||||
|
assert_eq!(i, 0);
|
||||||
|
// So `a` and `b` are equal after all?
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1434203908
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn f() -> usize {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = f();
|
||||||
|
let b = f();
|
||||||
|
|
||||||
|
// `a` and `b` are not equal.
|
||||||
|
assert_ne!(a, b);
|
||||||
|
// But they are the same number.
|
||||||
|
assert_eq!(format!("{a}"), format!("{b}"));
|
||||||
|
// And they are equal.
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
assert_eq!(format!("{}", a == b), "false");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "false");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Based on https://github.com/rust-lang/rust/issues/107975#issuecomment-1432161340
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn cmp(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp_in(a: usize, b: usize) -> bool {
|
||||||
|
a == b
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
assert_eq!(a.to_string(), b.to_string());
|
||||||
|
assert_eq!(format!("{}", a == b), "true");
|
||||||
|
assert_eq!(format!("{}", cmp_in(a, b)), "true");
|
||||||
|
assert_eq!(format!("{}", cmp(a, b)), "true");
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
println!("{a}"); // or b
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ne!(a, b);
|
||||||
|
assert_ne!(a, b);
|
||||||
|
let c = a;
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
|
||||||
|
println!("{a} {b}");
|
||||||
|
assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::{Ref, RefCell},
|
||||||
|
ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let i: usize = b - a;
|
||||||
|
|
||||||
|
// A surprise tool that will help us later.
|
||||||
|
let arr = [
|
||||||
|
RefCell::new(Some(Box::new(1u8))),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
RefCell::new(None),
|
||||||
|
];
|
||||||
|
|
||||||
|
// `i` is not 0
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
|
||||||
|
// Let's borrow the `i`-th element.
|
||||||
|
// If `i` is out of bounds, indexing will panic.
|
||||||
|
let r: Ref<Option<Box<u8>>> = arr[i].borrow();
|
||||||
|
|
||||||
|
// If we got here, it means `i` was in bounds.
|
||||||
|
// Now, two options are possible:
|
||||||
|
// EITHER `i` is not 0 (as we have asserted above),
|
||||||
|
// so the unwrap will panic, because only the 0-th element is `Some`
|
||||||
|
// OR the assert lied, `i` *is* 0, and the `unwrap` will not panic.
|
||||||
|
let r: &Box<u8> = r.as_ref().unwrap();
|
||||||
|
|
||||||
|
// If we got here, it means `i` *was* actually 0.
|
||||||
|
// Let's ignore the fact that the assert has lied
|
||||||
|
// and try to take a mutable reference to the 0-th element.
|
||||||
|
// `borrow_mut` should panic, because we are sill holding on
|
||||||
|
// to a shared `Ref` for the same `RefCell`.
|
||||||
|
*arr[0].borrow_mut() = None;
|
||||||
|
|
||||||
|
// But it doesn't panic!
|
||||||
|
// We have successfully replaced `Some(Box)` with `None`,
|
||||||
|
// while holding a shared reference to it.
|
||||||
|
// No unsafe involved.
|
||||||
|
|
||||||
|
// The `Box` has been deallocated by now, so this is a dangling reference!
|
||||||
|
let r: &u8 = &*r;
|
||||||
|
println!("{:p}", r);
|
||||||
|
|
||||||
|
// The following might segfault. Or it might not.
|
||||||
|
// Depends on the platform semantics
|
||||||
|
// and whatever happened to the pointed-to memory after deallocation.
|
||||||
|
// let u: u8 = *r;
|
||||||
|
// println!("{u}");
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
//@ known-bug: #107975
|
||||||
|
//@ compile-flags: -Copt-level=2
|
||||||
|
//@ run-pass
|
||||||
|
|
||||||
|
// Derived from https://github.com/rust-lang/rust/issues/107975#issuecomment-1431758601
|
||||||
|
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
let b: usize = {
|
||||||
|
let v = 0u8;
|
||||||
|
ptr::from_ref(&v).addr()
|
||||||
|
};
|
||||||
|
|
||||||
|
// So, are `a` and `b` equal?
|
||||||
|
|
||||||
|
// Let's check their difference.
|
||||||
|
let i: usize = a - b;
|
||||||
|
// It's not zero, which means `a` and `b` are not equal.
|
||||||
|
assert_ne!(i, 0);
|
||||||
|
// But it looks like zero...
|
||||||
|
assert_eq!(i.to_string(), "0");
|
||||||
|
// ...and now it *is* zero?
|
||||||
|
assert_eq!(i, 0);
|
||||||
|
// So `a` and `b` are equal after all?
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user