bevyengine / bevyengine/bevy

`Observer`s' system state can become invalid while they're running

Open
#20,736 1 comment 0 reactions 0 assignees View on GitHub
A-ECS C-Bug D-Unsafe I-Unsound
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version and features

69745d40 but also likely 0.16.1

## What you did

```rs
use bevy_ecs::{entity_disabling::Internal, prelude::*};

fn main() {
#[derive(EntityEvent)]
struct Ev;

fn bad_observer(_: On, q: Query<&mut Observer, With>, mut state: Local) {
*state = String::from("foobar12345");

for mut o in q {
*o = Observer::new(|_: On| {});
}

println!("{}", &*state);
}

let mut world = World::new();

world.add_observer(bad_observer);
world.trigger(Insert);
}

```

## What went wrong

The system causes undefied behaviour due to a use-after-free.

This safety comment is incorrect:

https://github.com/bevyengine/bevy/blob/69745d40e594fb34a99507e2f0be2385711e46a6/crates/bevy_ecs/src/observer/runner.rs#L53

Observers get mutable access to every entity/component, including their own state, so they can indeed drop their own state before the system has finished running.

I think it's fundamentally unsound to store the state of a running observer on a component that could be mutated while that is running.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.