Rust 1.67.0 breaks unit tests
robin-nitrokey opened this issue · comments
---- fs::tests::remove_dir_all stdout ----
generated PathBuf dir p"\0" using i = 0
creating p"\0"
generated PathBuf dir p"/tmp\0" using i = 4
creating p"/tmp\0"
creating p"/tmp/test\0"
thread 'fs::tests::remove_dir_all' panicked at 'already borrowed: BorrowMutError', src/fs.rs:1218:29
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- fs::tests::todo stdout ----
blocks going in: 6
generated PathBuf dir p"\0" using i = 0
creating p"\0"
generated PathBuf dir p"/tmp\0" using i = 4
creating p"/tmp\0"
creating p"/tmp/test\0"
thread 'fs::tests::todo' panicked at 'already borrowed: BorrowMutError', src/fs.rs:1218:29
---- tests::test_create stdout ----
creating p"/tmp\0"
thread 'tests::test_create' panicked at 'already borrowed: BorrowMutError', src/fs.rs:284:69
---- tests::test_fs_with stdout ----
creating p"/tmp\0"
thread 'tests::test_fs_with' panicked at 'already borrowed: BorrowMutError', src/fs.rs:284:69
Very odd. Here's a somewhat minimal failing test:
fn minimal() {
let mut backend = OtherRam::default();
let mut storage = OtherRamStorage::new(&mut backend);
Filesystem::format(&mut storage).unwrap();
Filesystem::mount_and_then(&mut storage, |fs| {
fs.create_dir(b"/tmp\0".try_into().unwrap()).unwrap();
fs.available_blocks().ok();
Ok(())
}).unwrap();
}
Both create_dir
and available_blocks
do a self.alloc.borrow_mut()
, to pass in .state
to ll:lfs_*
. Even explicitly dropping these &mut self.alloc.borrow_mut().state
doesn't fix.
@sosthene-nitrokey suggested that this may be caused by a struct with an undefined representation being used in the FFI causing undefined behavior as this is known to break stuff with 1.67.0.
https://octodon.social/@rust/109759251309886588
https://old.reddit.com/r/rust/comments/10lu5ah/announcing_rust_1670/j5z8rk4/?context=3
But as far as I see, all relevant structs already have #[repr(C)]
. Strangely, using RUSTFLAGS="-Z randomize-layout" cargo +nightly test
seemed to fix the problem though it should potentially make it worse.
I think I found the issue. It looks like this is just the lookahead buffer issue in disguise – the buffer overflow just manifests differently with 1.67.0. Fixed by #24.
Can also manifest as a segfault (e. g. if compiled with --release
):
signal: 11, SIGSEGV: invalid memory reference
Oh, so it's our bug, and not a compiler regression?
Yes, I think so. The layout changes in Rust 1.67.0 probably just cause us to access a different memory region causing a different error.