diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index bd2205743318..0cb33427e45a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -12,3 +12,7 @@ FOREACH(test_case ${test_cases})
   ADD_UNIT_TEST(${test_case})
   ADD_UNIT_TEST_SAN(${test_case})
 ENDFOREACH(test_case)
+
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+  ADD_SUBDIRECTORY(fuzz)
+ENDIF()
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 000000000000..cca74fd6ca12
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,18 @@
+FILE(GLOB test_cases "test-*.c")
+
+MACRO(ADD_FUZZER_TEST name)
+  ADD_EXECUTABLE(${name} ${name}.c)
+  TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+  TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+  TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+  TARGET_LINK_LIBRARIES(${name} ubox blobmsg_json json_script ${json})
+  ADD_TEST(
+    NAME ${name}
+    COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+  )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FOREACH(test_case ${test_cases})
+  GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+  ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
diff --git a/tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a b/tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a
new file mode 100644
index 0000000000000000000000000000000000000000..b4e009dd6d7e91ff56595a84010db2eb81e41622
GIT binary patch
diff --git a/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278 b/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278
new file mode 100644
index 000000000000..62f9457511f8
--- /dev/null
+++ b/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278
@@ -0,0 +1 @@
+6
\ No newline at end of file
diff --git a/tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9 b/tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9
new file mode 100644
index 0000000000000000000000000000000000000000..3d70d85eba81360f757bc71859316667610c5339
GIT binary patch
diff --git a/tests/fuzz/corpus/valid-blobmsg.bin b/tests/fuzz/corpus/valid-blobmsg.bin
new file mode 100644
index 0000000000000000000000000000000000000000..2d0c68e8a1273ae12ac6d4401c7471927809a926
GIT binary patch
diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 000000000000..7153847e0825
--- /dev/null
+++ b/tests/fuzz/test-fuzz.c
@@ -0,0 +1,76 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "blob.h"
+#include "blobmsg.h"
+
+static void fuzz_blobmsg_parse(const uint8_t *data, size_t size)
+{
+	enum {
+		FOO_MESSAGE,
+		FOO_LIST,
+		FOO_TESTDATA,
+		__FOO_MAX
+	};
+
+	static const struct blobmsg_policy foo_policy[] = {
+		[FOO_MESSAGE] = {
+			.name = "message",
+			.type = BLOBMSG_TYPE_STRING,
+		},
+		[FOO_LIST] = {
+			.name = "list",
+			.type = BLOBMSG_TYPE_ARRAY,
+		},
+		[FOO_TESTDATA] = {
+			.name = "testdata",
+			.type = BLOBMSG_TYPE_TABLE,
+		},
+	};
+
+	struct blob_attr *tb[__FOO_MAX];
+
+	blobmsg_parse(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size);
+	blobmsg_parse_array(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size);
+}
+
+static void fuzz_blob_parse(const uint8_t *data, size_t size)
+{
+	enum {
+		FOO_ATTR_NESTED,
+		FOO_ATTR_BINARY,
+		FOO_ATTR_STRING,
+		FOO_ATTR_INT8,
+		FOO_ATTR_INT16,
+		FOO_ATTR_INT32,
+		FOO_ATTR_INT64,
+		FOO_ATTR_DOUBLE,
+		__FOO_ATTR_MAX
+	};
+
+
+	static const struct blob_attr_info foo_policy[__FOO_ATTR_MAX] = {
+		[FOO_ATTR_NESTED] = { .type = BLOB_ATTR_NESTED },
+		[FOO_ATTR_BINARY] = { .type = BLOB_ATTR_BINARY },
+		[FOO_ATTR_STRING] = { .type = BLOB_ATTR_STRING },
+		[FOO_ATTR_INT8] = { .type = BLOB_ATTR_INT8 },
+		[FOO_ATTR_INT16] = { .type = BLOB_ATTR_INT16 },
+		[FOO_ATTR_INT32] = { .type = BLOB_ATTR_INT32 },
+		[FOO_ATTR_INT64] = { .type = BLOB_ATTR_INT64 },
+		[FOO_ATTR_DOUBLE] = { .type = BLOB_ATTR_DOUBLE },
+	};
+
+	struct blob_attr *foo[__FOO_ATTR_MAX];
+	struct blob_attr *buf = (struct blob_attr *)data;
+
+	blob_parse(buf, foo, foo_policy, __FOO_ATTR_MAX);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+	fuzz_blob_parse(data, size);
+	fuzz_blobmsg_parse(data, size);
+
+	return 0;
+}
