From ad219e9b011c454638a26dce4571a82330e68ec8 Mon Sep 17 00:00:00 2001 From: Mick Afaneh Date: Wed, 28 Oct 2026 23:19:15 -0400 Subject: [PATCH] fix(minarch): core extension list overflow and NULL crash Core_open() copies the core's valid_extensions into a 128-byte buffer with strcpy(). The VICE cores report 128 to 142 characters, so the copy overflows and leaves the list unterminated. On an RG28XX, the cheat lookup for a C64 game.zip then tries "game.tcrtgame.cht" instead of "game.tcrt.cht". Some cores that run without content, such as 2048, leave the list NULL, which segfaults. Copy with a bound, treat NULL as an empty list, and raise the buffer to 256 bytes so the VICE lists fit. The two local copies are sized to match. Tested on an RG28XX with the v6.15.0 runtime and on the desktop build. Co-Authored-By: Claude Opus 5.5 --- workspace/all/minarch/ma_cheats.c | 2 +- workspace/all/minarch/ma_core.c | 2 +- workspace/all/minarch/ma_game.c | 2 +- workspace/all/minarch/ma_internal.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/workspace/all/minarch/ma_cheats.c b/workspace/all/minarch/ma_cheats.c index b80cac6be..6262bc11a 100644 --- a/workspace/all/minarch/ma_cheats.c +++ b/workspace/all/minarch/ma_cheats.c @@ -221,7 +221,7 @@ void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { { int i = 0; char* ext; - char exts[128]; + char exts[sizeof(core.extensions)]; if (core.extensions == NULL || strlen(core.extensions) >= sizeof(exts)) { LOG_info("Invalid or too long core.extensions\n"); return; diff --git a/workspace/all/minarch/ma_core.c b/workspace/all/minarch/ma_core.c index e47b6dae7..4f15bc1c5 100644 --- a/workspace/all/minarch/ma_core.c +++ b/workspace/all/minarch/ma_core.c @@ -64,7 +64,7 @@ void Core_open(const char* core_path, const char* tag_name) { Core_getName((char*)core_path, (char*)core.name); sprintf((char*)core.version, "%s (%s)", info.library_name, info.library_version); strcpy((char*)core.tag, tag_name); - strcpy((char*)core.extensions, info.valid_extensions); + snprintf((char*)core.extensions, sizeof(core.extensions), "%s", info.valid_extensions ? info.valid_extensions : ""); core.need_fullpath = info.need_fullpath; diff --git a/workspace/all/minarch/ma_game.c b/workspace/all/minarch/ma_game.c index d971c388f..d811a1139 100644 --- a/workspace/all/minarch/ma_game.c +++ b/workspace/all/minarch/ma_game.c @@ -49,7 +49,7 @@ void Game_open(char* path) { int supports_zip = 0; int i = 0; char* ext; - char exts[128]; + char exts[sizeof(core.extensions)]; char* extensions[32]; strcpy(exts,core.extensions); while ((ext=strtok(i?NULL:exts,"|"))) { diff --git a/workspace/all/minarch/ma_internal.h b/workspace/all/minarch/ma_internal.h index b2967769d..137532ba2 100644 --- a/workspace/all/minarch/ma_internal.h +++ b/workspace/all/minarch/ma_internal.h @@ -20,7 +20,7 @@ struct Core { const char tag[8]; // eg. GBC const char name[128]; // eg. gambatte const char version[128]; // eg. Gambatte (v0.5.0-netlink 7e02df6) - const char extensions[128]; // eg. gb|gbc|dmg + const char extensions[256]; // eg. gb|gbc|dmg const char config_dir[MAX_PATH]; // eg. /mnt/sdcard/.userdata/h700/GB-gambatte const char states_dir[MAX_PATH]; // eg. /mnt/sdcard/.userdata/arm-480/GB-gambatte