From ba284f5ca04436559a4f7bbab9181229cac6de2c Mon Sep 17 00:00:00 2001 From: Nikita Borodikhin Date: Sat, 9 May 2026 16:14:48 -0500 Subject: [PATCH 1/3] fix: stack corruption on cheat loading --- workspace/all/minarch/minarch.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index ef7225333..f1c4dbc82 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -604,11 +604,16 @@ static int parse_cheats(struct Cheats *cheats, FILE *file) { } // return variations with/without extensions and other cruft -#define CHEAT_MAX_PATHS 16 +// note: CHEAT_MAX_PATHS must be large enough to contain one entry per extension supported by a core, plus ~5 more +// 48 is enough: retroarch cores with most extensions at the moment is VICE VIC-20 at 37 and rom-cleaner at 42 +#define CHEAT_MAX_PATHS 48 #define CHEAT_MAX_DISPLAY_PATHS 8 // the list of displayed paths will be a bit shorter, we cant render that much text #define CHEAT_MAX_LIST_LENGTH (CHEAT_MAX_DISPLAY_PATHS * MAX_PATH) static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { + // reserve a few entries at the end, for sanitized name and glob patterns + const int sanitized_paths_count = 3 + // Generate possible paths, ordered by most likely to be used (pre v6.2.3 style first) sprintf(paths[(*count)++], "%s/%s.cht", core.cheats_dir, game.name); // /mnt/SDCARD/Cheats/GB/Super Example World..cht if(CFG_getUseExtractedFileName()) @@ -627,7 +632,8 @@ static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { strcpy(exts, core.extensions); while ((ext = strtok(i ? NULL : exts, "|"))) { - if (*count >= CHEAT_MAX_PATHS - 1) { + // sanitized_paths_count slots are reserved for sanitized rom name, see below + if (*count >= CHEAT_MAX_PATHS - sanitized_paths_count) { LOG_info("Maximum cheat paths reached, stopping\n"); break; } @@ -660,6 +666,7 @@ static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { // eg. Super Example World (USA).zip -> Super Example World // Super Example World (USA) [!].7z -> Super Example World // Super Example World (USA) (Rev 1).rar -> Super Example World + // Important: update `sanitized_paths_count` if adding more sanitized variations char rom_name[MAX_PATH]; getDisplayName(game.alt_name, rom_name); sprintf(paths[(*count)++], "%s/%s.cht", core.cheats_dir, rom_name); // /mnt/SDCARD/Cheats/GB/Super Example World.cht @@ -670,18 +677,20 @@ static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { // Santitized alias, ignoring all extra cruft - including Cheat specifics like "(Game Breaker)" etc. // This is a wildcard that may match something unexpected, but also may find something when nothing else does. - getDisplayName(game.alt_name, rom_name); getAlias(game.path, rom_name); sprintf(paths[(*count)++], "%s/%s*.cht", core.cheats_dir, rom_name); // /mnt/SDCARD/Cheats/GB/Super Example World*.cht // Log all path candidates { - int i; - char list[CHEAT_MAX_LIST_LENGTH] = {0}; - for (i=0; i<*count; i++) { - strcat(list, paths[i]); - if (i < *count-1) strcat(list, ", "); + char *list = calloc(*count * (MAX_PATH + 2) + 1, 1); // path + separator for each entry + if (list != NULL) { + int i; + for (i=0; i<*count; i++) { + strcat(list, paths[i]); + if (i < *count-1) strcat(list, ", "); + } + LOG_info("Cheat paths to check: %s\n", list); + free(list); } - LOG_info("Cheat paths to check: %s\n", list); } } @@ -6845,8 +6854,8 @@ static int OptionCheats_openMenu(MenuList* list, int i) { else { // update for (int j = 0; j < cheatcodes.count; j++) { - struct Cheat *cheat = &cheatcodes.cheats[i]; - MenuItem *item = &OptionCheats_menu.items[i]; + struct Cheat *cheat = &cheatcodes.cheats[j]; + MenuItem *item = &OptionCheats_menu.items[j]; // I guess that makes sense, nobody is changing these but us - what about state restore? if(!cheat->enabled) continue; From b1d684c1ac514731b10533650c5f8ebb15704f37 Mon Sep 17 00:00:00 2001 From: Nikita Borodikhin Date: Sat, 9 May 2026 17:06:08 -0500 Subject: [PATCH 2/3] fix: missing semicolon in Cheat_getPaths --- workspace/all/minarch/minarch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index f1c4dbc82..a29ab597b 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -612,7 +612,7 @@ static int parse_cheats(struct Cheats *cheats, FILE *file) { #define CHEAT_MAX_LIST_LENGTH (CHEAT_MAX_DISPLAY_PATHS * MAX_PATH) static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { // reserve a few entries at the end, for sanitized name and glob patterns - const int sanitized_paths_count = 3 + const int sanitized_paths_count = 3; // Generate possible paths, ordered by most likely to be used (pre v6.2.3 style first) sprintf(paths[(*count)++], "%s/%s.cht", core.cheats_dir, game.name); // /mnt/SDCARD/Cheats/GB/Super Example World..cht From 1d8a592a75cf3612f845e9448ee1d51dcb268566 Mon Sep 17 00:00:00 2001 From: frysee Date: Wed, 13 May 2026 00:46:15 +0200 Subject: [PATCH 3/3] Apply suggestion from @frysee --- workspace/all/minarch/minarch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workspace/all/minarch/minarch.c b/workspace/all/minarch/minarch.c index a29ab597b..1a664f249 100644 --- a/workspace/all/minarch/minarch.c +++ b/workspace/all/minarch/minarch.c @@ -688,7 +688,7 @@ static void Cheat_getPaths(char paths[CHEAT_MAX_PATHS][MAX_PATH], int* count) { strcat(list, paths[i]); if (i < *count-1) strcat(list, ", "); } - LOG_info("Cheat paths to check: %s\n", list); + //LOG_info("Cheat paths to check: %s\n", list); free(list); } }