• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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