mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-29 12:15:39 +00:00
#5070 adds its own check before main() and rewrites the one-line main(), so defining CheckIntegerScanWidths there and calling it from main() made the two pull requests conflict. It now sits before RunChecks and runs after the other scanf checks.
318 lines
19 KiB
C++
318 lines
19 KiB
C++
#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>
|
|
#include <cstdio>
|
|
|
|
extern "C" {
|
|
int APS5_VABI snprintf_nid_postfix(char*, size_t, const char*, ...);
|
|
int APS5_VABI sprintf_nid_postfix(char*, const char*, ...);
|
|
int APS5_VABI printf_nid_postfix(const char*, ...);
|
|
int APS5_VABI libc_printf_nid_postfix(const char*, ...);
|
|
int APS5_VABI sscanf_nid_postfix(const char*, const char*, ...);
|
|
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 vsscanf_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*);
|
|
int* APS5_VABI __error_nid_postfix();
|
|
}
|
|
|
|
static void Require(bool condition) {
|
|
if (!condition) throw std::runtime_error("Formatting check failed");
|
|
}
|
|
|
|
static int APS5_VABI FormatList(char* buffer, size_t size, const char* format, ...) {
|
|
__builtin_sysv_va_list args;
|
|
__builtin_sysv_va_start(args, format);
|
|
VaList list;
|
|
std::memcpy(&list, args, sizeof(list));
|
|
const VaList original = list;
|
|
const int result = vsnprintf_nid_postfix(buffer, size, format, &list);
|
|
Require(std::memcmp(&list, &original, sizeof(list)) == 0);
|
|
__builtin_sysv_va_end(args);
|
|
return result;
|
|
}
|
|
|
|
static int APS5_VABI FormatListS(char* buffer, size_t size, const char* format, ...) {
|
|
__builtin_sysv_va_list args;
|
|
__builtin_sysv_va_start(args, format);
|
|
VaList list;
|
|
std::memcpy(&list, args, sizeof(list));
|
|
const int result = vsnprintf_s_nid_postfix(buffer, size, format, &list);
|
|
__builtin_sysv_va_end(args);
|
|
return result;
|
|
}
|
|
|
|
static int APS5_VABI ScanList(const char* buffer, const char* format, ...) {
|
|
__builtin_sysv_va_list args;
|
|
__builtin_sysv_va_start(args, format);
|
|
VaList list;
|
|
std::memcpy(&list, args, sizeof(list));
|
|
const int result = vsscanf_nid_postfix(buffer, format, &list);
|
|
__builtin_sysv_va_end(args);
|
|
return result;
|
|
}
|
|
|
|
static int APS5_VABI ScanListS(const char* buffer, const char* format, ...) {
|
|
__builtin_sysv_va_list args;
|
|
__builtin_sysv_va_start(args, format);
|
|
VaList list;
|
|
std::memcpy(&list, args, sizeof(list));
|
|
const int result = vsscanf_s_nid_postfix(buffer, format, &list);
|
|
__builtin_sysv_va_end(args);
|
|
return result;
|
|
}
|
|
|
|
static int APS5_VABI PrintList(const char* format, ...) {
|
|
__builtin_sysv_va_list args;
|
|
__builtin_sysv_va_start(args, format);
|
|
VaList list;
|
|
std::memcpy(&list, args, sizeof(list));
|
|
const int result = vprintf_nid_postfix(format, &list);
|
|
__builtin_sysv_va_end(args);
|
|
return result;
|
|
}
|
|
|
|
static bool CheckWidePrecision() {
|
|
const char16_t input[] = u"A\u00e9\u20ac\U0001f600Z";
|
|
const char* expected[] = {"", "A", "A", "A\xc3\xa9", "A\xc3\xa9", "A\xc3\xa9", "A\xc3\xa9\xe2\x82\xac",
|
|
"A\xc3\xa9\xe2\x82\xac", "A\xc3\xa9\xe2\x82\xac", "A\xc3\xa9\xe2\x82\xac",
|
|
"A\xc3\xa9\xe2\x82\xac\xf0\x9f\x98\x80", "A\xc3\xa9\xe2\x82\xac\xf0\x9f\x98\x80Z"};
|
|
bool correct = true;
|
|
for (int precision = 0; precision < 12; ++precision) {
|
|
char output[32];
|
|
std::memset(output, '!', sizeof(output));
|
|
const int count = snprintf_nid_postfix(output, sizeof(output), "%.*ls", precision, input);
|
|
const auto expectedSize = std::strlen(expected[precision]);
|
|
const bool matches = count == expectedSize && std::strcmp(output, expected[precision]) == 0 && output[expectedSize + 1] == '!';
|
|
if (!matches) std::fprintf(stderr, "wide precision %d: expected %zu complete UTF-8 bytes, received %d\n", precision, expectedSize, count);
|
|
correct &= matches;
|
|
}
|
|
if (!correct) return false;
|
|
char output[32];
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "[%5.1ls]", u"\u00e9") == 7 && std::strcmp(output, "[ ]") == 0);
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "[%-5.2ls]", u"\u00e9") == 7 && std::strcmp(output, "[\xc3\xa9 ]") == 0);
|
|
Require(FormatList(output, sizeof(output), "%.3ls", u"\U0001f600") == 0 && output[0] == 0);
|
|
Require(FormatList(output, sizeof(output), "%.*ls:%d", -1, u"\u00e9", 7) == 4 && std::strcmp(output, "\xc3\xa9:7") == 0);
|
|
const char16_t bounded[] = {u'A', u'B'};
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "%.2ls", bounded) == 2 && std::strcmp(output, "AB") == 0);
|
|
Require(snprintf_nid_postfix(nullptr, 0, "%.1ls", u"\u00e9") == 0);
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "%.1s", "\xc3\xa9") == 1 && static_cast<unsigned char>(output[0]) == 0xc3 && output[1] == 0);
|
|
Require(FormatList(output, sizeof(output), "%S:%lc:%C:%d", u"\u00e9", 0x20ac, 0x41, 7) == 10 && std::strcmp(output, "\xc3\xa9:\xe2\x82\xac:A:7") == 0);
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "%.*S", 3, u"\u00e9\u20ac") == 2 && std::strcmp(output, "\xc3\xa9") == 0);
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "[%ls]", static_cast<const char16_t*>(nullptr)) == 8 && std::strcmp(output, "[(null)]") == 0);
|
|
Require(snprintf_nid_postfix(output, sizeof(output), "a%lcb%C", 0, 0) == 4 && std::memcmp(output, "a\0b\0", 5) == 0);
|
|
Require(FormatList(output, sizeof(output), "%%ls:%2$d:%1$d", 3, 7) == 7 && std::strcmp(output, "%ls:7:3") == 0);
|
|
for (std::size_t capacity = 0; capacity <= 6; ++capacity) {
|
|
std::memset(output, '!', sizeof(output));
|
|
int count = -1;
|
|
Require(FormatList(capacity ? output : nullptr, capacity, "%ls%n", u"A\u00e9Z", &count) == 4 && count == 4);
|
|
const auto copied = capacity == 0 ? 0 : std::min<std::size_t>(capacity - 1, 4);
|
|
Require(std::memcmp(output, "A\xc3\xa9Z", copied) == 0 && output[capacity] == '!');
|
|
if (capacity) Require(output[copied] == 0);
|
|
}
|
|
return correct;
|
|
}
|
|
|
|
static void CheckIntegerScanWidths() {
|
|
int value = 7;
|
|
*__error_nid_postfix() = 0;
|
|
Require(sscanf_nid_postfix("2147483648", "%d", &value) == 1 && value == -2147483647 - 1 && *__error_nid_postfix() == 0);
|
|
Require(sscanf_nid_postfix("0xFFFFFFFF", "%i", &value) == 1 && value == -1 && *__error_nid_postfix() == 0);
|
|
Require(sscanf_nid_postfix("99999999999999999999", "%d", &value) == 1 && value == -1 && *__error_nid_postfix() == 34);
|
|
unsigned unsignedValue = 7;
|
|
Require(sscanf_nid_postfix("4294967296", "%u", &unsignedValue) == 1 && unsignedValue == 0);
|
|
Require(sscanf_nid_postfix("100000001", "%x", &unsignedValue) == 1 && unsignedValue == 1);
|
|
Require(sscanf_nid_postfix("40000000001", "%o", &unsignedValue) == 1 && unsignedValue == 1);
|
|
short shortValue = 7;
|
|
Require(sscanf_nid_postfix("5000000000", "%hd", &shortValue) == 1 && shortValue == -3584);
|
|
signed char charValue = 7;
|
|
Require(sscanf_nid_postfix("300", "%hhd", &charValue) == 1 && charValue == 44);
|
|
long long quad = 7;
|
|
Require(sscanf_nid_postfix("3000000000", "%qd", &quad) == 1 && quad == 3000000000ll);
|
|
unsigned long long unsignedQuad = 7;
|
|
Require(sscanf_nid_postfix("ffffffffff", "%qx", &unsignedQuad) == 1 && unsignedQuad == 0xffffffffffull);
|
|
int first = 7;
|
|
int second = 7;
|
|
int position = 0;
|
|
Require(sscanf_nid_postfix("12 34", "%d %d%n", &first, &second, &position) == 2 && first == 12 && second == 34 && position == 5);
|
|
value = 7;
|
|
Require(sscanf_nid_postfix("x", "%d", &value) == 0 && value == 7);
|
|
Require(sscanf_nid_postfix("1 x", "%d %d", &first, &value) == 1 && first == 1 && value == 7);
|
|
}
|
|
|
|
__attribute__((noinline)) static void APS5_VABI RunChecks() {
|
|
char buffer[1024];
|
|
Require(FormatList(buffer, sizeof(buffer), "Mount requested: %d", 0) == 18);
|
|
Require(std::strcmp(buffer, "Mount requested: 0") == 0);
|
|
for (int index = 0; index < 10000; ++index) {
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%d %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7, 8);
|
|
Require(std::strcmp(buffer, "1 2 3 4 5 6 7 8") == 0);
|
|
FormatList(buffer, sizeof(buffer), "%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %d", 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11);
|
|
Require(std::strcmp(buffer, "1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11") == 0);
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%ld %lu %lld %zu %td %jd", -4294967297LL, 4294967297ULL, -5LL, 7ULL, -8LL, 9LL);
|
|
Require(std::strcmp(buffer, "-4294967297 4294967297 -5 7 -8 9") == 0);
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%s:%*.*f:%d", "test", -8, 2, 1.25, 7);
|
|
Require(std::strcmp(buffer, "test:1.25 :7") == 0);
|
|
FormatList(buffer, sizeof(buffer), "%d %d %d %d %d %d %d %.3Lf %.1f", 1, 2, 3, 4, 5, 6, 7, 1.125L, 2.5);
|
|
Require(std::strcmp(buffer, "1 2 3 4 5 6 7 1.125 2.5") == 0);
|
|
}
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f", 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.);
|
|
Require(std::strcmp(buffer, "1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0") == 0);
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%.3Lf %d %.1f", 1.125L, 7, 2.5);
|
|
Require(std::strcmp(buffer, "1.125 7 2.5") == 0);
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "%'d|%'u|%'.2f|%'-8ld|%'+05d|%'g", 1234567, 4000000000u, 1234567.891, 1234567LL, 42, 1e6) == 50);
|
|
Require(std::strcmp(buffer, "1234567|4000000000|1234567.89|1234567 |+0042|1e+06") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "%'lld %'zu", 1234567890123LL, static_cast<std::size_t>(9876543210)) == 24 && std::strcmp(buffer, "1234567890123 9876543210") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "%'d %ls", 1234567, u"x") == 9 && std::strcmp(buffer, "1234567 x") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "%2$s %1$d %2$s", 7, "x") == 5 && std::strcmp(buffer, "x 7 x") == 0);
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "%3$.1Lf|%2$.2f|%1$hhd|%4$s", 257, 2.5, 1.5L, "end") == 14);
|
|
Require(std::strcmp(buffer, "1.5|2.50|1|end") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "%9$d%8$d%7$d%6$d%5$d%4$d%3$d%2$d%1$d", 1, 2, 3, 4, 5, 6, 7, 8, 9) == 9 && std::strcmp(buffer, "987654321") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "%11$d %10$g %9$g %8$g %7$g %6$g %5$g %4$g %3$g %2$g %1$g", 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11) == 23 &&
|
|
std::strcmp(buffer, "11 10 9 8 7 6 5 4 3 2 1") == 0);
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%1$*2$.*3$f][%1$-*2$.1f][%4$*2$c]", 3.5, 7, 2, 'z') == 27);
|
|
Require(std::strcmp(buffer, "[ 3.50][3.5 ][ z]") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "[%2$*1$d][%2$.*1$d]", -4, 5) == 9 && std::strcmp(buffer, "[5 ][5]") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "[%1$*2$d]", 5, 3) == 5 && std::strcmp(buffer, "[ 5]") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "%2$ls|%1$C|%3$d", 0x41, u"\u00e9", 7) == 6 && std::strcmp(buffer, "\xc3\xa9|A|7") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "%2$d %d %ls|%*5$d|%1$d", 1, 2, 3, u"x", 4) == 12 && std::strcmp(buffer, "2 3 x| 4|1") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "[%*3$d]%ls", 5, u"", 3) == 5 && std::strcmp(buffer, "[ 5]") == 0);
|
|
const char* const invalidPositions[] = {"%0$d%ls", "%100$d%ls", "%*0$d%ls"};
|
|
for (const char* format : invalidPositions) {
|
|
bool threw = false;
|
|
try {
|
|
FormatList(buffer, sizeof(buffer), format, 1, u"");
|
|
} catch (const std::invalid_argument&) {
|
|
threw = true;
|
|
}
|
|
Require(threw);
|
|
}
|
|
char expected[1024];
|
|
std::snprintf(expected, sizeof(expected), "%#08x %.3e %a %g 0x%llx", 42u, 1.25, 1.25, 1.25,
|
|
static_cast<unsigned long long>(reinterpret_cast<std::uintptr_t>(buffer)));
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%#08x %.3e %a %g %p", 42u, 1.25, 1.25, 1.25, static_cast<void*>(buffer));
|
|
Require(std::strcmp(buffer, expected) == 0);
|
|
#ifdef _WIN32
|
|
char pointers[128];
|
|
const auto address = [](std::uintptr_t value) { return reinterpret_cast<void*>(value); };
|
|
Require(snprintf_nid_postfix(pointers, sizeof(pointers), "%p|%p|%p", address(0), address(0x1234), address(0xdeadbeef12)) == 23 &&
|
|
std::strcmp(pointers, "0x0|0x1234|0xdeadbeef12") == 0);
|
|
Require(snprintf_nid_postfix(pointers, sizeof(pointers), "[%8p][%-8p][%08p][%.6p][%10.4p][%.0p]",
|
|
address(0x1a), address(0x1a), address(0x1a), address(0x1a), address(0x1a), address(0)) == 56 &&
|
|
std::strcmp(pointers, "[ 0x1a][0x1a ][0x00001a][0x00001a][ 0x001a][0x]") == 0);
|
|
Require(snprintf_nid_postfix(pointers, sizeof(pointers), "[%+p][% p][%#p][%*p][%-*p]", address(0x1a), address(0x1a),
|
|
address(0x1a), 6, address(0xf), -6, address(0xf)) == 34 &&
|
|
std::strcmp(pointers, "[0x1a][0x1a][0x1a][ 0xf][0xf ]") == 0);
|
|
Require(snprintf_nid_postfix(pointers, 6, "%p", address(0xabcdef)) == 8 && std::strcmp(pointers, "0xabc") == 0);
|
|
#endif
|
|
snprintf_nid_postfix(buffer, sizeof(buffer), "%.*s", -1, "unlimited");
|
|
Require(std::strcmp(buffer, "unlimited") == 0);
|
|
buffer[5] = '!';
|
|
Require(snprintf_nid_postfix(buffer, 5, "%s", "abcdef") == 6);
|
|
Require(std::strcmp(buffer, "abcd") == 0 && buffer[5] == '!');
|
|
Require(snprintf_nid_postfix(nullptr, 0, "%s:%d", "abcdef", 123) == 10);
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%s]", static_cast<const char*>(nullptr)) == 8 && std::strcmp(buffer, "[(null)]") == 0);
|
|
buffer[0] = 'x';
|
|
Require(snprintf_nid_postfix(buffer, 1, "%d", 123) == 3 && buffer[0] == 0);
|
|
Require(sprintf_nid_postfix(buffer, "%hhd %hhu %hd %hu %%", 255, 257, 65535, 65537) == 11);
|
|
Require(std::strcmp(buffer, "-1 1 -1 1 %") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "[%#.0o][%#.o][%#5.0o][%-#4.0o][%#.*o][%#.0o][%.0o][%#o][%#.3o]", 0u, 0u, 0u, 0u, 0, 0u, 8u, 0u, 0u, 0u) == 37);
|
|
Require(std::strcmp(buffer, "[0][0][ 0][0 ][0][010][][0][000]") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "[%#.0lo][%#.0hho][%#.0x]", 0ull, 0u, 0u) == 8 && std::strcmp(buffer, "[0][0][]") == 0);
|
|
Require(FormatList(buffer, sizeof(buffer), "[%#.0o][%ls]", 0u, u"x") == 6 && std::strcmp(buffer, "[0][x]") == 0);
|
|
Require(sprintf_nid_postfix(buffer, "%d %d %d %d %d %d", 1, 2, 3, 4, 5, 6) == 11);
|
|
Require(std::strcmp(buffer, "1 2 3 4 5 6") == 0);
|
|
int first = 0, second = 0, third = 0, fourth = 0, fifth = 0, sixth = 0;
|
|
char word[16] = {};
|
|
double real = 0.0;
|
|
Require(sscanf_nid_postfix("1 2 3 4 5 6 seven 8.5", "%d %d %d %d %d %d %15s %lf",
|
|
&first, &second, &third, &fourth, &fifth, &sixth, word, &real) == 8);
|
|
Require(first == 1 && second == 2 && third == 3 && fourth == 4 && fifth == 5 && sixth == 6);
|
|
Require(std::strcmp(word, "seven") == 0 && real == 8.5);
|
|
int binary = -1, binaryEnd = -1;
|
|
char binaryRest[8] = {};
|
|
Require(sscanf_nid_postfix("0b101", "%i%n%7s", &binary, &binaryEnd, binaryRest) == 2);
|
|
Require(binary == 0 && binaryEnd == 1 && std::strcmp(binaryRest, "b101") == 0);
|
|
Require(ScanList(" -0B11", "%i", &binary) == 1 && binary == 0);
|
|
Require(ScanListS("0b1", "%i", &binary) == 1 && binary == 0);
|
|
Require(sscanf_nid_postfix("0x1f", "%i", &binary) == 1 && binary == 31);
|
|
#ifdef _WIN32
|
|
int scanned = -1;
|
|
int position = -1;
|
|
Require(sscanf_nid_postfix("12", "%*d%d", &scanned) == 0 && scanned == -1);
|
|
Require(sscanf_nid_postfix("12 ", "%*d %d", &scanned) == 0);
|
|
Require(sscanf_nid_postfix("abc", "%*s%d", &scanned) == 0);
|
|
Require(sscanf_nid_postfix("a", "%*c%d", &scanned) == 0);
|
|
Require(sscanf_nid_postfix("abc", "%*[a-z]%d", &scanned) == 0);
|
|
Require(sscanf_nid_postfix("12", "%*d%n%d", &position, &scanned) == 0 && position == 2);
|
|
Require(sscanf_nid_postfix("12", "%*d%d%d", &scanned, &first) == 0);
|
|
Require(sscanf_nid_postfix("1 2", "%d%*d%d", &scanned, &first) == 1 && scanned == 1);
|
|
Require(sscanf_nid_postfix("1 2 3", "%*d %d %*d", &scanned) == 1 && scanned == 2);
|
|
Require(sscanf_nid_postfix("", "%*d", &scanned) == EOF);
|
|
Require(sscanf_nid_postfix(" ", "%*d%d", &scanned) == EOF);
|
|
Require(sscanf_nid_postfix("", "%d", &scanned) == EOF);
|
|
#else
|
|
char16_t wide[4] = {u'!', u'!', u'!', u'!'};
|
|
const auto rejects = [&](const char* format) {
|
|
try { sscanf_nid_postfix("ab cd", format, wide); } catch (const std::runtime_error&) { return wide[0] == u'!'; }
|
|
return false;
|
|
};
|
|
Require(rejects("%ls") && rejects("%*s %3lc") && rejects("%l[a-z]") && rejects("%S") && rejects("%2$C") && rejects("%'ls"));
|
|
const auto secureRejects = [&](const char* format) {
|
|
try { ScanListS("ab cd", format, wide, 4u); } catch (const std::runtime_error&) { return wide[0] == u'!'; }
|
|
return false;
|
|
};
|
|
Require(secureRejects("%ls") && secureRejects("%lc"));
|
|
char narrow[8] = {};
|
|
Require(sscanf_nid_postfix("ab%", "%7[^%ls]", narrow) == 1 && std::strcmp(narrow, "ab") == 0);
|
|
#endif
|
|
long long count = -1;
|
|
int smallCount = -1;
|
|
Require(snprintf_nid_postfix(buffer, 3, "abcd%lnEF%n", &count, &smallCount) == 6);
|
|
Require(count == 4 && smallCount == 6 && std::strcmp(buffer, "ab") == 0);
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "a%cb", 0) == 3);
|
|
Require(buffer[0] == 'a' && buffer[1] == 0 && buffer[2] == 'b' && buffer[3] == 0);
|
|
*__error_nid_postfix() = 35;
|
|
Require(snprintf_nid_postfix(buffer, sizeof(buffer), "[%m][%.8m][%-10.5m][%d]", 7) == 59);
|
|
Require(std::strcmp(buffer, "[Resource temporarily unavailable][Resource][Resou ][7]") == 0);
|
|
Require(*__error_nid_postfix() == 35);
|
|
*__error_nid_postfix() = 63;
|
|
Require(FormatList(buffer, sizeof(buffer), "%s: %m", "open") == 24 && std::strcmp(buffer, "open: File name too long") == 0);
|
|
Require(printf_nid_postfix("printf: %d %.1f\n", 7, 2.5) == 14);
|
|
Require(libc_printf_nid_postfix("libc_printf: %s\n", "OK") == 16);
|
|
Require(libc_printf_nid_postfix("%d %d %d %d %d %d %d\n", 1, 22, 333, 4444, 55555, 666666, 7777777) == 35);
|
|
Require(PrintList("vprintf: %d\n", 42) == 12);
|
|
Require(FormatListS(buffer, sizeof(buffer), "%d-%s", 42, "x") == 4 && std::strcmp(buffer, "42-x") == 0);
|
|
int scanNum = 0;
|
|
char scanWord[8] = {};
|
|
Require(ScanListS("123 test", "%d %s", &scanNum, scanWord, 8u) == 2 && scanNum == 123 && std::strcmp(scanWord, "test") == 0);
|
|
char tooSmall[4] = {'x', 'x', 'x', 'x'};
|
|
Require(ScanListS("abcdef", "%s", tooSmall, 4u) == 0 && tooSmall[0] == '\0');
|
|
CheckIntegerScanWidths();
|
|
std::puts("Formatting checks passed: 10000 iterations");
|
|
}
|
|
|
|
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; }
|