Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/fuzz/fuzz_bfd_ext.c
Line
Count
Source (jump to first uncovered line)
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
/*
15
 * This is an example fuzzer targeted a given architecture. The point of this is
16
 * that the general fuzz_bfd fuzzer has too large reacability which makes it
17
 * difficult to reach the entire codebase in practice. The goal is to create
18
 * more targeted fuzzers that are more likely to explore a given code area.
19
 *
20
 */
21
#include "sysdep.h"
22
#include "bfd.h"
23
#include "libbfd.h"
24
25
#include <stdint.h>
26
#include <stdio.h>
27
#include <unistd.h>
28
29
591
static int bufferToFile(char *name, const uint8_t *Data, size_t Size) {
30
591
  int fd = mkstemp(name);
31
591
  if (fd < 0) {
32
0
    printf("failed mkstemp, errno=%d\n", errno);
33
0
    return -2;
34
0
  }
35
591
  if (write(fd, Data, Size) != Size) {
36
0
    printf("failed write, errno=%d\n", errno);
37
0
    close(fd);
38
0
    return -3;
39
0
  }
40
591
  close(fd);
41
591
  return 0;
42
591
}
43
44
591
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
45
591
  char tmpfilename[32];
46
47
591
  if (bfd_init() != BFD_INIT_MAGIC)
48
0
    abort();
49
50
  /*
51
      char **names = bfd_target_list();
52
      while (*names != NULL) {
53
        printf("Name: %s\n", *names);
54
        names++;
55
      }
56
  */
57
58
591
  bfd_cleanup cleanup = NULL;
59
60
591
  strncpy(tmpfilename, "/tmp/fuzz.bfd-XXXXXX", 31);
61
591
  if (bufferToFile(tmpfilename, Data, Size) < 0) {
62
0
    return 0;
63
0
  }
64
  // bfd *file = bfd_openr (tmpfilename, "elf32-frv");
65
591
  bfd *file = bfd_openr(tmpfilename, "pef");
66
591
  if (file == NULL) {
67
0
    remove(tmpfilename);
68
0
    return 0;
69
0
  }
70
71
591
  if (!bfd_read_p(file) ||
72
591
      (unsigned int)file->format >= (unsigned int)bfd_type_end) {
73
0
    bfd_close(file);
74
0
    return 0;
75
0
  }
76
77
591
  bool doAnalysis = false;
78
591
  if (bfd_seek(file, (file_ptr)0, SEEK_SET) == 0) {
79
591
    file->format = bfd_object;
80
591
    cleanup = BFD_SEND_FMT(file, _bfd_check_format, (file));
81
591
    if (cleanup) {
82
48
      doAnalysis = true;
83
48
      cleanup(file);
84
48
    }
85
591
    file->format = bfd_unknown;
86
591
  }
87
88
591
  if (file != NULL) {
89
591
    bfd_close(file);
90
591
  }
91
92
591
  if (doAnalysis) {
93
    // We have a file with the target data we want.
94
    // Let's open as a write file this time, which should trigger
95
    // more actions on the code when calling bfd_close.
96
    // TODO: do more processing on this, e.g. use the file as
97
    // input to some of the other utilities.
98
48
    bfd *wFile = bfd_openw(tmpfilename, "pef");
99
48
    if (file != NULL) {
100
48
      bfd_close(wFile);
101
48
    }
102
48
  }
103
104
591
  remove(tmpfilename);
105
591
  return 0;
106
591
}