diff --git a/fuzzing/.gitignore b/fuzzing/.gitignore
index c82a26201784a79292c0b29b40c31e2d9eb9fd9b..520b91fba32656699eb7bcf0646a812459f7abf8 100644
--- a/fuzzing/.gitignore
+++ b/fuzzing/.gitignore
@@ -1 +1,2 @@
 afl-build
+libfuzzer-build
diff --git a/fuzzing/CMakeLists.txt b/fuzzing/CMakeLists.txt
index fdd7126e98684ce7c88906ac5bdadaa903af15cf..5a72afdca6165bbc5d603ef80415252a9e7f7b82 100644
--- a/fuzzing/CMakeLists.txt
+++ b/fuzzing/CMakeLists.txt
@@ -5,23 +5,26 @@ if (ENABLE_FUZZING)
         message(FATAL_ERROR "Couldn't find afl-fuzz.")
     endif()
 
+    option(ENABLE_LIBFUZZER "Enable fuzzing with libfuzzer (only works with llvm 5 which hasn't been release at this point)" Off)
+    if (ENABLE_LIBFUZZER)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer")
+    endif()
+
+    add_library(fuzz-target fuzz-target.c)
+    target_link_libraries(fuzz-target "${CJSON_LIB}")
+
     add_executable(afl-main afl.c)
-    target_link_libraries(afl-main "${CJSON_LIB}")
+    target_link_libraries(afl-main fuzz-target)
 
     if (NOT ENABLE_SANITIZERS)
         message(FATAL_ERROR "Enable sanitizers with -DENABLE_SANITIZERS=On to do fuzzing.")
     endif()
 
-    option(ENABLE_FUZZING_PRINT "Fuzz printing functions together with parser." On)
-    set(fuzz_print_parameter "no")
-    if (ENABLE_FUZZING_PRINT)
-        set(fuzz_print_parameter "yes")
-    endif()
 
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error")
 
     add_custom_target(afl
-        COMMAND "${AFL_FUZZ}" -i "${CMAKE_CURRENT_SOURCE_DIR}/inputs" -o "${CMAKE_CURRENT_BINARY_DIR}/findings" -x "${CMAKE_CURRENT_SOURCE_DIR}/json.dict" -- "${CMAKE_CURRENT_BINARY_DIR}/afl-main" "@@" "${fuzz_print_parameter}"
+        COMMAND "${AFL_FUZZ}" -i "${CMAKE_CURRENT_SOURCE_DIR}/inputs" -o "${CMAKE_CURRENT_BINARY_DIR}/findings" -x "${CMAKE_CURRENT_SOURCE_DIR}/json.dict" -- "${CMAKE_CURRENT_BINARY_DIR}/afl-main" "@@"
         DEPENDS afl-main)
 
 
diff --git a/fuzzing/afl.c b/fuzzing/afl.c
index 036ed14bcb1ab257090af031cf718536394b0ac5..22158280f3f78df61b952c2f6d29d2d7ab9b2658 100644
--- a/fuzzing/afl.c
+++ b/fuzzing/afl.c
@@ -24,54 +24,71 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "../cJSON.h"
+#include "fuzz-target.h"
 
-static char *read_file(const char *filename)
+static char *read_file(const char *filename, size_t *size)
 {
     FILE *file = NULL;
     long length = 0;
     char *content = NULL;
     size_t read_chars = 0;
 
+    if (size == NULL)
+    {
+        goto fail;
+    }
+
     /* open in read binary mode */
     file = fopen(filename, "rb");
     if (file == NULL)
     {
-        goto cleanup;
+        goto fail;
     }
 
     /* get the length */
     if (fseek(file, 0, SEEK_END) != 0)
     {
-        goto cleanup;
+        goto fail;
     }
     length = ftell(file);
     if (length < 0)
     {
-        goto cleanup;
+        goto fail;
     }
     if (fseek(file, 0, SEEK_SET) != 0)
     {
-        goto cleanup;
+        goto fail;
     }
 
     /* allocate content buffer */
     content = (char*)malloc((size_t)length + sizeof(""));
     if (content == NULL)
     {
-        goto cleanup;
+        goto fail;
     }
 
     /* read the file into memory */
     read_chars = fread(content, sizeof(char), (size_t)length, file);
     if ((long)read_chars != length)
     {
-        free(content);
-        content = NULL;
-        goto cleanup;
+        goto fail;
     }
     content[read_chars] = '\0';
 
+    *size = read_chars + sizeof("");
+
+    goto cleanup;
+
+fail:
+    if (size != NULL)
+    {
+        *size = 0;
+    }
+    if (content != NULL)
+    {
+        free(content);
+        content = NULL;
+    }
 
 cleanup:
     if (file != NULL)
@@ -85,92 +102,50 @@ cleanup:
 int main(int argc, char** argv)
 {
     const char *filename = NULL;
-    cJSON *item = NULL;
     char *json = NULL;
     int status = EXIT_FAILURE;
     char *printed_json = NULL;
 
-    if ((argc < 2) || (argc > 3))
+    if (argc != 2)
     {
         printf("Usage:\n");
-        printf("%s input_file [enable_printing]\n", argv[0]);
+        printf("%s input_file\n", argv[0]);
         printf("\t input_file: file containing the test data\n");
-        printf("\t enable_printing: print after parsing, 'yes' or 'no', defaults to 'no'\n");
         goto cleanup;
     }
 
     filename = argv[1];
 
-#if __AFL_HAVE_MANUAL_CONTROL
+#if defined(__AFL_HAVE_MANUAL_CONTROL) && __AFL_HAVE_MANUAL_CONTROL
     while (__AFL_LOOP(1000))
     {
-#endif
-    status = EXIT_SUCCESS;
-
-    json = read_file(filename);
-    if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0'))
+#else
     {
-        status = EXIT_FAILURE;
-        goto cleanup;
-    }
-    item = cJSON_Parse(json + 2);
-    if (item == NULL)
-    {
-        goto cleanup;
-    }
+#endif
+        size_t size = 0;
+        status = EXIT_SUCCESS;
 
-    if ((argc == 3) && (strncmp(argv[2], "yes", 3) == 0))
-    {
-        int do_format = 0;
-        if (json[1] == 'f')
+        json = read_file(filename, &size);
+        if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0'))
         {
-            do_format = 1;
+            status = EXIT_FAILURE;
+            goto cleanup;
         }
 
-        if (json[0] == 'b')
-        {
-            /* buffered printing */
-            printed_json = cJSON_PrintBuffered(item, 1, do_format);
-        }
-        else
+        LLVMFuzzerTestOneInput(json, size);
+
+    cleanup:
+        if (json != NULL)
         {
-            /* unbuffered printing */
-            if (do_format)
-            {
-                printed_json = cJSON_Print(item);
-            }
-            else
-            {
-                printed_json = cJSON_PrintUnformatted(item);
-            }
+            free(json);
+            json = NULL;
         }
-        if (printed_json == NULL)
+        if (printed_json != NULL)
         {
-            status = EXIT_FAILURE;
-            goto cleanup;
+            free(printed_json);
+            printed_json = NULL;
         }
-        printf("%s\n", printed_json);
-    }
-
-cleanup:
-    if (item != NULL)
-    {
-        cJSON_Delete(item);
-        item = NULL;
     }
-    if (json != NULL)
-    {
-        free(json);
-        json = NULL;
-    }
-    if (printed_json != NULL)
-    {
-        free(printed_json);
-        printed_json = NULL;
-    }
-#if __AFL_HAVE_MANUAL_CONTROL
-    }
-#endif
 
     return status;
 }
diff --git a/fuzzing/fuzz-target.c b/fuzzing/fuzz-target.c
new file mode 100644
index 0000000000000000000000000000000000000000..057a296a21f2067379971009281a205e0f8e5460
--- /dev/null
+++ b/fuzzing/fuzz-target.c
@@ -0,0 +1,129 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "fuzz-target.h"
+#include "../cJSON.h"
+
+static void minify(const unsigned char *data, size_t size)
+{
+    unsigned char *copied_data = (unsigned char*)malloc(size);
+    if (copied_data == NULL)
+    {
+        return;
+    }
+
+    memcpy(copied_data, data, size);
+
+    cJSON_Minify((char*)copied_data);
+
+    free(copied_data);
+
+    return;
+}
+
+static void printing(cJSON *json, unsigned char format_setting, unsigned char buffered_setting)
+{
+    unsigned char *printed = NULL;
+
+    if (buffered_setting == '1')
+    {
+        printed = (unsigned char*)cJSON_PrintBuffered(json, 1, (format_setting == '1'));
+    }
+    else
+    {
+        if (format_setting == '1')
+        {
+            printed = (unsigned char*)cJSON_Print(json);
+        }
+        else
+        {
+            printed = (unsigned char*)cJSON_PrintUnformatted(json);
+        }
+    }
+
+    if (printed != NULL)
+    {
+        free(printed);
+    }
+}
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size)
+{
+    unsigned char minify_setting = '\0'; /* minify instead of parsing */
+    unsigned char require_zero_setting = '\0'; /* zero termination required */
+    unsigned char format_setting = '\0'; /* formatted printing */
+    unsigned char buffered_setting = '\0'; /* buffered printing */
+    const size_t data_offset = 4;
+
+    cJSON *json = NULL;
+
+    /* don't work with NULL or without mode selector */
+    if ((data == NULL) || (size < data_offset))
+    {
+        return 0;
+    }
+
+    /* get configuration from the beginning of the test case */
+    minify_setting = data[0];
+    require_zero_setting = data[1];
+    format_setting = data[2];
+    buffered_setting = data[3];
+
+    /* check if settings are valid */
+    if ((minify_setting != '0') && (minify_setting != '1'))
+    {
+        return 0;
+    }
+    if ((require_zero_setting != '0') && (require_zero_setting != '1'))
+    {
+        return 0;
+    }
+    if ((format_setting != '0') && (format_setting != '1'))
+    {
+        return 0;
+    }
+    if ((buffered_setting != '0') && (buffered_setting != '1'))
+    {
+        return 0;
+    }
+
+    if (minify_setting == '1')
+    {
+        minify(data + data_offset, size);
+        return 0;
+    }
+
+    json = cJSON_ParseWithOpts((const char*)data + data_offset, NULL, (require_zero_setting == '1'));
+    if (json == NULL)
+    {
+        return 0;
+    }
+
+    printing(json, format_setting, buffered_setting);
+
+    free(json);
+
+    return 0;
+}
diff --git a/fuzzing/fuzz-target.h b/fuzzing/fuzz-target.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b3115d9becdf6bbad7d1149b10bed0816dc0e88
--- /dev/null
+++ b/fuzzing/fuzz-target.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+*/
+
+#include <stdlib.h>
+
+#ifndef CJSON_FUZZ_TARGET
+#define CJSON_FUZZ_TARGET
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+
+#endif /* CJSON_FUZZ_TARGET */
diff --git a/fuzzing/inputs/test1 b/fuzzing/inputs/test1
index 6a0c0d7c596034f729dc2acc2e4262b2396750c8..c88024fbfbdc143af8e16dc3a2a67788998abb01 100644
--- a/fuzzing/inputs/test1
+++ b/fuzzing/inputs/test1
@@ -1,4 +1,4 @@
-bf{
+0111{
     "glossary": {
         "title": "example glossary",
 		"GlossDiv": {
diff --git a/fuzzing/inputs/test10 b/fuzzing/inputs/test10
index 01e9a82f67d09b2a5e5bff75bc1f00fdf8ef97ce..58526971a1f76847e89a73ad51c1e47d3c7c5a0b 100644
--- a/fuzzing/inputs/test10
+++ b/fuzzing/inputs/test10
@@ -1 +1 @@
-bf["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
+0111["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
diff --git a/fuzzing/inputs/test11 b/fuzzing/inputs/test11
index 818c6e0f286296dd6b2d897c0985797114717593..686d07989637febdb51db9fbfc10802583b8bbc7 100644
--- a/fuzzing/inputs/test11
+++ b/fuzzing/inputs/test11
@@ -1,4 +1,4 @@
-bf{
+0111{
 "name": "Jack (\"Bee\") Nimble", 
 "format": {"type":       "rect", 
 "width":      1920, 
diff --git a/fuzzing/inputs/test2 b/fuzzing/inputs/test2
index 3fdf8cb78682e4e8d967c843103ef073d04b8af2..04aa455b074465d05a6ae8ba913217d09105581d 100644
--- a/fuzzing/inputs/test2
+++ b/fuzzing/inputs/test2
@@ -1,4 +1,4 @@
-bf{"menu": {
+0111{"menu": {
   "id": "file",
   "value": "File",
   "popup": {
diff --git a/fuzzing/inputs/test3 b/fuzzing/inputs/test3
index 7143163ba2dfa8ee539b534aa84f9762da9bd887..d1e0a0786f72d3f75e0edba8410af1f593911d14 100644
--- a/fuzzing/inputs/test3
+++ b/fuzzing/inputs/test3
@@ -1,4 +1,4 @@
-bf{"widget": {
+0111{"widget": {
     "debug": "on",
     "window": {
         "title": "Sample Konfabulator Widget",
diff --git a/fuzzing/inputs/test3.bu b/fuzzing/inputs/test3.bu
index 6fc93d3cfc788d2e299c99ee8babf589451cb84f..e58848cec07c5029b00e129dc064265da4defcbe 100644
--- a/fuzzing/inputs/test3.bu
+++ b/fuzzing/inputs/test3.bu
@@ -1,4 +1,4 @@
-bu{"widget": {
+0101{"widget": {
     "debug": "on",
     "window": {
         "title": "Sample Konfabulator Widget",
diff --git a/fuzzing/inputs/test3.uf b/fuzzing/inputs/test3.uf
index d48df612644fca0a5ac7ab2b37017be35c2e3d38..6b983b782fbd509b69c27cd427826286974271a6 100644
--- a/fuzzing/inputs/test3.uf
+++ b/fuzzing/inputs/test3.uf
@@ -1,4 +1,4 @@
-uf{"widget": {
+0110{"widget": {
     "debug": "on",
     "window": {
         "title": "Sample Konfabulator Widget",
diff --git a/fuzzing/inputs/test3.uu b/fuzzing/inputs/test3.uu
index ad6ae54102c43f45bd0c8e66d5c1071bd492ff5a..7e4482b1493d797fd8c1887e8fc9d58037538729 100644
--- a/fuzzing/inputs/test3.uu
+++ b/fuzzing/inputs/test3.uu
@@ -1,4 +1,4 @@
-uu{"widget": {
+0100{"widget": {
     "debug": "on",
     "window": {
         "title": "Sample Konfabulator Widget",
diff --git a/fuzzing/inputs/test4 b/fuzzing/inputs/test4
index e24ae9b3d704e330d5c45d65741da4e931b5c838..ca248f90e5d384fedcc383527cc21cac2b4be2cf 100644
--- a/fuzzing/inputs/test4
+++ b/fuzzing/inputs/test4
@@ -1,4 +1,4 @@
-bf{"web-app": {
+0111{"web-app": {
   "servlet": [   
     {
       "servlet-name": "cofaxCDS",
diff --git a/fuzzing/inputs/test5 b/fuzzing/inputs/test5
index f6cc84e131f9022bcc017b6cfa8ea65a64b50382..814e7e8087acf2edab56901af3c1fc4e3152f4b3 100644
--- a/fuzzing/inputs/test5
+++ b/fuzzing/inputs/test5
@@ -1,4 +1,4 @@
-bf{"menu": {
+0111{"menu": {
     "header": "SVG Viewer",
     "items": [
         {"id": "Open"},
diff --git a/fuzzing/inputs/test6 b/fuzzing/inputs/test6
index af279752e8c4ee6a5e172057f27fe18ca5453200..e637a4049210b1d2cbd9e9e32e13f0760f332f8c 100644
--- a/fuzzing/inputs/test6
+++ b/fuzzing/inputs/test6
@@ -1,4 +1,4 @@
-bf<!DOCTYPE html>
+0111<!DOCTYPE html>
     <html>
     <head>
       <meta name="viewport" content="width=device-width, initial-scale=1">
diff --git a/fuzzing/inputs/test7 b/fuzzing/inputs/test7
index 4a3c0b7a1be7526f5e51fc3bcb7e0d2bcc475c31..ce7cd3cf35b780e25142fbd0edae7c0045c9b0f2 100644
--- a/fuzzing/inputs/test7
+++ b/fuzzing/inputs/test7
@@ -1,4 +1,4 @@
-bf[
+0111[
 	 {
 	 "precision": "zip",
 	 "Latitude":  37.7668,
diff --git a/fuzzing/inputs/test8 b/fuzzing/inputs/test8
index 3ffe570ce1fb30341a9c312211df58b000b0032d..aed7bd0d79424a3d3c2bd2354890a8308f5e6fe0 100644
--- a/fuzzing/inputs/test8
+++ b/fuzzing/inputs/test8
@@ -1,4 +1,4 @@
-bf{
+0111{
 		"Image": {
 			"Width":  800,
 			"Height": 600,
diff --git a/fuzzing/inputs/test9 b/fuzzing/inputs/test9
index 28c9033ad64858ec33bc4695134e876c769a1f25..a99c4eb0bbc4e99b3c50c1b9641e380e20e07826 100644
--- a/fuzzing/inputs/test9
+++ b/fuzzing/inputs/test9
@@ -1,4 +1,4 @@
-bf[
+0111[
     [0, -1, 0],
     [1, 0, 0],
     [0, 0, 1]
diff --git a/fuzzing/libfuzzer.sh b/fuzzing/libfuzzer.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3c81917cc8b76f3d6e1608a408bf7331370d827c
--- /dev/null
+++ b/fuzzing/libfuzzer.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+mkdir -p libfuzzer-build || exit 1
+cd libfuzzer-build || exit 1
+#cleanup
+rm -r -- *
+
+CC=clang cmake ../.. -DENABLE_FUZZING=On -DENABLE_SANITIZERS=On -DBUILD_SHARED_LIBS=Off -DCMAKE_BUILD_TYPE=Debug -DENABLE_LIBFUZZER=On
+make fuzz-target