From ee2891c55e0386ae803aa4d09a4e3110db3143ef Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 31 Mar 2026 20:12:41 +0200 Subject: [PATCH] [common] unify std::random_device (#3801) Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3801 Reviewed-by: CamilleLaVey Co-authored-by: lizzie Co-committed-by: lizzie --- src/common/CMakeLists.txt | 2 ++ src/common/random.cpp | 19 +++++++++++++++++++ src/common/random.h | 13 +++++++++++++ src/common/tiny_mt.h | 8 +------- src/common/uuid.cpp | 11 +++++------ src/core/file_sys/registered_cache.cpp | 7 ++----- .../board/nintendo/nx/k_system_control.cpp | 12 +++--------- .../board/nintendo/nx/k_system_control.h | 4 +++- src/core/hle/kernel/k_page_bitmap.h | 5 +++-- src/core/hle/kernel/k_thread.cpp | 9 ++++----- src/core/hle/service/mii/mii_util.h | 12 +++++++----- .../loader/deconstructed_rom_directory.cpp | 3 ++- src/core/loader/kip.cpp | 3 ++- src/core/loader/nro.cpp | 3 ++- src/frontend_common/settings_generator.cpp | 9 +++------ src/hid_core/frontend/input_converter.cpp | 19 +++++++++++-------- src/input_common/drivers/udp_client.cpp | 8 ++------ src/network/room.cpp | 4 +--- 18 files changed, 85 insertions(+), 66 deletions(-) create mode 100644 src/common/random.cpp create mode 100644 src/common/random.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 1ee4794272..98c1688441 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -134,6 +134,8 @@ add_library( typed_address.h uint128.h unique_function.h + random.cpp + random.h uuid.cpp uuid.h vector_math.h diff --git a/src/common/random.cpp b/src/common/random.cpp new file mode 100644 index 0000000000..d6865ee807 --- /dev/null +++ b/src/common/random.cpp @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "common/random.h" + +static std::random_device g_random_device; + +namespace Common::Random { + [[nodiscard]] u32 Random32(u32 seed) noexcept { + return g_random_device(); + } + [[nodiscard]] u64 Random64(u64 seed) noexcept { + return g_random_device(); + } + [[nodiscard]] std::mt19937 GetMT19937() noexcept { + return std::mt19937(g_random_device()); + } +} diff --git a/src/common/random.h b/src/common/random.h new file mode 100644 index 0000000000..83210f6dc2 --- /dev/null +++ b/src/common/random.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include "common/common_types.h" + +namespace Common::Random { + [[nodiscard]] u32 Random32(u32 seed) noexcept; + [[nodiscard]] u64 Random64(u64 seed) noexcept; + [[nodiscard]] std::mt19937 GetMT19937() noexcept; +} diff --git a/src/common/tiny_mt.h b/src/common/tiny_mt.h index c9f9ed4a5d..4b556a33eb 100644 --- a/src/common/tiny_mt.h +++ b/src/common/tiny_mt.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -218,12 +218,6 @@ public: return t0; } - u64 GenerateRandomU64() { - const u32 lo = this->GenerateRandomU32(); - const u32 hi = this->GenerateRandomU32(); - return (u64{hi} << 32) | u64{lo}; - } - float GenerateRandomF32() { // Floats have 24 bits of mantissa. constexpr u32 MantissaBits = 24; diff --git a/src/common/uuid.cpp b/src/common/uuid.cpp index 8f0dba452c..d4a5733c26 100644 --- a/src/common/uuid.cpp +++ b/src/common/uuid.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -10,6 +13,7 @@ #include "common/assert.h" #include "common/tiny_mt.h" #include "common/uuid.h" +#include "common/random.h" namespace Common { @@ -175,21 +179,16 @@ u128 UUID::AsU128() const { } UUID UUID::MakeRandom() { - std::random_device device; - - return MakeRandomWithSeed(device()); + return MakeRandomWithSeed(Common::Random::Random32(0)); } UUID UUID::MakeRandomWithSeed(u32 seed) { // Create and initialize our RNG. TinyMT rng; rng.Initialize(seed); - UUID uuid; - // Populate the UUID with random bytes. rng.GenerateRandomBytes(uuid.uuid.data(), sizeof(UUID)); - return uuid; } diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 61671ea333..af41820a36 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp @@ -12,6 +12,7 @@ #include "common/fs/path_util.h" #include "common/hex_util.h" #include "common/logging.h" +#include "common/random.h" #include "common/string_util.h" #include "core/crypto/key_manager.h" #include "core/file_sys/card_image.h" @@ -490,17 +491,13 @@ std::vector PlaceholderCache::List() const { } NcaID PlaceholderCache::Generate() { - std::random_device device; - std::mt19937 gen(device()); + auto gen = Common::Random::GetMT19937(); std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); - NcaID out{}; - const auto v1 = distribution(gen); const auto v2 = distribution(gen); std::memcpy(out.data(), &v1, sizeof(u64)); std::memcpy(out.data() + sizeof(u64), &v2, sizeof(u64)); - return out; } diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp index 1446653916..3343d1d282 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -7,6 +7,7 @@ #include #include "common/literals.h" +#include "common/random.h" #include "common/settings.h" #include "core/hle/kernel/board/nintendo/nx/k_system_control.h" @@ -201,15 +202,8 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) { } // Anonymous namespace -u64 KSystemControl::GenerateRandomU64() { - std::random_device device; - std::mt19937 gen(device()); - std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); - return distribution(gen); -} - u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { - return GenerateUniformRange(min, max, GenerateRandomU64); + return GenerateUniformRange(min, max, Common::Random::GetMT19937()); } size_t KSystemControl::CalculateRequiredSecureMemorySize(size_t size, u32 pool) { diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h index 60c5e58b73..41a25ba1c8 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -33,7 +36,6 @@ public: // Randomness. static u64 GenerateRandomRange(u64 min, u64 max); - static u64 GenerateRandomU64(); // Secure Memory. static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool); diff --git a/src/core/hle/kernel/k_page_bitmap.h b/src/core/hle/kernel/k_page_bitmap.h index fc21b81574..27bd682c5c 100644 --- a/src/core/hle/kernel/k_page_bitmap.h +++ b/src/core/hle/kernel/k_page_bitmap.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project @@ -14,6 +14,7 @@ #include "common/bit_util.h" #include "common/common_types.h" #include "common/tiny_mt.h" +#include "common/random.h" #include "core/hle/kernel/k_system_control.h" namespace Kernel { @@ -23,7 +24,7 @@ public: class RandomBitGenerator { public: RandomBitGenerator() { - m_rng.Initialize(static_cast(KSystemControl::GenerateRandomU64())); + m_rng.Initialize(u32(Common::Random::Random64(0))); } u64 SelectRandomBit(u64 bitmap) { diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 17bdb7b6fa..ea9b7eb114 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -20,6 +20,7 @@ #include "common/fiber.h" #include "common/logging.h" #include "common/settings.h" +#include "common/random.h" #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" @@ -45,8 +46,7 @@ namespace { constexpr inline s32 TerminatingThreadPriority = Kernel::Svc::SystemThreadPriorityHighest - 1; -static void ResetThreadContext32(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point, - u64 arg) { +static void ResetThreadContext32(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point, u64 arg) { ctx = {}; ctx.r[0] = arg; ctx.r[15] = entry_point; @@ -55,11 +55,10 @@ static void ResetThreadContext32(Kernel::Svc::ThreadContext& ctx, u64 stack_top, ctx.fpsr = 0; } -static void ResetThreadContext64(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point, - u64 arg) { +static void ResetThreadContext64(Kernel::Svc::ThreadContext& ctx, u64 stack_top, u64 entry_point, u64 arg) { ctx = {}; ctx.r[0] = arg; - ctx.r[18] = Kernel::KSystemControl::GenerateRandomU64() | 1; + ctx.r[18] = Common::Random::Random64(0) | 1; ctx.pc = entry_point; ctx.sp = stack_top; ctx.fpcr = 0; diff --git a/src/core/hle/service/mii/mii_util.h b/src/core/hle/service/mii/mii_util.h index 3534fa31d5..2ef006765c 100644 --- a/src/core/hle/service/mii/mii_util.h +++ b/src/core/hle/service/mii/mii_util.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,6 +10,7 @@ #include #include "common/common_types.h" +#include "common/random.h" #include "common/swap.h" #include "common/uuid.h" #include "core/hle/service/mii/mii_types.h" @@ -65,11 +69,9 @@ public: template static T GetRandomValue(T min, T max) { - std::random_device device; - std::mt19937 gen(device()); - std::uniform_int_distribution distribution(static_cast(min), - static_cast(max)); - return static_cast(distribution(gen)); + std::uniform_int_distribution distribution{u64(min), u64(max)}; + auto gen = Common::Random::GetMT19937(); + return T(distribution(gen)); } template diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 4e0b119f21..2ea63e137e 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -6,6 +6,7 @@ #include #include "common/logging.h" +#include "common/random.h" #include "common/settings.h" #include "core/core.h" #include "core/file_sys/content_archive.h" @@ -229,7 +230,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect // TODO: this is bad form of ASLR, it sucks size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue() ? ::Settings::values.rng_seed.GetValue() - : std::rand()) * 0x734287f27) & 0xfff000; + : Common::Random::Random64(0)) * 0x734287f27) & 0xfff000; // Setup the process code layout if (process.LoadFromMetadata(metadata, code_size, fastmem_base, aslr_offset, is_hbl).IsError()) { diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index db6c98c5a3..81449ac8b8 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -6,6 +6,7 @@ #include #include "common/settings.h" +#include "common/random.h" #include "core/file_sys/kernel_executable.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.h" @@ -90,7 +91,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, // TODO: this is bad form of ASLR, it sucks size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue() ? ::Settings::values.rng_seed.GetValue() - : std::rand()) * 0x734287f27) & 0xfff000; + : Common::Random::Random64(0)) * 0x734287f27) & 0xfff000; // Setup the process code layout if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), codeset.memory.size(), 0, aslr_offset, false).IsError()) { diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index b429aa9e80..e7c5ac01b1 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -11,6 +11,7 @@ #include "common/common_types.h" #include "common/logging.h" #include "common/settings.h" +#include "common/random.h" #include "common/swap.h" #include "core/core.h" #include "core/file_sys/control_metadata.h" @@ -243,7 +244,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, // TODO: this is bad form of ASLR, it sucks size_t aslr_offset = ((::Settings::values.rng_seed_enabled.GetValue() ? ::Settings::values.rng_seed.GetValue() - : std::rand()) * 0x734287f27) & 0xfff000; + : Common::Random::Random64(0)) * 0x734287f27) & 0xfff000; // Setup the process code layout if (process diff --git a/src/frontend_common/settings_generator.cpp b/src/frontend_common/settings_generator.cpp index 46625656b1..2b1a0f35d7 100644 --- a/src/frontend_common/settings_generator.cpp +++ b/src/frontend_common/settings_generator.cpp @@ -4,22 +4,21 @@ #include #include #include "common/settings.h" +#include "common/random.h" #include "settings_generator.h" namespace FrontendCommon { void GenerateSettings() { - static std::random_device rd; - + auto gen = Common::Random::GetMT19937(); // Web Token if (Settings::values.eden_token.GetValue().empty()) { static constexpr const size_t token_length = 48; static constexpr const frozen::string token_set = "abcdefghijklmnopqrstuvwxyz"; static std::uniform_int_distribution token_dist(0, token_set.size() - 1); std::string result; - for (size_t i = 0; i < token_length; ++i) { - size_t idx = token_dist(rd); + size_t idx = token_dist(gen); result += token_set[idx]; } Settings::values.eden_token.SetValue(result); @@ -27,8 +26,6 @@ void GenerateSettings() { // Randomly generated number because, well, we fill the rest automagically ;) // Other serial parts are filled by Region_Index - std::random_device device; - std::mt19937 gen(device()); std::uniform_int_distribution distribution(1, (std::numeric_limits::max)()); if (Settings::values.serial_unit.GetValue() == 0) Settings::values.serial_unit.SetValue(distribution(gen)); diff --git a/src/hid_core/frontend/input_converter.cpp b/src/hid_core/frontend/input_converter.cpp index f245a3f769..0709f5c930 100644 --- a/src/hid_core/frontend/input_converter.cpp +++ b/src/hid_core/frontend/input_converter.cpp @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include +#include "common/random.h" #include "common/input.h" #include "hid_core/frontend/input_converter.h" @@ -119,15 +123,14 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu .properties = properties, }; if (TransformToButton(callback).value) { - std::random_device device; - std::mt19937 gen(device()); std::uniform_int_distribution distribution(-5000, 5000); - status.accel.x.raw_value = static_cast(distribution(gen)) * 0.001f; - status.accel.y.raw_value = static_cast(distribution(gen)) * 0.001f; - status.accel.z.raw_value = static_cast(distribution(gen)) * 0.001f; - status.gyro.x.raw_value = static_cast(distribution(gen)) * 0.001f; - status.gyro.y.raw_value = static_cast(distribution(gen)) * 0.001f; - status.gyro.z.raw_value = static_cast(distribution(gen)) * 0.001f; + auto gen = Common::Random::GetMT19937(); + status.accel.x.raw_value = f32(distribution(gen)) * 0.001f; + status.accel.y.raw_value = f32(distribution(gen)) * 0.001f; + status.accel.z.raw_value = f32(distribution(gen)) * 0.001f; + status.gyro.x.raw_value = f32(distribution(gen)) * 0.001f; + status.gyro.y.raw_value = f32(distribution(gen)) * 0.001f; + status.gyro.z.raw_value = f32(distribution(gen)) * 0.001f; } break; } diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp index c930e19de3..fc216e3c9f 100644 --- a/src/input_common/drivers/udp_client.cpp +++ b/src/input_common/drivers/udp_client.cpp @@ -11,6 +11,7 @@ #include "common/logging.h" #include "common/param_package.h" +#include "common/random.h" #include "common/settings.h" #include "input_common/drivers/udp_client.h" #include "input_common/helpers/udp_protocol.h" @@ -31,7 +32,7 @@ public: explicit Socket(const std::string& host, u16 port, SocketCallback callback_) : callback(std::move(callback_)), timer(io_context), - socket(io_context, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()) { + socket(io_context, udp::endpoint(udp::v4(), 0)), client_id(Common::Random::Random32(0)) { boost::system::error_code ec{}; auto ipv4 = boost::asio::ip::make_address_v4(host, ec); if (ec.value() != boost::system::errc::success) { @@ -64,11 +65,6 @@ public: } private: - u32 GenerateRandomClientId() const { - std::random_device device; - return device(); - } - void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) { if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { switch (*type) { diff --git a/src/network/room.cpp b/src/network/room.cpp index 7c257d2bd4..2069673bae 100644 --- a/src/network/room.cpp +++ b/src/network/room.cpp @@ -23,8 +23,6 @@ namespace Network { class Room::RoomImpl { public: - std::mt19937 random_gen; ///< Random number generator. Used for GenerateFakeIPAddress - ENetHost* server = nullptr; ///< Network interface. std::atomic state{State::Closed}; ///< Current state of the room. @@ -51,7 +49,7 @@ public: IPBanList ip_ban_list; ///< List of banned IP addresses mutable std::mutex ban_list_mutex; ///< Mutex for the ban lists - RoomImpl() : random_gen(std::random_device()()) {} + RoomImpl() {} /// Thread that receives and dispatches network packets std::optional room_thread;