• 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 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)28 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29   if (size < 2)
30     return 0;
31 
32   bool done = false;
33   bool is_canonical = data[0] & 1;
34   bool is_unicode = data[1] & 1;
35   data += 2;
36   size -= 2;
37 
38   yaml_parser_t parser;
39   yaml_emitter_t emitter;
40   yaml_event_t input_event;
41   yaml_document_t output_document;
42 
43   int root;
44 
45   /* Initialize the parser and emitter objects. */
46 
47   if (!yaml_parser_initialize(&parser)) {
48     return 1;
49   }
50 
51   if (!yaml_emitter_initialize(&emitter)) {
52     yaml_parser_delete(&parser);
53     return 1;
54   }
55 
56   /* Set the parser parameters. */
57 
58   yaml_parser_set_input_string(&parser, data, size);
59 
60   /* Set the emitter parameters. */
61   yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
62   yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
63 
64   yaml_emitter_set_canonical(&emitter, is_canonical);
65   yaml_emitter_set_unicode(&emitter, is_unicode);
66 
67   /* Create and emit the STREAM-START event. */
68 
69   if (!yaml_emitter_open(&emitter))
70     goto error;
71 
72   /* Create a output_document object. */
73 
74   if (!yaml_document_initialize(&output_document, NULL, NULL, NULL, 0, 0))
75     goto error;
76 
77   /* Create the root sequence. */
78 
79   root = yaml_document_add_sequence(&output_document, NULL,
80                                     YAML_BLOCK_SEQUENCE_STYLE);
81   if (!root)
82     goto error;
83 
84   /* Loop through the input events. */
85 
86   while (!done) {
87     int properties, key, value, map, seq;
88 
89     /* Get the next event. */
90 
91     if (!yaml_parser_parse(&parser, &input_event))
92       goto error;
93 
94     /* Check if this is the stream end. */
95 
96     done = (input_event.type == YAML_STREAM_END_EVENT);
97 
98     /* Create a mapping node and attach it to the root sequence. */
99 
100     properties = yaml_document_add_mapping(&output_document, NULL,
101                                            YAML_BLOCK_MAPPING_STYLE);
102     if (!properties)
103       goto error;
104     if (!yaml_document_append_sequence_item(&output_document, root, properties))
105       goto error;
106 
107     /* Analyze the event. */
108 
109     switch (input_event.type) {
110     case YAML_STREAM_START_EVENT:
111 
112       /* Add 'type': 'STREAM-START'. */
113 
114       key = yaml_document_add_scalar(&output_document, NULL,
115                                      (yaml_char_t *)"type", -1,
116                                      YAML_PLAIN_SCALAR_STYLE);
117       if (!key)
118         goto error;
119       value = yaml_document_add_scalar(&output_document, NULL,
120                                        (yaml_char_t *)"STREAM-START", -1,
121                                        YAML_PLAIN_SCALAR_STYLE);
122       if (!value)
123         goto error;
124       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
125                                              value))
126         goto error;
127 
128       /* Add 'encoding': <encoding>. */
129 
130       if (input_event.data.stream_start.encoding) {
131         yaml_encoding_t encoding = input_event.data.stream_start.encoding;
132 
133         key = yaml_document_add_scalar(&output_document, NULL,
134                                        (yaml_char_t *)"encoding", -1,
135                                        YAML_PLAIN_SCALAR_STYLE);
136         if (!key)
137           goto error;
138         value = yaml_document_add_scalar(
139             &output_document, NULL,
140             (encoding == YAML_UTF8_ENCODING
141                  ? (yaml_char_t *)"utf-8"
142                  : encoding == YAML_UTF16LE_ENCODING
143                        ? (yaml_char_t *)"utf-16-le"
144                        : encoding == YAML_UTF16BE_ENCODING
145                              ? (yaml_char_t *)"utf-16-be"
146                              : (yaml_char_t *)"unknown"),
147             -1, YAML_PLAIN_SCALAR_STYLE);
148         if (!value)
149           goto error;
150         if (!yaml_document_append_mapping_pair(&output_document, properties,
151                                                key, value))
152           goto error;
153       }
154 
155       break;
156 
157     case YAML_STREAM_END_EVENT:
158 
159       /* Add 'type': 'STREAM-END'. */
160 
161       key = yaml_document_add_scalar(&output_document, NULL,
162                                      (yaml_char_t *)"type", -1,
163                                      YAML_PLAIN_SCALAR_STYLE);
164       if (!key)
165         goto error;
166       value = yaml_document_add_scalar(&output_document, NULL,
167                                        (yaml_char_t *)"STREAM-END", -1,
168                                        YAML_PLAIN_SCALAR_STYLE);
169       if (!value)
170         goto error;
171       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
172                                              value))
173         goto error;
174 
175       break;
176 
177     case YAML_DOCUMENT_START_EVENT:
178 
179       /* Add 'type': 'DOCUMENT-START'. */
180 
181       key = yaml_document_add_scalar(&output_document, NULL,
182                                      (yaml_char_t *)"type", -1,
183                                      YAML_PLAIN_SCALAR_STYLE);
184       if (!key)
185         goto error;
186       value = yaml_document_add_scalar(&output_document, NULL,
187                                        (yaml_char_t *)"DOCUMENT-START", -1,
188                                        YAML_PLAIN_SCALAR_STYLE);
189       if (!value)
190         goto error;
191       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
192                                              value))
193         goto error;
194 
195       /* Display the output_document version numbers. */
196 
197       if (input_event.data.document_start.version_directive) {
198         yaml_version_directive_t *version =
199             input_event.data.document_start.version_directive;
200         char number[64];
201 
202         /* Add 'version': {}. */
203 
204         key = yaml_document_add_scalar(&output_document, NULL,
205                                        (yaml_char_t *)"version", -1,
206                                        YAML_PLAIN_SCALAR_STYLE);
207         if (!key)
208           goto error;
209         map = yaml_document_add_mapping(&output_document, NULL,
210                                         YAML_FLOW_MAPPING_STYLE);
211         if (!map)
212           goto error;
213         if (!yaml_document_append_mapping_pair(&output_document, properties,
214                                                key, map))
215           goto error;
216 
217         /* Add 'major': <number>. */
218 
219         key = yaml_document_add_scalar(&output_document, NULL,
220                                        (yaml_char_t *)"major", -1,
221                                        YAML_PLAIN_SCALAR_STYLE);
222         if (!key)
223           goto error;
224         sprintf(number, "%d", version->major);
225         value = yaml_document_add_scalar(
226             &output_document, (yaml_char_t *)YAML_INT_TAG,
227             (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE);
228         if (!value)
229           goto error;
230         if (!yaml_document_append_mapping_pair(&output_document, map, key,
231                                                value))
232           goto error;
233 
234         /* Add 'minor': <number>. */
235 
236         key = yaml_document_add_scalar(&output_document, NULL,
237                                        (yaml_char_t *)"minor", -1,
238                                        YAML_PLAIN_SCALAR_STYLE);
239         if (!key)
240           goto error;
241         sprintf(number, "%d", version->minor);
242         value = yaml_document_add_scalar(
243             &output_document, (yaml_char_t *)YAML_INT_TAG,
244             (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE);
245         if (!value)
246           goto error;
247         if (!yaml_document_append_mapping_pair(&output_document, map, key,
248                                                value))
249           goto error;
250       }
251 
252       /* Display the output_document tag directives. */
253 
254       if (input_event.data.document_start.tag_directives.start !=
255           input_event.data.document_start.tag_directives.end) {
256         yaml_tag_directive_t *tag;
257 
258         /* Add 'tags': []. */
259 
260         key = yaml_document_add_scalar(&output_document, NULL,
261                                        (yaml_char_t *)"tags", -1,
262                                        YAML_PLAIN_SCALAR_STYLE);
263         if (!key)
264           goto error;
265         seq = yaml_document_add_sequence(&output_document, NULL,
266                                          YAML_BLOCK_SEQUENCE_STYLE);
267         if (!seq)
268           goto error;
269         if (!yaml_document_append_mapping_pair(&output_document, properties,
270                                                key, seq))
271           goto error;
272 
273         for (tag = input_event.data.document_start.tag_directives.start;
274              tag != input_event.data.document_start.tag_directives.end; tag++) {
275           /* Add {}. */
276 
277           map = yaml_document_add_mapping(&output_document, NULL,
278                                           YAML_FLOW_MAPPING_STYLE);
279           if (!map)
280             goto error;
281           if (!yaml_document_append_sequence_item(&output_document, seq, map))
282             goto error;
283 
284           /* Add 'handle': <handle>. */
285 
286           key = yaml_document_add_scalar(&output_document, NULL,
287                                          (yaml_char_t *)"handle", -1,
288                                          YAML_PLAIN_SCALAR_STYLE);
289           if (!key)
290             goto error;
291           value = yaml_document_add_scalar(&output_document, NULL, tag->handle,
292                                            -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
293           if (!value)
294             goto error;
295           if (!yaml_document_append_mapping_pair(&output_document, map, key,
296                                                  value))
297             goto error;
298 
299           /* Add 'prefix': <prefix>. */
300 
301           key = yaml_document_add_scalar(&output_document, NULL,
302                                          (yaml_char_t *)"prefix", -1,
303                                          YAML_PLAIN_SCALAR_STYLE);
304           if (!key)
305             goto error;
306           value = yaml_document_add_scalar(&output_document, NULL, tag->prefix,
307                                            -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
308           if (!value)
309             goto error;
310           if (!yaml_document_append_mapping_pair(&output_document, map, key,
311                                                  value))
312             goto error;
313         }
314       }
315 
316       /* Add 'implicit': <flag>. */
317 
318       key = yaml_document_add_scalar(&output_document, NULL,
319                                      (yaml_char_t *)"implicit", -1,
320                                      YAML_PLAIN_SCALAR_STYLE);
321       if (!key)
322         goto error;
323       value = yaml_document_add_scalar(
324           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
325           (input_event.data.document_start.implicit ? (yaml_char_t *)"true"
326                                                     : (yaml_char_t *)"false"),
327           -1, YAML_PLAIN_SCALAR_STYLE);
328       if (!value)
329         goto error;
330       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
331                                              value))
332         goto error;
333 
334       break;
335 
336     case YAML_DOCUMENT_END_EVENT:
337 
338       /* Add 'type': 'DOCUMENT-END'. */
339 
340       key = yaml_document_add_scalar(&output_document, NULL,
341                                      (yaml_char_t *)"type", -1,
342                                      YAML_PLAIN_SCALAR_STYLE);
343       if (!key)
344         goto error;
345       value = yaml_document_add_scalar(&output_document, NULL,
346                                        (yaml_char_t *)"DOCUMENT-END", -1,
347                                        YAML_PLAIN_SCALAR_STYLE);
348       if (!value)
349         goto error;
350       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
351                                              value))
352         goto error;
353 
354       /* Add 'implicit': <flag>. */
355 
356       key = yaml_document_add_scalar(&output_document, NULL,
357                                      (yaml_char_t *)"implicit", -1,
358                                      YAML_PLAIN_SCALAR_STYLE);
359       if (!key)
360         goto error;
361       value = yaml_document_add_scalar(
362           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
363           (input_event.data.document_end.implicit ? (yaml_char_t *)"true"
364                                                   : (yaml_char_t *)"false"),
365           -1, YAML_PLAIN_SCALAR_STYLE);
366       if (!value)
367         goto error;
368       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
369                                              value))
370         goto error;
371 
372       break;
373 
374     case YAML_ALIAS_EVENT:
375 
376       /* Add 'type': 'ALIAS'. */
377 
378       key = yaml_document_add_scalar(&output_document, NULL,
379                                      (yaml_char_t *)"type", -1,
380                                      YAML_PLAIN_SCALAR_STYLE);
381       if (!key)
382         goto error;
383       value = yaml_document_add_scalar(&output_document, NULL,
384                                        (yaml_char_t *)"ALIAS", -1,
385                                        YAML_PLAIN_SCALAR_STYLE);
386       if (!value)
387         goto error;
388       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
389                                              value))
390         goto error;
391 
392       /* Add 'anchor': <anchor>. */
393 
394       key = yaml_document_add_scalar(&output_document, NULL,
395                                      (yaml_char_t *)"anchor", -1,
396                                      YAML_PLAIN_SCALAR_STYLE);
397       if (!key)
398         goto error;
399       value = yaml_document_add_scalar(&output_document, NULL,
400                                        input_event.data.alias.anchor, -1,
401                                        YAML_DOUBLE_QUOTED_SCALAR_STYLE);
402       if (!value)
403         goto error;
404       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
405                                              value))
406         goto error;
407 
408       break;
409 
410     case YAML_SCALAR_EVENT:
411 
412       /* Add 'type': 'SCALAR'. */
413 
414       key = yaml_document_add_scalar(&output_document, NULL,
415                                      (yaml_char_t *)"type", -1,
416                                      YAML_PLAIN_SCALAR_STYLE);
417       if (!key)
418         goto error;
419       value = yaml_document_add_scalar(&output_document, NULL,
420                                        (yaml_char_t *)"SCALAR", -1,
421                                        YAML_PLAIN_SCALAR_STYLE);
422       if (!value)
423         goto error;
424       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
425                                              value))
426         goto error;
427 
428       /* Add 'anchor': <anchor>. */
429 
430       if (input_event.data.scalar.anchor) {
431         key = yaml_document_add_scalar(&output_document, NULL,
432                                        (yaml_char_t *)"anchor", -1,
433                                        YAML_PLAIN_SCALAR_STYLE);
434         if (!key)
435           goto error;
436         value = yaml_document_add_scalar(&output_document, NULL,
437                                          input_event.data.scalar.anchor, -1,
438                                          YAML_DOUBLE_QUOTED_SCALAR_STYLE);
439         if (!value)
440           goto error;
441         if (!yaml_document_append_mapping_pair(&output_document, properties,
442                                                key, value))
443           goto error;
444       }
445 
446       /* Add 'tag': <tag>. */
447 
448       if (input_event.data.scalar.tag) {
449         key = yaml_document_add_scalar(&output_document, NULL,
450                                        (yaml_char_t *)"tag", -1,
451                                        YAML_PLAIN_SCALAR_STYLE);
452         if (!key)
453           goto error;
454         value = yaml_document_add_scalar(&output_document, NULL,
455                                          input_event.data.scalar.tag, -1,
456                                          YAML_DOUBLE_QUOTED_SCALAR_STYLE);
457         if (!value)
458           goto error;
459         if (!yaml_document_append_mapping_pair(&output_document, properties,
460                                                key, value))
461           goto error;
462       }
463 
464       /* Add 'value': <value>. */
465 
466       key = yaml_document_add_scalar(&output_document, NULL,
467                                      (yaml_char_t *)"value", -1,
468                                      YAML_PLAIN_SCALAR_STYLE);
469       if (!key)
470         goto error;
471       value = yaml_document_add_scalar(
472           &output_document, NULL, input_event.data.scalar.value,
473           input_event.data.scalar.length, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
474       if (!value)
475         goto error;
476       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
477                                              value))
478         goto error;
479 
480       /* Display if the scalar tag is implicit. */
481 
482       /* Add 'implicit': {} */
483 
484       key = yaml_document_add_scalar(&output_document, NULL,
485                                      (yaml_char_t *)"version", -1,
486                                      YAML_PLAIN_SCALAR_STYLE);
487       if (!key)
488         goto error;
489       map = yaml_document_add_mapping(&output_document, NULL,
490                                       YAML_FLOW_MAPPING_STYLE);
491       if (!map)
492         goto error;
493       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
494                                              map))
495         goto error;
496 
497       /* Add 'plain': <flag>. */
498 
499       key = yaml_document_add_scalar(&output_document, NULL,
500                                      (yaml_char_t *)"plain", -1,
501                                      YAML_PLAIN_SCALAR_STYLE);
502       if (!key)
503         goto error;
504       value = yaml_document_add_scalar(
505           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
506           (input_event.data.scalar.plain_implicit ? (yaml_char_t *)"true"
507                                                   : (yaml_char_t *)"false"),
508           -1, YAML_PLAIN_SCALAR_STYLE);
509       if (!value)
510         goto error;
511       if (!yaml_document_append_mapping_pair(&output_document, map, key, value))
512         goto error;
513 
514       /* Add 'quoted': <flag>. */
515 
516       key = yaml_document_add_scalar(&output_document, NULL,
517                                      (yaml_char_t *)"quoted", -1,
518                                      YAML_PLAIN_SCALAR_STYLE);
519       if (!key)
520         goto error;
521       value = yaml_document_add_scalar(
522           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
523           (input_event.data.scalar.quoted_implicit ? (yaml_char_t *)"true"
524                                                    : (yaml_char_t *)"false"),
525           -1, YAML_PLAIN_SCALAR_STYLE);
526       if (!value)
527         goto error;
528       if (!yaml_document_append_mapping_pair(&output_document, map, key, value))
529         goto error;
530 
531       /* Display the style information. */
532 
533       if (input_event.data.scalar.style) {
534         yaml_scalar_style_t style = input_event.data.scalar.style;
535 
536         /* Add 'style': <style>. */
537 
538         key = yaml_document_add_scalar(&output_document, NULL,
539                                        (yaml_char_t *)"style", -1,
540                                        YAML_PLAIN_SCALAR_STYLE);
541         if (!key)
542           goto error;
543         value = yaml_document_add_scalar(
544             &output_document, NULL,
545             (yaml_char_t
546                  *)(style == YAML_PLAIN_SCALAR_STYLE
547                         ? "plain"
548                         : style == YAML_SINGLE_QUOTED_SCALAR_STYLE
549                               ? "single-quoted"
550                               : style == YAML_DOUBLE_QUOTED_SCALAR_STYLE
551                                     ? "double-quoted"
552                                     : style == YAML_LITERAL_SCALAR_STYLE
553                                           ? "literal"
554                                           : style == YAML_FOLDED_SCALAR_STYLE
555                                                 ? "folded"
556                                                 : "unknown"),
557             -1, YAML_PLAIN_SCALAR_STYLE);
558         if (!value)
559           goto error;
560         if (!yaml_document_append_mapping_pair(&output_document, properties,
561                                                key, value))
562           goto error;
563       }
564 
565       break;
566 
567     case YAML_SEQUENCE_START_EVENT:
568 
569       /* Add 'type': 'SEQUENCE-START'. */
570 
571       key = yaml_document_add_scalar(&output_document, NULL,
572                                      (yaml_char_t *)"type", -1,
573                                      YAML_PLAIN_SCALAR_STYLE);
574       if (!key)
575         goto error;
576       value = yaml_document_add_scalar(&output_document, NULL,
577                                        (yaml_char_t *)"SEQUENCE-START", -1,
578                                        YAML_PLAIN_SCALAR_STYLE);
579       if (!value)
580         goto error;
581       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
582                                              value))
583         goto error;
584 
585       /* Add 'anchor': <anchor>. */
586 
587       if (input_event.data.sequence_start.anchor) {
588         key = yaml_document_add_scalar(&output_document, NULL,
589                                        (yaml_char_t *)"anchor", -1,
590                                        YAML_PLAIN_SCALAR_STYLE);
591         if (!key)
592           goto error;
593         value = yaml_document_add_scalar(&output_document, NULL,
594                                          input_event.data.sequence_start.anchor,
595                                          -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
596         if (!value)
597           goto error;
598         if (!yaml_document_append_mapping_pair(&output_document, properties,
599                                                key, value))
600           goto error;
601       }
602 
603       /* Add 'tag': <tag>. */
604 
605       if (input_event.data.sequence_start.tag) {
606         key = yaml_document_add_scalar(&output_document, NULL,
607                                        (yaml_char_t *)"tag", -1,
608                                        YAML_PLAIN_SCALAR_STYLE);
609         if (!key)
610           goto error;
611         value = yaml_document_add_scalar(&output_document, NULL,
612                                          input_event.data.sequence_start.tag,
613                                          -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
614         if (!value)
615           goto error;
616         if (!yaml_document_append_mapping_pair(&output_document, properties,
617                                                key, value))
618           goto error;
619       }
620 
621       /* Add 'implicit': <flag>. */
622 
623       key = yaml_document_add_scalar(&output_document, NULL,
624                                      (yaml_char_t *)"implicit", -1,
625                                      YAML_PLAIN_SCALAR_STYLE);
626       if (!key)
627         goto error;
628       value = yaml_document_add_scalar(
629           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
630           (input_event.data.sequence_start.implicit ? (yaml_char_t *)"true"
631                                                     : (yaml_char_t *)"false"),
632           -1, YAML_PLAIN_SCALAR_STYLE);
633       if (!value)
634         goto error;
635       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
636                                              value))
637         goto error;
638 
639       /* Display the style information. */
640 
641       if (input_event.data.sequence_start.style) {
642         yaml_sequence_style_t style = input_event.data.sequence_start.style;
643 
644         /* Add 'style': <style>. */
645 
646         key = yaml_document_add_scalar(&output_document, NULL,
647                                        (yaml_char_t *)"style", -1,
648                                        YAML_PLAIN_SCALAR_STYLE);
649         if (!key)
650           goto error;
651         value = yaml_document_add_scalar(
652             &output_document, NULL,
653             (yaml_char_t *)(style == YAML_BLOCK_SEQUENCE_STYLE
654                                 ? "block"
655                                 : style == YAML_FLOW_SEQUENCE_STYLE
656                                       ? "flow"
657                                       : "unknown"),
658             -1, YAML_PLAIN_SCALAR_STYLE);
659         if (!value)
660           goto error;
661         if (!yaml_document_append_mapping_pair(&output_document, properties,
662                                                key, value))
663           goto error;
664       }
665 
666       break;
667 
668     case YAML_SEQUENCE_END_EVENT:
669 
670       /* Add 'type': 'SEQUENCE-END'. */
671 
672       key = yaml_document_add_scalar(&output_document, NULL,
673                                      (yaml_char_t *)"type", -1,
674                                      YAML_PLAIN_SCALAR_STYLE);
675       if (!key)
676         goto error;
677       value = yaml_document_add_scalar(&output_document, NULL,
678                                        (yaml_char_t *)"SEQUENCE-END", -1,
679                                        YAML_PLAIN_SCALAR_STYLE);
680       if (!value)
681         goto error;
682       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
683                                              value))
684         goto error;
685 
686       break;
687 
688     case YAML_MAPPING_START_EVENT:
689 
690       /* Add 'type': 'MAPPING-START'. */
691 
692       key = yaml_document_add_scalar(&output_document, NULL,
693                                      (yaml_char_t *)"type", -1,
694                                      YAML_PLAIN_SCALAR_STYLE);
695       if (!key)
696         goto error;
697       value = yaml_document_add_scalar(&output_document, NULL,
698                                        (yaml_char_t *)"MAPPING-START", -1,
699                                        YAML_PLAIN_SCALAR_STYLE);
700       if (!value)
701         goto error;
702       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
703                                              value))
704         goto error;
705 
706       /* Add 'anchor': <anchor>. */
707 
708       if (input_event.data.mapping_start.anchor) {
709         key = yaml_document_add_scalar(&output_document, NULL,
710                                        (yaml_char_t *)"anchor", -1,
711                                        YAML_PLAIN_SCALAR_STYLE);
712         if (!key)
713           goto error;
714         value = yaml_document_add_scalar(&output_document, NULL,
715                                          input_event.data.mapping_start.anchor,
716                                          -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
717         if (!value)
718           goto error;
719         if (!yaml_document_append_mapping_pair(&output_document, properties,
720                                                key, value))
721           goto error;
722       }
723 
724       /* Add 'tag': <tag>. */
725 
726       if (input_event.data.mapping_start.tag) {
727         key = yaml_document_add_scalar(&output_document, NULL,
728                                        (yaml_char_t *)"tag", -1,
729                                        YAML_PLAIN_SCALAR_STYLE);
730         if (!key)
731           goto error;
732         value = yaml_document_add_scalar(&output_document, NULL,
733                                          input_event.data.mapping_start.tag, -1,
734                                          YAML_DOUBLE_QUOTED_SCALAR_STYLE);
735         if (!value)
736           goto error;
737         if (!yaml_document_append_mapping_pair(&output_document, properties,
738                                                key, value))
739           goto error;
740       }
741 
742       /* Add 'implicit': <flag>. */
743 
744       key = yaml_document_add_scalar(&output_document, NULL,
745                                      (yaml_char_t *)"implicit", -1,
746                                      YAML_PLAIN_SCALAR_STYLE);
747       if (!key)
748         goto error;
749       value = yaml_document_add_scalar(
750           &output_document, (yaml_char_t *)YAML_BOOL_TAG,
751           (yaml_char_t *)(input_event.data.mapping_start.implicit ? "true"
752                                                                   : "false"),
753           -1, YAML_PLAIN_SCALAR_STYLE);
754       if (!value)
755         goto error;
756       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
757                                              value))
758         goto error;
759 
760       /* Display the style information. */
761 
762       if (input_event.data.sequence_start.style) {
763         yaml_sequence_style_t style = input_event.data.sequence_start.style;
764 
765         /* Add 'style': <style>. */
766 
767         key = yaml_document_add_scalar(&output_document, NULL,
768                                        (yaml_char_t *)"style", -1,
769                                        YAML_PLAIN_SCALAR_STYLE);
770         if (!key)
771           goto error;
772         value = yaml_document_add_scalar(
773             &output_document, NULL,
774             (yaml_char_t *)(style == YAML_BLOCK_MAPPING_STYLE
775                                 ? "block"
776                                 : style == YAML_FLOW_MAPPING_STYLE ? "flow"
777                                                                    : "unknown"),
778             -1, YAML_PLAIN_SCALAR_STYLE);
779         if (!value)
780           goto error;
781         if (!yaml_document_append_mapping_pair(&output_document, properties,
782                                                key, value))
783           goto error;
784       }
785 
786       break;
787 
788     case YAML_MAPPING_END_EVENT:
789 
790       /* Add 'type': 'MAPPING-END'. */
791 
792       key = yaml_document_add_scalar(&output_document, NULL,
793                                      (yaml_char_t *)"type", -1,
794                                      YAML_PLAIN_SCALAR_STYLE);
795       if (!key)
796         goto error;
797       value = yaml_document_add_scalar(&output_document, NULL,
798                                        (yaml_char_t *)"MAPPING-END", -1,
799                                        YAML_PLAIN_SCALAR_STYLE);
800       if (!value)
801         goto error;
802       if (!yaml_document_append_mapping_pair(&output_document, properties, key,
803                                              value))
804         goto error;
805 
806       break;
807 
808     default:
809       /* It couldn't really happen. */
810       break;
811     }
812 
813     /* Delete the event object. */
814 
815     yaml_event_delete(&input_event);
816   }
817 
818   if (!yaml_emitter_dump(&emitter, &output_document))
819     goto error;
820 
821   yaml_emitter_close(&emitter);
822 
823 error:
824 
825   free(out.buf);
826 
827   yaml_event_delete(&input_event);
828   yaml_document_delete(&output_document);
829   yaml_parser_delete(&parser);
830   yaml_emitter_delete(&emitter);
831 
832   return 0;
833 }
834