/src/libdwarf/fuzz/fuzz_die_cu_attrs.c
Line | Count | Source |
1 | | /* Copyright 2024 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 | | #include <fcntl.h> /* open() O_RDONLY O_BINARY */ |
13 | | #include <stdint.h> |
14 | | #include <stdio.h> |
15 | | #include <stdlib.h> |
16 | | #include <string.h> |
17 | | #include <sys/stat.h> |
18 | | #include <sys/types.h> |
19 | | #include <unistd.h> |
20 | | |
21 | | /* |
22 | | * Libdwarf library callers can only use these headers. |
23 | | */ |
24 | | #include "dwarf.h" |
25 | | #include "libdwarf.h" |
26 | | #ifndef O_BINARY |
27 | 13.2k | #define O_BINARY 0 |
28 | | #endif |
29 | | |
30 | | /* As originally written, reading a fuzzed object, |
31 | | this group of statements |
32 | | will loop 'forever', meaning until any running |
33 | | Sanitizer will run out of memory keeping track, |
34 | | or without a Sanitizer involved the application will |
35 | | run out of membore.. |
36 | | |
37 | | There are memory leaks on every error and from |
38 | | any successful calls. |
39 | | |
40 | | That is not a reproducible regression test. |
41 | | |
42 | | The problem is that nothing here sets 'attr' |
43 | | or checks for failure. |
44 | | there is no sane stopping condition. |
45 | | If the object being read is trivial this might stop |
46 | | in an acceptable time. |
47 | | But we check for null 'attr' (it is NULL, see below) |
48 | | and stop. |
49 | | It's a a silly testcase as writen, and tests very |
50 | | little of a practical nature. |
51 | | David Anderson December 13, 2024. */ |
52 | | |
53 | | |
54 | | |
55 | | |
56 | | /* |
57 | | * Fuzzer function |
58 | | */ |
59 | 13.2k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
60 | 13.2k | char filename[256]; |
61 | | #ifdef DWREGRESSIONTEMP |
62 | | /* Under msys2, the /tmp/ results in an open fail */ |
63 | | sprintf(filename, "junklibfuzzer.%d", getpid()); |
64 | | #else |
65 | 13.2k | sprintf(filename, "/tmp/libfuzzer.%d", getpid()); |
66 | 13.2k | #endif |
67 | 13.2k | FILE *fp = fopen(filename, "wb"); |
68 | 13.2k | if (!fp) { |
69 | 0 | printf("FAIL libfuzzer cannot open temp as writeable %s\n", |
70 | 0 | filename); |
71 | 0 | return 0; |
72 | 0 | } |
73 | 13.2k | fwrite(data, size, 1, fp); |
74 | 13.2k | fclose(fp); |
75 | | |
76 | 13.2k | Dwarf_Debug dbg = 0; |
77 | 13.2k | int fuzz_fd = 0; |
78 | 13.2k | int res = DW_DLV_ERROR; |
79 | 13.2k | Dwarf_Error error = 0; |
80 | 13.2k | Dwarf_Handler errhand = 0; |
81 | 13.2k | Dwarf_Ptr errarg = 0; |
82 | 13.2k | Dwarf_Error *errp = 0; |
83 | 13.2k | int i = 0; |
84 | 13.2k | Dwarf_Die die = 0; |
85 | | |
86 | 13.2k | fuzz_fd = open(filename, O_RDONLY|O_BINARY); |
87 | 13.2k | if (fuzz_fd != -1) { |
88 | 13.2k | res = |
89 | 13.2k | dwarf_init_b(fuzz_fd, DW_GROUPNUMBER_ANY, errhand, errarg, &dbg, errp); |
90 | 13.2k | if (res == DW_DLV_OK) { |
91 | 6.20k | Dwarf_Bool is_info = 0; |
92 | 6.20k | Dwarf_Unsigned cu_header_length = 0; |
93 | 6.20k | Dwarf_Half version_stamp = 0; |
94 | 6.20k | Dwarf_Off abbrev_offset = 0; |
95 | 6.20k | Dwarf_Half address_size = 0; |
96 | 6.20k | Dwarf_Half length_size = 0; |
97 | 6.20k | Dwarf_Half extension_size = 0; |
98 | 6.20k | Dwarf_Sig8 type_signature; |
99 | 6.20k | Dwarf_Unsigned typeoffset = 0; |
100 | 6.20k | Dwarf_Unsigned next_cu_header_offset = 0; |
101 | 6.20k | Dwarf_Half header_cu_type = 0; |
102 | 6.20k | Dwarf_Die cu_die = 0; |
103 | 6.20k | static const Dwarf_Sig8 zerosignature; |
104 | | |
105 | 6.20k | type_signature = zerosignature; |
106 | 6.20k | res = dwarf_next_cu_header_d( |
107 | 6.20k | dbg, is_info, &cu_header_length, &version_stamp, &abbrev_offset, |
108 | 6.20k | &address_size, &length_size, &extension_size, &type_signature, |
109 | 6.20k | &typeoffset, &next_cu_header_offset, &header_cu_type, errp); |
110 | 6.20k | if (res == DW_DLV_OK) { |
111 | 3.25k | res = dwarf_siblingof_b(dbg, NULL, is_info, &cu_die, errp); |
112 | 3.25k | if (res == DW_DLV_OK) { |
113 | 2.96k | Dwarf_Unsigned unsign = 0; |
114 | 2.96k | res = dwarf_bytesize(cu_die, &unsign, errp); |
115 | 2.96k | res = dwarf_bitsize(cu_die, &unsign, errp); |
116 | 2.96k | res = dwarf_arrayorder(cu_die, &unsign, errp); |
117 | | |
118 | 2.96k | Dwarf_Off section_offset = 0; |
119 | 2.96k | Dwarf_Off local_offset = 0; |
120 | 2.96k | res = dwarf_die_offsets(cu_die, §ion_offset, &local_offset, errp); |
121 | | |
122 | 2.96k | Dwarf_Off off = 0; |
123 | 2.96k | res = dwarf_dietype_offset(die, &off, &is_info, &error); |
124 | | |
125 | 2.96k | Dwarf_Off agoff = 0; |
126 | 2.96k | Dwarf_Unsigned acount = 0; |
127 | 2.96k | res = dwarf_die_abbrev_global_offset(cu_die, &agoff, &acount, errp); |
128 | | |
129 | 2.96k | Dwarf_Bool someinfo = dwarf_get_die_infotypes_flag(cu_die); |
130 | | |
131 | 2.96k | Dwarf_Off globaloff = 0; |
132 | 2.96k | Dwarf_Unsigned length = 0; |
133 | 2.96k | res = dwarf_die_CU_offset_range(cu_die, &globaloff, &length, errp); |
134 | | |
135 | 2.96k | Dwarf_Half address_size = 0; |
136 | 2.96k | res = dwarf_get_address_size(dbg, &address_size, errp); |
137 | | |
138 | 2.96k | Dwarf_Unsigned offcnt = 0; |
139 | 2.96k | Dwarf_Off *offbuf = 0; |
140 | 2.96k | res = dwarf_offset_list(dbg, section_offset, is_info, &offbuf, |
141 | 2.96k | &offcnt, errp); |
142 | | |
143 | 2.96k | Dwarf_Off die_goff = 0; |
144 | 2.96k | res = dwarf_dieoffset(cu_die, &die_goff, errp); |
145 | | |
146 | 2.96k | int abbrev_code = dwarf_die_abbrev_code(cu_die); |
147 | | |
148 | 2.96k | Dwarf_Bool has_attr = 0; |
149 | 2.96k | res = dwarf_hasattr(cu_die, DW_AT_external, &has_attr, errp); |
150 | | |
151 | 2.96k | Dwarf_Bool is_dwo = 0; |
152 | 2.96k | Dwarf_Half offset_size = 0; |
153 | 2.96k | Dwarf_Off offset_of_length = 0; |
154 | 2.96k | Dwarf_Unsigned total_byte_length = 0; |
155 | 2.96k | Dwarf_Sig8 *typesign = 0; |
156 | | |
157 | 2.96k | res = dwarf_cu_header_basics( |
158 | 2.96k | cu_die, &version_stamp, &is_info, &is_dwo, &offset_size, |
159 | 2.96k | &address_size, &extension_size, &typesign, &offset_of_length, |
160 | 2.96k | &total_byte_length, errp); |
161 | | |
162 | 2.96k | Dwarf_Debug_Fission_Per_CU percu; |
163 | 2.96k | memset(&percu, 0, sizeof(percu)); |
164 | 2.96k | res = dwarf_get_debugfission_for_die(cu_die, &percu, errp); |
165 | 2.96k | char *name = 0; |
166 | 2.96k | Dwarf_Half tag = 0; |
167 | 2.96k | const char *tagname = 0; |
168 | 2.96k | int res = 0; |
169 | 2.96k | Dwarf_Attribute *atlist = 0; |
170 | 2.96k | Dwarf_Signed atcount = 0; |
171 | 2.96k | Dwarf_Attribute attr = 0; |
172 | 2.96k | Dwarf_Half formnum = 0; |
173 | 2.96k | const char *formname = "form-name-unavailable"; |
174 | | |
175 | 2.96k | if (res == DW_DLV_ERROR || res == DW_DLV_NO_ENTRY) { |
176 | 0 | dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
177 | 0 | dwarf_finish(dbg); |
178 | 0 | close(fuzz_fd); |
179 | 0 | return 0; |
180 | 0 | } |
181 | | |
182 | 2.96k | res = dwarf_diename(cu_die, &name, errp); |
183 | | |
184 | 2.96k | res = dwarf_get_TAG_name(tag, &tagname); |
185 | | |
186 | 2.96k | res = dwarf_attr(cu_die, DW_AT_name, &attr, errp); |
187 | 2.96k | if (res != DW_DLV_OK) { |
188 | 683 | printf("Forcing close, " |
189 | 683 | "Null attr due to error means all will fail " |
190 | 683 | "and the list of errors is unreasonably long \n"); |
191 | 683 | fflush(stdout); |
192 | 683 | dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
193 | 683 | dwarf_finish(dbg); |
194 | 683 | close(fuzz_fd); |
195 | 683 | return 0; |
196 | 683 | } |
197 | 2.28k | #if 1 |
198 | 2.28k | if (!attr) { |
199 | 0 | printf("Forcing close, " |
200 | 0 | "Null attr corrupt object or \n"); |
201 | 0 | fflush(stdout); |
202 | 0 | dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
203 | 0 | dwarf_finish(dbg); |
204 | 0 | close(fuzz_fd); |
205 | 0 | return 0; |
206 | 0 | } |
207 | 2.28k | #endif |
208 | 2.28k | res = dwarf_attrlist(cu_die, &atlist, &atcount, errp); |
209 | 21.9k | for (i = 0; i < atcount; ++i) { |
210 | 19.6k | Dwarf_Half attrnum = 0; |
211 | 19.6k | const char *attrname = 0; |
212 | 19.6k | res = dwarf_whatform(attr, &formnum, errp); |
213 | | #if 0 |
214 | | if (!attr) { |
215 | | printf("Forcing close, " |
216 | | "Null attr corrupt object or \n"); |
217 | | fflush(stdout); |
218 | | dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
219 | | dwarf_finish(dbg); |
220 | | close(fuzz_fd); |
221 | | return 0; |
222 | | } |
223 | | #endif |
224 | 19.6k | Dwarf_Bool *dw_returned_bool = 0; |
225 | 19.6k | res = dwarf_hasform(attr, formnum, dw_returned_bool, errp); |
226 | 19.6k | res = dwarf_get_FORM_name(formnum, &formname); |
227 | 19.6k | Dwarf_Block *tempb = 0; |
228 | 19.6k | res = dwarf_formblock(attr, &tempb, errp); |
229 | 19.6k | if (res == DW_DLV_OK) { |
230 | 4.04k | Dwarf_Dsc_Head h = 0; |
231 | | /* Dwarf_Unsigned u = 0; unused */ |
232 | 4.04k | Dwarf_Unsigned arraycount = 0; |
233 | 4.04k | int sres = 0; |
234 | | |
235 | 4.04k | sres = dwarf_discr_list(dbg, (Dwarf_Small *)tempb->bl_data, |
236 | 4.04k | tempb->bl_len, &h, &arraycount, errp); |
237 | 4.04k | } |
238 | 19.6k | res = dwarf_whatattr(atlist[i], &attrnum, errp); |
239 | 19.6k | dwarf_get_AT_name(attrnum, &attrname); |
240 | 19.6k | dwarf_dealloc_attribute(atlist[i]); |
241 | 19.6k | atlist[i] = 0; |
242 | 19.6k | char *stringval = 0; |
243 | 19.6k | res = dwarf_bitoffset(cu_die, &attrnum, &unsign, errp); |
244 | 19.6k | res = dwarf_die_text(cu_die, attrnum, &stringval, errp); |
245 | 19.6k | res = dwarf_get_form_class(version_stamp, attrnum, |
246 | 19.6k | next_cu_header_offset, formnum); |
247 | 19.6k | } |
248 | 2.28k | res = dwarf_set_tied_dbg(dbg, NULL, errp); |
249 | 2.28k | } |
250 | 2.57k | dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); |
251 | 2.57k | } |
252 | 6.20k | } |
253 | 13.2k | } |
254 | 12.5k | dwarf_finish(dbg); |
255 | 12.5k | close(fuzz_fd); |
256 | 12.5k | unlink(filename); |
257 | 12.5k | return 0; |
258 | 13.2k | } |