Repository: LadybirdBrowser/ladybird
File: AK/Random.cpp (C++)

Code before:
    // it doesn't seem to be required.
    arc4random_buf(buf, size);
#elif defined(AK_OS_LINUX)
    int ret;
    while (size > 0u) {
        // We are checking for all error codes out of an abundance of caution, however EINTR is the only one that's very plausible to happen.
        ret = getrandom(buf, size, 0);

        // EINTR can be handled safely by just trying again
        if (ret == -1 && errno != EINTR) [[unlikely]]
            return Error::from_errno(errno);

        // Per the manual:
        //
        // > On success, getrandom() returns the number of bytes that were
        // > copied to the buffer buf.  This may be less than the number of
        // > bytes requested via buflen if either GRND_RANDOM was specified in
        // > flags and insufficient entropy was present in the random source or
        // > the system call was interrupted by a signal.
        //
        // > The user of getrandom() *must* always check the return value, to
        // > determine whether either an error occurred or fewer bytes than
        // > requested were returned.
        if (ret > 0) [[likely]] {
            size -= ret;
            buf += ret;
        }
    }
#elif defined(AK_OS_WINDOWS)
    // Documented to always return TRUE
    g_system.ProcessPrng((PBYTE)buf, size);
#else
    // There shouldn't be a build target where this can happen.
    static_assert(false, "This build target doesn't have a valid CSPRNG interface specified in AK/Random.cpp.");
#endif
    return {};
}

namespace AK {

void fill_with_random(Bytes bytes)
{
    MUST(csprng(bytes.data(), bytes.size()));
}

u32 get_random_uniform(u32 max_bounds)
{
    // If we try to divide all 2**32 numbers into groups of "max_bounds" numbers, we may end up
    // with a group around 2**32-1 that is a bit too small. For this reason, the implementation
    // `arc4random() % max_bounds` would be insufficient. Here we compute the last number of the
    // last "full group". Note that if max_bounds is a divisor of UINT32_MAX,

Review comment (suggestion):
Please rebase to have CI rerun. Also check for compile errors locally as this doesn't appear to compile, and even if it did after fixing the const issue and we allowed the gnu extension, it is a code smell. You are doing void* arithmetic here. Also you are assigning to a const variable. https://godbolt.org/z/z54bW34z1
This whole thing is very verbose too, like it was said previously. 

Code after:
    while (size > 0u) {
        // EINTR can be handled safely by just trying again. Others are fatal
        // See manual for more details
        int ret = getrandom(out, size, 0);
        if (ret == -1 && errno != EINTR) [[unlikely]]
            return Error::from_errno(errno);

        // If ret > 0 then ret indicates how much was copied
        if (ret > 0) [[likely]] {
            size -= ret;
            out += ret;
        }
    }
#elif defined(AK_OS_WINDOWS)
    // Documented to always return TRUE
    g_system.ProcessPrng((PBYTE)buf, size);
#else
    static_assert(false, "This build target doesn't have a valid CSPRNG interface specified in AK/Random.cpp.");
#endif
    return {};
}

namespace AK {

void fill_with_random(Bytes bytes)
{
    MUST(csprng(bytes.data(), bytes.size()));
}

u32 get_random_uniform(u32 max_bounds)
{
    // If we try to divide all 2**32 numbers into groups of "max_bounds" numbers, we may end up
    // with a group around 2**32-1 that is a bit too small. For this reason, the implementation
    // `arc4random() % max_bounds` would be insufficient. Here we compute the last number of the
    // last "full group". Note that if max_bounds is a divisor of UINT32_MAX,
    // then we end up with UINT32_MAX:
    u32 const max_usable = UINT32_MAX - (static_cast<u64>(UINT32_MAX) + 1) % max_bounds;
    auto random_value = get_random<u32>();
    for (int i = 0; i < 20 && random_value > max_usable; ++i) {
        // By chance we picked a value from the incomplete group. Note that this group has size at
        // most 2**31-1, so picking this group has a chance of less than 50%.
        // In practice, this means that for the worst possible input, there is still only a
        // once-in-a-million chance to get to iteration 20. In theory we should be able to loop
        // forever. Here we prefer marginally imperfect random numbers over weird runtime behavior.
        random_value = get_random<u32>();
    }
    return random_value % max_bounds;
}

u64 get_random_uniform_64(u64 max_bounds)
{