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
}