World implements Send without bounds on EntityStore and ComponentStore
Hi there, we (Rust group @sslab-gatech) are scanning crates on crates.io for potential soundness bugs. We noticed that World
implements Send
without any bounds on the EntityStore
and ComponentStore
.
https://gitlab.redox-os.org/redox-os/dces-rust/-/blob/develop/src/world.rs#L37-42
unsafe impl<E, C, Ctx> Send for World<E, C, Ctx>
where
E: EntityStore,
C: ComponentStore
{
}
We think this should be EntityStore + Send
and ComponentStore + Send
, otherwise it's possible to send non-Send types across thread boundaries as part of the world. Here's an example with an EntityStore
that uses an Rc
causing a segfault from safe rust code:
#![forbid(unsafe_code)]
use dces::prelude::*;
use dces::entity::EntityStore;
use std::rc::Rc;
struct MyEntityStore {
entity_store_rc: Rc<i32>
}
impl EntityStore for MyEntityStore {
fn register_entity(&mut self, entity: impl Into<Entity>) {
println!("Thread: {:p}", self.entity_store_rc);
// Races with the Rc in the main thread.
for _ in 0..100_000_000 {
self.entity_store_rc.clone();
}
}
fn remove_entity(&mut self, entity: impl Into<Entity>) { }
}
fn main() {
let rc = Rc::new(42);
let entity_store = MyEntityStore { entity_store_rc: rc.clone() };
let mut world = World::from_stores(entity_store, ComponentStore::default());
std::thread::spawn(move || {
world.create_entity().build();
});
println!("Main: {:p}", rc);
for _ in 0..100_000_000 {
rc.clone();
}
}
Output:
Main: 0x562f05d16b50
Thread: 0x562f05d16b50
Terminated with signal 4 (SIGILL)