Coverage Report

Created: 2026-10-13 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/lib/fuzz.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-only
2
3
#include <fuzz.h>
4
#include <string.h>
5
#include <common.h>
6
7
#define for_each_fuzz_test(test) \
8
26
  for (test = &__barebox_fuzz_tests_start; \
9
182
       test != &__barebox_fuzz_tests_end; test++)
10
11
int call_for_each_fuzz_test(int (*fn)(const struct fuzz_test *test, void *ctx),
12
          void *ctx)
13
0
{
14
0
  const struct fuzz_test *test;
15
0
  int ret;
16
17
0
  for_each_fuzz_test(test) {
18
0
    ret = fn(test, ctx);
19
0
    if (ret)
20
0
      return ret;
21
0
  }
22
23
0
  return 0;
24
0
}
25
26
static int list_fuzz_test_one(const struct fuzz_test *test, void *ctx)
27
0
{
28
0
  int (*println)(const char *) = ctx;
29
30
0
  println(test->name);
31
0
  return 0;
32
0
}
33
34
void list_fuzz_tests(int (*println)(const char *))
35
0
{
36
0
  call_for_each_fuzz_test(list_fuzz_test_one, println);
37
0
}
38
39
#ifdef CONFIG_FUZZ_EXTERNAL
40
const u8 *fuzzer_get_data(size_t *len);
41
#else
42
static inline const u8 *fuzzer_get_data(size_t *len)
43
{
44
  return NULL;
45
}
46
#endif
47
48
extern int LLVMFuzzerRunDriver(int *argc, char ***argv,
49
             int (*cb)(const uint8_t *, size_t));
50
51
static const struct fuzz_test *fuzz;
52
static int *saved_argc;
53
static char ***saved_argv;
54
55
static int fuzzer_run(const uint8_t *buf, size_t len)
56
25.9k
{
57
25.9k
  return fuzz_test_once(fuzz, buf, len);
58
25.9k
}
59
60
/*
61
 * barebox supplies its own main() and enters libFuzzer via
62
 * LLVMFuzzerRunDriver(), so the fuzzing engine's own main() is never
63
 * executed. It is still linked in when an external engine (e.g.
64
 * OSS-Fuzz's LIB_FUZZING_ENGINE) is used, because the C runtime's
65
 * reference to main() extracts the engine's main object file before
66
 * --defsym=main=sandbox_main takes effect. Define the entry point it
67
 * references, so the link succeeds.
68
 */
69
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
70
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
71
0
{
72
0
  fuzz_test_setup(fuzz);
73
74
0
  return fuzzer_run(data, size);
75
0
}
76
77
static int fuzz_main(void)
78
26
{
79
26
  int ret = -1;
80
81
  /* buffering would make coverage depend on earlier inputs */
82
26
  log_set_max_messages(-1);
83
84
26
  fuzz_test_setup(fuzz);
85
86
26
  if (IS_ENABLED(CONFIG_FUZZ_EXTERNAL)) {
87
26
    ret = LLVMFuzzerRunDriver(saved_argc, saved_argv, fuzzer_run);
88
26
    pr_emerg("libfuzzer unexpectedly ended: %d\n", ret);
89
26
  } else {
90
0
    pr_emerg("libfuzzer not supported in this build\n");
91
0
  }
92
93
26
  return ret;
94
26
}
95
96
int setup_external_fuzz(const char *fuzz_name,
97
      int *argc, char ***argv)
98
26
{
99
26
  const struct fuzz_test *test;
100
101
26
  saved_argc = argc;
102
26
  saved_argv = argv;
103
104
182
  for_each_fuzz_test(test) {
105
182
    if (streq_ptr(test->name, fuzz_name)) {
106
26
      fuzz = test;
107
26
      barebox_main = fuzz_main;
108
26
      barebox_loglevel = MSG_CRIT;
109
26
      return 0;
110
26
    }
111
182
  }
112
113
0
  return -1;
114
26
}
115
116
bool fuzz_external_active(void)
117
0
{
118
0
  return fuzz != NULL;
119
0
}