## Coverage Report

#### Created: 2025-03-01 02:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /libfido2/fuzz/clock.c

    Line
    Count
    Source
    1
    /*
    2
     * Copyright (c) 2021 Yubico AB. All rights reserved.
    3
     * Use of this source code is governed by a BSD-style
    4
     * license that can be found in the LICENSE file.
    5
     * SPDX-License-Identifier: BSD-2-Clause
    6
     */
    7
    8
    #include <stdint.h>
    9
    #include <time.h>
    10
    11
    #include "mutator_aux.h"
    12
    13
    /*
    14
     * A pseudo-random monotonic clock with a probabilistic discontinuity to
    15
     * the end of time (as measured by struct timespec).
    16
     */
    17
    18
    extern int prng_up;
    19
    extern int __wrap_clock_gettime(clockid_t, struct timespec *);
    20
    extern int __real_clock_gettime(clockid_t, struct timespec *);
    21
    extern int __wrap_usleep(unsigned int);
    22
    static TLS struct timespec fuzz_clock;
    23
    24
    static void
    25
    tick(unsigned int usec)
    26
    7.63M
    {
    27
    7.63M
            long long drift;
    28
    29
            /*
    30
             * Simulate a jump to the end of time with 0.125% probability.
    31
             * This condition should be gracefully handled by callers of
    32
             * clock_gettime().
    33
             */
    34
    7.63M
            if (uniform_random(800) < 1) {
    35
    7.89k
                    fuzz_clock.tv_sec = LLONG_MAX;
    36
    7.89k
                    fuzz_clock.tv_nsec = LONG_MAX;
    37
    7.89k
                    return;
    38
    7.89k
            }
    39
    40
    7.63M
            drift = usec * 1000LL + (long long)uniform_random(10000000); /* 10ms */
    41
    7.63M
            if (LLONG_MAX - drift < (long long)fuzz_clock.tv_nsec) {
    42
    6.55k
                    fuzz_clock_reset(); /* Not much we can do here. */
    43
    7.62M
            } else if (drift + (long long)fuzz_clock.tv_nsec < 1000000000) {
    44
    7.42M
                    fuzz_clock.tv_nsec += (long)(drift);
    45
    7.42M
            } else {
    46
    198k
                    fuzz_clock.tv_sec  += (long)(drift / 1000000000);
    47
    198k
                    fuzz_clock.tv_nsec += (long)(drift % 1000000000);
    48
    198k
            }
    49
    7.63M
    }
    50
    51
    int
    52
    __wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
    53
    7.64M
    {
    54
    7.64M
            if (!prng_up || clk_id != CLOCK_MONOTONIC)
    55
    0
                    return __real_clock_gettime(clk_id, tp);
    56
    7.64M
            if (uniform_random(400) < 1)
    57
    17.8k
                    return -1;
    58
    59
    7.63M
            tick(0);
    60
    7.63M
            *tp = fuzz_clock;
    61
    62
    7.63M
            return 0;
    63
    7.64M
    }
    64
    65
    int
    66
    __wrap_usleep(unsigned int usec)
    67
    7.64k
    {
    68
    7.64k
            if (uniform_random(400) < 1)
    69
    12
                    return -1;
    70
    71
    7.63k
            tick(usec);
    72
    73
    7.63k
            return 0;
    74
    7.64k
    }
    75
    76
    void
    77
    fuzz_clock_reset(void)
    78
    176k
    {
    79
    176k
            memset(&fuzz_clock, 0, sizeof(fuzz_clock));
    80
    176k
    }