Coverage Report

Created: 2023-11-27 06:29

/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
12.6k
void fuzz_logic_one(char *filename, int compression_type) {
28
12.6k
  (void)elf_version(EV_CURRENT);
29
12.6k
  int fd = open(filename, O_RDONLY);
30
12.6k
  Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
31
12.6k
  if (elf != NULL) {
32
12.5k
    size_t strndx;
33
12.5k
    elf_getshdrstrndx(elf, &strndx);
34
35
12.5k
    Elf_Scn *scn = NULL;
36
    // Iterate through sections
37
2.79M
    while ((scn = elf_nextscn(elf, scn)) != NULL) {
38
2.78M
      GElf_Shdr mem;
39
2.78M
      GElf_Shdr *shdr = gelf_getshdr(scn, &mem);
40
2.78M
      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.78M
      if ((shdr->sh_flags & SHF_COMPRESSED) != 0) {
46
986k
        if (elf_compress(scn, compression_type, 0) >= 0) {
47
49.2k
          elf_getdata(scn, NULL);
48
49.2k
        }
49
1.79M
      } else if (name != NULL) {
50
270k
        if (name[0] == '.' && name[1] == 'z') {
51
201k
          if (elf_compress_gnu(scn, 0, 0) >= 0) {
52
280
            elf_getdata(scn, NULL);
53
280
          }
54
201k
        }
55
270k
      }
56
2.78M
    }
57
12.5k
    elf_end(elf);
58
12.5k
  }
59
12.6k
  close(fd);
60
12.6k
}
61
62
25.2k
void fuzz_logic_twice(char *filename, int open_flags, Elf_Cmd cmd) {
63
25.2k
  (void)elf_version(EV_CURRENT);
64
25.2k
  int fd = open(filename, open_flags);
65
25.2k
  Elf *elf = elf_begin(fd, cmd, NULL);
66
25.2k
  if (elf != NULL) {
67
12.5k
    size_t elf_size = 0;
68
12.5k
    elf_rawfile(elf, &elf_size);
69
12.5k
    elf_end(elf);
70
12.5k
  }
71
25.2k
  close(fd);
72
25.2k
}
73
74
17.5k
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
75
17.5k
  char filename[] = "/tmp/fuzz-libelf.XXXXXX";
76
17.5k
  int fd;
77
17.5k
  ssize_t n;
78
79
17.5k
  fd = mkstemp(filename);
80
17.5k
  assert(fd >= 0);
81
82
17.5k
  n = write_retry(fd, data, size);
83
17.5k
  assert(n == (ssize_t) size);
84
85
17.5k
  close(fd);
86
87
17.5k
  fuzz_logic_one(filename, 0);
88
17.5k
  fuzz_logic_one(filename, 1);
89
17.5k
  fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ);
90
17.5k
  fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR);
91
17.5k
  fuzz_logic_twice(filename, O_RDONLY, ELF_C_READ_MMAP);
92
17.5k
  fuzz_logic_twice(filename, O_RDONLY | O_WRONLY, ELF_C_RDWR_MMAP);
93
94
17.5k
  unlink(filename);
95
17.5k
  return 0;
96
17.5k
}