Hello, we have noticed a soundness/memory safety issue in this crate which allows safe Rust code to trigger undefined behavior while scanning crates.io.
unsafe impl<T: ?Sized + Send, U: ?Sized> Send for MappedMutexGuard<'_, T, U> {} unsafe impl<T: ?Sized + Sync, U: ?Sized> Sync for MappedMutexGuard<'_, T, U> {} DescriptionSend/Sync implementation for MappedMutexGuard only considers variance on T, while MappedMutexGuard dereferences to U.
This can lead to data race in safe Rust code when a closure used in MutexGuard::map()
returns U that is unrelated to T.
#![forbid(unsafe_code)] use crossbeam_utils::thread; use futures::lock::{Mutex, MutexGuard}; use std::ops::Deref; use std::rc::Rc; const NUM_CLONES: usize = 1000000; fn main() { let mutex = Mutex::new(true); let mutex_guard = futures::executor::block_on(mutex.lock()); // T: bool, U: Rc<bool> // MappedMutexGuard is Send+Sync and Deref to U, due to: // unsafe impl<T: ?Sized + Send, U: ?Sized> Send for MappedMutexGuard<'_, T, U> {} // unsafe impl<T: ?Sized + Sync, U: ?Sized> Sync for MappedMutexGuard<'_, T, U> {} let mapped_mutex_guard = MutexGuard::map(mutex_guard, |_| Box::leak(Box::new(Rc::new(true)))); // We demonstrate the issue by racing the non-atomic reference counter type `Rc` between two threads. thread::scope(|s| { let child = s.spawn(|_| { // &Rc<bool> sent to another thread let rc_ref = mapped_mutex_guard.deref(); for _ in 0..NUM_CLONES { std::mem::forget(rc_ref.clone()); } }); // if `child.join().unwrap()` is here, the program succeeds let rc_ref = mapped_mutex_guard.deref(); for _ in 0..NUM_CLONES { std::mem::forget(rc_ref.clone()); } child.join().unwrap(); // We made NUM_CLONES on both threads plus initial 1 reference. // But in reality we'll see that the strong_count varies across every run due to data race. assert_eq!(Rc::strong_count(rc_ref), 2 * NUM_CLONES + 1); }) .unwrap(); }
Output:
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `1240979`,
right: `2000001`', src/main.rs:64:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Return Code: 101
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4