From adbd41dabf93abdea30a072127c6b4e5496e7f3c Mon Sep 17 00:00:00 2001 From: Steveice10 Date: Fri, 30 Dec 2016 18:54:07 -0800 Subject: [PATCH] Make copy of target item to prevent use-after-free issues. --- source/ui/section/action/deletecontents.c | 38 +++++++++++++---------- source/ui/section/action/installcias.c | 16 ++++++++-- source/ui/section/action/installtickets.c | 16 ++++++++-- source/ui/section/action/pastecontents.c | 18 +++++++++-- 4 files changed, 64 insertions(+), 24 deletions(-) diff --git a/source/ui/section/action/deletecontents.c b/source/ui/section/action/deletecontents.c index 6bd3d7a..b4f4b8a 100644 --- a/source/ui/section/action/deletecontents.c +++ b/source/ui/section/action/deletecontents.c @@ -17,9 +17,9 @@ typedef struct { linked_list* items; + + list_item* targetItem; file_info* target; - FS_Archive archive; - char path[FILE_PATH_MAX]; linked_list contents; @@ -32,7 +32,7 @@ static void action_delete_draw_top(ui_view* view, void* data, float x1, float y1 u32 curr = deleteData->deleteInfo.processed; if(curr < deleteData->deleteInfo.total) { ui_draw_file_info(view, ((list_item*) linked_list_get(&deleteData->contents, linked_list_size(&deleteData->contents) - curr - 1))->data, x1, y1, x2, y2); - } else if(deleteData->target != NULL) { + } else { ui_draw_file_info(view, deleteData->target, x1, y1, x2, y2); } } @@ -46,10 +46,10 @@ static Result action_delete_delete(void* data, u32 index) { FS_Path* fsPath = util_make_path_utf8(info->path); if(fsPath != NULL) { - if(util_is_dir(deleteData->archive, info->path)) { - res = FSUSER_DeleteDirectory(deleteData->archive, *fsPath); + if(util_is_dir(deleteData->target->archive, info->path)) { + res = FSUSER_DeleteDirectory(deleteData->target->archive, *fsPath); } else { - res = FSUSER_DeleteFile(deleteData->archive, *fsPath); + res = FSUSER_DeleteFile(deleteData->target->archive, *fsPath); } util_free_path_utf8(fsPath); @@ -66,10 +66,6 @@ static Result action_delete_delete(void* data, u32 index) { file_info* currInfo = (file_info*) item->data; if(strncmp(currInfo->path, info->path, FILE_PATH_MAX) == 0) { - if(currInfo == deleteData->target) { - deleteData->target = NULL; - } - linked_list_iter_remove(&iter); task_free_file(item); } @@ -106,6 +102,13 @@ static bool action_delete_error(void* data, u32 index, Result res) { static void action_delete_free_data(delete_data* data) { task_clear_files(&data->contents); linked_list_destroy(&data->contents); + + if(data->targetItem != NULL) { + task_free_file(data->targetItem); + data->targetItem = NULL; + data->target = NULL; + } + free(data); } @@ -113,7 +116,7 @@ static void action_delete_update(ui_view* view, void* data, float* progress, cha delete_data* deleteData = (delete_data*) data; if(deleteData->deleteInfo.finished) { - FSUSER_ControlArchive(deleteData->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); + FSUSER_ControlArchive(deleteData->target->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); ui_pop(); info_destroy(view); @@ -143,7 +146,7 @@ static void action_delete_onresponse(ui_view* view, void* data, bool response) { if(R_SUCCEEDED(res)) { info_display("Deleting", "Press B to cancel.", true, data, action_delete_update, action_delete_draw_top); } else { - error_display_res(deleteData->target, deleteData->target != NULL ? ui_draw_file_info : NULL, res, "Failed to initiate delete operation."); + error_display_res(NULL, NULL, res, "Failed to initiate delete operation."); action_delete_free_data(deleteData); } @@ -202,9 +205,10 @@ static void action_delete_internal(linked_list* items, list_item* selected, cons } data->items = items; - data->target = (file_info*) selected->data; - data->archive = data->target->archive; - strncpy(data->path, data->target->path, FILE_PATH_MAX); + + file_info* targetInfo = (file_info*) selected->data; + task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes); + data->target = (file_info*) data->targetItem->data; data->deleteInfo.data = data; @@ -233,8 +237,8 @@ static void action_delete_internal(linked_list* items, list_item* selected, cons loadingData->message = message; loadingData->popData.items = &data->contents; - loadingData->popData.archive = data->archive; - strncpy(loadingData->popData.path, data->path, FILE_PATH_MAX); + loadingData->popData.archive = data->target->archive; + strncpy(loadingData->popData.path, data->target->path, FILE_PATH_MAX); loadingData->popData.recursive = recursive; loadingData->popData.includeBase = includeBase; loadingData->popData.filter = ciasOnly ? util_filter_cias : ticketsOnly ? util_filter_tickets : NULL; diff --git a/source/ui/section/action/installcias.c b/source/ui/section/action/installcias.c index b31f0b2..ddc8aba 100644 --- a/source/ui/section/action/installcias.c +++ b/source/ui/section/action/installcias.c @@ -17,6 +17,8 @@ typedef struct { linked_list* items; + + list_item* targetItem; file_info* target; linked_list contents; @@ -39,7 +41,7 @@ static void action_install_cias_draw_top(ui_view* view, void* data, float x1, fl u32 curr = installData->installInfo.processed; if(curr < installData->installInfo.total) { ui_draw_file_info(view, ((list_item*) linked_list_get(&installData->contents, curr))->data, x1, y1, x2, y2); - } else if(installData->target != NULL) { + } else { ui_draw_file_info(view, installData->target, x1, y1, x2, y2); } } @@ -212,6 +214,13 @@ bool action_install_cias_error(void* data, u32 index, Result res) { static void action_install_cias_free_data(install_cias_data* data) { task_clear_files(&data->contents); linked_list_destroy(&data->contents); + + if(data->targetItem != NULL) { + task_free_file(data->targetItem); + data->targetItem = NULL; + data->target = NULL; + } + free(data); } @@ -310,7 +319,10 @@ static void action_install_cias_internal(linked_list* items, list_item* selected } data->items = items; - data->target = (file_info*) selected->data; + + file_info* targetInfo = (file_info*) selected->data; + task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes); + data->target = (file_info*) data->targetItem->data; data->delete = delete; diff --git a/source/ui/section/action/installtickets.c b/source/ui/section/action/installtickets.c index 4b92aca..ab35e19 100644 --- a/source/ui/section/action/installtickets.c +++ b/source/ui/section/action/installtickets.c @@ -17,6 +17,8 @@ typedef struct { linked_list* items; + + list_item* targetItem; file_info* target; linked_list contents; @@ -33,7 +35,7 @@ static void action_install_tickets_draw_top(ui_view* view, void* data, float x1, u32 curr = installData->installInfo.processed; if(curr < installData->installInfo.total) { ui_draw_file_info(view, ((list_item*) linked_list_get(&installData->contents, curr))->data, x1, y1, x2, y2); - } else if(installData->target != NULL) { + } else { ui_draw_file_info(view, installData->target, x1, y1, x2, y2); } } @@ -172,6 +174,13 @@ static bool action_install_tickets_error(void* data, u32 index, Result res) { static void action_install_tickets_free_data(install_tickets_data* data) { task_clear_files(&data->contents); linked_list_destroy(&data->contents); + + if(data->targetItem != NULL) { + task_free_file(data->targetItem); + data->targetItem = NULL; + data->target = NULL; + } + free(data); } @@ -276,7 +285,10 @@ static void action_install_tickets_internal(linked_list* items, list_item* selec } data->items = items; - data->target = (file_info*) selected->data; + + file_info* targetInfo = (file_info*) selected->data; + task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes); + data->target = (file_info*) data->targetItem->data; data->delete = delete; diff --git a/source/ui/section/action/pastecontents.c b/source/ui/section/action/pastecontents.c index ccc700d..8f75679 100644 --- a/source/ui/section/action/pastecontents.c +++ b/source/ui/section/action/pastecontents.c @@ -18,6 +18,8 @@ typedef struct { linked_list* items; + + list_item* targetItem; file_info* target; linked_list contents; @@ -31,7 +33,7 @@ static void action_paste_contents_draw_top(ui_view* view, void* data, float x1, u32 curr = pasteData->pasteInfo.processed; if(curr < pasteData->pasteInfo.total) { ui_draw_file_info(view, ((list_item*) linked_list_get(&pasteData->contents, curr))->data, x1, y1, x2, y2); - } else if(pasteData->target != NULL) { + } else { ui_draw_file_info(view, pasteData->target, x1, y1, x2, y2); } } @@ -246,6 +248,13 @@ static bool action_paste_contents_error(void* data, u32 index, Result res) { static void action_paste_contents_free_data(paste_contents_data* data) { task_clear_files(&data->contents); linked_list_destroy(&data->contents); + + if(data->targetItem != NULL) { + task_free_file(data->targetItem); + data->targetItem = NULL; + data->target = NULL; + } + free(data); } @@ -284,7 +293,7 @@ static void action_paste_contents_onresponse(ui_view* view, void* data, bool res if(R_SUCCEEDED(res)) { info_display("Pasting Contents", "Press B to cancel.", true, data, action_paste_contents_update, action_paste_contents_draw_top); } else { - error_display_res(pasteData->target, ui_draw_file_info, res, "Failed to initiate paste operation."); + error_display_res(NULL, NULL, res, "Failed to initiate paste operation."); action_paste_contents_free_data(pasteData); } @@ -346,7 +355,10 @@ void action_paste_contents(linked_list* items, list_item* selected) { } data->items = items; - data->target = (file_info*) selected->data; + + file_info* targetInfo = (file_info*) selected->data; + task_create_file_item(&data->targetItem, targetInfo->archive, targetInfo->path, targetInfo->attributes); + data->target = (file_info*) data->targetItem->data; data->pasteInfo.data = data;