mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
libc: fix UTF-16 printf strings and precision limits
This commit is contained in:
@@ -316,10 +316,9 @@ inline std::string SafeCsv(std::string_view text) {
|
|||||||
return std::string(text);
|
return std::string(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string Utf16ToUtf8(const char16_t* utf16) {
|
inline std::string Utf16ToUtf8(std::u16string_view utf16) {
|
||||||
std::u16string input(utf16);
|
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
||||||
return convert.to_bytes(input);
|
return convert.to_bytes(utf16.begin(), utf16.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ByteBuffer HexToBin(std::string_view text) {
|
inline ByteBuffer HexToBin(std::string_view text) {
|
||||||
|
|||||||
+31
-18
@@ -11,6 +11,7 @@
|
|||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/stringUtils.h"
|
||||||
#include "libs/vaContext.h"
|
#include "libs/vaContext.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
@@ -431,12 +432,13 @@ static size_t _etoa(out_fct_type out, std::vector<char>* buffer, size_t idx, siz
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int _strnlen_s(const char* str, size_t maxsize) {
|
template <typename Char>
|
||||||
const char* s = nullptr;
|
static size_t _strnlen_s(const Char* str, size_t maxsize) {
|
||||||
for (s = str; (*s != 0) && ((maxsize--) != 0u); ++s) {
|
size_t size = 0;
|
||||||
;
|
while (size < maxsize && str[size] != 0) {
|
||||||
|
++size;
|
||||||
}
|
}
|
||||||
return static_cast<unsigned int>(s - str);
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
@@ -694,26 +696,37 @@ static int kyty_printf_internal(bool sn, char* sn_s, size_t sn_n, const char* fo
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 's': {
|
case 's': {
|
||||||
// const char* p = va_arg(va, char*);
|
const size_t limit = (flags & FLAGS_PRECISION) != 0u ? precision : maxlen;
|
||||||
const char* p = VaArg_ptr<const char>(va_list);
|
const char* p = VaArg_ptr<const char>(va_list);
|
||||||
unsigned int l =
|
std::string converted;
|
||||||
_strnlen_s(p, precision != 0u ? precision : static_cast<size_t>(-1));
|
if ((flags & FLAGS_LONG) != 0u) {
|
||||||
// pre padding
|
// The guest ABI uses a 16-bit code unit for wchar_t.
|
||||||
if ((flags & FLAGS_PRECISION) != 0u) {
|
const auto* wide = reinterpret_cast<const char16_t*>(p);
|
||||||
l = (l < precision ? l : precision);
|
std::u16string_view text(wide, _strnlen_s(wide, limit));
|
||||||
|
if (text.size() == limit && !text.empty() &&
|
||||||
|
text.back() >= 0xd800 && text.back() <= 0xdbff) {
|
||||||
|
text.remove_suffix(1);
|
||||||
|
}
|
||||||
|
converted = Common::Utf16ToUtf8(text);
|
||||||
|
p = converted.c_str();
|
||||||
|
}
|
||||||
|
size_t length = _strnlen_s(p, limit);
|
||||||
|
if ((flags & FLAGS_LONG) != 0u && length < converted.size()) {
|
||||||
|
// A wide-string precision cannot split a multibyte character.
|
||||||
|
while (length != 0 && (static_cast<uint8_t>(p[length]) & 0xc0) == 0x80) {
|
||||||
|
--length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ((flags & FLAGS_LEFT) == 0u) {
|
if ((flags & FLAGS_LEFT) == 0u) {
|
||||||
while (l++ < width) {
|
for (size_t i = length; i < width; ++i) {
|
||||||
out(' ', &buffer, idx++, maxlen);
|
out(' ', &buffer, idx++, maxlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// string output
|
for (size_t i = 0; i < length; ++i) {
|
||||||
while ((*p != 0) && (((flags & FLAGS_PRECISION) == 0u) || ((precision--) != 0u))) {
|
out(p[i], &buffer, idx++, maxlen);
|
||||||
out(*(p++), &buffer, idx++, maxlen);
|
|
||||||
}
|
}
|
||||||
// post padding
|
|
||||||
if ((flags & FLAGS_LEFT) != 0u) {
|
if ((flags & FLAGS_LEFT) != 0u) {
|
||||||
while (l++ < width) {
|
for (size_t i = length; i < width; ++i) {
|
||||||
out(' ', &buffer, idx++, maxlen);
|
out(' ', &buffer, idx++, maxlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user