Description
cf. https://octodon.social/@fasterthanlime/109785229512000455
Relevant PR: bearcove/loona#74 (comment) (but it's annoying to run - requires Linux, with a recent enough kernel to have io_uring support)
Here's essentially the shape of the problem, I'll try to come up with a MVCE:
#![allow(incomplete_features)]
#![feature(async_fn_in_trait)]
trait WriteOwned {
async fn writev_all(&self) {
self.writev();
}
async fn writev(&self) {
self.write();
}
async fn write(&self);
}
impl WriteOwned for TcpStream {
async fn write(&self) {
// forward to actual impl
}
async fn writev(&self) {
// forward to actual impl
}
}
When the concrete type is TcpStream
, not only does stream.writev_all
call WriteOwned::writev
(the default impl) instead of <TcpStream as WriteOwned>::writev
, it seems to call it with.. the wrong calling convention? Valgrind is very unhappy and the program ends up segfaulting.
Valgrind output:
2023-01-31T18:20:45.691210Z DEBUG hring_bingo_ktls: Connected to httpbingo
WriteOwned::writev_all, calling writev with 13 items
==125831== Use of uninitialised value of size 8
==125831== at 0x196CB6: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:0)
==125831== by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831== by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831== by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831== by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831== by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831== by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831== by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831== by 0x21D819: tokio::runtime::task::harness::poll_future::{{closure}} (harness.rs:476)
==125831== by 0x2DB032: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once (unwind_safe.rs:271)
==125831== by 0x2C867B: std::panicking::try::do_call (panicking.rs:483)
==125831== by 0x2C99AA: __rust_try (in /home/amos/bearcove/hring/target/debug/hring-bingo-ktls)
==125831==
WriteOwned::write_v with 👈 ==125831== Conditional jump or move depends on uninitialised value(s)
==125831== at 0x52CEF6: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:230)
==125831== by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831== by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831== by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831== by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831== by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831== by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831== by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831== by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831== by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831== by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831== by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831==
==125831== Conditional jump or move depends on uninitialised value(s)
==125831== at 0x52CFBF: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:249)
==125831== by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831== by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831== by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831== by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831== by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831== by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831== by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831== by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831== by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831== by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831== by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831==
==125831== Conditional jump or move depends on uninitialised value(s)
==125831== at 0x52CFAB: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:257)
==125831== by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831== by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831== by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831== by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831== by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831== by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831== by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831== by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831== by 0x2CDEA9: tokio::runtime::task::core::Core<T,S>::poll::{{closure}} (core.rs:223)
==125831== by 0x1B5A60: tokio::loom::std::unsafe_cell::UnsafeCell<T>::with_mut (unsafe_cell.rs:14)
==125831== by 0x2CDC85: tokio::runtime::task::core::Core<T,S>::poll (core.rs:212)
==125831==
==125831== Syscall param write(buf) points to uninitialised byte(s)
==125831== at 0x4A81D94: write (write.c:26)
==125831== by 0x4FE2FE: <std::io::stdio::StderrLock as std::io::Write>::write_all (fd.rs:152)
==125831== by 0x4FF5D5: <std::io::Write::write_fmt::Adapter<T> as core::fmt::Write>::write_str (mod.rs:1671)
==125831== by 0x52CFFD: core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:273)
==125831== by 0x525D7D: core::fmt::write (mod.rs:1213)
==125831== by 0x4FE153: <&std::io::stdio::Stderr as std::io::Write>::write_fmt (mod.rs:1682)
==125831== by 0x4FE97A: std::io::stdio::_eprint (stdio.rs:908)
==125831== by 0x196EB1: hring_buffet::io::WriteOwned::writev::{{closure}} (io.rs:46)
==125831== by 0x19664B: hring_buffet::io::WriteOwned::writev_all::{{closure}} (io.rs:96)
==125831== by 0x19ED21: hring::h1::client::request::{{closure}} (client.rs:57)
==125831== by 0x1DB7B4: <hring_bingo_ktls::SDriver as hring::ServerDriver>::handle::{{closure}} (main.rs:234)
==125831== by 0x2AAA9D: hring::h2::server::end_headers::{{closure}} (server.rs:764)
==125831== Address 0x1ffeff3187 is on thread 1's stack
==125831== in frame #3, created by core::fmt::num::imp::<impl core::fmt::Display for u64>::fmt (num.rs:279)
==125831==
2 buffers 👈
Note that a rustc bug wasn't my first guess here, since there's "mmap a large chunk of memory and use unsafe code to divvy it up" and "pass ownership of buffers to the kernel for io_uring" fuckery going on, but I feel reasonably confident I can come up with a MVCE if someone doesn't beat me to the punch.