runloop: fix use-after-free of menu handle across core_run()

runloop_check_state() caches menu_st->driver_data in a local at
function entry. When the menu is alive with menu_pause_libretro
disabled, display_menu_libretro() runs a core frame mid-function;
if retro_run triggers a driver reinit (e.g.
RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO -> CMD_EVENT_REINIT), the menu
handle is freed and recreated, and the subsequent
menu->driver_ctx->set_texture dereference reads freed memory.

Observed as a Play Console SIGSEGV in runloop_check_state on
Android (1.22.2 / 2026-08-26, arm64); faulting instruction confirmed
against BuildId 46031fc2 to be the driver_ctx->set_texture load.

Re-fetch the handle after display_menu_libretro() before touching it.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-08-30 16:01:37 +02:00
1 parent e7d7833af9
commit e03f25c569
1 file changed
+11 -3
+11 -3
View File
@@ -6989,10 +6989,18 @@ static enum runloop_state_enum runloop_check_state(
libretro_running, current_time))
video_driver_cached_frame();
if (menu->driver_ctx->set_texture)
menu->driver_ctx->set_texture(menu->userdata);
/* Core execution inside display_menu_libretro() can trigger
* a driver reinit (e.g. RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO
* -> CMD_EVENT_REINIT), which frees and recreates the menu
* handle - the cached pointer must be re-fetched before it
* is dereferenced again */
if ((menu = menu_st->driver_data))
{
if (menu->driver_ctx && menu->driver_ctx->set_texture)
menu->driver_ctx->set_texture(menu->userdata);
menu->state = 0;
menu->state = 0;
}
}
/* Feed the audio device one frame of silence while the core is