Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/binutils/fuzz_windres.c
Line
Count
Source
1
/* Copyright 2021 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
 * We convert windres.c into a header file to make convenient for fuzzing.
15
 * We do this for several of the binutils applications when creating
16
 * the binutils fuzzers.
17
 */
18
#include "fuzz_windres.h"
19
20
/*
21
 *
22
 * This fuzzer performs initial checks on the data
23
 * that are similar to what the windres application does, however
24
 * with the caveat that windres will fatally exit and the fuzzer simply returns, i.e.
25
 * fuzzing continues. The purpose is to enable further analysis.
26
 *
27
 * Down the line, perhaps it makes sense to chage binutils to have less fatals and
28
 * more graceful exits. This would be useful for the fuzzing.
29
 */
30
31
static enum res_format
32
14.6k
fuzz_format_check_from_mem(const uint8_t *data, size_t size) {
33
14.6k
  int magic;
34
14.6k
  if (size < 2) {
35
1
  return RES_FORMAT_UNKNOWN;
36
1
  }
37
14.6k
  if (data[0] == 0x4d && data[1] == 0x5a) {
38
13.1k
  return RES_FORMAT_COFF;
39
13.1k
  }
40
1.52k
  magic = data[0] << 8 | data[1];
41
1.52k
  if (magic == 0x14c || magic == 0x166 || magic == 0x184 || magic == 0x268 || magic == 0x1f0 || magic == 0x290) {
42
1.44k
      return RES_FORMAT_COFF;
43
1.44k
  }
44
74
  return RES_FORMAT_UNKNOWN;
45
1.52k
}
46
47
int
48
fuzz_check_coff_rsrc (const char *filename, const char *target)
49
14.5k
{
50
14.5k
  int retval = 0;
51
14.5k
  bfd *abfd;
52
14.5k
  windres_bfd wrbfd;
53
14.5k
  asection *sec;
54
55
14.5k
  abfd = bfd_openr (filename, target);
56
14.5k
  if (abfd == NULL) {
57
0
    return 0;
58
0
  }
59
60
14.5k
  if (! bfd_check_format (abfd, bfd_object)) {
61
6.56k
    retval = 0;
62
6.56k
    goto cleanup;
63
6.56k
    }
64
65
7.98k
  sec = bfd_get_section_by_name (abfd, ".rsrc");
66
7.98k
  if (sec == NULL || sec->size == 0) {
67
5.29k
    retval = 0;
68
5.29k
    goto cleanup;
69
5.29k
    }
70
71
2.69k
  set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
72
73
2.69k
  bfd_size_type filesize = get_file_size (filename);
74
2.69k
  if ((ufile_ptr) sec->filepos > filesize
75
2.59k
      || sec->size > filesize - sec->filepos) {
76
147
    retval = 0;
77
147
    goto cleanup;
78
147
  }
79
80
2.54k
  retval = 1;
81
14.5k
cleanup:
82
14.5k
  bfd_close (abfd);
83
14.5k
  return retval;
84
2.54k
}
85
86
87
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
88
int
89
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
90
14.6k
{
91
14.6k
  if (size > 16384)
92
2
    return 0;
93
14.6k
  enum res_format input_format;
94
14.6k
   input_format = fuzz_format_check_from_mem(data, size);;
95
14.6k
  if (input_format != RES_FORMAT_COFF) {
96
75
    return 0;
97
75
  }
98
99
14.5k
  char filename[256];
100
14.5k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
101
14.5k
  FILE *fp = fopen(filename, "wb");
102
14.5k
  if (!fp) {
103
0
    return 0;
104
0
  }
105
14.5k
  fwrite(data, size, 1, fp);
106
14.5k
  fclose(fp);
107
108
109
14.5k
  program_name = "fuzz_windres";
110
111
  // For now we only check FORMAT_COFF, this can be extended to
112
  // the two additional formats later.
113
14.5k
  if (input_format == RES_FORMAT_COFF) {
114
14.5k
    if (fuzz_check_coff_rsrc(filename, NULL) != 0) {
115
2.54k
      res_init ();
116
2.54k
      read_coff_rsrc (filename, NULL);
117
2.54k
      obstack_free (&res_obstack, NULL);
118
2.54k
    }
119
14.5k
  }
120
121
14.5k
  unlink(filename);
122
14.5k
  return 0;
123
14.5k
}