aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ravi Jotwani <rjotwani@google.com>2020-08-12 15:44:24 -0700
committerGravatar GitHub <noreply@github.com>2020-08-12 15:44:24 -0700
commit8a74af8f52c9e6c934c0f3aea3896bee080224f5 (patch)
tree9eaa14ad399ab494b1390f6166b90684099eec7d
parent089c9e039b11b216705a3bc2dc77cad039ac328c (diff)
[libyaml] Add more fuzz targets (#4043)
* added draco integration files * wrote build file and Dockerfile for Draco * added more fuzzers, updated build script to generate corpus and options for each * place yaml.dict in SRC first, rather than in OUT directly * changed fuzzers from c++ to c, updated build script * started using booleans instead of ints, updated naming conventions * replaced all instances of with * removed memsets, stopped using first two bytes of input, and removed file I/O * fixed style, changed function return types to bool instead of int * added libyaml_parser_fuzzer back, implemented string handling to not exceed buffer size in libyaml_emitter_fuzzer, and made style fixes * changed boolean functions to return error, not success * fixed inverted check * changed variable names, fixed crash in libyaml_emitter_fuzzer * fixed addition/subtraction style * make a dynamically growing heap buffer * place yaml_write_handler in distinct header file, style fixes * fix style and memory safety issues in reformatter fuzzers, remove unused vars * consistent assignment of done variables
-rw-r--r--projects/libyaml/Dockerfile4
-rwxr-xr-xprojects/libyaml/build.sh23
-rw-r--r--projects/libyaml/libyaml_deconstructor_alt_fuzzer.c833
-rw-r--r--projects/libyaml/libyaml_deconstructor_fuzzer.c994
-rw-r--r--projects/libyaml/libyaml_dumper_fuzzer.c311
-rw-r--r--projects/libyaml/libyaml_emitter_fuzzer.c298
-rw-r--r--projects/libyaml/libyaml_fuzzer.cc21
-rw-r--r--projects/libyaml/libyaml_loader_fuzzer.c51
-rw-r--r--projects/libyaml/libyaml_parser_fuzzer.c49
-rw-r--r--projects/libyaml/libyaml_reformatter_alt_fuzzer.c86
-rw-r--r--projects/libyaml/libyaml_reformatter_fuzzer.c86
-rw-r--r--projects/libyaml/libyaml_scanner_fuzzer.c51
-rw-r--r--projects/libyaml/yaml_write_handler.h37
13 files changed, 2816 insertions, 28 deletions
diff --git a/projects/libyaml/Dockerfile b/projects/libyaml/Dockerfile
index d52249eb..8477cced 100644
--- a/projects/libyaml/Dockerfile
+++ b/projects/libyaml/Dockerfile
@@ -18,7 +18,7 @@ FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone --depth=1 https://github.com/yaml/libyaml
-RUN zip libyaml_fuzzer_seed_corpus.zip libyaml/examples/*
+RUN zip $SRC/libyaml_seed_corpus.zip libyaml/examples/*
WORKDIR libyaml
-COPY build.sh libyaml_fuzzer.cc libyaml_fuzzer.options yaml.dict $SRC/
+COPY build.sh *.h *_fuzzer.c libyaml_fuzzer.options yaml.dict $SRC/
diff --git a/projects/libyaml/build.sh b/projects/libyaml/build.sh
index f78b99ba..1eb31302 100755
--- a/projects/libyaml/build.sh
+++ b/projects/libyaml/build.sh
@@ -18,9 +18,22 @@
./configure
make "-j$(nproc)"
-$CXX $CXXFLAGS -std=c++11 -Iinclude \
- $SRC/libyaml_fuzzer.cc -o $OUT/libyaml_fuzzer \
- $LIB_FUZZING_ENGINE src/.libs/libyaml.a
+for fuzzer in $SRC/*_fuzzer.c; do
+ fuzzer_basename=$(basename -s .c $fuzzer)
-cp $SRC/libyaml_fuzzer_seed_corpus.zip $OUT/
-cp $SRC/*.dict $SRC/*.options $OUT/
+ $CC $CFLAGS \
+ -I $SRC -Iinclude \
+ -c $fuzzer -o $fuzzer_basename.o
+
+ $CXX $CXXFLAGS \
+ -std=c++11 \
+ $fuzzer_basename.o \
+ -o $OUT/$fuzzer_basename \
+ $LIB_FUZZING_ENGINE \
+ src/.libs/libyaml.a
+
+ cp $SRC/libyaml_seed_corpus.zip "${OUT}/${fuzzer_basename}_seed_corpus.zip"
+ cp $SRC/libyaml_fuzzer.options "${OUT}/${fuzzer_basename}.options"
+done
+
+cp $SRC/yaml.dict $OUT/
diff --git a/projects/libyaml/libyaml_deconstructor_alt_fuzzer.c b/projects/libyaml/libyaml_deconstructor_alt_fuzzer.c
new file mode 100644
index 00000000..b8ac2fe5
--- /dev/null
+++ b/projects/libyaml/libyaml_deconstructor_alt_fuzzer.c
@@ -0,0 +1,833 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ bool done = false;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+ yaml_event_t input_event;
+ yaml_document_t output_document;
+
+ int root;
+
+ /* Initialize the parser and emitter objects. */
+
+ if (!yaml_parser_initialize(&parser)) {
+ return 1;
+ }
+
+ if (!yaml_emitter_initialize(&emitter)) {
+ yaml_parser_delete(&parser);
+ return 1;
+ }
+
+ /* Set the parser parameters. */
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ /* Set the emitter parameters. */
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ /* Create and emit the STREAM-START event. */
+
+ if (!yaml_emitter_open(&emitter))
+ goto error;
+
+ /* Create a output_document object. */
+
+ if (!yaml_document_initialize(&output_document, NULL, NULL, NULL, 0, 0))
+ goto error;
+
+ /* Create the root sequence. */
+
+ root = yaml_document_add_sequence(&output_document, NULL,
+ YAML_BLOCK_SEQUENCE_STYLE);
+ if (!root)
+ goto error;
+
+ /* Loop through the input events. */
+
+ while (!done) {
+ int properties, key, value, map, seq;
+
+ /* Get the next event. */
+
+ if (!yaml_parser_parse(&parser, &input_event))
+ goto error;
+
+ /* Check if this is the stream end. */
+
+ done = (input_event.type == YAML_STREAM_END_EVENT);
+
+ /* Create a mapping node and attach it to the root sequence. */
+
+ properties = yaml_document_add_mapping(&output_document, NULL,
+ YAML_BLOCK_MAPPING_STYLE);
+ if (!properties)
+ goto error;
+ if (!yaml_document_append_sequence_item(&output_document, root, properties))
+ goto error;
+
+ /* Analyze the event. */
+
+ switch (input_event.type) {
+ case YAML_STREAM_START_EVENT:
+
+ /* Add 'type': 'STREAM-START'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"STREAM-START", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'encoding': <encoding>. */
+
+ if (input_event.data.stream_start.encoding) {
+ yaml_encoding_t encoding = input_event.data.stream_start.encoding;
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"encoding", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, NULL,
+ (encoding == YAML_UTF8_ENCODING
+ ? (yaml_char_t *)"utf-8"
+ : encoding == YAML_UTF16LE_ENCODING
+ ? (yaml_char_t *)"utf-16-le"
+ : encoding == YAML_UTF16BE_ENCODING
+ ? (yaml_char_t *)"utf-16-be"
+ : (yaml_char_t *)"unknown"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ break;
+
+ case YAML_STREAM_END_EVENT:
+
+ /* Add 'type': 'STREAM-END'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"STREAM-END", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ case YAML_DOCUMENT_START_EVENT:
+
+ /* Add 'type': 'DOCUMENT-START'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"DOCUMENT-START", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Display the output_document version numbers. */
+
+ if (input_event.data.document_start.version_directive) {
+ yaml_version_directive_t *version =
+ input_event.data.document_start.version_directive;
+ char number[64];
+
+ /* Add 'version': {}. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"version", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ map = yaml_document_add_mapping(&output_document, NULL,
+ YAML_FLOW_MAPPING_STYLE);
+ if (!map)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, map))
+ goto error;
+
+ /* Add 'major': <number>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"major", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ sprintf(number, "%d", version->major);
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key,
+ value))
+ goto error;
+
+ /* Add 'minor': <number>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"minor", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ sprintf(number, "%d", version->minor);
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_INT_TAG,
+ (yaml_char_t *)number, -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key,
+ value))
+ goto error;
+ }
+
+ /* Display the output_document tag directives. */
+
+ if (input_event.data.document_start.tag_directives.start !=
+ input_event.data.document_start.tag_directives.end) {
+ yaml_tag_directive_t *tag;
+
+ /* Add 'tags': []. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"tags", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ seq = yaml_document_add_sequence(&output_document, NULL,
+ YAML_BLOCK_SEQUENCE_STYLE);
+ if (!seq)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, seq))
+ goto error;
+
+ for (tag = input_event.data.document_start.tag_directives.start;
+ tag != input_event.data.document_start.tag_directives.end; tag++) {
+ /* Add {}. */
+
+ map = yaml_document_add_mapping(&output_document, NULL,
+ YAML_FLOW_MAPPING_STYLE);
+ if (!map)
+ goto error;
+ if (!yaml_document_append_sequence_item(&output_document, seq, map))
+ goto error;
+
+ /* Add 'handle': <handle>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"handle", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL, tag->handle,
+ -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key,
+ value))
+ goto error;
+
+ /* Add 'prefix': <prefix>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"prefix", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL, tag->prefix,
+ -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key,
+ value))
+ goto error;
+ }
+ }
+
+ /* Add 'implicit': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"implicit", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (input_event.data.document_start.implicit ? (yaml_char_t *)"true"
+ : (yaml_char_t *)"false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ case YAML_DOCUMENT_END_EVENT:
+
+ /* Add 'type': 'DOCUMENT-END'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"DOCUMENT-END", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'implicit': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"implicit", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (input_event.data.document_end.implicit ? (yaml_char_t *)"true"
+ : (yaml_char_t *)"false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ case YAML_ALIAS_EVENT:
+
+ /* Add 'type': 'ALIAS'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"ALIAS", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'anchor': <anchor>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"anchor", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.alias.anchor, -1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ case YAML_SCALAR_EVENT:
+
+ /* Add 'type': 'SCALAR'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"SCALAR", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'anchor': <anchor>. */
+
+ if (input_event.data.scalar.anchor) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"anchor", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.scalar.anchor, -1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'tag': <tag>. */
+
+ if (input_event.data.scalar.tag) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"tag", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.scalar.tag, -1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'value': <value>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"value", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, NULL, input_event.data.scalar.value,
+ input_event.data.scalar.length, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Display if the scalar tag is implicit. */
+
+ /* Add 'implicit': {} */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"version", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ map = yaml_document_add_mapping(&output_document, NULL,
+ YAML_FLOW_MAPPING_STYLE);
+ if (!map)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ map))
+ goto error;
+
+ /* Add 'plain': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"plain", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (input_event.data.scalar.plain_implicit ? (yaml_char_t *)"true"
+ : (yaml_char_t *)"false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key, value))
+ goto error;
+
+ /* Add 'quoted': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"quoted", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (input_event.data.scalar.quoted_implicit ? (yaml_char_t *)"true"
+ : (yaml_char_t *)"false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, map, key, value))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.scalar.style) {
+ yaml_scalar_style_t style = input_event.data.scalar.style;
+
+ /* Add 'style': <style>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"style", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, NULL,
+ (yaml_char_t
+ *)(style == YAML_PLAIN_SCALAR_STYLE
+ ? "plain"
+ : style == YAML_SINGLE_QUOTED_SCALAR_STYLE
+ ? "single-quoted"
+ : style == YAML_DOUBLE_QUOTED_SCALAR_STYLE
+ ? "double-quoted"
+ : style == YAML_LITERAL_SCALAR_STYLE
+ ? "literal"
+ : style == YAML_FOLDED_SCALAR_STYLE
+ ? "folded"
+ : "unknown"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+
+ /* Add 'type': 'SEQUENCE-START'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"SEQUENCE-START", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'anchor': <anchor>. */
+
+ if (input_event.data.sequence_start.anchor) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"anchor", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.sequence_start.anchor,
+ -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'tag': <tag>. */
+
+ if (input_event.data.sequence_start.tag) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"tag", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.sequence_start.tag,
+ -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'implicit': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"implicit", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (input_event.data.sequence_start.implicit ? (yaml_char_t *)"true"
+ : (yaml_char_t *)"false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.sequence_start.style) {
+ yaml_sequence_style_t style = input_event.data.sequence_start.style;
+
+ /* Add 'style': <style>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"style", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, NULL,
+ (yaml_char_t *)(style == YAML_BLOCK_SEQUENCE_STYLE
+ ? "block"
+ : style == YAML_FLOW_SEQUENCE_STYLE
+ ? "flow"
+ : "unknown"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ break;
+
+ case YAML_SEQUENCE_END_EVENT:
+
+ /* Add 'type': 'SEQUENCE-END'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"SEQUENCE-END", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+
+ /* Add 'type': 'MAPPING-START'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"MAPPING-START", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Add 'anchor': <anchor>. */
+
+ if (input_event.data.mapping_start.anchor) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"anchor", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.mapping_start.anchor,
+ -1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'tag': <tag>. */
+
+ if (input_event.data.mapping_start.tag) {
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"tag", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ input_event.data.mapping_start.tag, -1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ /* Add 'implicit': <flag>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"implicit", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, (yaml_char_t *)YAML_BOOL_TAG,
+ (yaml_char_t *)(input_event.data.mapping_start.implicit ? "true"
+ : "false"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.sequence_start.style) {
+ yaml_sequence_style_t style = input_event.data.sequence_start.style;
+
+ /* Add 'style': <style>. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"style", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(
+ &output_document, NULL,
+ (yaml_char_t *)(style == YAML_BLOCK_MAPPING_STYLE
+ ? "block"
+ : style == YAML_FLOW_MAPPING_STYLE ? "flow"
+ : "unknown"),
+ -1, YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties,
+ key, value))
+ goto error;
+ }
+
+ break;
+
+ case YAML_MAPPING_END_EVENT:
+
+ /* Add 'type': 'MAPPING-END'. */
+
+ key = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"type", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!key)
+ goto error;
+ value = yaml_document_add_scalar(&output_document, NULL,
+ (yaml_char_t *)"MAPPING-END", -1,
+ YAML_PLAIN_SCALAR_STYLE);
+ if (!value)
+ goto error;
+ if (!yaml_document_append_mapping_pair(&output_document, properties, key,
+ value))
+ goto error;
+
+ break;
+
+ default:
+ /* It couldn't really happen. */
+ break;
+ }
+
+ /* Delete the event object. */
+
+ yaml_event_delete(&input_event);
+ }
+
+ if (!yaml_emitter_dump(&emitter, &output_document))
+ goto error;
+
+ yaml_emitter_close(&emitter);
+
+error:
+
+ free(out.buf);
+
+ yaml_event_delete(&input_event);
+ yaml_document_delete(&output_document);
+ yaml_parser_delete(&parser);
+ yaml_emitter_delete(&emitter);
+
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_deconstructor_fuzzer.c b/projects/libyaml/libyaml_deconstructor_fuzzer.c
new file mode 100644
index 00000000..2f1079b8
--- /dev/null
+++ b/projects/libyaml/libyaml_deconstructor_fuzzer.c
@@ -0,0 +1,994 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ bool done = false;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+ yaml_event_t input_event;
+ yaml_event_t output_event;
+
+ /* Initialize the parser and emitter objects. */
+
+ if (!yaml_parser_initialize(&parser)) {
+ return 1;
+ }
+
+ if (!yaml_emitter_initialize(&emitter)) {
+ yaml_parser_delete(&parser);
+ return 1;
+ }
+
+ /* Set the parser parameters. */
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ /* Set the emitter parameters. */
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ /* Create and emit the STREAM-START event. */
+
+ if (!yaml_stream_start_event_initialize(&output_event, YAML_UTF8_ENCODING))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Create and emit the DOCUMENT-START event. */
+
+ if (!yaml_document_start_event_initialize(&output_event, NULL, NULL, NULL, 0))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Create and emit the SEQUENCE-START event. */
+
+ if (!yaml_sequence_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:seq", 1,
+ YAML_BLOCK_SEQUENCE_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Loop through the input events. */
+
+ while (!done) {
+ /* Get the next event. */
+
+ if (!yaml_parser_parse(&parser, &input_event))
+ goto error;
+
+ /* Check if this is the stream end. */
+
+ done = (input_event.type == YAML_STREAM_END_EVENT);
+
+ /* Create and emit a MAPPING-START event. */
+
+ if (!yaml_mapping_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:map", 1,
+ YAML_BLOCK_MAPPING_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Analyze the event. */
+
+ switch (input_event.type) {
+ case YAML_STREAM_START_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'STREAM-START'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"STREAM-START", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display encoding information. */
+
+ if (input_event.data.stream_start.encoding) {
+ yaml_encoding_t encoding = input_event.data.stream_start.encoding;
+
+ /* Write 'encoding'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"encoding", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the stream encoding. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)(encoding == YAML_UTF8_ENCODING
+ ? "utf-8"
+ : encoding == YAML_UTF16LE_ENCODING
+ ? "utf-16-le"
+ : encoding == YAML_UTF16BE_ENCODING
+ ? "utf-16-be"
+ : "unknown"),
+ -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ break;
+
+ case YAML_STREAM_END_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'STREAM-END'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"STREAM-END", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ case YAML_DOCUMENT_START_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'DOCUMENT-START'. */
+
+ if (!yaml_scalar_event_initialize(&output_event, NULL,
+ (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"DOCUMENT-START", -1, 1,
+ 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the document version numbers. */
+
+ if (input_event.data.document_start.version_directive) {
+ yaml_version_directive_t *version =
+ input_event.data.document_start.version_directive;
+ char number[64];
+
+ /* Write 'version'. */
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"version", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write '{'. */
+
+ if (!yaml_mapping_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:map", 1,
+ YAML_FLOW_MAPPING_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'major'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"major", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write a number. */
+
+ sprintf(number, "%d", version->major);
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:int",
+ (yaml_char_t *)number, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'minor'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"minor", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write a number. */
+
+ sprintf(number, "%d", version->minor);
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:int",
+ (yaml_char_t *)number, -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write '}'. */
+
+ if (!yaml_mapping_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Display the document tag directives. */
+
+ if (input_event.data.document_start.tag_directives.start !=
+ input_event.data.document_start.tag_directives.end) {
+ yaml_tag_directive_t *tag;
+
+ /* Write 'tags'. */
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"tags", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Start a block sequence. */
+
+ if (!yaml_sequence_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:seq", 1,
+ YAML_BLOCK_SEQUENCE_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ for (tag = input_event.data.document_start.tag_directives.start;
+ tag != input_event.data.document_start.tag_directives.end; tag++) {
+ /* Write '{'. */
+
+ if (!yaml_mapping_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:map",
+ 1, YAML_FLOW_MAPPING_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'handle'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"handle", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the tag directive handle. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)tag->handle, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'prefix'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"prefix", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the tag directive prefix. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)tag->prefix, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write '}'. */
+
+ if (!yaml_mapping_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* End a block sequence. */
+
+ if (!yaml_sequence_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Write 'implicit'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"implicit", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the document is implicit. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.document_start.implicit
+ ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ case YAML_DOCUMENT_END_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'DOCUMENT-END'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"DOCUMENT-END", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'implicit'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"implicit", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the document is implicit. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.document_end.implicit ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ case YAML_ALIAS_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'ALIAS'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"ALIAS", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'anchor'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"anchor", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the alias anchor. */
+
+ if (!yaml_scalar_event_initialize(&output_event, NULL,
+ (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.alias.anchor, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ case YAML_SCALAR_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'SCALAR'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"SCALAR", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the scalar anchor. */
+
+ if (input_event.data.scalar.anchor) {
+ /* Write 'anchor'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"anchor", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar anchor. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.scalar.anchor, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Display the scalar tag. */
+
+ if (input_event.data.scalar.tag) {
+ /* Write 'tag'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"tag", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar tag. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.scalar.tag, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Display the scalar value. */
+
+ /* Write 'value'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"value", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar value. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.scalar.value, input_event.data.scalar.length, 0,
+ 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display if the scalar tag is implicit. */
+
+ /* Write 'implicit'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"implicit", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write '{'. */
+
+ if (!yaml_mapping_start_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:map", 1,
+ YAML_FLOW_MAPPING_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'plain'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"plain", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the scalar is implicit in the plain style. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.scalar.plain_implicit ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'quoted'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"non-plain", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the scalar is implicit in a non-plain style. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.scalar.quoted_implicit
+ ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write '}'. */
+
+ if (!yaml_mapping_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.scalar.style) {
+ yaml_scalar_style_t style = input_event.data.scalar.style;
+
+ /* Write 'style'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"style", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar style. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t
+ *)(style == YAML_PLAIN_SCALAR_STYLE
+ ? "plain"
+ : style == YAML_SINGLE_QUOTED_SCALAR_STYLE
+ ? "single-quoted"
+ : style == YAML_DOUBLE_QUOTED_SCALAR_STYLE
+ ? "double-quoted"
+ : style == YAML_LITERAL_SCALAR_STYLE
+ ? "literal"
+ : style ==
+ YAML_FOLDED_SCALAR_STYLE
+ ? "folded"
+ : "unknown"),
+ -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ break;
+
+ case YAML_SEQUENCE_START_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'SEQUENCE-START'. */
+
+ if (!yaml_scalar_event_initialize(&output_event, NULL,
+ (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"SEQUENCE-START", -1, 1,
+ 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the sequence anchor. */
+
+ if (input_event.data.sequence_start.anchor) {
+ /* Write 'anchor'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"anchor", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the sequence anchor. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.sequence_start.anchor, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Display the sequence tag. */
+
+ if (input_event.data.sequence_start.tag) {
+ /* Write 'tag'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"tag", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the sequence tag. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.sequence_start.tag, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Write 'implicit'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"implicit", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the sequence tag is implicit. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.sequence_start.implicit
+ ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.sequence_start.style) {
+ yaml_sequence_style_t style = input_event.data.sequence_start.style;
+
+ /* Write 'style'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"style", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar style. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)(style == YAML_BLOCK_SEQUENCE_STYLE
+ ? "block"
+ : style == YAML_FLOW_SEQUENCE_STYLE
+ ? "flow"
+ : "unknown"),
+ -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ break;
+
+ case YAML_SEQUENCE_END_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'SEQUENCE-END'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"SEQUENCE-END", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ case YAML_MAPPING_START_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'MAPPING-START'. */
+
+ if (!yaml_scalar_event_initialize(&output_event, NULL,
+ (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"MAPPING-START", -1, 1,
+ 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the mapping anchor. */
+
+ if (input_event.data.mapping_start.anchor) {
+ /* Write 'anchor'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"anchor", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the mapping anchor. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.mapping_start.anchor, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Display the mapping tag. */
+
+ if (input_event.data.mapping_start.tag) {
+ /* Write 'tag'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"tag", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the mapping tag. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ input_event.data.mapping_start.tag, -1, 0, 1,
+ YAML_DOUBLE_QUOTED_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Write 'implicit'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"implicit", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write if the mapping tag is implicit. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:bool",
+ (yaml_char_t *)(input_event.data.mapping_start.implicit
+ ? "true"
+ : "false"),
+ -1, 1, 0, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Display the style information. */
+
+ if (input_event.data.mapping_start.style) {
+ yaml_mapping_style_t style = input_event.data.mapping_start.style;
+
+ /* Write 'style'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"style", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write the scalar style. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)(style == YAML_BLOCK_MAPPING_STYLE
+ ? "block"
+ : style == YAML_FLOW_MAPPING_STYLE
+ ? "flow"
+ : "unknown"),
+ -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ break;
+
+ case YAML_MAPPING_END_EVENT:
+
+ /* Write 'type'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"type", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Write 'MAPPING-END'. */
+
+ if (!yaml_scalar_event_initialize(
+ &output_event, NULL, (yaml_char_t *)"tag:yaml.org,2002:str",
+ (yaml_char_t *)"MAPPING-END", -1, 1, 1, YAML_PLAIN_SCALAR_STYLE))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ break;
+
+ default:
+ /* It couldn't really happen. */
+ break;
+ }
+
+ /* Delete the event object. */
+
+ yaml_event_delete(&input_event);
+
+ /* Create and emit a MAPPING-END event. */
+
+ if (!yaml_mapping_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+ }
+
+ /* Create and emit the SEQUENCE-END event. */
+
+ if (!yaml_sequence_end_event_initialize(&output_event))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Create and emit the DOCUMENT-END event. */
+
+ if (!yaml_document_end_event_initialize(&output_event, 0))
+ goto error;
+ if (!yaml_emitter_emit(&emitter, &output_event))
+ goto error;
+
+ /* Create and emit the STREAM-END event. */
+
+ if (!yaml_stream_end_event_initialize(&output_event))
+ goto error;
+ yaml_emitter_emit(&emitter, &output_event);
+
+error:
+
+ free(out.buf);
+
+ yaml_event_delete(&input_event);
+ yaml_parser_delete(&parser);
+ yaml_emitter_delete(&emitter);
+
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_dumper_fuzzer.c b/projects/libyaml/libyaml_dumper_fuzzer.c
new file mode 100644
index 00000000..5ad8a4e0
--- /dev/null
+++ b/projects/libyaml/libyaml_dumper_fuzzer.c
@@ -0,0 +1,311 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#define MAX_DOCUMENTS 16
+
+bool nodes_equal(yaml_document_t *document1, int index1,
+ yaml_document_t *document2, int index2, int level) {
+ const bool equal = true;
+
+ if (level++ > 1000)
+ return !equal;
+ yaml_node_t *node1 = yaml_document_get_node(document1, index1);
+
+ if (!node1)
+ return !equal;
+
+ yaml_node_t *node2 = yaml_document_get_node(document2, index2);
+
+ if (!node2)
+ return !equal;
+
+ if (node1->type != node2->type)
+ return !equal;
+
+ if (strcmp((char *)node1->tag, (char *)node2->tag) != 0)
+ return !equal;
+
+ switch (node1->type) {
+ case YAML_SCALAR_NODE:
+ if (node1->data.scalar.length != node2->data.scalar.length)
+ return !equal;
+ if (strncmp((char *)node1->data.scalar.value,
+ (char *)node2->data.scalar.value,
+ node1->data.scalar.length) != 0)
+ return !equal;
+ break;
+ case YAML_SEQUENCE_NODE:
+ if ((node1->data.sequence.items.top - node1->data.sequence.items.start) !=
+ (node2->data.sequence.items.top - node2->data.sequence.items.start))
+ return !equal;
+ for (int k = 0; k < (node1->data.sequence.items.top -
+ node1->data.sequence.items.start);
+ k++) {
+ if (!nodes_equal(document1, node1->data.sequence.items.start[k],
+ document2, node2->data.sequence.items.start[k], level))
+ return !equal;
+ }
+ break;
+ case YAML_MAPPING_NODE:
+ if ((node1->data.mapping.pairs.top - node1->data.mapping.pairs.start) !=
+ (node2->data.mapping.pairs.top - node2->data.mapping.pairs.start))
+ return !equal;
+ for (int k = 0;
+ k < (node1->data.mapping.pairs.top - node1->data.mapping.pairs.start);
+ k++) {
+ if (!nodes_equal(document1, node1->data.mapping.pairs.start[k].key,
+ document2, node2->data.mapping.pairs.start[k].key,
+ level))
+ return !equal;
+ if (!nodes_equal(document1, node1->data.mapping.pairs.start[k].value,
+ document2, node2->data.mapping.pairs.start[k].value,
+ level))
+ return !equal;
+ }
+ break;
+ default:
+ return !equal;
+ }
+ return equal;
+}
+
+bool documents_equal(yaml_document_t *document1, yaml_document_t *document2) {
+
+ const bool equal = true;
+
+ if ((document1->version_directive && !document2->version_directive) ||
+ (!document1->version_directive && document2->version_directive) ||
+ (document1->version_directive && document2->version_directive &&
+ (document1->version_directive->major !=
+ document2->version_directive->major ||
+ document1->version_directive->minor !=
+ document2->version_directive->minor)))
+ return !equal;
+
+ if ((document1->tag_directives.end - document1->tag_directives.start) !=
+ (document2->tag_directives.end - document2->tag_directives.start))
+ return !equal;
+ for (int k = 0;
+ k < (document1->tag_directives.end - document1->tag_directives.start);
+ k++) {
+ if ((strcmp((char *)document1->tag_directives.start[k].handle,
+ (char *)document2->tag_directives.start[k].handle) != 0) ||
+ (strcmp((char *)document1->tag_directives.start[k].prefix,
+ (char *)document2->tag_directives.start[k].prefix) != 0))
+ return !equal;
+ }
+
+ if ((document1->nodes.top - document1->nodes.start) !=
+ (document2->nodes.top - document2->nodes.start))
+ return !equal;
+
+ if (document1->nodes.top != document1->nodes.start) {
+ if (!nodes_equal(document1, 1, document2, 1, 0))
+ return !equal;
+ }
+
+ return equal;
+}
+
+bool copy_document(yaml_document_t *document_to,
+ yaml_document_t *document_from) {
+ bool error = true;
+
+ yaml_node_t *node;
+ yaml_node_item_t *item;
+ yaml_node_pair_t *pair;
+
+ if (!yaml_document_initialize(document_to, document_from->version_directive,
+ document_from->tag_directives.start,
+ document_from->tag_directives.end,
+ document_from->start_implicit,
+ document_from->end_implicit))
+ return !error;
+
+ for (node = document_from->nodes.start; node < document_from->nodes.top;
+ node++) {
+ switch (node->type) {
+ case YAML_SCALAR_NODE:
+ if (!yaml_document_add_scalar(
+ document_to, node->tag, node->data.scalar.value,
+ node->data.scalar.length, node->data.scalar.style))
+ goto out;
+ break;
+ case YAML_SEQUENCE_NODE:
+ if (!yaml_document_add_sequence(document_to, node->tag,
+ node->data.sequence.style))
+ goto out;
+ break;
+ case YAML_MAPPING_NODE:
+ if (!yaml_document_add_mapping(document_to, node->tag,
+ node->data.mapping.style))
+ goto out;
+ break;
+ default:
+ goto out;
+ }
+ }
+
+ for (node = document_from->nodes.start; node < document_from->nodes.top;
+ node++) {
+ switch (node->type) {
+ case YAML_SEQUENCE_NODE:
+ for (item = node->data.sequence.items.start;
+ item < node->data.sequence.items.top; item++) {
+ if (!yaml_document_append_sequence_item(
+ document_to, node - document_from->nodes.start + 1, *item))
+ goto out;
+ }
+ break;
+ case YAML_MAPPING_NODE:
+ for (pair = node->data.mapping.pairs.start;
+ pair < node->data.mapping.pairs.top; pair++) {
+ if (!yaml_document_append_mapping_pair(
+ document_to, node - document_from->nodes.start + 1, pair->key,
+ pair->value))
+ goto out;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return error;
+
+out:
+ yaml_document_delete(document_to);
+ return !error;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+
+ yaml_document_t document;
+ yaml_document_t documents[MAX_DOCUMENTS];
+ size_t document_number = 0;
+ int count = 0;
+ bool done = false;
+ bool equal = false;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ if (!yaml_parser_initialize(&parser))
+ return 0;
+
+ yaml_parser_set_input_string(&parser, data, size);
+ if (!yaml_emitter_initialize(&emitter))
+ return 0;
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+ yaml_emitter_open(&emitter);
+
+ while (!done) {
+ if (!yaml_parser_load(&parser, &document)) {
+ equal = 1;
+ break;
+ }
+
+ done = (!yaml_document_get_root_node(&document));
+ if (!done) {
+ if (document_number >= MAX_DOCUMENTS) {
+ yaml_document_delete(&document);
+ equal = true;
+ break;
+ }
+
+ if (!copy_document(&documents[document_number++], &document)) {
+ yaml_document_delete(&document);
+ equal = true;
+ break;
+ }
+ if (!(yaml_emitter_dump(&emitter, &document) ||
+ (yaml_emitter_flush(&emitter) && 0))) {
+ equal = true;
+ break;
+ }
+
+ count++;
+ } else {
+ yaml_document_delete(&document);
+ }
+ }
+
+ yaml_parser_delete(&parser);
+ yaml_emitter_close(&emitter);
+ yaml_emitter_delete(&emitter);
+
+ if (!equal) {
+ count = 0;
+ done = false;
+ if (!yaml_parser_initialize(&parser))
+ goto error;
+
+ if (!out.buf) {
+ yaml_parser_delete(&parser);
+ goto error;
+ }
+
+ yaml_parser_set_input_string(&parser, out.buf, out.size);
+
+ while (!done) {
+ if (!yaml_parser_load(&parser, &document)) {
+ yaml_parser_delete(&parser);
+ goto error;
+ }
+
+ done = (!yaml_document_get_root_node(&document));
+ if (!done) {
+ if (!documents_equal(documents + count, &document)) {
+ yaml_parser_delete(&parser);
+ goto error;
+ }
+ count++;
+ }
+ yaml_document_delete(&document);
+ }
+ yaml_parser_delete(&parser);
+ }
+
+ for (int k = 0; k < document_number; k++) {
+ yaml_document_delete(documents + k);
+ }
+
+error:
+
+ free(out.buf);
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_emitter_fuzzer.c b/projects/libyaml/libyaml_emitter_fuzzer.c
new file mode 100644
index 00000000..d44bd609
--- /dev/null
+++ b/projects/libyaml/libyaml_emitter_fuzzer.c
@@ -0,0 +1,298 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#define MAX_EVENTS 1024
+
+bool events_equal(yaml_event_t *event1, yaml_event_t *event2) {
+
+ const bool equal = true;
+
+ if (event1->type != event2->type)
+ return equal;
+
+ switch (event1->type) {
+ case YAML_STREAM_START_EVENT:
+ return !equal;
+
+ case YAML_DOCUMENT_START_EVENT:
+ if ((event1->data.document_start.version_directive &&
+ !event2->data.document_start.version_directive) ||
+ (!event1->data.document_start.version_directive &&
+ event2->data.document_start.version_directive) ||
+ (event1->data.document_start.version_directive &&
+ event2->data.document_start.version_directive &&
+ (event1->data.document_start.version_directive->major !=
+ event2->data.document_start.version_directive->major ||
+ event1->data.document_start.version_directive->minor !=
+ event2->data.document_start.version_directive->minor)))
+ return equal;
+ if ((event1->data.document_start.tag_directives.end -
+ event1->data.document_start.tag_directives.start) !=
+ (event2->data.document_start.tag_directives.end -
+ event2->data.document_start.tag_directives.start))
+ return equal;
+ for (int k = 0; k < (event1->data.document_start.tag_directives.end -
+ event1->data.document_start.tag_directives.start);
+ k++) {
+ if ((strcmp((char *)event1->data.document_start.tag_directives.start[k]
+ .handle,
+ (char *)event2->data.document_start.tag_directives.start[k]
+ .handle) != 0) ||
+ (strcmp((char *)event1->data.document_start.tag_directives.start[k]
+ .prefix,
+ (char *)event2->data.document_start.tag_directives.start[k]
+ .prefix) != 0))
+ return equal;
+ }
+ return !equal;
+
+ case YAML_DOCUMENT_END_EVENT:
+ return !equal;
+
+ case YAML_ALIAS_EVENT:
+ return (strcmp((char *)event1->data.alias.anchor,
+ (char *)event2->data.alias.anchor) == 0);
+
+ case YAML_SCALAR_EVENT:
+ if ((event1->data.scalar.anchor && !event2->data.scalar.anchor) ||
+ (!event1->data.scalar.anchor && event2->data.scalar.anchor) ||
+ (event1->data.scalar.anchor && event2->data.scalar.anchor &&
+ strcmp((char *)event1->data.scalar.anchor,
+ (char *)event2->data.scalar.anchor) != 0))
+ return equal;
+ if ((event1->data.scalar.tag && !event2->data.scalar.tag &&
+ strcmp((char *)event1->data.scalar.tag, "!") != 0) ||
+ (!event1->data.scalar.tag && event2->data.scalar.tag &&
+ strcmp((char *)event2->data.scalar.tag, "!") != 0) ||
+ (event1->data.scalar.tag && event2->data.scalar.tag &&
+ strcmp((char *)event1->data.scalar.tag,
+ (char *)event2->data.scalar.tag) != 0))
+ return equal;
+ if ((event1->data.scalar.length != event2->data.scalar.length) ||
+ memcmp(event1->data.scalar.value, event2->data.scalar.value,
+ event1->data.scalar.length) != 0)
+ return equal;
+ if ((event1->data.scalar.plain_implicit !=
+ event2->data.scalar.plain_implicit) ||
+ (event1->data.scalar.quoted_implicit !=
+ event2->data.scalar.quoted_implicit))
+ return equal;
+ return !equal;
+
+ case YAML_SEQUENCE_START_EVENT:
+ if ((event1->data.sequence_start.anchor &&
+ !event2->data.sequence_start.anchor) ||
+ (!event1->data.sequence_start.anchor &&
+ event2->data.sequence_start.anchor) ||
+ (event1->data.sequence_start.anchor &&
+ event2->data.sequence_start.anchor &&
+ strcmp((char *)event1->data.sequence_start.anchor,
+ (char *)event2->data.sequence_start.anchor) != 0))
+ return equal;
+ if ((event1->data.sequence_start.tag && !event2->data.sequence_start.tag) ||
+ (!event1->data.sequence_start.tag && event2->data.sequence_start.tag) ||
+ (event1->data.sequence_start.tag && event2->data.sequence_start.tag &&
+ strcmp((char *)event1->data.sequence_start.tag,
+ (char *)event2->data.sequence_start.tag) != 0))
+ return equal;
+ if ((event1->data.sequence_start.implicit !=
+ event2->data.sequence_start.implicit))
+ return equal;
+ return !equal;
+
+ case YAML_MAPPING_START_EVENT:
+ if ((event1->data.mapping_start.anchor &&
+ !event2->data.mapping_start.anchor) ||
+ (!event1->data.mapping_start.anchor &&
+ event2->data.mapping_start.anchor) ||
+ (event1->data.mapping_start.anchor &&
+ event2->data.mapping_start.anchor &&
+ strcmp((char *)event1->data.mapping_start.anchor,
+ (char *)event2->data.mapping_start.anchor) != 0))
+ return equal;
+ if ((event1->data.mapping_start.tag && !event2->data.mapping_start.tag) ||
+ (!event1->data.mapping_start.tag && event2->data.mapping_start.tag) ||
+ (event1->data.mapping_start.tag && event2->data.mapping_start.tag &&
+ strcmp((char *)event1->data.mapping_start.tag,
+ (char *)event2->data.mapping_start.tag) != 0))
+ return equal;
+ if ((event1->data.mapping_start.implicit !=
+ event2->data.mapping_start.implicit))
+ return equal;
+ return !equal;
+
+ default:
+ return !equal;
+ }
+}
+
+bool copy_event(yaml_event_t *event_to, yaml_event_t *event_from) {
+
+ switch (event_from->type) {
+ case YAML_STREAM_START_EVENT:
+ return yaml_stream_start_event_initialize(
+ event_to, event_from->data.stream_start.encoding);
+
+ case YAML_STREAM_END_EVENT:
+ return yaml_stream_end_event_initialize(event_to);
+
+ case YAML_DOCUMENT_START_EVENT:
+ return yaml_document_start_event_initialize(
+ event_to, event_from->data.document_start.version_directive,
+ event_from->data.document_start.tag_directives.start,
+ event_from->data.document_start.tag_directives.end,
+ event_from->data.document_start.implicit);
+
+ case YAML_DOCUMENT_END_EVENT:
+ return yaml_document_end_event_initialize(
+ event_to, event_from->data.document_end.implicit);
+
+ case YAML_ALIAS_EVENT:
+ return yaml_alias_event_initialize(event_to, event_from->data.alias.anchor);
+
+ case YAML_SCALAR_EVENT:
+ return yaml_scalar_event_initialize(
+ event_to, event_from->data.scalar.anchor, event_from->data.scalar.tag,
+ event_from->data.scalar.value, event_from->data.scalar.length,
+ event_from->data.scalar.plain_implicit,
+ event_from->data.scalar.quoted_implicit, event_from->data.scalar.style);
+
+ case YAML_SEQUENCE_START_EVENT:
+ return yaml_sequence_start_event_initialize(
+ event_to, event_from->data.sequence_start.anchor,
+ event_from->data.sequence_start.tag,
+ event_from->data.sequence_start.implicit,
+ event_from->data.sequence_start.style);
+
+ case YAML_SEQUENCE_END_EVENT:
+ return yaml_sequence_end_event_initialize(event_to);
+
+ case YAML_MAPPING_START_EVENT:
+ return yaml_mapping_start_event_initialize(
+ event_to, event_from->data.mapping_start.anchor,
+ event_from->data.mapping_start.tag,
+ event_from->data.mapping_start.implicit,
+ event_from->data.mapping_start.style);
+
+ case YAML_MAPPING_END_EVENT:
+ return yaml_mapping_end_event_initialize(event_to);
+ }
+
+ return false;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+ yaml_event_t event;
+ yaml_event_t events[MAX_EVENTS];
+ size_t event_number = 0;
+ bool done = false;
+ int count = 0;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ if (!yaml_parser_initialize(&parser))
+ return 0;
+
+ yaml_parser_set_input_string(&parser, data, size);
+ if (!yaml_emitter_initialize(&emitter)) {
+ yaml_parser_delete(&parser);
+ return 0;
+ }
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+
+ while (!done) {
+ if (!yaml_parser_parse(&parser, &event)) {
+ goto delete_parser;
+ }
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+ if (event_number >= MAX_EVENTS) {
+ yaml_event_delete(&event);
+ goto delete_parser;
+ }
+
+ if (copy_event(&events[event_number++], &event)) {
+ yaml_event_delete(&event);
+ goto delete_parser;
+ }
+
+ if (!yaml_emitter_emit(&emitter, &event)) {
+ goto delete_parser;
+ }
+
+ }
+
+ yaml_parser_delete(&parser);
+
+ done = false;
+ if (!yaml_parser_initialize(&parser))
+ goto error;
+
+ yaml_parser_set_input_string(&parser, out.buf, out.size);
+
+ while (!done) {
+ if (!yaml_parser_parse(&parser, &event))
+ break;
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+ if (events_equal(events + count, &event)) {
+ yaml_event_delete(&event);
+ break;
+ }
+
+ yaml_event_delete(&event);
+ count++;
+ }
+
+delete_parser:
+
+ yaml_parser_delete(&parser);
+
+error:
+
+ yaml_emitter_delete(&emitter);
+
+ for (int k = 0; k < event_number; k++) {
+ yaml_event_delete(events + k);
+ }
+
+ free(out.buf);
+
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_fuzzer.cc b/projects/libyaml/libyaml_fuzzer.cc
deleted file mode 100644
index 57d50937..00000000
--- a/projects/libyaml/libyaml_fuzzer.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <stdint.h>
-
-#include <yaml.h>
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- yaml_parser_t parser;
- yaml_parser_initialize(&parser);
- yaml_parser_set_input_string(&parser, data, size);
-
- int done = 0;
- while (!done) {
- yaml_event_t event;
- if (!yaml_parser_parse(&parser, &event)) {
- break;
- }
- done = (event.type == YAML_STREAM_END_EVENT);
- yaml_event_delete(&event);
- }
- yaml_parser_delete(&parser);
- return 0;
-}
diff --git a/projects/libyaml/libyaml_loader_fuzzer.c b/projects/libyaml/libyaml_loader_fuzzer.c
new file mode 100644
index 00000000..6986feab
--- /dev/null
+++ b/projects/libyaml/libyaml_loader_fuzzer.c
@@ -0,0 +1,51 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ yaml_parser_t parser;
+ yaml_document_t document;
+ bool done = false;
+
+ if(!yaml_parser_initialize(&parser))
+ return 0;
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ while (!done)
+ {
+ if (!yaml_parser_load(&parser, &document)) {
+ break;
+ }
+
+ done = (!yaml_document_get_root_node(&document));
+
+ yaml_document_delete(&document);
+ }
+
+ yaml_parser_delete(&parser);
+
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_parser_fuzzer.c b/projects/libyaml/libyaml_parser_fuzzer.c
new file mode 100644
index 00000000..a0119bb3
--- /dev/null
+++ b/projects/libyaml/libyaml_parser_fuzzer.c
@@ -0,0 +1,49 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ yaml_parser_t parser;
+ yaml_event_t event;
+ bool done = false;
+
+ if(!yaml_parser_initialize(&parser))
+ return 0;
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ while (!done)
+ {
+ if (!yaml_parser_parse(&parser, &event)) break;
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+
+ yaml_event_delete(&event);
+ }
+
+ yaml_parser_delete(&parser);
+
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_reformatter_alt_fuzzer.c b/projects/libyaml/libyaml_reformatter_alt_fuzzer.c
new file mode 100644
index 00000000..5ca6c2b4
--- /dev/null
+++ b/projects/libyaml/libyaml_reformatter_alt_fuzzer.c
@@ -0,0 +1,86 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ bool done = false;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+ yaml_document_t document;
+
+ /* Initialize the parser and emitter objects. */
+
+ if (!yaml_parser_initialize(&parser))
+ return 0;
+
+ if (!yaml_emitter_initialize(&emitter))
+ goto cleanup_parser;
+
+ /* Set the parser parameters. */
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ /* Set the emitter parameters. */
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ /* The main loop. */
+
+ while (!done) {
+ /* Get the next event. */
+
+ if (!yaml_parser_load(&parser, &document))
+ break;
+
+ /* Check if this is the stream end. */
+
+ done = (!yaml_document_get_root_node(&document));
+
+ /* Emit the event. */
+
+ if (!yaml_emitter_dump(&emitter, &document))
+ break;
+ }
+
+ free(out.buf);
+ yaml_emitter_delete(&emitter);
+
+cleanup_parser:
+
+ yaml_parser_delete(&parser);
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_reformatter_fuzzer.c b/projects/libyaml/libyaml_reformatter_fuzzer.c
new file mode 100644
index 00000000..a43243f0
--- /dev/null
+++ b/projects/libyaml/libyaml_reformatter_fuzzer.c
@@ -0,0 +1,86 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include "yaml_write_handler.h"
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 2)
+ return 0;
+
+ bool done = false;
+ bool is_canonical = data[0] & 1;
+ bool is_unicode = data[1] & 1;
+ data += 2;
+ size -= 2;
+
+ yaml_parser_t parser;
+ yaml_emitter_t emitter;
+ yaml_event_t event;
+
+ /* Initialize the parser and emitter objects. */
+
+ if (!yaml_parser_initialize(&parser))
+ return 0;
+
+ if (!yaml_emitter_initialize(&emitter))
+ goto cleanup_parser;
+
+ /* Set the parser parameters. */
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ /* Set the emitter parameters. */
+ yaml_output_buffer_t out = {/*buf=*/NULL, /*size=*/0};
+ yaml_emitter_set_output(&emitter, yaml_write_handler, &out);
+
+ yaml_emitter_set_canonical(&emitter, is_canonical);
+ yaml_emitter_set_unicode(&emitter, is_unicode);
+
+ /* The main loop. */
+
+ while (!done) {
+ /* Get the next event. */
+
+ if (!yaml_parser_parse(&parser, &event))
+ break;
+
+ /* Check if this is the stream end. */
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+
+ /* Emit the event. */
+
+ if (!yaml_emitter_emit(&emitter, &event))
+ break;
+ }
+
+ free(out.buf);
+ yaml_emitter_delete(&emitter);
+
+cleanup_parser:
+
+ yaml_parser_delete(&parser);
+ return 0;
+}
diff --git a/projects/libyaml/libyaml_scanner_fuzzer.c b/projects/libyaml/libyaml_scanner_fuzzer.c
new file mode 100644
index 00000000..681f8b6d
--- /dev/null
+++ b/projects/libyaml/libyaml_scanner_fuzzer.c
@@ -0,0 +1,51 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "yaml.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ yaml_parser_t parser;
+ yaml_token_t token;
+ bool done = false;
+
+ if(!yaml_parser_initialize(&parser))
+ return 0;
+
+ yaml_parser_set_input_string(&parser, data, size);
+
+ while (!done)
+ {
+ if (!yaml_parser_scan(&parser, &token)) {
+ break;
+ }
+
+ done = (token.type == YAML_STREAM_END_TOKEN);
+
+ yaml_token_delete(&token);
+ }
+
+ yaml_parser_delete(&parser);
+
+ return 0;
+}
diff --git a/projects/libyaml/yaml_write_handler.h b/projects/libyaml/yaml_write_handler.h
new file mode 100644
index 00000000..cb5d26e8
--- /dev/null
+++ b/projects/libyaml/yaml_write_handler.h
@@ -0,0 +1,37 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef YAML_WRITE_HANDLER_H_
+#define YAML_WRITE_HANDLER_H_
+
+typedef struct yaml_output_buffer {
+ unsigned char *buf;
+ size_t size;
+} yaml_output_buffer_t;
+
+static int yaml_write_handler(void *data, unsigned char *buffer, size_t size) {
+ yaml_output_buffer_t *out = (yaml_output_buffer_t *)data;
+
+ out->buf = (unsigned char *)realloc(out->buf, out->size + size);
+ if (!out->buf) {
+ out->size = 0;
+ return 1;
+ }
+
+ memcpy(out->buf + out->size, buffer, size);
+ out->size += size;
+ return 0;
+}
+
+#endif // YAML_WRITE_HANDLER_H_