From 7725e19069215005047585633f72cb8291d57c9a Mon Sep 17 00:00:00 2001 From: Marc Date: Wed, 5 Oct 2022 19:08:57 +0200 Subject: [PATCH] fixed some memory leaks --- CMakeLists.txt | 9 +++++--- src/file.c | 25 ++++++++++++++-------- src/fomod.c | 53 +++++++++++++++++++++++++++++++++++++++------- src/fomod.h | 9 ++++++-- src/fomod/group.c | 1 + src/fomod/parser.c | 3 ++- src/main.c | 6 +++++- src/order.c | 4 +++- src/steam.c | 3 +++ 9 files changed, 88 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b2e40b..fd2e4c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,12 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -fsanitize=address -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations") -set(CMAKE_C_FLAGS_DEBUG "-g -Werror") +if(CMAKE_BUILD_TYPE MATCHES DEBUG) + add_link_options(-fsanitize=address) +endif() + +set(CMAKE_C_FLAGS "-Wall -Wextra -pedantic -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wmaybe-uninitialized") +set(CMAKE_C_FLAGS_DEBUG "-g -fsanitize=address -Werror -O0") set(CMAKE_C_FLAGS_RELEASE "-O2") # generate the compile_commands for vscode / clang @@ -38,7 +42,6 @@ pkg_search_module(LIBXML REQUIRED libxml-2.0) target_include_directories(ModManager PRIVATE ${GLIB_INCLUDE_DIRS} ${LIBXML_INCLUDE_DIRS} ${AUDIT_INCLUDE_DIRS}) -add_link_options(-fsanitize=address) target_link_libraries(ModManager ${GLIB_LDFLAGS}) target_link_libraries(ModManager ${LIBXML_LIBRARIES}) diff --git a/src/file.c b/src/file.c index 2f0177d..e395b1b 100644 --- a/src/file.c +++ b/src/file.c @@ -100,22 +100,29 @@ void casefold(const char * folder) { //removes .. & . from the list if(strcmp(dir->d_name, "..") != 0 && strcmp(dir->d_name, ".") != 0) { //only look at ascii and hope for the best. - gchar * file = g_build_path("/", folder, dir->d_name, NULL); + gchar * file = g_build_filename(folder, dir->d_name, NULL); gchar * destinationName = g_ascii_strdown(dir->d_name, -1); gchar * destination = g_build_path("/", folder,destinationName, NULL); - int result = move(file, destination); - if(result != EXIT_SUCCESS) { - fprintf(stderr, "Move failed: %s => %s \n", dir->d_name, destinationName); - } - g_free(destinationName); - g_free(destination); - if(dir->d_type == DT_DIR) { - casefold(file); + if(strcmp(destinationName, dir->d_name) != 0) { + + int result = move(file, destination); + if(result != EXIT_SUCCESS) { + fprintf(stderr, "Move failed: %s => %s \n", dir->d_name, destinationName); + } + + } g_free(file); + g_free(destinationName); + + if(dir->d_type == DT_DIR) { + casefold(destination); + } + + g_free(destination); } } closedir(d); diff --git a/src/fomod.c b/src/fomod.c index 51c4bab..784f451 100644 --- a/src/fomod.c +++ b/src/fomod.c @@ -12,6 +12,7 @@ #include "fomod.h" #include "file.h" +#include "fomod/fomodTypes.h" #include "libxml/globals.h" static int getInputCount(const char * input) { @@ -44,7 +45,7 @@ static gint priorityCmp(gconstpointer a, gconstpointer b) { const FOModFile_t * fileA = (const FOModFile_t *)a; const FOModFile_t * fileB = (const FOModFile_t *)b; - return fileA->priority - fileB->priority; + return fileB->priority - fileA->priority; } static void printfOptionsInOrder(FOModGroup_t group) { @@ -120,9 +121,10 @@ static void sortGroup(FOModGroup_t * group) { } //TODO: handle error -int processFileOperations(GList * pendingFileOperations, const char * modFolder, const char * destination) { - pendingFileOperations = g_list_sort(pendingFileOperations, priorityCmp); - GList * currentFileOperation = pendingFileOperations; +int processFileOperations(GList ** pendingFileOperations, const char * modFolder, const char * destination) { + //priority higher a less important and should be processed first. + *pendingFileOperations = g_list_sort(*pendingFileOperations, priorityCmp); + GList * currentFileOperation = *pendingFileOperations; while(currentFileOperation != NULL) { //TODO: support destination @@ -171,6 +173,13 @@ GList * processCondFiles(const FOMod_t * fomod, GList * flagList, GList * pendin FOModFile_t * fileCopy = malloc(sizeof(*file)); *fileCopy = *file; + //changing pathes to lowercase since we used casefold and the pathes in the xml might not like it + char * destination = g_ascii_strdown(file->destination, -1); + fileCopy->destination = destination; + + char * source = g_ascii_strdown(file->source, -1); + fileCopy->source = source; + pendingFileOperations = g_list_append(pendingFileOperations, fileCopy); } } @@ -178,6 +187,18 @@ GList * processCondFiles(const FOMod_t * fomod, GList * flagList, GList * pendin return pendingFileOperations; } +void freeFileOperations(GList * fileOperations) { + GList * fileOperationsStart = fileOperations; + while(fileOperations != NULL) { + FOModFile_t * file = (FOModFile_t *)fileOperations->data; + if(file->destination != NULL)free(file->destination); + if(file->source != NULL)free(file->source); + fileOperations = g_list_next(fileOperations); + } + + g_list_free_full(fileOperationsStart, free); +} + int installFOMod(const char * modFolder, const char * destination) { //everything should be lowercase since we use casefold() before calling any install function char * fomodFolder = g_build_path("/", modFolder, "fomod", NULL); @@ -259,6 +280,10 @@ int installFOMod(const char * modFolder, const char * destination) { min = 0; max = 0; break; + default: + //never happen; + fprintf(stderr, "unexpected type please report this issue %d, %d", group.type, __LINE__); + return EXIT_FAILURE; } @@ -277,11 +302,14 @@ int installFOMod(const char * modFolder, const char * destination) { } } + //processing user input + GRegex* regex = g_regex_new("\\s*", 0, 0, NULL); char ** choices = g_regex_split(regex, inputBuffer, 0); g_regex_unref(regex); for(int choiceId = 0; choices[choiceId] != NULL; choiceId++) { + //TODO: safer user input int choice = atoi(choices[choiceId]); FOModPlugin_t plugin = group.plugins[choice]; for(int flagId = 0; flagId < plugin.flagCount; flagId++) { @@ -292,9 +320,18 @@ int installFOMod(const char * modFolder, const char * destination) { for(int pluginId = 0; pluginId < plugin.fileCount; pluginId++) { const FOModFile_t * file = &plugin.files[pluginId]; - FOModFile_t * fileCopy = malloc(sizeof(*file)); + FOModFile_t * fileCopy = malloc(sizeof(FOModFile_t)); *fileCopy = *file; + //changing pathes to lowercase since we used casefold and the pathes in the xml might not like it + char * destination = g_ascii_strdown(file->destination, -1); + fileCopy->destination = strdup(destination); + g_free(destination); + + char * source = g_ascii_strdown(file->source, -1); + fileCopy->source = strdup(source); + g_free(source); + pendingFileOperations = g_list_append(pendingFileOperations, fileCopy); } } @@ -304,14 +341,14 @@ int installFOMod(const char * modFolder, const char * destination) { } } - + //TODO: manage multiple files with the same name pendingFileOperations = processCondFiles(&fomod, flagList, pendingFileOperations); - processFileOperations(pendingFileOperations, modFolder, destination); + processFileOperations(&pendingFileOperations, modFolder, destination); printf("FOMod successfully installed!\n"); g_list_free(flagList); - g_list_free_full(pendingFileOperations, free); + freeFileOperations(pendingFileOperations); freeFOMod(&fomod); g_free(fomodFolder); return EXIT_SUCCESS; diff --git a/src/fomod.h b/src/fomod.h index 368af57..a7bb6af 100644 --- a/src/fomod.h +++ b/src/fomod.h @@ -35,8 +35,13 @@ GList * processCondFiles(const FOMod_t * fomod, GList * flagList, GList * pendin * @param destination folder of the new mod that contains the result of the process. * @return error code */ -int processFileOperations(GList * pendingFileOperations, const char * modFolder, const char * destination); - +int processFileOperations(GList ** pendingFileOperations, const char * modFolder, const char * destination); +/** + * @brief + * + * @param fileOperations + */ +void freeFileOperations(GList * fileOperations); #endif diff --git a/src/fomod/group.c b/src/fomod/group.c index 60d434d..9ea650c 100644 --- a/src/fomod/group.c +++ b/src/fomod/group.c @@ -36,6 +36,7 @@ static TypeDescriptor_t getDescriptor(const char * descriptor) { } void freeGroup(FOModGroup_t * group) { + free(group->name); if(group->pluginCount == 0) return; for(int pluginId = 0; pluginId < group->pluginCount; pluginId++) { FOModPlugin_t * plugin = &group->plugins[pluginId]; diff --git a/src/fomod/parser.c b/src/fomod/parser.c index 3703cc8..34a07c4 100644 --- a/src/fomod/parser.c +++ b/src/fomod/parser.c @@ -36,16 +36,17 @@ void freeFOMod(FOMod_t * fomod) { for(int groupId = 0; groupId < step->groupCount; groupId++) { FOModGroup_t * group = &step->groups[groupId]; freeGroup(group); - free(step->groups[groupId].plugins); } for(int flagId = 0; flagId < step->flagCount; flagId++) { FOModFlag_t * flag = &(step->requiredFlags[flagId]); free(flag->name); free(flag->value); } + free(step->groups); free(step->requiredFlags); free(step->name); } + free(fomod->steps); //set every counter to zero and every pointer to null memset(fomod, 0, sizeof(FOMod_t)); diff --git a/src/main.c b/src/main.c index 59b014e..01ba228 100644 --- a/src/main.c +++ b/src/main.c @@ -137,6 +137,7 @@ static int listAllMods(int argc, char ** argv) { free(home); GList * mods = listMods(appid); + GList * p_mods = mods; unsigned short index = 0; printf("Id | Installed | Name\n"); @@ -150,13 +151,15 @@ static int listAllMods(int argc, char ** argv) { printf(DISABLED_COLOR " %d | ✕ | %s\n", index, modName); } + g_free(modPath); + index++; mods = g_list_next(mods); } free(modFolder); - free(mods); + g_list_free_full(p_mods, free); return EXIT_SUCCESS; } @@ -535,6 +538,7 @@ int main(int argc, char ** argv) { int searchStatus; gamePaths = search_games(&searchStatus); + int returnValue = EXIT_SUCCESS; if(searchStatus == EXIT_FAILURE) { returnValue = EXIT_FAILURE; diff --git a/src/order.c b/src/order.c index ca9a163..75cc403 100644 --- a/src/order.c +++ b/src/order.c @@ -51,6 +51,7 @@ GList * listMods(int appid) { Mod_t * mod = alloca(sizeof(Mod_t)); mod->modId = modId; + //we are going to return this value so no alloca here mod->name = strdup(dir->d_name); //strdup but on the stack //add one for the \0 @@ -120,6 +121,7 @@ int swapPlace(int appid, int modIdA, int modIdB) { char * modAFolder = g_build_filename(modFolder, listA->data, ORDER_FILE, NULL); char * modBFolder = g_build_filename(modFolder, listB->data, ORDER_FILE, NULL); + g_free(modFolder); FILE * fileA = fopen(modAFolder, "w"); FILE * fileB = fopen(modBFolder, "w"); @@ -138,6 +140,6 @@ int swapPlace(int appid, int modIdA, int modIdB) { fclose(fileA); fclose(fileB); - g_list_free(list); + g_list_free_full(list, free); return EXIT_SUCCESS; } diff --git a/src/steam.c b/src/steam.c index 4703c29..177d934 100644 --- a/src/steam.c +++ b/src/steam.c @@ -125,8 +125,11 @@ static ValveLibraries_t * parseVDF(const char * path, size_t * size, int * statu } else { library->apps[library->appsCount - 1].update = strtoul(value, NULL, 10); } + free(value); isAppId = !isAppId; break; + default: + free(value); } //field apps is using braces so the syntax is different if(nextFieldToFill != FIELD_APPS)nextFieldToFill = -1;