-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Hello fellow Rustacean,
we (Rust group @sslab-gatech) are scanning Rust code on crates.io for potential memory safety and soundness bugs and found an issue in this crate which allows safe Rust code to exhibit an undefined behavior.
Issue Description
Lines 48 to 49 in 966b949
unsafe impl<T> Send for RingBuffer<T> {} | |
unsafe impl<T> Sync for RingBuffer<T> {} |
RingBuffer
implements Send/Sync regardless of whether the internal type implements Send/Sync. This allows users to send a non-Send type across threads with RingBuffer
.
RingBuffer
's Send/Sync should probably have a trait bound on the internal type T
, or if RingBuffer
needs to implement Send/Sync and it is not meant to be created by the end user, new()
should be hidden with pub(crate)
or so.
Reproduction
Below is an example program that sends Non-Send type across threads using safe APIs of disrustor
.
Show Detail
This example just shows that non-Send type is sent across the thread, but it is possible to demonstrate a data race with a more complicated example.
#![forbid(unsafe_code)]
#[macro_use]
extern crate static_assertions;
use disrustor::internal::RingBuffer;
use std::marker::PhantomData;
use std::thread;
struct NonSend {
created_thread: thread::ThreadId,
// Mark this struct as `NonSend`
_marker: PhantomData<*mut ()>,
}
assert_not_impl_all!(NonSend: Send);
impl Default for NonSend {
fn default() -> Self {
NonSend {
created_thread: thread::current().id(),
_marker: PhantomData,
}
}
}
impl Drop for NonSend {
fn drop(&mut self) {
if thread::current().id() != self.created_thread {
panic!("NonSend destructor is running on a wrong thread!");
}
}
}
fn main() {
let buffer = RingBuffer::<NonSend>::new(1);
let handle = thread::spawn(move || {
drop(buffer);
});
handle.join().unwrap();
}
Output:
thread '<unnamed>' panicked at 'NonSend destructor is running on a wrong thread!', src/main.rs:47:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Any', src/main.rs:59:19
Return code 101
Tested Environment
- Crate: disrustor
- Version: 0.2.0
- OS: Ubuntu 20.04.1 LTS
- Rustc version: rustc 1.48.0 (7eac88abb 2020-11-16)
- 3rd party dependencies:
static_assertions = { version = "1.1.0" }