-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Description
What problem does this solve or what need does it fill?
There is an unsound interaction between EntityRef::get_components
#13375 and declaring resource access from queries #16843 where safe code can get read access to a resource without checking for conflicts. If a QueryData
requests read access to a resource, then a system like
fn system(query: Query<EntityRef>, res: ResMut<SomeResource>) {
query.single().get_components::<QueryDataUsingSomeResource>();
}
will create a &SomeResource
during get_components()
at the same time as the &mut SomeResource
from ResMut
, resulting in UB.
The bad SAFETY
comment is in EntityRef::get_components
:
bevy/crates/bevy_ecs/src/world/entity_ref.rs
Line 294 in 6bb0473
// - We have read-only access to all components of this entity. |
While we do have access to all components, the query may also require resource access that
EntityRef
does not have.
What solution would you like?
Create a new unsafe trait
for a WorldQuery
that does no resource access, and bound the get_components
methods by that trait.
Additional context
This is difficult to actually trigger at the moment, so may not be urgent to fix. It requires a custom QueryData
impl, as the only in-engine use of a WorldQuery
requesting resource access is AssetChanged<A>
, a QueryFilter
.
If we start expanding the cases where queries access data outside of the current entity, particularly for relations, then this may become more important.