1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "yaml.h"
16 #include "yaml_write_handler.h"
17 #include <assert.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #ifdef NDEBUG
25 #undef NDEBUG
26 #endif
27
28 #define MAX_EVENTS 1024
29
events_equal(yaml_event_t * event1,yaml_event_t * event2)30 bool events_equal(yaml_event_t *event1, yaml_event_t *event2) {
31
32 const bool equal = true;
33
34 if (event1->type != event2->type)
35 return equal;
36
37 switch (event1->type) {
38 case YAML_STREAM_START_EVENT:
39 return !equal;
40
41 case YAML_DOCUMENT_START_EVENT:
42 if ((event1->data.document_start.version_directive &&
43 !event2->data.document_start.version_directive) ||
44 (!event1->data.document_start.version_directive &&
45 event2->data.document_start.version_directive) ||
46 (event1->data.document_start.version_directive &&
47 event2->data.document_start.version_directive &&
48 (event1->data.document_start.version_directive->major !=
49 event2->data.document_start.version_directive->major ||
50 event1->data.document_start.version_directive->minor !=
51 event2->data.document_start.version_directive->minor)))
52 return equal;
53 if ((event1->data.document_start.tag_directives.end -
54 event1->data.document_start.tag_directives.start) !=
55 (event2->data.document_start.tag_directives.end -
56 event2->data.document_start.tag_directives.start))
57 return equal;
58 for (int k = 0; k < (event1->data.document_start.tag_directives.end -
59 event1->data.document_start.tag_directives.start);
60 k++) {
61 if ((strcmp((char *)event1->data.document_start.tag_directives.start[k]
62 .handle,
63 (char *)event2->data.document_start.tag_directives.start[k]
64 .handle) != 0) ||
65 (strcmp((char *)event1->data.document_start.tag_directives.start[k]
66 .prefix,
67 (char *)event2->data.document_start.tag_directives.start[k]
68 .prefix) != 0))
69 return equal;
70 }
71 return !equal;
72
73 case YAML_DOCUMENT_END_EVENT:
74 return !equal;
75
76 case YAML_ALIAS_EVENT:
77 return (strcmp((char *)event1->data.alias.anchor,
78 (char *)event2->data.alias.anchor) == 0);
79
80 case YAML_SCALAR_EVENT:
81 if ((event1->data.scalar.anchor && !event2->data.scalar.anchor) ||
82 (!event1->data.scalar.anchor && event2->data.scalar.anchor) ||
83 (event1->data.scalar.anchor && event2->data.scalar.anchor &&
84 strcmp((char *)event1->data.scalar.anchor,
85 (char *)event2->data.scalar.anchor) != 0))
86 return equal;
87 if ((event1->data.scalar.tag && !event2->data.scalar.tag &&
88 strcmp((char *)event1->data.scalar.tag, "!") != 0) ||
89 (!event1->data.scalar.tag && event2->data.scalar.tag &&
90 strcmp((char *)event2->data.scalar.tag, "!") != 0) ||
91 (event1->data.scalar.tag && event2->data.scalar.tag &&
92 strcmp((char *)event1->data.scalar.tag,
93 (char *)event2->data.scalar.tag) != 0))
94 return equal;
95 if ((event1->data.scalar.length != event2->data.scalar.length) ||
96 memcmp(event1->data.scalar.value, event2->data.scalar.value,
97 event1->data.scalar.length) != 0)
98 return equal;
99 if ((event1->data.scalar.plain_implicit !=
100 event2->data.scalar.plain_implicit) ||
101 (event1->data.scalar.quoted_implicit !=
102 event2->data.scalar.quoted_implicit))
103 return equal;
104 return !equal;
105
106 case YAML_SEQUENCE_START_EVENT:
107 if ((event1->data.sequence_start.anchor &&
108 !event2->data.sequence_start.anchor) ||
109 (!event1->data.sequence_start.anchor &&
110 event2->data.sequence_start.anchor) ||
111 (event1->data.sequence_start.anchor &&
112 event2->data.sequence_start.anchor &&
113 strcmp((char *)event1->data.sequence_start.anchor,
114 (char *)event2->data.sequence_start.anchor) != 0))
115 return equal;
116 if ((event1->data.sequence_start.tag && !event2->data.sequence_start.tag) ||
117 (!event1->data.sequence_start.tag && event2->data.sequence_start.tag) ||
118 (event1->data.sequence_start.tag && event2->data.sequence_start.tag &&
119 strcmp((char *)event1->data.sequence_start.tag,
120 (char *)event2->data.sequence_start.tag) != 0))
121 return equal;
122 if ((event1->data.sequence_start.implicit !=
123 event2->data.sequence_start.implicit))
124 return equal;
125 return !equal;
126
127 case YAML_MAPPING_START_EVENT:
128 if ((event1->data.mapping_start.anchor &&
129 !event2->data.mapping_start.anchor) ||
130 (!event1->data.mapping_start.anchor &&
131 event2->data.mapping_start.anchor) ||
132 (event1->data.mapping_start.anchor &&
133 event2->data.mapping_start.anchor &&
134 strcmp((char *)event1->data.mapping_start.anchor,
135 (char *)event2->data.mapping_start.anchor) != 0))
136 return equal;
137 if ((event1->data.mapping_start.tag && !event2->data.mapping_start.tag) ||
138 (!event1->data.mapping_start.tag && event2->data.mapping_start.tag) ||
139 (event1->data.mapping_start.tag && event2->data.mapping_start.tag &&
140 strcmp((char *)event1->data.mapping_start.tag,
141 (char *)event2->data.mapping_start.tag) != 0))
142 return equal;
143 if ((event1->data.mapping_start.implicit !=
144 event2->data.mapping_start.implicit))
145 return equal;
146 return !equal;
147
148 default:
149 return !equal;
150 }
151 }
152
copy_event(yaml_event_t * event_to,yaml_event_t * event_from)153 bool copy_event(yaml_event_t *event_to, yaml_event_t *event_from) {
154
155 switch (event_from->type) {
156 case YAML_STREAM_START_EVENT:
157 return yaml_stream_start_event_initialize(
158 event_to, event_from->data.stream_start.encoding);
159
160 case YAML_STREAM_END_EVENT:
161 return yaml_stream_end_event_initialize(event_to);
162
163 case YAML_DOCUMENT_START_EVENT:
164 return yaml_document_start_event_initialize(
165 event_to, event_from->data.document_start.version_directive,
166 event_from->data.document_start.tag_directives.start,
167 event_from->data.document_start.tag_directives.end,
168 event_from->data.document_start.implicit);
169
170 case YAML_DOCUMENT_END_EVENT:
171 return yaml_document_end_event_initialize(
172 event_to, event_from->data.document_end.implicit);
173
174 case YAML_ALIAS_EVENT:
175 return yaml_alias_event_initialize(event_to, event_from->data.alias.anchor);
176
177 case YAML_SCALAR_EVENT:
178 return yaml_scalar_event_initialize(
179 event_to, event_from->data.scalar.anchor, event_from->data.scalar.tag,
180 event_from->data.scalar.value, event_from->data.scalar.length,
181 event_from->data.scalar.plain_implicit,
182 event_from->data.scalar.quoted_implicit, event_from->data.scalar.style);
183
184 case YAML_SEQUENCE_START_EVENT:
185 return yaml_sequence_start_event_initialize(
186 event_to, event_from->data.sequence_start.anchor,
187 event_from->data.sequence_start.tag,
188 event_from->data.sequence_start.implicit,
189 event_from->data.sequence_start.style);
190
191 case YAML_SEQUENCE_END_EVENT:
192 return yaml_sequence_end_event_initialize(event_to);
193
194 case YAML_MAPPING_START_EVENT:
195 return yaml_mapping_start_event_initialize(
196 event_to, event_from->data.mapping_start.anchor,
197 event_from->data.mapping_start.tag,
198 event_from->data.mapping_start.implicit,
199 event_from->data.mapping_start.style);
200
201 case YAML_MAPPING_END_EVENT:
202 return yaml_mapping_end_event_initialize(event_to);
203 }
204
205 return false;
206 }
207
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)208 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
209 if (size < 2)
210 return 0;
211
212 yaml_parser_t parser;
213 yaml_emitter_t emitter;
214 yaml_event_t event;
215 yaml_event_t events[MAX_EVENTS];
216 size_t event_number = 0;
217 bool done = false;
218 int count = 0;
219 bool is_canonical = data[0] & 1;
220 bool is_unicode = data[1] & 1;
221 data += 2;
222 size -= 2;
223
224 if (!yaml_parser_initialize(&parser))
225 return 0;
226
227 yaml_parser_set_input_string(&parser, data, size);
228 if (!yaml_emitter_initialize(&emitter)) {
229 yaml_parser_delete(&parser);
230 return 0;
231 }
232
233 yaml_emitter_set_canonical(&emitter, is_canonical);
234 yaml_emitter_set_unicode(&emitter, is_unicode);
235
236 yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
237 yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
238
239 while (!done) {
240 if (!yaml_parser_parse(&parser, &event)) {
241 goto delete_parser;
242 }
243
244 done = (event.type == YAML_STREAM_END_EVENT);
245 if (event_number >= MAX_EVENTS) {
246 yaml_event_delete(&event);
247 goto delete_parser;
248 }
249
250 if (copy_event(&events[event_number++], &event)) {
251 yaml_event_delete(&event);
252 goto delete_parser;
253 }
254
255 if (!yaml_emitter_emit(&emitter, &event)) {
256 goto delete_parser;
257 }
258
259 }
260
261 yaml_parser_delete(&parser);
262
263 done = false;
264 if (!yaml_parser_initialize(&parser))
265 goto error;
266
267 yaml_parser_set_input_string(&parser, out.buf, out.size);
268
269 while (!done) {
270 if (!yaml_parser_parse(&parser, &event))
271 break;
272
273 done = (event.type == YAML_STREAM_END_EVENT);
274 if (events_equal(events + count, &event)) {
275 yaml_event_delete(&event);
276 break;
277 }
278
279 yaml_event_delete(&event);
280 count++;
281 }
282
283 delete_parser:
284
285 yaml_parser_delete(&parser);
286
287 error:
288
289 yaml_emitter_delete(&emitter);
290
291 for (int k = 0; k < event_number; k++) {
292 yaml_event_delete(events + k);
293 }
294
295 free(out.buf);
296
297 return 0;
298 }
299