diff --git a/core/libs/prx/libc/src/AllocatingStrings.cpp b/core/libs/prx/libc/src/AllocatingStrings.cpp index 74779c475..2e91cc215 100644 --- a/core/libs/prx/libc/src/AllocatingStrings.cpp +++ b/core/libs/prx/libc/src/AllocatingStrings.cpp @@ -1,20 +1,15 @@ #include "prx/libc/include/ApplicationHeap.hpp" #include "prx/libc/include/General.hpp" +#include "SceTypes.hpp" #include #include -#include -#include #include -#include #include -#include - -#ifdef _WIN32 -#include "prx/libc/include/WindowsFormatting.hpp" -#endif extern "C" { +int APS5_VABI vasprintf_nid_postfix(char** destination, const char* format, VaList* args); + char* APS5_VABI strndup_nid_postfix(const char* source, std::size_t limit) { std::size_t length = 0; while (length < limit && source[length] != '\0') ++length; @@ -35,9 +30,6 @@ char* APS5_VABI strdup_nid_postfix(const char* source) { } int APS5_VABI asprintf_nid_postfix(char** destination, const char* format, ...) { - if (!destination) { errno = 22; return -1; } - *destination = nullptr; - if (!format) { errno = 22; return -1; } #ifdef _WIN32 __builtin_sysv_va_list args; __builtin_sysv_va_start(args, format); @@ -45,36 +37,7 @@ int APS5_VABI asprintf_nid_postfix(char** destination, const char* format, ...) std::va_list args; va_start(args, format); #endif - int result = -1; - try { -#ifdef _WIN32 - std::string text; - const int count = LibcDetail::FormatWindows(nullptr, 0, format, args, &text); - const char* source = text.c_str(); -#else - char* text = nullptr; - const int count = ::vasprintf(&text, format, args); - std::unique_ptr owner(text, std::free); - const char* source = text; -#endif - if (count >= 0) { - auto* output = static_cast(ApplicationHeapAllocate_nid_no_patch(static_cast(count) + 1)); - if (output) { - std::memcpy(output, source, static_cast(count) + 1); - *destination = output; - result = count; - } else errno = 12; - } - } catch (const std::bad_alloc&) { - errno = 12; - } catch (...) { -#ifdef _WIN32 - __builtin_sysv_va_end(args); -#else - va_end(args); -#endif - throw; - } + const int result = vasprintf_nid_postfix(destination, format, reinterpret_cast(args)); #ifdef _WIN32 __builtin_sysv_va_end(args); #else diff --git a/core/libs/tests/Formatting.cpp b/core/libs/tests/Formatting.cpp index 0b83a58c1..ca97bddf2 100644 --- a/core/libs/tests/Formatting.cpp +++ b/core/libs/tests/Formatting.cpp @@ -1,5 +1,9 @@ #include "SceTypes.hpp" +#include "prx/libc/include/ApplicationHeap.hpp" +#include "prx/libc/include/GuestHeap.hpp" #include +#include +#include #include #include #include @@ -15,6 +19,8 @@ int APS5_VABI vsnprintf_nid_postfix(char*, size_t, const char*, VaList*); int APS5_VABI vsnprintf_s_nid_postfix(char*, size_t, const char*, VaList*); int APS5_VABI vsscanf_s_nid_postfix(const char*, const char*, VaList*); int APS5_VABI vprintf_nid_postfix(const char*, VaList*); +int APS5_VABI asprintf_nid_postfix(char**, const char*, ...); +void APS5_VABI free_nid_postfix(void*); } static void Require(bool condition) { @@ -228,4 +234,17 @@ __attribute__((noinline)) static void APS5_VABI RunChecks() { std::puts("Formatting checks passed: 10000 iterations"); } -int main() { RunChecks(); return CheckWidePrecision() ? 0 : 1; } +static void* APS5_VABI Allocate(std::size_t bytes) { return GuestHeap::GuestHeapAllocate_nid_postfix(bytes); } +static void APS5_VABI Release(void* pointer) { GuestHeap::GuestHeapFree_nid_postfix(pointer); } +static void* APS5_VABI Unused() { std::abort(); } + +static void CheckAllocatingFormat() { + const std::array api{reinterpret_cast(&Allocate), reinterpret_cast(&Release), reinterpret_cast(&Unused), + reinterpret_cast(&Unused), reinterpret_cast(&Unused), reinterpret_cast(&Unused), reinterpret_cast(&Unused)}; + ApplicationHeapRegister_nid_no_patch(api.data()); + char* allocated = nullptr; + Require(asprintf_nid_postfix(&allocated, "%ls:%S:%lc:%d", u"\u00e9", u"ab", 0x20ac, 7) == 11 && std::strcmp(allocated, "\xc3\xa9:ab:\xe2\x82\xac:7") == 0); + free_nid_postfix(allocated); +} + +int main() { RunChecks(); CheckAllocatingFormat(); return CheckWidePrecision() ? 0 : 1; }