Coverage Report

Created: 2026-04-04 08:16

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
15.5k
fuzz_format_check_from_mem(const uint8_t *data, size_t size) {
33
15.5k
  int magic;
34
15.5k
  if (size < 2) {
35
1
  return RES_FORMAT_UNKNOWN;
36
1
  }
37
15.5k
  if (data[0] == 0x4d && data[1] == 0x5a) {
38
13.9k
  return RES_FORMAT_COFF;
39
13.9k
  }
40
1.58k
  magic = data[0] << 8 | data[1];
41
1.58k
  if (magic == 0x14c || magic == 0x166 || magic == 0x184 || magic == 0x268 || magic == 0x1f0 || magic == 0x290) {
42
1.51k
      return RES_FORMAT_COFF;
43
1.51k
  }
44
69
  return RES_FORMAT_UNKNOWN;
45
1.58k
}
46
47
int
48
fuzz_check_coff_rsrc (const char *filename, const char *target)
49
15.4k
{
50
15.4k
  int retval = 0;
51
15.4k
  bfd *abfd;
52
15.4k
  windres_bfd wrbfd;
53
15.4k
  asection *sec;
54
55
15.4k
  abfd = bfd_openr (filename, target);
56
15.4k
  if (abfd == NULL) {
57
0
    return 0;
58
0
  }
59
60
15.4k
  if (! bfd_check_format (abfd, bfd_object)) {
61
7.00k
    retval = 0;
62
7.00k
    goto cleanup;
63
7.00k
    }
64
65
8.42k
  sec = bfd_get_section_by_name (abfd, ".rsrc");
66
8.42k
  if (sec == NULL || sec->size == 0) {
67
5.62k
    retval = 0;
68
5.62k
    goto cleanup;
69
5.62k
    }
70
71
2.80k
  set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD);
72
73
2.80k
  bfd_size_type filesize = get_file_size (filename);
74
2.80k
  if ((ufile_ptr) sec->filepos > filesize
75
2.71k
      || sec->size > filesize - sec->filepos) {
76
146
    retval = 0;
77
146
    goto cleanup;
78
146
  }
79
80
2.65k
  retval = 1;
81
15.4k
cleanup:
82
15.4k
  bfd_close (abfd);
83
15.4k
  return retval;
84
2.65k
}
85
86
87
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
88
int
89
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
90
15.5k
{
91
15.5k
  if (size > 16384)
92
2
    return 0;
93
15.5k
  enum res_format input_format;
94
15.5k
   input_format = fuzz_format_check_from_mem(data, size);;
95
15.5k
  if (input_format != RES_FORMAT_COFF) {
96
70
    return 0;
97
70
  }
98
99
15.4k
  char filename[256];
100
15.4k
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
101
15.4k
  FILE *fp = fopen(filename, "wb");
102
15.4k
  if (!fp) {
103
0
    return 0;
104
0
  }
105
15.4k
  fwrite(data, size, 1, fp);
106
15.4k
  fclose(fp);
107
108
109
15.4k
  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
15.4k
  if (input_format == RES_FORMAT_COFF) {
114
15.4k
    if (fuzz_check_coff_rsrc(filename, NULL) != 0) {
115
2.65k
      res_init ();
116
2.65k
      read_coff_rsrc (filename, NULL);
117
2.65k
      obstack_free (&res_obstack, NULL);
118
2.65k
    }
119
15.4k
  }
120
121
15.4k
  unlink(filename);
122
15.4k
  return 0;
123
15.4k
}