Bithack / principia

Open source physics-based sandbox game.
https://principia-web.se
Other
260 stars 25 forks source link

Robot Manager targetting an absorbed robot crashes the game on Windows with certain inputs #152

Open MineCake147E opened 5 months ago

MineCake147E commented 5 months ago
Principia version

1.5.2 Beta build 2023-12-26

OS / Hardware
Summary

image

  1. The level is set to the Adventure mode.
  2. There is a Robot Manager.
  3. Aside from the Adventure Robot, there's an additional robot that is controlled by the Robot Manager with its IN16 is somehow activated, while being somehow absorbed.
  4. After the simulation starts playing and the controlled robot is absorbed, the Principia crashes.

Here is a table of Inputs that crash the game when the controlled robot gets absorbed.

Input ID Crashes Description
0 God mode ON/OFF.
1 Speed modifier (0.0-1.0). Only enabled if the cable is plugged in. A value of 0.0 means the robot is unable to walk.
2 Disable action (useful for disabling box mode until certain power up is enabled).
3 Jump strength multiplier.
4 HP increase (heal), value * 10
5 HP decrease (damage), value * 10
6 Max HP increase, value * 10
7 Max HP decrease, value * 10
8 Weapon damage multiplier 0.0 = No extra damage, 1.0 = 5 times the damage.
9 Toggle robot action.
10 Walk left.
11 Walk right.
12 Stop all movement.
13 Jump.
14 Aim.
15 Attack.
16 Attach to nearest backpack/RC
17 Detach from any backpack/RC
18 ✅* Respawn
19 Freeze
20 Toggle roaming (non-adventure robots only).
21 Cycle weapons
22 Cycle factions

❌: The game doesn't crash ✅: The game crashes

* For IN18, the robot under control doesn't fall. There are some additional set of conditions to crash the game. To crash the game, one of these conditions below must be satisfied.

  1. The robot should initially be touching the Absorber.
  2. The IN18 of the Robot Manager should be connected to the OUT0 of the Absorber, so that the Robot Manager lets the robot respawn only after the robot is absorbed.
Steps to reproduce
  1. Create a new Empty Adventure level.
  2. Put the things listed below:
    1. A Robot Manager.
    2. One of any kind of Robot that can be controlled by a Robot Manager.
    3. Some object that absorbs the robot.
    4. A Jumper with the value set to 1.0.
  3. Connect the Jumper to the IN16 of the Robot Manager.
  4. Let the Robot Manager track the Robot.
  5. Play the game.
  6. Observe the Principia crashes.
rollerozxa commented 5 months ago

Can indeed reproduce.

image

Strangely only crashes on Windows, works fine on Linux.

griffi-gh commented 5 months ago

i think this is another use after free...?

rollerozxa commented 5 months ago

Yes, obviously.

griffi-gh commented 2 months ago

seems like the Robot Manager never receives ENTITY_EVENT_REMOVE, even though it's subscribed to it
literally have no idea why this doesn't work, since Lua Script relies on the same event and it does work there... (even if it's actually not handled properly)

griffi-gh commented 2 months ago

seems like subscriptions get reset??? between initialization and actual absorb.
calling subscribe every frame (hack) fixes the issue....??

griffi-gh commented 2 months ago

https://github.com/Bithack/principia/blob/87b00fb5930a03be0bce75fae8e2b6e86eccd0bc/src/src/entity.hh#L839-L845

... interesting...
seems like this is a side effect of the default setup implementation, which clears all listeners and subscriptions
(The robot manager subscribes to the ENTITY_EVENT_REMOVE event in the init "stage", which gets called before setup)

Commenting out the following lines in the setup implementation "fixes" the issue:

// this->listeners.clear();
// this->subscriptions.clear();

image

But I'm pretty sure this has some unintended side effects...

By the way, saving and reloading the state before the robot is absorbed causes the game to not crash, since setup is not called if the level is reloaded from a state buffer:

https://github.com/Bithack/principia/blob/87b00fb5930a03be0bce75fae8e2b6e86eccd0bc/src/src/entity.cc#L560-L578