Coverage Report

Created: 2025-11-13 06:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fuzz_libunwind.c
Line
Count
Source
1
/* Copyright 2023 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
 * The main idea behind this fuzzer is the generate arbitrary stack traces
15
 * by way of recursive funcitons, and then using various calls to libunwind
16
 * apis arbitrarily.
17
 */
18
#define UNW_LOCAL_ONLY
19
#include <libunwind.h>
20
#include <stdint.h>
21
#include <stdlib.h>
22
#include <string.h>
23
24
void get_random_reg(int);
25
void get_proc_name();
26
void dispatch(const uint8_t *data, size_t size);
27
void check_is_signal();
28
void get_save_loc(int reg);
29
void recurse1(const uint8_t *data, size_t size);
30
void recurse2(const uint8_t *data, size_t size);
31
void recurse3(const uint8_t *data, size_t size);
32
void recurse4(const uint8_t *data, size_t size);
33
34
825
void get_save_loc(int regnum) {
35
825
  unw_cursor_t cursor;
36
825
  unw_context_t uc;
37
825
  unw_word_t reference_reg;
38
39
825
  unw_getcontext(&uc);
40
825
  unw_init_local(&cursor, &uc);
41
825
  unw_save_loc_t loc;
42
7.42k
  while (unw_step(&cursor) > 0) {
43
6.60k
    unw_get_save_loc(&cursor, regnum, &loc);
44
6.60k
  }
45
825
}
46
47
1.45k
void get_random_reg(int regnum) {
48
1.45k
  unw_cursor_t cursor;
49
1.45k
  unw_context_t uc;
50
1.45k
  unw_word_t reference_reg;
51
52
1.45k
  unw_getcontext(&uc);
53
1.45k
  unw_init_local(&cursor, &uc);
54
13.0k
  while (unw_step(&cursor) > 0) {
55
11.6k
    unw_get_reg(&cursor, regnum, &reference_reg);
56
11.6k
  }
57
1.45k
}
58
59
142
void check_is_signal() {
60
142
  unw_cursor_t cursor;
61
142
  unw_context_t uc;
62
142
  unw_word_t reference_reg;
63
64
142
  unw_getcontext(&uc);
65
142
  unw_init_local(&cursor, &uc);
66
1.27k
  while (unw_step(&cursor) > 0) {
67
1.13k
    if (unw_is_signal_frame(&cursor)) {
68
0
      return;
69
0
    }
70
1.13k
  }
71
142
}
72
73
3.95k
void get_proc_name() {
74
3.95k
  unw_cursor_t cursor;
75
3.95k
  unw_context_t uc;
76
77
3.95k
  unw_getcontext(&uc);
78
3.95k
  unw_init_local(&cursor, &uc);
79
35.6k
  while (unw_step(&cursor) > 0) {
80
31.6k
    unw_word_t offset;
81
31.6k
    char buf[512];
82
31.6k
    unw_get_proc_name(&cursor, buf, sizeof(buf), &offset);
83
31.6k
  }
84
3.95k
}
85
86
7.87k
void dispatch(const uint8_t *data, size_t size) {
87
7.87k
  if (size < 8) {
88
324
    return;
89
324
  }
90
7.54k
  uint8_t decider = data[0] % 4;
91
7.54k
  data += 2;
92
7.54k
  size -= 2;
93
7.54k
  if (decider == 0) {
94
4.31k
    recurse1(data, size);
95
4.31k
  } else if (decider == 1) {
96
1.83k
    recurse2(data, size);
97
1.83k
  } else if (decider == 2) {
98
315
    recurse3(data, size);
99
1.07k
  } else {
100
1.07k
    recurse4(data, size);
101
1.07k
  }
102
7.54k
}
103
104
4.31k
void recurse1(const uint8_t *data, size_t size) {
105
4.31k
  if (data[0] == 0x01) {
106
3.95k
    get_proc_name();
107
3.95k
  }
108
4.31k
  data += 2;
109
4.31k
  size -= 2;
110
111
4.31k
  dispatch(data, size);
112
4.31k
  return;
113
4.31k
}
114
115
1.83k
void recurse2(const uint8_t *data, size_t size) {
116
1.83k
  if (data[0] == 0x01) {
117
1.45k
    get_random_reg((int)data[1]);
118
1.45k
  }
119
1.83k
  data += 2;
120
1.83k
  size -= 2;
121
122
1.83k
  dispatch(data, size);
123
1.83k
  return;
124
1.83k
}
125
126
315
void recurse3(const uint8_t *data, size_t size) {
127
315
  if (data[0] == 0x01) {
128
142
    check_is_signal((int)data[1]);
129
142
  }
130
315
  data += 2;
131
315
  size -= 2;
132
133
315
  dispatch(data, size);
134
315
  return;
135
315
}
136
137
1.07k
void recurse4(const uint8_t *data, size_t size) {
138
1.07k
  if (data[0] == 0x01) {
139
825
    get_save_loc((int)data[1]);
140
825
  }
141
1.07k
  data += 2;
142
1.07k
  size -= 2;
143
144
1.07k
  dispatch(data, size);
145
1.07k
  return;
146
1.07k
}
147
148
353
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
149
  // Ensure we have a bit of data but not too much to cause stackoverflows.
150
353
  if (size < 12 || size > 512) {
151
29
    return 0;
152
29
  }
153
154
324
  dispatch(data, size);
155
324
  return 0;
156
353
}