Coverage Report

Created: 2021-10-21 13:35

/libfido2/fuzz/clock.c
Line
Count
Source (jump to first uncovered line)
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
 */
6
7
#include <stdint.h>
8
#include <time.h>
9
10
#include "mutator_aux.h"
11
12
/*
13
 * A pseudo-random monotonic clock with a probabilistic discontinuity to
14
 * the end of time (as measured by struct timespec).
15
 */
16
17
extern int prng_up;
18
extern int __wrap_clock_gettime(clockid_t, struct timespec *);
19
extern int __real_clock_gettime(clockid_t, struct timespec *);
20
extern int __wrap_usleep(unsigned int);
21
static TLS struct timespec fuzz_clock;
22
23
static void
24
tick(unsigned int usec)
25
773k
{
26
773k
        long long drift;
27
28
        /*
29
         * Simulate a jump to the end of time with 0.125% probability.
30
         * This condition should be gracefully handled by callers of
31
         * clock_gettime().
32
         */
33
773k
        if (uniform_random(800) < 1) {
34
1.16k
                fuzz_clock.tv_sec = LLONG_MAX;
35
1.16k
                fuzz_clock.tv_nsec = LONG_MAX;
36
1.16k
                return;
37
1.16k
        }
38
39
772k
        drift = usec * 1000LL + (long long)uniform_random(10000000); /* 10ms */
40
772k
        if (LLONG_MAX - drift < (long long)fuzz_clock.tv_nsec) {
41
1.00k
                fuzz_clock_reset(); /* Not much we can do here. */
42
771k
        } else if (drift + (long long)fuzz_clock.tv_nsec < 1000000000) {
43
728k
                fuzz_clock.tv_nsec += (long)(drift);
44
728k
        } else {
45
42.8k
                fuzz_clock.tv_sec  += (long)(drift / 1000000000);
46
42.8k
                fuzz_clock.tv_nsec += (long)(drift % 1000000000);
47
42.8k
        }
48
772k
}
49
50
int
51
__wrap_clock_gettime(clockid_t clk_id, struct timespec *tp)
52
774k
{
53
774k
        if (!prng_up || clk_id != CLOCK_MONOTONIC)
54
774k
                return __real_clock_gettime(clk_id, tp);
55
774k
        if (uniform_random(400) < 1)
56
1.71k
                return -1;
57
58
772k
        tick(0);
59
772k
        *tp = fuzz_clock;
60
61
772k
        return 0;
62
772k
}
63
64
int
65
__wrap_usleep(unsigned int usec)
66
927
{
67
927
        if (uniform_random(400) < 1)
68
3
                return -1;
69
70
924
        tick(usec);
71
72
924
        return 0;
73
924
}
74
75
void
76
fuzz_clock_reset(void)
77
17.0k
{
78
17.0k
        memset(&fuzz_clock, 0, sizeof(fuzz_clock));
79
17.0k
}