Fix data abort crash in Mac special files removal (listdir)

The listdir function had three memory corruption bugs causing a
data abort (Err:19) on the Switch:

1. Heap buffer overflow: CpyStr("sd:/") allocated only 5 bytes but
   listdir appends full subdirectory paths in-place via memcpy.
   Fixed by using a 1024-byte stack buffer instead.

2. Use-after-free: _DeleteFileSimple(path) freed the shared traversal
   buffer, but the loop continued using it. Fixed by inlining f_unlink
   without freeing.

3. Recursive free + missing else: free(path) at the end of listdir
   freed the buffer shared across all recursive frames, and a missing
   else caused recursion into directories that were just deleted.
   Removed the free and added an else guard.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-13 21:16:58 +01:00
parent 763cb43983
commit ef9c1eaf7a

View File

@@ -100,11 +100,10 @@ int listdir(char *path, u32 hos_folder, int *deleted_count)
if (!hos_folder && !strcmp(fno.fname, "Nintendo"))
continue;
// // Set new directory or file.
// Set new directory or file.
memcpy(&path[dirLength], "/", 1);
memcpy(&path[dirLength + 1], fno.fname, strlen(fno.fname) + 1);
// gfx_printf("THING: %s\n", fno.fname);
// gfx_printf("Pfad: %s\n", dir);
// Is it a directory?
if (fno.fattrib & AM_DIR)
{
@@ -121,9 +120,10 @@ int listdir(char *path, u32 hos_folder, int *deleted_count)
_FolderDelete(path);
if (deleted_count) (*deleted_count)++;
}
// Enter the directory.
listdir(path, 0, deleted_count);
else {
// Only recurse into directories that were not deleted.
listdir(path, 0, deleted_count);
}
if (res != FR_OK)
break;
} else {
@@ -136,13 +136,14 @@ int listdir(char *path, u32 hos_folder, int *deleted_count)
strcmp(fno.fname, ".TemporaryItems") == 0 ||
_StartsWith(fno.fname, "._")
) {
_DeleteFileSimple(path);
res = f_unlink(path);
if (res)
DrawError(newErrCode(res));
if (deleted_count) (*deleted_count)++;
}
}
}
f_closedir(&dir);
free(path);
return res;
}
@@ -362,7 +363,8 @@ void m_entry_fixMacSpecialFolders(){
gfx_clearscreen();
gfx_printf("\n\n-- Mac-Ordner reparieren (dies kann ein wenig dauern, bitte warten.)\n\n");
int deleted = 0;
char *path = CpyStr("sd:/");
char path[1024];
strcpy(path, "sd:/");
listdir(path, 0, &deleted);
if (deleted > 0)
gfx_printf("\n%d Mac-Datei(en)/Ordner entfernt.\n", deleted);