Description
(Moving this to a separate issue because PR #50882 is already full of noise)
Reduced STR:
- Take current rust master
- Apply the following patch:
diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs
index 84bd275..4df7730 100644
--- a/src/liballoc/alloc.rs
+++ b/src/liballoc/alloc.rs
@@ -172,7 +172,7 @@ pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
if size != 0 {
let layout = Layout::from_size_align_unchecked(size, align);
- dealloc(ptr as *mut u8, layout);
+ Global.dealloc(NonNull::new_unchecked(ptr).cast(), layout);
}
}
- Compile rust against the system llvm (5 or 6)
- Run libstd tests (
x.py test src/libstd --stage 1
)
What happens then is that sync::once::tests::wait_for_force_to_finish
fails with:
thread '<unnamed>' panicked at 'assertion failed: t1.join().is_ok()', libstd/sync/once.rs:582:9
The disassembly for wait_for_force_to_finish
only contains one call to std::thread::JoinHandle::join
, instead of the expected two when the code is not miscompiled. That call is followed by a test that jumps to a panic when the result of JoinHandle::join
is ... Ok(())
:
93371: e8 aa fd 07 00 callq 113120 <_ZN41_$LT$std..thread..JoinHandle$LT$T$GT$$GT
$4join17h0fb3b129ec2e38aeE>
93376: 48 89 c3 mov %rax,%rbx
93379: 49 89 d7 mov %rdx,%r15
9337c: 48 85 db test %rbx,%rbx
9337f: 74 1b je 9339c <_ZN3std4sync4once5tests24wait_for_force_to_fin
ish17h6199051fcaa3ff6aE+0x21c>
That JoinHandle::join
returns a Result<(), Box<Any>>
, and Ok(())
is represented as (0, whatever)
. The destination of that jump is the panic code.
At some point, I'm not entirely sure with what state of the tree, it was even better. The error was:
thread '<unnamed>' panicked at 'assertion failed: t2.join().is_ok()', libstd/sync/once.rs:583:9
And there were two calls to std::thread::JoinHandle::join
, as expected, but they didn't have the same result handling:
93c79: e8 32 c5 07 00 callq 1101b0 <_ZN41_$LT$std..thread..JoinHandle$LT$T$GT$$GT$4join17hc6e7f9bb7d72483aE>
93c7e: 48 89 c3 mov %rax,%rbx
93c81: 49 89 d7 mov %rdx,%r15
93c84: 48 85 db test %rbx,%rbx
93c87: 75 5e jne 93ce7 <_ZN3std4sync4once5tests24wait_for_force_to_finish17h13c0ef8dd5eb6a3aE+0x267>
(snip)
93c9f: e8 0c c5 07 00 callq 1101b0 <_ZN41_$LT$std..thread..JoinHandle$LT$T$GT$$GT$4join17hc6e7f9bb7d72483aE>
93ca4: 48 89 c3 mov %rax,%rbx
93ca7: 49 89 d7 mov %rdx,%r15
93caa: 48 85 db test %rbx,%rbx
93cad: 74 1b je 93cca <_ZN3std4sync4once5tests24wait_for_force_to_finish17h13c0ef8dd5eb6a3aE+0x24a>
The destination of both jumps is panic code. The first jump, corresponding to t1.join().is_ok()
is correct, and the second, corresponding to t2.join().is_ok()
is broken, thus the test failure.
Even better: this doesn't happen when compiling with the bundled llvm. It also doesn't happen when extracting the test from libstd and compiling with a faulty compiler. It seems the fact that it's part of libstd, and that most of libstd is compiled along the test, plays a role.
I'm trying to get the corresponding mir and llvm-ir.