Commit 3741954
committed
task_save_handler and task_load_handler run on the threaded task
worker. Their handlers call into core function pointers:
content_get_serialized_data invokes core->retro_serialize, and
task_load_handler invokes core_unserialize which calls
core->retro_unserialize.
CMD_EVENT_CORE_DEINIT runs runloop_event_deinit_core which calls
uninit_libretro_symbols, which calls dylib_close. If a save/load
state task is still running on the worker when the dylib closes,
the worker's next call into the core dispatches through a freed
function pointer.
The existing wait at retroarch.c:4379 only fires when
settings->bools.savestate_auto_save is enabled, and only covers
the auto-state save kicked off three lines earlier. It does not
cover a manually-triggered save state (menu, hotkey, netplay
request) that was already in flight when the user closed content
with savestate_auto_save disabled. It also does not cover load
state tasks at all.
Add unconditional waits for both save and load state tasks before
runloop_event_deinit_core runs. task_queue_wait is a no-op when
no matching task is in flight, so this is cheap on the common
path. When a task is in flight, we let it finish - canceling
mid-write would risk a truncated state file, which is worse than
the brief delay during content close.
Closes a real worker-thread / dylib_close UAF that triggers any
time the user manually saves a state and closes content before
the write completes.1 parent 3eedad0 commit 3741954
1 file changed
Lines changed: 17 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4379 | 4379 | | |
4380 | 4380 | | |
4381 | 4381 | | |
| 4382 | + | |
| 4383 | + | |
| 4384 | + | |
| 4385 | + | |
| 4386 | + | |
| 4387 | + | |
| 4388 | + | |
| 4389 | + | |
| 4390 | + | |
| 4391 | + | |
| 4392 | + | |
| 4393 | + | |
| 4394 | + | |
| 4395 | + | |
| 4396 | + | |
| 4397 | + | |
| 4398 | + | |
4382 | 4399 | | |
4383 | 4400 | | |
4384 | 4401 | | |
| |||
0 commit comments