1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-26 04:02:11 +00:00

Title handler bugfixes.

* Fixed possible invalid memory accesses using TitleInfo pointers from gamecard titles if the gamecard they belong to is taken out.
* Fixed invalid for loop condition in _titleGetInfoFromStorageByTitleId() if no gamecard titles have been retrieved.
This commit is contained in:
Pablo Curiel 2020-10-27 17:23:19 -04:00
parent 14ee45b38a
commit 278afbabfa
4 changed files with 63 additions and 56 deletions

View file

@ -751,26 +751,6 @@ int main(int argc, char *argv[])
{
consoleClear();
if (menu == 2 && titleIsGameCardInfoUpdated())
{
free(app_metadata);
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
if (!app_metadata)
{
consolePrint("\napp metadata failed\n");
goto out2;
}
menu = selected_idx = scroll = 0;
title_idx = title_scroll = 0;
type_idx = type_scroll = 0;
list_count = list_idx = 0;
continue;
}
printf("press b to %s.\n", menu == 0 ? "exit" : "go back");
printf("______________________________\n\n");

View file

@ -796,26 +796,6 @@ int main(int argc, char *argv[])
{
consoleClear();
if (menu == 2 && titleIsGameCardInfoUpdated())
{
free(app_metadata);
app_metadata = titleGetApplicationMetadataEntries(false, &app_count);
if (!app_metadata)
{
consolePrint("\napp metadata failed\n");
goto out2;
}
menu = selected_idx = scroll = 0;
title_idx = title_scroll = 0;
type_idx = type_scroll = 0;
list_count = list_idx = 0;
continue;
}
printf("press b to %s.\n", menu == 0 ? "exit" : "go back");
printf("______________________________\n\n");

View file

@ -35,7 +35,8 @@ typedef struct {
static Mutex g_titleMutex = 0;
static Thread g_titleGameCardInfoThread = {0};
static UEvent g_titleGameCardInfoThreadExitEvent = {0}, *g_titleGameCardStatusChangeUserEvent = NULL;
static UEvent g_titleGameCardInfoThreadExitEvent = {0}, *g_titleGameCardStatusChangeUserEvent = NULL, g_titleGameCardUpdateInfoUserEvent = {0};
static CondVar g_gameCardCondVar = 0;
static bool g_titleInterfaceInit = false, g_titleGameCardInfoThreadCreated = false, g_titleGameCardAvailable = false, g_titleGameCardInfoUpdated = false;
@ -477,6 +478,9 @@ bool titleInitialize(void)
goto end;
}
/* Create usermode gamecard update info event. */
ueventCreate(&g_titleGameCardUpdateInfoUserEvent, true);
/* Create gamecard title info thread. */
if (!(g_titleGameCardInfoThreadCreated = titleCreateGameCardInfoThread())) goto end;
@ -728,8 +732,22 @@ end:
bool titleIsGameCardInfoUpdated(void)
{
mutexLock(&g_titleMutex);
/* Check if the gamecard thread detected a gamecard status change. */
bool ret = g_titleGameCardInfoUpdated;
if (ret) g_titleGameCardInfoUpdated = false; /* Update flag to avoid updating application metadata entries in the caller function if it's not needed. */
if (!ret) goto end;
/* Signal the gamecard update info user event. */
ueventSignal(&g_titleGameCardUpdateInfoUserEvent);
/* Wait for the gamecard thread to wakes us up. */
condvarWait(&g_gameCardCondVar, &g_titleMutex);
/* Update output value and gamecard info updated flag (if needed). */
ret = g_titleGameCardInfoUpdated;
if (ret) g_titleGameCardInfoUpdated = false;
end:
mutexUnlock(&g_titleMutex);
return ret;
}
@ -1258,8 +1276,6 @@ static bool titleLoadPersistentStorageTitleInfo(void)
/* Return right away if title info has already been retrieved. */
if (g_titleInfo || g_titleInfoCount) return true;
g_titleInfoCount = 0;
for(u8 i = NcmStorageId_BuiltInSystem; i <= NcmStorageId_SdCard; i++)
{
/* Retrieve content meta keys from the current storage. */
@ -1397,6 +1413,11 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id)
/* Update title info count. */
g_titleInfoCount += total;
/* Update success flag. Nothing past this point will generate errors. */
/* Also jump to the end of this function if we're dealing with eMMC System titles. */
success = true;
if (storage_id == NcmStorageId_BuiltInSystem) goto end;
/* Update linked lists pointers for user applications, patches and add-on contents. */
g_titleInfoOrphanCount = 0;
for(u32 i = 0; i < g_titleInfoCount; i++)
@ -1449,8 +1470,6 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id)
}
}
success = true;
end:
if (meta_keys) free(meta_keys);
@ -1559,14 +1578,11 @@ static void titleGameCardInfoThreadFunc(void *arg)
Result rc = 0;
int idx = 0;
bool first_run = true;
Waiter gamecard_status_event_waiter = waiterForUEvent(g_titleGameCardStatusChangeUserEvent);
Waiter exit_event_waiter = waiterForUEvent(&g_titleGameCardInfoThreadExitEvent);
/* Initial gamecard title info retrieval. */
mutexLock(&g_titleMutex);
titleRefreshGameCardTitleInfo();
mutexUnlock(&g_titleMutex);
Waiter update_info_waiter = waiterForUEvent(&g_titleGameCardUpdateInfoUserEvent);
while(true)
{
@ -1577,10 +1593,40 @@ static void titleGameCardInfoThreadFunc(void *arg)
/* Exit event triggered. */
if (idx == 1) break;
if (!first_run)
{
/* Update gamecard info updated flag. */
mutexLock(&g_titleMutex);
g_titleGameCardInfoUpdated = true;
mutexUnlock(&g_titleMutex);
/* Wait until another function signals us (titleIsGameCardInfoUpdated() or titleExit()). */
rc = waitMulti(&idx, -1, update_info_waiter, exit_event_waiter);
if (R_FAILED(rc))
{
mutexLock(&g_titleMutex);
g_titleGameCardInfoUpdated = false;
mutexUnlock(&g_titleMutex);
continue;
}
/* Exit event triggered. */
if (idx == 1) break;
}
/* Update gamecard title info. */
mutexLock(&g_titleMutex);
g_titleGameCardInfoUpdated = titleRefreshGameCardTitleInfo();
g_titleGameCardInfoUpdated = (titleRefreshGameCardTitleInfo() && !first_run);
mutexUnlock(&g_titleMutex);
if (first_run)
{
/* Disable first run flag. */
first_run = false;
} else {
/* Wake up titleIsGameCardInfoUpdated(). */
condvarWakeAll(&g_gameCardCondVar);
}
}
/* Update gamecard flags. */
@ -1791,7 +1837,7 @@ static TitleInfo *_titleGetInfoFromStorageByTitleId(u8 storage_id, u64 title_id,
/* Speed up gamecard lookups. */
u32 start_idx = (storage_id == NcmStorageId_GameCard ? g_titleInfoGameCardStartIndex : 0);
u32 max_val = ((storage_id == NcmStorageId_GameCard || storage_id == NcmStorageId_Any) ? g_titleInfoCount : g_titleInfoGameCardStartIndex);
u32 max_val = ((storage_id == NcmStorageId_GameCard || storage_id == NcmStorageId_Any) ? g_titleInfoCount : (g_titleInfoGameCardCount ? g_titleInfoGameCardStartIndex : g_titleInfoCount));
for(u32 i = start_idx; i < max_val; i++)
{
@ -1804,7 +1850,7 @@ static TitleInfo *_titleGetInfoFromStorageByTitleId(u8 storage_id, u64 title_id,
}
}
//if (!info) LOGFILE("Unable to find TitleInfo entry with ID \"%016lX\"! (storage ID %u).", title_id, storage_id);
if (!info && lock) LOGFILE("Unable to find TitleInfo entry with ID \"%016lX\"! (storage ID %u).", title_id, storage_id);
end:
if (lock) mutexUnlock(&g_titleMutex);

View file

@ -108,8 +108,9 @@ bool titleAreOrphanTitlesAvailable(void);
/// Returns NULL if an error occurs.
TitleInfo **titleGetInfoFromOrphanTitles(u32 *out_count);
/// Returns true if the gamecard title info entries have been updated (e.g. after a new gamecard has been inserted, of after the current one has been taken out).
/// If titleGetApplicationMetadataEntries() has been previously called, its returned buffer should be freed and a new titleGetApplicationMetadataEntries() call should be issued.
/// Checks if a gamecard status update has been detected by the background gamecard title info thread (e.g. after a new gamecard has been inserted, of after the current one has been taken out).
/// If so, gamecard title info entries will be updated or freed during this call, depending on the current gamecard status.
/// If this function returns true and titleGetApplicationMetadataEntries() has been previously called, its returned buffer should be freed and titleGetApplicationMetadataEntries() should be called again.
bool titleIsGameCardInfoUpdated(void);
/// Returns a pointer to a dynamically allocated buffer that holds a filename string suitable for output title dumps.