From 5ac10820ea011514bb1eab9d398fd6f0364a8f14 Mon Sep 17 00:00:00 2001 From: Hannah Lyons <7751607+babyhuey@users.noreply.github.com> Date: Thu, 8 Oct 2026 11:24:12 -0400 Subject: [PATCH] feat(libScePosixForWebKit): implement arc4random_buf --- core/libs/CMakeLists.txt | 10 +++++ core/libs/prx/libScePosixForWebKit/Export.cpp | 13 +++++++ core/libs/tests/GuestPosixRandom.cpp | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 core/libs/tests/GuestPosixRandom.cpp diff --git a/core/libs/CMakeLists.txt b/core/libs/CMakeLists.txt index 32eb46fa5..bae33c894 100644 --- a/core/libs/CMakeLists.txt +++ b/core/libs/CMakeLists.txt @@ -238,4 +238,14 @@ if(BUILD_TESTING) set_tests_properties(savedata_native_write_replacement PROPERTIES ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$") endif() + + add_test_executable(guest_posix_random_tests tests/GuestPosixRandom.cpp) + target_include_directories(guest_posix_random_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(guest_posix_random_tests PRIVATE libScePosixForWebKit) + configure_windows_unwind(guest_posix_random_tests) + add_test(NAME guest_posix_random COMMAND guest_posix_random_tests) + if(WIN32) + set_tests_properties(guest_posix_random PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() endif() diff --git a/core/libs/prx/libScePosixForWebKit/Export.cpp b/core/libs/prx/libScePosixForWebKit/Export.cpp index 71f7b26f6..509ea37a9 100644 --- a/core/libs/prx/libScePosixForWebKit/Export.cpp +++ b/core/libs/prx/libScePosixForWebKit/Export.cpp @@ -1,5 +1,9 @@ #include "prx/libc/include/general/VabiMacros.hpp" +#include #include +#include +#include +#include extern "C" { @@ -19,4 +23,13 @@ char* APS5_VABI strcasestr_nid_postfix(const char* text, const char* needle) { return nullptr; } +void APS5_VABI arc4random_buf_nid_postfix(void* buffer, std::size_t size) { + static thread_local std::random_device device; + auto* bytes = static_cast(buffer); + for (std::size_t offset = 0; offset < size; offset += sizeof(unsigned int)) { + const unsigned int value = device(); + std::memcpy(bytes + offset, &value, std::min(sizeof(value), size - offset)); + } +} + } diff --git a/core/libs/tests/GuestPosixRandom.cpp b/core/libs/tests/GuestPosixRandom.cpp new file mode 100644 index 000000000..43526c711 --- /dev/null +++ b/core/libs/tests/GuestPosixRandom.cpp @@ -0,0 +1,37 @@ +#include "prx/libc/include/general/VabiMacros.hpp" +#include +#include +#include +#include +#include +#include + +extern "C" void APS5_VABI arc4random_buf_nid_postfix(void*, std::size_t); + +void Require(bool condition, std::source_location location = std::source_location::current()) { + if (!condition) { + std::fprintf(stderr, "Posix random check failed at line %u\n", location.line()); + std::abort(); + } +} + +int main() { + std::array first{}; + std::array second{}; + first.fill(0xa5); + arc4random_buf_nid_postfix(first.data(), 0); + Require(std::all_of(first.begin(), first.end(), [](unsigned char value) { return value == 0xa5; })); + for (const std::size_t size : {1u, 3u, 5u, 4098u}) { + first.fill(0xa5); + arc4random_buf_nid_postfix(first.data(), size); + Require(std::all_of(first.begin() + static_cast(size), first.end(), + [](unsigned char value) { return value == 0xa5; })); + } + arc4random_buf_nid_postfix(first.data(), first.size()); + arc4random_buf_nid_postfix(second.data(), second.size()); + Require(first != second); + std::array counts{}; + for (const auto value : first) ++counts[value]; + Require(*std::max_element(counts.begin(), counts.end()) < 64); + return 0; +}