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_readelf.c
Line
Count
Source
1
/* Copyright 2020 Google Inc.
2
3
Licensed under the Apache License, Version 2.0 (the "License");
4
you may not use this file except in compliance with the License.
5
You may obtain a copy of the License at
6
7
      http://www.apache.org/licenses/LICENSE-2.0
8
9
Unless required by applicable law or agreed to in writing, software
10
distributed under the License is distributed on an "AS IS" BASIS,
11
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
See the License for the specific language governing permissions and
13
limitations under the License.
14
*/
15
16
/*
17
 * We convert readelf.c into a header file to make convenient for fuzzing.
18
 * We do this for several of the binutils applications when creating
19
 * the binutils fuzzers.
20
 */
21
#include "readelf.h"
22
23
#include "bfd.h"
24
#include "libbfd.h"
25
26
139
int check_architecture(char *tmpfilename, char *arch_string) {
27
139
  bfd_cleanup cleanup = NULL;
28
139
  bfd *file = bfd_openr(tmpfilename, arch_string);
29
139
  if (file == NULL) {
30
27
    remove(tmpfilename);
31
27
    return 0;
32
27
  }
33
34
112
  if (!bfd_read_p(file) ||
35
112
      (unsigned int)file->format >= (unsigned int)bfd_type_end) {
36
0
    bfd_close(file);
37
0
    return 0;
38
0
  }
39
40
112
  bool doAnalysis = false;
41
112
  if (bfd_seek(file, (file_ptr)0, SEEK_SET) == 0) {
42
112
    file->format = bfd_object;
43
112
    cleanup = BFD_SEND_FMT(file, _bfd_check_format, (file));
44
112
    if (cleanup) {
45
0
      doAnalysis = true;
46
0
      cleanup(file);
47
0
    }
48
112
    file->format = bfd_unknown;
49
112
  }
50
51
112
  if (file != NULL) {
52
112
    bfd_close(file);
53
112
  }
54
55
  // return 1 if the architecture matches.
56
112
  if (doAnalysis) {
57
0
    return 1;
58
0
  }
59
112
  return 0;
60
112
}
61
62
// int gb=0;
63
64
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
65
174
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
66
174
  if (size > 16384)
67
35
    return 0;
68
139
  char filename[256];
69
139
  sprintf(filename, "/tmp/libfuzzer.%d", getpid());
70
71
139
  FILE *fp = fopen(filename, "wb");
72
139
  if (!fp)
73
0
    return 0;
74
75
    /* Code to quickly extract target list.
76
     * This is used to identify new targets but should
77
     * not be in the fuzz code.
78
    if (gb == 0) {
79
      char **doublel = bfd_target_list();
80
      while (*doublel != NULL) {
81
        printf("Target: %s\n", *doublel);
82
        doublel++;
83
      }
84
      gb=1;
85
    }
86
    exit(0);
87
    */
88
89
139
#ifdef READELF_TARGETED
90
139
  if (check_architecture(filename, READELF_TARGETED) == 0) {
91
139
    unlink(filename);
92
139
    return 0;
93
139
  }
94
0
#endif
95
96
0
  fwrite(data, size, 1, fp);
97
0
  fclose(fp);
98
0
  do_syms = true;
99
0
  do_reloc = true;
100
0
  do_unwind = true;
101
0
  do_dynamic = true;
102
0
  do_header = true;
103
0
  do_sections = true;
104
0
  do_section_groups = true;
105
0
  do_segments = true;
106
0
  do_version = true;
107
0
  do_histogram = true;
108
0
  do_arch = true;
109
0
  do_notes = true;
110
111
  // Enable DWARF analysis
112
  // We must call both dwarf_select_sections_by_letters and
113
  // dwarf_select_sections_all since dwarf_select_sections_all does not set
114
  // do_debug_lines |= FLAG_DEBUG_LINES_DECODED;
115
0
  dwarf_select_sections_by_letters("L");
116
0
  dwarf_select_sections_all();
117
118
  // Main fuzz entrypoint
119
0
  process_file(filename);
120
121
0
  unlink(filename);
122
123
0
  free(dump_ctf_symtab_name);
124
0
  dump_ctf_symtab_name = NULL;
125
0
  free(dump_ctf_strtab_name);
126
0
  dump_ctf_strtab_name = NULL;
127
0
  free(dump_ctf_parent_name);
128
0
  dump_ctf_parent_name = NULL;
129
130
0
  return 0;
131
139
}