Skip to content

Inserting components is not panic-safe #20368

@SkiFire13

Description

@SkiFire13

Bevy version

f96eaa4 and 0.16

What you did

use bevy_ecs::prelude::*;

#[derive(Component)]
struct A(&'static u8);

fn panics() -> A {
    // Just to avoid printing the panic message, but any panic!() works 
    std::panic::resume_unwind(Box::new(()));
}

#[derive(Component)]
#[require(A = panics())]
struct B;

let mut world = World::new();

let mut e = world.spawn_empty();

std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    e.insert(B);
}));

// The EntityWorldMut thinks it's still at the old location
assert!(!e.contains::<A>());

let id = e.id();
let e = world.entity_mut(id);

// But after refetching the location it thinks it's at the new location, but A is not initialized.
println!("{}", e.get::<A>().unwrap().0);

What went wrong

The program segfaulted when trying to read from the reference in the A component that did not get initialized.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-BugAn unexpected or incorrect behaviorD-UnsafeTouches with unsafe code in some wayP-UnsoundA bug that results in undefined compiler behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions