## Coverage Report

#### Created: 2023-09-23 17:42

    /libfido2/fuzz/uniform_random.c

    Line
    Count
    Source (jump to first uncovered line)
    1
    /*
    2
     * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
    3
     *
    4
     * Permission to use, copy, modify, and distribute this software for any
    5
     * purpose with or without fee is hereby granted, provided that the above
    6
     * copyright notice and this permission notice appear in all copies.
    7
     *
    8
     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    9
     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    10
     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    11
     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    12
     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    13
     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    14
     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    15
     */
    16
    17
    #include <stdint.h>
    18
    #include <stdlib.h>
    19
    20
    uint32_t uniform_random(uint32_t);
    21
    unsigned long prng_uint32(void);
    22
    23
    /*
    24
     * Calculate a uniformly distributed random number less than upper_bound
    25
     * avoiding "modulo bias".
    26
     *
    27
     * Uniformity is achieved by generating new random numbers until the one
    28
     * returned is outside the range [0, 2**32 % upper_bound).  This
    29
     * guarantees the selected random number will be inside
    30
     * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
    31
     * after reduction modulo upper_bound.
    32
     */
    33
    uint32_t
    34
    uniform_random(uint32_t upper_bound)
    35
    18.0M
    {
    36
    18.0M
            uint32_t r, min;
    37
    38
    18.0M
            if (upper_bound < 2)
    39
    0
                    return 0;
    40
    41
            /* 2**32 % x == (2**32 - x) % x */
    42
    18.0M
            min = -upper_bound % upper_bound;
    43
    44
            /*
    45
             * This could theoretically loop forever but each retry has
    46
             * p > 0.5 (worst case, usually far better) of selecting a
    47
             * number inside the range we need, so it should rarely need
    48
             * to re-roll.
    49
             */
    50
    18.0M
            for (;;) {
    51
    18.0M
                    r = (uint32_t)prng_uint32();
    52
    18.0M
                    if (r >= min)
    53
    18.0M
                            break;
    54
    18.0M
            }
    55
    56
    18.0M
            return r % upper_bound;
    57
    18.0M
    }