From 98c4ab0c18319123dded12672308d3754ef26269 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 10 Jan 2023 17:25:45 +0000 Subject: [PATCH] Ensure `Query` does not use the wrong `World` (#7150) `Query` relies on the `World` it stores being the same as the world used for creating the `QueryState` it stores. If they are not the same then everything is very unsound. This was not actually being checked anywhere, `Query::new` did not have a safety invariant or even an assertion that the `WorldId`'s are the same. This shouldn't have any user facing impact unless we have really messed up in bevy and have unsoundness elsewhere (in which case we would now get a panic instead of being unsound). --- crates/bevy_ecs/src/system/mod.rs | 11 +++++++++++ crates/bevy_ecs/src/system/query.rs | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index be66144b4a6a8..300752dc31e7b 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -1202,4 +1202,15 @@ mod tests { ); }); } + + #[test] + #[should_panic = "Attempted to use bevy_ecs::query::state::QueryState<()> with a mismatched World."] + fn query_validates_world_id() { + let mut world1 = World::new(); + let world2 = World::new(); + let qstate = world1.query::<()>(); + // SAFETY: doesnt access anything + let query = unsafe { Query::new(&world2, &qstate, 0, 0) }; + query.iter(); + } } diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 8f7e4f70bc303..c376223b4eff8 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -295,6 +295,10 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for Query<'w, impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> { /// Creates a new query. /// + /// # Panics + /// + /// This will panic if the world used to create `state` is not `world`. + /// /// # Safety /// /// This will create a query that could violate memory safety rules. Make sure that this is only @@ -306,6 +310,8 @@ impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> { last_change_tick: u32, change_tick: u32, ) -> Self { + state.validate_world(world); + Self { force_read_only_component_access: false, world,