Merge pull request #3978 from zmeizy/claude/asprintf-guest-wide
fix(libc): format 16-bit wide arguments in asprintf on Linux
This commit is contained in:
commit
d2d4c07aab
|
|
@ -1,20 +1,15 @@
|
|||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "SceTypes.hpp"
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
#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<char, decltype(&std::free)> owner(text, std::free);
|
||||
const char* source = text;
|
||||
#endif
|
||||
if (count >= 0) {
|
||||
auto* output = static_cast<char*>(ApplicationHeapAllocate_nid_no_patch(static_cast<std::size_t>(count) + 1));
|
||||
if (output) {
|
||||
std::memcpy(output, source, static_cast<std::size_t>(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<VaList*>(args));
|
||||
#ifdef _WIN32
|
||||
__builtin_sysv_va_end(args);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/ApplicationHeap.hpp"
|
||||
#include "prx/libc/include/GuestHeap.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <cstdint>
|
||||
|
|
@ -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<void*, 10> api{reinterpret_cast<void*>(&Allocate), reinterpret_cast<void*>(&Release), reinterpret_cast<void*>(&Unused),
|
||||
reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&Unused), reinterpret_cast<void*>(&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; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue