Skip to content

ComponentsQueuedRegistrator::queue_register_component does not ensure components are registered only once #20014

Open
@SkiFire13

Description

@SkiFire13

Bevy version

0.16.1

What you did

#[derive(Component)]
struct A;

loop {
    let w = World::new();

    std::thread::scope(|s| {
        let c1 = s.spawn(|| w.components_queue().queue_register_component::<A>());
        let c2 = s.spawn(|| w.components_queue().queue_register_component::<A>());

        let (c1, c2) = (c1.join().unwrap(), c2.join().unwrap());
        assert_eq!(c1, c2);
    });
}

What went wrong

After some iterations the assert_eq fails.

Additional information

The issue is a TOCTOU bug in queue_register_component: it first acquires and releases a read lock to check if the component is registered, then forces a registration of the component if it wasn't already registered. However this ignored the possibility of another thread registering the component inbetween the check and the new registration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-BugAn unexpected or incorrect behaviorD-Domain-AgnosticCan be tackled by anyone with generic programming or Rust skillsD-ModestA "normal" level of difficulty; suitable for simple features or challenging fixesS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions