diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index e837bfa59..25c65099d 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -1,6 +1,8 @@ #include +#include #include #include +#include extern "C" { @@ -36,20 +38,56 @@ int fflush_nid_postfix(FILE* stream) { return std::fflush(stream); } +constexpr std::uintptr_t AlignedBlockTag = 1; + void* malloc_nid_postfix(size_t size) { - return std::malloc(size); + const size_t headerSize = sizeof(std::uintptr_t); + void* rawPtr = std::malloc(size + headerSize); + if (rawPtr == nullptr) { + throw std::bad_alloc(); + } + *reinterpret_cast(rawPtr) = 0; + return static_cast(rawPtr) + headerSize; } void free_nid_postfix(void* ptr) { - std::free(ptr); + if (ptr == nullptr) { + return; + } + const std::uintptr_t headerValue = reinterpret_cast(ptr)[-1]; + if (headerValue == AlignedBlockTag) { + std::free(reinterpret_cast(ptr)[-2]); + } else { + std::free(reinterpret_cast(ptr) - sizeof(std::uintptr_t)); + } } void* realloc_nid_postfix(void* ptr, size_t newSize) { - return std::realloc(ptr, newSize); + if (ptr == nullptr) { + return malloc_nid_postfix(newSize); + } + const size_t headerSize = sizeof(std::uintptr_t); + void* rawPtr = static_cast(ptr) - headerSize; + void* newRawPtr = std::realloc(rawPtr, newSize + headerSize); + if (newRawPtr == nullptr) { + throw std::bad_alloc(); + } + return static_cast(newRawPtr) + headerSize; } void* memalign_nid_postfix(size_t alignment, size_t size) { - return std::aligned_alloc(alignment, size); + const size_t headerSize = sizeof(void*) * 2; + const size_t worstCaseSize = size + alignment + headerSize; + void* rawPtr = std::malloc(worstCaseSize); + if (rawPtr == nullptr) { + throw std::bad_alloc(); + } + const std::uintptr_t rawAddress = reinterpret_cast(rawPtr) + headerSize; + const std::uintptr_t alignedAddress = (rawAddress + alignment - 1) & ~(alignment - 1); + void* alignedPtr = reinterpret_cast(alignedAddress); + reinterpret_cast(alignedPtr)[-1] = reinterpret_cast(AlignedBlockTag); + reinterpret_cast(alignedPtr)[-2] = rawPtr; + return alignedPtr; } void qsort_nid_postfix(void* base, size_t count, size_t size, int (*compare)(const void*, const void*)) { diff --git a/core/libs/prx/libc/src/Process.cpp b/core/libs/prx/libc/src/Process.cpp index fd873ea2a..2c272da0c 100644 --- a/core/libs/prx/libc/src/Process.cpp +++ b/core/libs/prx/libc/src/Process.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include "SceTypes.hpp" @@ -37,7 +38,21 @@ int atexit_nid_postfix(atexit_func_t func) { } int setenv_nid_postfix(const char* name, const char* value, int overwrite) { - return ::setenv(name, value, overwrite); + if (overwrite == 0 && std::getenv(name) != nullptr) { + return 0; + } + const size_t nameLength = std::strlen(name); + const size_t valueLength = std::strlen(value); + char* entry = static_cast(std::malloc(nameLength + valueLength + 2)); + if (entry == nullptr) { + errno = ENOMEM; + return -1; + } + std::memcpy(entry, name, nameLength); + entry[nameLength] = '='; + std::memcpy(entry + nameLength + 1, value, valueLength); + entry[nameLength + 1 + valueLength] = '\0'; + return ::putenv(entry); } }