#include "prx/libc/include/Api.hpp" #include #include #include #include #include #include #include #include #include static void Require(bool condition) { if (!condition) { std::fputs("GuestStrncmpBoundary check failed\n", stderr); std::abort(); } } #ifdef _WIN32 #include #else #include #include #endif class Buffer { unsigned char* allocation; std::size_t page; public: Buffer() { #ifdef _WIN32 SYSTEM_INFO info{}; GetSystemInfo(&info); page = info.dwPageSize; allocation = static_cast(VirtualAlloc(nullptr, page * 3, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS)); Require(allocation != nullptr); DWORD previous; Require(VirtualProtect(allocation + page, page, PAGE_READWRITE, &previous) != 0); #else const long size = sysconf(_SC_PAGESIZE); Require(size > 0); page = static_cast(size); allocation = static_cast(mmap(nullptr, page * 3, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); Require(allocation != MAP_FAILED); Require(mprotect(allocation + page, page, PROT_READ | PROT_WRITE) == 0); #endif std::memset(allocation + page, 0xa5, page); } ~Buffer() { #ifdef _WIN32 Require(VirtualFree(allocation, 0, MEM_RELEASE) != 0); #else Require(munmap(allocation, page * 3) == 0); #endif } Buffer(const Buffer&) = delete; Buffer& operator=(const Buffer&) = delete; template T* At(std::size_t count) { Require(count <= (page - 32) / sizeof(T)); return reinterpret_cast(allocation + page * 2 - (std::max)(count, std::size_t{1}) * sizeof(T)); } }; template static void Prefix(const T* data) { for (int index = 1; index <= 8; ++index) Require(data[-index] == static_cast(sizeof(T) == 1 ? 0xa5 : 0xa5a5)); } static int Sign(int value) { return (value > 0) - (value < 0); } int main() { Buffer first, second; for (std::size_t count = 0; count <= 128; ++count) { auto* left = first.At(count); auto* right = second.At(count); const auto extent = (std::max)(count, std::size_t{1}); for (int mode = 0; mode < 7; ++mode) { for (std::size_t index = 0; index < extent; ++index) left[index] = right[index] = static_cast(1 + (index * 131 + count) % 255); if (count != 0) { const std::size_t position = mode % 3 == 0 ? 0 : mode % 3 == 1 ? count / 2 : count - 1; if (mode < 3) { left[position] = 255; right[position] = 1; } if (mode >= 3 && mode < 6) { left[position] = right[position] = 0; } if (mode != 6 && position + 1 < count) { left[position + 1] = 1; right[position + 1] = 255; } } int expected = 0; for (std::size_t index = 0; index < count; ++index) { if (left[index] != right[index]) { expected = static_cast(left[index]) - right[index]; break; } if (left[index] == 0) break; } const std::vector a(left, left + extent), b(right, right + extent); Require(Sign(strncmp_nid_postfix(reinterpret_cast(left), reinterpret_cast(right), count)) == Sign(expected)); Require(Sign(strncmp_nid_postfix(reinterpret_cast(right), reinterpret_cast(left), count)) == -Sign(expected)); Require(std::equal(a.begin(), a.end(), left) && std::equal(b.begin(), b.end(), right)); } } }