Coverage Report

Created: 2025-07-11 06:44

/src/fuzz-libelf.c
Line
Count
Source
1
/* Copyright 2022 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
#include <assert.h>
14
#include <fcntl.h>
15
#include <gelf.h>
16
#include <inttypes.h>
17
#include <libelf.h>
18
#include <stdio.h>
19
#include <stdlib.h>
20
#include <string.h>
21
#include <sys/stat.h>
22
#include <sys/types.h>
23
#include <unistd.h>
24
#include "system.h"
25
26
27
11.5k
void fuzz_logic_one(char *filename, int compression_type) {
28
11.5k
  (void)elf_version(EV_CURRENT);
29
11.5k
  int fd = open(filename, O_RDONLY);
30
11.5k
  Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
31
11.5k
  if (elf != NULL) {
32
11.3k
    size_t strndx;
33
11.3k
    elf_getshdrstrndx(elf, &strndx);
34
35
11.3k
    Elf_Scn *scn = NULL;
36
    // Iterate through sections
37
2.89M
    while ((scn = elf_nextscn(elf, scn)) != NULL) {
38
2.88M
      GElf_Shdr mem;
39
2.88M
      GElf_Shdr *shdr = gelf_getshdr(scn, &mem);
40
2.88M
      const char *name = elf_strptr(elf, strndx, shdr->sh_name);
41
42
      // Two options for reading sections. We keep the code structure
43
      // so it resembles the test code.
44
      // Compress and get data of the section
45
2.88M
      if ((shdr->sh_flags & SHF_COMPRESSED) != 0) {
46
983k
        if (elf_compress(scn, compression_type, 0) >= 0) {
47
48.6k
          elf_getdata(scn, NULL);
48
48.6k
        }
49
1.90M
      } else if (name != NULL) {
50
316k
        if (name[0] == '.' && name[1] == 'z') {
51
247k
          if (elf_compress_gnu(scn, 0, 0) >= 0) {
52
439
            elf_getdata(scn, NULL);
53
439
          }
54
247k
        }
55
316k
      }
56
2.88M
    }
57
11.3k
    elf_end(elf);
58
11.3k
  }
59
11.5k
  close(fd);
60
11.5k
}
61
62
23.0k
void fuzz_logic_twice(char *filename, int open_flags, Elf_Cmd cmd) {
63
23.0k
  (void)elf_version(EV_CURRENT);
64
23.0k
  int fd = open(filename, open_flags);
65
23.0k
  Elf *elf = elf_begin(fd, cmd, NULL);
66
23.0k
  if (elf != NULL) {
67
11.3k
    size_t elf_size = 0;
68
11.3k
    elf_rawfile(elf, &elf_size);
69
11.3k
    elf_end(elf);
70
11.3k
  }
71
23.0k
  close(fd);
72
23.0k
}
73
74
5.76k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
75
5.76k
  char filename[] = "/tmp/fuzz-libelf.XXXXXX";
76
5.76k
  int fd;
77
5.76k
  ssize_t n;
78
79
5.76k
  fd = mkstemp(filename);
80
5.76k
  assert(fd >= 0);
81
82
5.76k
  n = write_retry(fd, data, size);
83
5.76k
  assert(n == (ssize_t) size);
84
85
5.76k
  close(fd);
86
87
5.76k
  fuzz_logic_one(filename, 0);
88
5.76k
  fuzz_logic_one(filename, 1);
89
5.76k
  fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ);
90
5.76k
  fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR);
91
5.76k
  fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ_MMAP);
92
5.76k
  fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR_MMAP);
93
94
5.76k
  unlink(filename);
95
5.76k
  return 0;
96
5.76k
}