From ef91f1ef110658ff6a645c9688fb8438df338260 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 8 May 2022 14:46:16 +0200 Subject: [PATCH] Improve error handling by using std::nothrow everywhere --- wumsloader/src/elfio/elfio_section.hpp | 20 ++++--- wumsloader/src/module/ModuleDataFactory.cpp | 52 ++++++++++++------- wumsloader/src/module/ModuleDataFactory.h | 2 +- .../src/module/ModuleDataPersistence.cpp | 13 ++--- wumsloader/src/utils/StringTools.h | 10 +++- wumsloader/src/utils/utils.h | 17 ++++++ 6 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 wumsloader/src/utils/utils.h diff --git a/wumsloader/src/elfio/elfio_section.hpp b/wumsloader/src/elfio/elfio_section.hpp index d7dd808..e54096e 100644 --- a/wumsloader/src/elfio/elfio_section.hpp +++ b/wumsloader/src/elfio/elfio_section.hpp @@ -244,11 +244,15 @@ class section_impl : public section if ( ( 0 != size ) && ( 0 != data ) ) { stream.seekg( (*convertor)( header.sh_offset ) ); if (get_flags() & 0x08000000){ - uint32_t uncompressed_size = size; - stream.read( (char *) &uncompressed_size, 4); + uint32_t decompressed_size = size; + stream.read( (char *) &decompressed_size, 4); stream.read( data, size - 4); - char* uncompressedData = new char[uncompressed_size + 1]; + char* decompressedData = new (std::nothrow) char[decompressed_size + 1]; + if(!decompressedData) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocated memory for decompressing the section"); + OSFatal("Failed to allocated memory for decompressing the section"); + } int ret = 0; z_stream s; @@ -265,8 +269,8 @@ class section_impl : public section s.avail_in = size - 4; s.next_in = (Bytef *)data; - s.avail_out = uncompressed_size; - s.next_out = (Bytef *)&uncompressedData[0]; + s.avail_out = decompressed_size; + s.next_out = (Bytef *)&decompressedData[0]; ret = inflate(&s, Z_FINISH); if (ret != Z_OK && ret != Z_STREAM_END){ @@ -276,9 +280,9 @@ class section_impl : public section inflateEnd(&s); delete [] data; - data = uncompressedData; - data_size = uncompressed_size; - set_size(uncompressed_size); + data = decompressedData; + data_size = decompressed_size; + set_size(decompressed_size); data[data_size] = 0; // Ensure data is ended with 0 to avoid oob read }else{ diff --git a/wumsloader/src/module/ModuleDataFactory.cpp b/wumsloader/src/module/ModuleDataFactory.cpp index 3dda318..ae7e691 100644 --- a/wumsloader/src/module/ModuleDataFactory.cpp +++ b/wumsloader/src/module/ModuleDataFactory.cpp @@ -20,6 +20,7 @@ #include "utils/ElfUtils.h" #include "utils/OnLeavingScope.h" #include "utils/logger.h" +#include "utils/utils.h" #include #include #include @@ -30,7 +31,7 @@ using namespace ELFIO; std::optional> ModuleDataFactory::load(const std::string &path) { elfio reader; - auto moduleData = std::make_shared(); + auto moduleData = make_shared_nothrow(); if (!moduleData) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc module data"); return {}; @@ -52,7 +53,7 @@ std::optional> ModuleDataFactory::load(const std::st } uint32_t sec_num = reader.sections.size(); - auto destinations = std::make_unique(sec_num); + auto destinations = make_unique_nothrow(sec_num); if (!destinations) { DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array"); return {}; @@ -83,7 +84,7 @@ std::optional> ModuleDataFactory::load(const std::st } } - auto data = std::make_unique(text_size + data_size); + auto data = make_unique_nothrow(text_size + data_size); if (!data) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for the .text section (%d bytes)", text_size); return {}; @@ -146,7 +147,11 @@ std::optional> ModuleDataFactory::load(const std::st moduleData->setSBSSLocation(destination, sectionSize); memset(reinterpret_cast(destination), 0, sectionSize); } - auto sectionInfo = std::make_shared(psec->get_name(), destination, sectionSize); + auto sectionInfo = make_shared_nothrow(psec->get_name(), destination, sectionSize); + if (!sectionInfo) { + DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for section info"); + return {}; + } moduleData->addSectionInfo(sectionInfo); DEBUG_FUNCTION_LINE("Saved %s section info. Location: %08X size: %08X", psec->get_name().c_str(), destination, sectionSize); @@ -175,9 +180,10 @@ std::optional> ModuleDataFactory::load(const std::st for (size_t j = 0; j < entries_count; j++) { wums_entry_t *exp = &entries[j]; DEBUG_FUNCTION_LINE("Saving export of type %08X, name %s, target: %08X", exp->type, exp->name, exp->address); - auto exportData = std::make_unique(exp->type, exp->name, exp->address); + auto exportData = make_unique_nothrow(exp->type, exp->name, exp->address); if (!exportData) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc ExportData"); + return {}; } moduleData->addExportData(std::move(exportData)); } @@ -192,9 +198,10 @@ std::optional> ModuleDataFactory::load(const std::st for (size_t j = 0; j < entries_count; j++) { wums_hook_t *hook = &hooks[j]; DEBUG_FUNCTION_LINE("Saving hook of type %08X, target: %08X", hook->type, hook->target); - auto hookData = std::make_unique(hook->type, hook->target); + auto hookData = make_unique_nothrow(hook->type, hook->target); if (!hookData) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc HookData"); + return {}; } moduleData->addHookData(std::move(hookData)); } @@ -272,9 +279,10 @@ std::optional> ModuleDataFactory::load(const std::st continue; } auto finalAddress = offsetVal + sectionOpt.value()->getAddress(); - auto functionSymbolData = std::make_shared(name, (void *) finalAddress, (uint32_t) size); + auto functionSymbolData = make_shared_nothrow(name, (void *) finalAddress, (uint32_t) size); if (!functionSymbolData) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc FunctionSymbolData"); + return std::nullopt; } else { moduleData->addFunctionSymbolData(std::move(functionSymbolData)); } @@ -293,7 +301,7 @@ std::optional> ModuleDataFactory::load(const std::st if (totalSize > text_size + data_size) { DEBUG_FUNCTION_LINE_ERR("We didn't allocate enough memory!!"); - OSFatal("We didn't allocate enough memory!!"); + return std::nullopt; } moduleData->setDataPtr(std::move(data), totalSize); @@ -307,7 +315,7 @@ std::optional> ModuleDataFactory::load(const std::st return moduleData; } -void ModuleDataFactory::getImportRelocationData(std::shared_ptr &moduleData, ELFIO::elfio &reader, uint8_t **destinations) { +bool ModuleDataFactory::getImportRelocationData(std::shared_ptr &moduleData, ELFIO::elfio &reader, uint8_t **destinations) { std::map> infoMap; uint32_t sec_num = reader.sections.size(); @@ -315,7 +323,12 @@ void ModuleDataFactory::getImportRelocationData(std::shared_ptr &mod for (uint32_t i = 0; i < sec_num; ++i) { auto *psec = reader.sections[i]; if (psec->get_type() == 0x80000002) { - infoMap[i] = std::make_shared(psec->get_name()); + auto info = make_shared_nothrow(psec->get_name()); + if (!info) { + DEBUG_FUNCTION_LINE_ERR("Failed too allocate ImportRPLInformation"); + return false; + } + infoMap[i] = std::move(info); } } @@ -348,23 +361,23 @@ void ModuleDataFactory::getImportRelocationData(std::shared_ptr &mod OSFatal("Relocation is referencing a unknown section."); } - auto relocationData = std::make_unique(type, - offset - 0x02000000, - addend, - (void *) (destinations[section_index] + 0x02000000), - sym_name, - infoMap[sym_section_index]); + auto relocationData = make_unique_nothrow(type, + offset - 0x02000000, + addend, + (void *) (destinations[section_index] + 0x02000000), + sym_name, + infoMap[sym_section_index]); if (!relocationData) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc relocation data"); - OSFatal("Failed to alloc relocation data"); - continue; + return false; } moduleData->addRelocationData(std::move(relocationData)); } } } + return true; } bool ModuleDataFactory::linkSection(elfio &reader, uint32_t section_index, uint32_t destination, uint32_t base_text, uint32_t base_data, relocation_trampoline_entry_t *trampoline_data, @@ -386,8 +399,7 @@ bool ModuleDataFactory::linkSection(elfio &reader, uint32_t section_index, uint3 if (!rel.get_entry(j, offset, sym_value, sym_name, type, addend, sym_section_index)) { DEBUG_FUNCTION_LINE_ERR("Failed to get relocation"); - OSFatal("Failed to get relocation"); - break; + return false; } auto adjusted_sym_value = (uint32_t) sym_value; diff --git a/wumsloader/src/module/ModuleDataFactory.h b/wumsloader/src/module/ModuleDataFactory.h index c938ed1..2728bc1 100644 --- a/wumsloader/src/module/ModuleDataFactory.h +++ b/wumsloader/src/module/ModuleDataFactory.h @@ -37,5 +37,5 @@ public: relocation_trampoline_entry_t *trampoline_data, uint32_t trampoline_data_length); - static void getImportRelocationData(std::shared_ptr &moduleData, ELFIO::elfio &reader, uint8_t **destinations); + static bool getImportRelocationData(std::shared_ptr &moduleData, ELFIO::elfio &reader, uint8_t **destinations); }; diff --git a/wumsloader/src/module/ModuleDataPersistence.cpp b/wumsloader/src/module/ModuleDataPersistence.cpp index b088662..62b446d 100644 --- a/wumsloader/src/module/ModuleDataPersistence.cpp +++ b/wumsloader/src/module/ModuleDataPersistence.cpp @@ -1,9 +1,10 @@ #include "ModuleDataPersistence.h" #include "globals.h" +#include "utils/utils.h" #include bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformation, const std::vector> &moduleList) { - auto module_data_list = std::make_unique(moduleList.size()); + auto module_data_list = make_unique_nothrow(moduleList.size()); if (!module_data_list) { DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory to persist module data"); return false; @@ -73,7 +74,7 @@ bool ModuleDataPersistence::saveModuleData(module_information_single_t &module_d bool ModuleDataPersistence::saveFunctionSymbolDataForModule(module_information_single_t &module_data, const std::shared_ptr &module) { uint32_t entryCount = module->getFunctionSymbolDataList().size(); - auto function_symbol_data = std::make_unique(entryCount); + auto function_symbol_data = make_unique_nothrow(entryCount); if (!function_symbol_data) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the function symbol data."); return false; @@ -98,7 +99,7 @@ bool ModuleDataPersistence::saveFunctionSymbolDataForModule(module_information_s } bool ModuleDataPersistence::saveExportDataForModule(module_information_single_t &module_data, const std::shared_ptr &module) { - auto export_data = std::make_unique(module->getExportDataList().size()); + auto export_data = make_unique_nothrow(module->getExportDataList().size()); if (!export_data) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the export data."); return false; @@ -124,7 +125,7 @@ bool ModuleDataPersistence::saveExportDataForModule(module_information_single_t } bool ModuleDataPersistence::saveHookDataForModule(module_information_single_t &module_data, const std::shared_ptr &module) { - auto hook_data = std::make_unique(module->getHookDataList().size()); + auto hook_data = make_unique_nothrow(module->getHookDataList().size()); if (!hook_data) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the hook data."); return false; @@ -149,7 +150,7 @@ bool ModuleDataPersistence::saveHookDataForModule(module_information_single_t &m } bool ModuleDataPersistence::saveRelocationDataForModule(module_information_single_t &module_data, const std::shared_ptr &module) { - auto relocation_data = std::make_unique(module->getRelocationDataList().size()); + auto relocation_data = make_unique_nothrow(module->getRelocationDataList().size()); if (!relocation_data) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the relocation data."); return false; @@ -164,7 +165,7 @@ bool ModuleDataPersistence::saveRelocationDataForModule(module_information_singl uint32_t rplInfoTotalCount = rplInfoCountSet.size(); rplInfoCountSet.clear(); - auto rpl_data = std::make_unique(rplInfoTotalCount); + auto rpl_data = make_unique_nothrow(rplInfoTotalCount); if (!rpl_data) { DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the RPLInfos."); return false; diff --git a/wumsloader/src/utils/StringTools.h b/wumsloader/src/utils/StringTools.h index 3a2bdda..c64de2c 100644 --- a/wumsloader/src/utils/StringTools.h +++ b/wumsloader/src/utils/StringTools.h @@ -25,6 +25,9 @@ ***************************************************************************/ #pragma once +#include "logger.h" +#include "utils.h" +#include #include #include #include @@ -34,7 +37,12 @@ template std::string string_format(const std::string &format, Args... args) { int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0' auto size = static_cast(size_s); - auto buf = std::make_unique(size); + auto buf = make_unique_nothrow(size); + if (!buf) { + DEBUG_FUNCTION_LINE_ERR("string_format failed, not enough memory"); + OSFatal("string_format failed, not enough memory"); + return std::string(""); + } std::snprintf(buf.get(), size, format.c_str(), args...); return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside } diff --git a/wumsloader/src/utils/utils.h b/wumsloader/src/utils/utils.h new file mode 100644 index 0000000..a71f4f9 --- /dev/null +++ b/wumsloader/src/utils/utils.h @@ -0,0 +1,17 @@ +#pragma once +#include + +template +std::unique_ptr make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::unique_ptr(new (std::nothrow) T(std::forward(args)...)); +} + +template +inline typename std::_MakeUniq::__array make_unique_nothrow(size_t num) noexcept { + return std::unique_ptr(new (std::nothrow) std::remove_extent_t[num]()); +} + +template +std::shared_ptr make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward(args)...))) { + return std::shared_ptr(new (std::nothrow) T(std::forward(args)...)); +}