Improve error handling by using std::nothrow everywhere

This commit is contained in:
Maschell 2022-05-08 14:46:16 +02:00
parent 99791f5edf
commit ef91f1ef11
6 changed files with 78 additions and 36 deletions

View File

@ -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{

View File

@ -20,6 +20,7 @@
#include "utils/ElfUtils.h"
#include "utils/OnLeavingScope.h"
#include "utils/logger.h"
#include "utils/utils.h"
#include <coreinit/cache.h>
#include <coreinit/memdefaultheap.h>
#include <map>
@ -30,7 +31,7 @@ using namespace ELFIO;
std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::string &path) {
elfio reader;
auto moduleData = std::make_shared<ModuleData>();
auto moduleData = make_shared_nothrow<ModuleData>();
if (!moduleData) {
DEBUG_FUNCTION_LINE_ERR("Failed to alloc module data");
return {};
@ -52,7 +53,7 @@ std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
}
uint32_t sec_num = reader.sections.size();
auto destinations = std::make_unique<uint8_t *[]>(sec_num);
auto destinations = make_unique_nothrow<uint8_t *[]>(sec_num);
if (!destinations) {
DEBUG_FUNCTION_LINE_ERR("Failed alloc memory for destinations array");
return {};
@ -83,7 +84,7 @@ std::optional<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
}
}
auto data = std::make_unique<uint8_t[]>(text_size + data_size);
auto data = make_unique_nothrow<uint8_t[]>(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<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
moduleData->setSBSSLocation(destination, sectionSize);
memset(reinterpret_cast<void *>(destination), 0, sectionSize);
}
auto sectionInfo = std::make_shared<SectionInfo>(psec->get_name(), destination, sectionSize);
auto sectionInfo = make_shared_nothrow<SectionInfo>(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<std::shared_ptr<ModuleData>> 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<ExportData>(exp->type, exp->name, exp->address);
auto exportData = make_unique_nothrow<ExportData>(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<std::shared_ptr<ModuleData>> 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<HookData>(hook->type, hook->target);
auto hookData = make_unique_nothrow<HookData>(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<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
continue;
}
auto finalAddress = offsetVal + sectionOpt.value()->getAddress();
auto functionSymbolData = std::make_shared<FunctionSymbolData>(name, (void *) finalAddress, (uint32_t) size);
auto functionSymbolData = make_shared_nothrow<FunctionSymbolData>(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<std::shared_ptr<ModuleData>> 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<std::shared_ptr<ModuleData>> ModuleDataFactory::load(const std::st
return moduleData;
}
void ModuleDataFactory::getImportRelocationData(std::shared_ptr<ModuleData> &moduleData, ELFIO::elfio &reader, uint8_t **destinations) {
bool ModuleDataFactory::getImportRelocationData(std::shared_ptr<ModuleData> &moduleData, ELFIO::elfio &reader, uint8_t **destinations) {
std::map<uint32_t, std::shared_ptr<ImportRPLInformation>> infoMap;
uint32_t sec_num = reader.sections.size();
@ -315,7 +323,12 @@ void ModuleDataFactory::getImportRelocationData(std::shared_ptr<ModuleData> &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<ImportRPLInformation>(psec->get_name());
auto info = make_shared_nothrow<ImportRPLInformation>(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<ModuleData> &mod
OSFatal("Relocation is referencing a unknown section.");
}
auto relocationData = std::make_unique<RelocationData>(type,
offset - 0x02000000,
addend,
(void *) (destinations[section_index] + 0x02000000),
sym_name,
infoMap[sym_section_index]);
auto relocationData = make_unique_nothrow<RelocationData>(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;

View File

@ -37,5 +37,5 @@ public:
relocation_trampoline_entry_t *trampoline_data,
uint32_t trampoline_data_length);
static void getImportRelocationData(std::shared_ptr<ModuleData> &moduleData, ELFIO::elfio &reader, uint8_t **destinations);
static bool getImportRelocationData(std::shared_ptr<ModuleData> &moduleData, ELFIO::elfio &reader, uint8_t **destinations);
};

View File

@ -1,9 +1,10 @@
#include "ModuleDataPersistence.h"
#include "globals.h"
#include "utils/utils.h"
#include <coreinit/cache.h>
bool ModuleDataPersistence::saveModuleData(module_information_t *moduleInformation, const std::vector<std::shared_ptr<ModuleData>> &moduleList) {
auto module_data_list = std::make_unique<module_information_single_t[]>(moduleList.size());
auto module_data_list = make_unique_nothrow<module_information_single_t[]>(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<ModuleData> &module) {
uint32_t entryCount = module->getFunctionSymbolDataList().size();
auto function_symbol_data = std::make_unique<module_function_symbol_data_t[]>(entryCount);
auto function_symbol_data = make_unique_nothrow<module_function_symbol_data_t[]>(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<ModuleData> &module) {
auto export_data = std::make_unique<export_data_t[]>(module->getExportDataList().size());
auto export_data = make_unique_nothrow<export_data_t[]>(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<ModuleData> &module) {
auto hook_data = std::make_unique<hook_data_t[]>(module->getHookDataList().size());
auto hook_data = make_unique_nothrow<hook_data_t[]>(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<ModuleData> &module) {
auto relocation_data = std::make_unique<dyn_linking_relocation_entry_t[]>(module->getRelocationDataList().size());
auto relocation_data = make_unique_nothrow<dyn_linking_relocation_entry_t[]>(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<dyn_linking_import_t[]>(rplInfoTotalCount);
auto rpl_data = make_unique_nothrow<dyn_linking_import_t[]>(rplInfoTotalCount);
if (!rpl_data) {
DEBUG_FUNCTION_LINE_ERR("Failed to allocate memory for the RPLInfos.");
return false;

View File

@ -25,6 +25,9 @@
***************************************************************************/
#pragma once
#include "logger.h"
#include "utils.h"
#include <coreinit/debug.h>
#include <memory>
#include <string>
#include <vector>
@ -34,7 +37,12 @@ template<typename... Args>
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_t>(size_s);
auto buf = std::make_unique<char[]>(size);
auto buf = make_unique_nothrow<char[]>(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
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <memory>
template<class T, class... Args>
std::unique_ptr<T> make_unique_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
return std::unique_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
}
template<typename T>
inline typename std::_MakeUniq<T>::__array make_unique_nothrow(size_t num) noexcept {
return std::unique_ptr<T>(new (std::nothrow) std::remove_extent_t<T>[num]());
}
template<class T, class... Args>
std::shared_ptr<T> make_shared_nothrow(Args &&...args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
return std::shared_ptr<T>(new (std::nothrow) T(std::forward<Args>(args)...));
}