Coverage Report

Created: 2026-02-14 08:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/AK/Random.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Platform.h>
10
#include <AK/Span.h>
11
#include <AK/StdLibExtras.h>
12
#include <AK/Types.h>
13
#include <stdlib.h>
14
15
#if defined(__unix__)
16
#    include <unistd.h>
17
#endif
18
19
namespace AK {
20
21
inline void fill_with_random([[maybe_unused]] Bytes bytes)
22
0
{
23
0
#if defined(AK_OS_SERENITY) || defined(AK_OS_BSD_GENERIC) || defined(AK_OS_HAIKU) || AK_LIBC_GLIBC_PREREQ(2, 36)
24
0
    arc4random_buf(bytes.data(), bytes.size());
25
#elif defined(OSS_FUZZ)
26
#else
27
    auto fill_with_random_fallback = [&]() {
28
        for (auto& byte : bytes)
29
            byte = rand();
30
    };
31
32
#    if defined(__unix__)
33
    // The maximum permitted value for the getentropy length argument.
34
    static constexpr size_t getentropy_length_limit = 256;
35
    auto iterations = bytes.size() / getentropy_length_limit;
36
37
    for (size_t i = 0; i < iterations; ++i) {
38
        if (getentropy(bytes.data(), getentropy_length_limit) != 0) {
39
            fill_with_random_fallback();
40
            return;
41
        }
42
43
        bytes = bytes.slice(getentropy_length_limit);
44
    }
45
46
    if (bytes.is_empty() || getentropy(bytes.data(), bytes.size()) == 0)
47
        return;
48
#    endif
49
50
    fill_with_random_fallback();
51
#endif
52
0
}
53
54
template<typename T>
55
inline T get_random()
56
0
{
57
0
    T t;
58
0
    fill_with_random({ &t, sizeof(T) });
59
0
    return t;
60
0
}
Unexecuted instantiation: unsigned int AK::get_random<unsigned int>()
Unexecuted instantiation: unsigned long AK::get_random<unsigned long>()
Unexecuted instantiation: unsigned char AK::get_random<unsigned char>()
61
62
u32 get_random_uniform(u32 max_bounds);
63
u64 get_random_uniform_64(u64 max_bounds);
64
65
template<typename Collection>
66
inline void shuffle(Collection& collection)
67
{
68
    // Fisher-Yates shuffle
69
    for (size_t i = collection.size() - 1; i >= 1; --i) {
70
        size_t j = get_random_uniform(i + 1);
71
        AK::swap(collection[i], collection[j]);
72
    }
73
}
74
75
}
76
77
#if USING_AK_GLOBALLY
78
using AK::fill_with_random;
79
using AK::get_random;
80
using AK::get_random_uniform;
81
using AK::shuffle;
82
#endif