Coverage Report

Created: 2026-10-28 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ostree/tests/fuzz-bootconfig.c
Line
Count
Source
1
/* Copyright 2026 Google LLC
2
Licensed under the Apache License, Version 2.0 (the "License");
3
you may not use this file except in compliance with the License.
4
You may obtain a copy of the License at
5
      http://www.apache.org/licenses/LICENSE-2.0
6
Unless required by applicable law or agreed to in writing, software
7
distributed under the License is distributed on an "AS IS" BASIS,
8
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
See the License for the specific language governing permissions and
10
limitations under the License.
11
*/
12
13
/*
14
 * Fuzz target for ostree bootconfig parsing.
15
 * Exercises OstreeBootconfigParser which parses bootloader entry files
16
 * with key=value pairs, overlay initrds, and tries counter parsing.
17
 */
18
19
#include "config.h"
20
#include <glib.h>
21
#include <gio/gio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <stdint.h>
25
#include <unistd.h>
26
#include <fcntl.h>
27
28
#include "libglnx.h"
29
#include "ostree.h"
30
31
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
32
33
int
34
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
35
685
{
36
685
  if (size < 1 || size > 65536)
37
10
    return 0;
38
39
675
  g_autoptr(GError) error = NULL;
40
41
  /* Create a temp file with the fuzz data as a bootconfig file.
42
   * Use a filename that exercises the tries counter parser.
43
   */
44
675
  g_autofree char *tmpdir = g_dir_make_tmp("fuzz-bootconfig-XXXXXX", &error);
45
675
  if (!tmpdir)
46
0
    return 0;
47
48
  /* Build a filename with potential tries counter suffix from fuzz data */
49
675
  g_autofree char *filename = NULL;
50
675
  if (size >= 2 && data[0] == '+')
51
283
    {
52
      /* Use first bytes as the filename suffix to exercise parse_bootloader_tries */
53
283
      size_t name_len = 0;
54
4.14k
      for (name_len = 0; name_len < size && name_len < 64; name_len++)
55
3.87k
        {
56
3.87k
          if (data[name_len] == '\0' || data[name_len] == '/')
57
4
            break;
58
3.87k
        }
59
283
      g_autofree char *name_part = g_strndup((const char *)data, name_len);
60
283
      filename = g_strdup_printf("entry%s.conf", name_part);
61
283
      data += name_len;
62
283
      size -= name_len;
63
283
    }
64
392
  else
65
392
    {
66
392
      filename = g_strdup("entry+3-1.conf");
67
392
    }
68
69
675
  g_autofree char *filepath = g_build_filename(tmpdir, filename, NULL);
70
675
  if (!g_file_set_contents(filepath, (const char *)data, size, &error))
71
0
    {
72
0
      g_rmdir(tmpdir);
73
0
      return 0;
74
0
    }
75
76
675
  g_autoptr(OstreeBootconfigParser) parser = ostree_bootconfig_parser_new();
77
675
  ostree_bootconfig_parser_parse_at(parser, AT_FDCWD, filepath, NULL, &error);
78
675
  g_clear_error(&error);
79
80
675
  if (parser)
81
675
    {
82
      /* Exercise the getters */
83
675
      ostree_bootconfig_parser_get_tries_left(parser);
84
675
      ostree_bootconfig_parser_get_tries_done(parser);
85
675
      ostree_bootconfig_parser_get(parser, "title");
86
675
      ostree_bootconfig_parser_get(parser, "linux");
87
675
      ostree_bootconfig_parser_get(parser, "initrd");
88
675
      ostree_bootconfig_parser_get(parser, "options");
89
90
      /* Exercise write-back */
91
675
      g_autofree char *outpath = g_build_filename(tmpdir, "output.conf", NULL);
92
675
      ostree_bootconfig_parser_write_at(parser, AT_FDCWD, outpath, NULL, &error);
93
675
      g_clear_error(&error);
94
675
      unlink(outpath);
95
96
      /* Exercise clone */
97
675
      g_autoptr(OstreeBootconfigParser) cloned = ostree_bootconfig_parser_clone(parser);
98
675
    }
99
100
675
  unlink(filepath);
101
675
  g_rmdir(tmpdir);
102
675
  return 0;
103
675
}