[glib: 1/2] Integrate oss-fuzz targets
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/2] Integrate oss-fuzz targets
- Date: Thu, 11 Oct 2018 00:02:20 +0000 (UTC)
commit a2c09f57f6f491630ea949f38c4bfec95c47ef90
Author: pdknsk <pdknsk gmail com>
Date: Thu Oct 11 00:02:03 2018 +0000
Integrate oss-fuzz targets
fuzzing/README.md | 49 ++++++++++++++++++++++++++++++++++++++++++
fuzzing/driver.c | 32 +++++++++++++++++++++++++++
fuzzing/fuzz.h | 22 +++++++++++++++++++
fuzzing/fuzz_bookmark.c | 15 +++++++++++++
fuzzing/fuzz_bookmark.corpus | 1 +
fuzzing/fuzz_dbus_message.c | 28 ++++++++++++++++++++++++
fuzzing/fuzz_key.c | 16 ++++++++++++++
fuzzing/fuzz_key.corpus | 2 ++
fuzzing/fuzz_variant_binary.c | 21 ++++++++++++++++++
fuzzing/fuzz_variant_text.c | 21 ++++++++++++++++++
fuzzing/fuzz_variant_text.dict | 32 +++++++++++++++++++++++++++
fuzzing/meson.build | 28 ++++++++++++++++++++++++
meson.build | 1 +
13 files changed, 268 insertions(+)
---
diff --git a/fuzzing/README.md b/fuzzing/README.md
new file mode 100644
index 000000000..bcf32b51a
--- /dev/null
+++ b/fuzzing/README.md
@@ -0,0 +1,49 @@
+Fuzz targets used by [oss-fuzz](https://github.com/google/oss-fuzz/).
+
+## How to add new targets
+
+Add **fuzz_target_name.c** and edit `meson.build` accordingly.
+
+New targets are picked up by oss-fuzz automatically within a day. Targets must not be renamed once added.
+
+Add (optional) **fuzz_target_name.dict** containing keywords and magic bytes.
+
+Add (optional) **fuzz_target_name.corpus** with file names on separate lines. Wildcards `?`, `*` and `**`
are supported. Examples below.
+
+```bash
+glib/* # all files in directory glib
+glib/** # all files in directory glib and sub-directories
+**.xbel # all files ending with .xbel in the repository
+```
+
+Recommended reading: [Fuzz Target](https://llvm.org/docs/LibFuzzer.html#fuzz-target),
[Dictionaries](https://llvm.org/docs/LibFuzzer.html#dictionaries),
[Corpus](https://llvm.org/docs/LibFuzzer.html#corpus)
+
+## How to reproduce oss-fuzz bugs locally
+
+Build with at least the following flags, choosing a sanitizer as needed. A somewhat recent version of
[clang](http://clang.llvm.org/) is recommended.
+
+```bash
+$ CC=clang CXX=clang++ meson DIR -Db_sanitize=<address|undefined> -Db_lundef=false
+```
+
+Afterwards run the affected target against the provided test case.
+
+```bash
+$ DIR/fuzzing/fuzz_target_name FILE
+```
+
+#### FAQs
+
+###### What about Memory Sanitizer (MSAN)?
+
+Correct MSAN instrumentation is [difficult to
achieve](https://clang.llvm.org/docs/MemorySanitizer.html#handling-external-code) locally, so false positives
are very likely to mask the actual bug.
+
+If need be, [you can still
reproduce](https://github.com/google/oss-fuzz/blob/master/docs/reproducing.md#building-using-docker) those
bugs with the oss-fuzz provided docker images.
+
+###### There are no file/function names in the stack trace.
+
+`llvm-symbolizer` must be in `PATH`.
+
+###### UndefinedBehavior Sanitizer (UBSAN) doesn't provide a stack trace.
+
+Set environment variable `UBSAN_OPTIONS` to `print_stacktrace=1` prior to running the target.
diff --git a/fuzzing/driver.c b/fuzzing/driver.c
new file mode 100644
index 000000000..99e965ba6
--- /dev/null
+++ b/fuzzing/driver.c
@@ -0,0 +1,32 @@
+/* Simpler gnu89 version of StandaloneFuzzTargetMain.c from LLVM */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
+
+int
+main (int argc, char **argv)
+{
+ FILE *f;
+ size_t n_read, len;
+ unsigned char *buf;
+
+ if (argc < 2)
+ return 1;
+
+ f = fopen (argv[1], "r");
+ assert (f);
+ fseek (f, 0, SEEK_END);
+ len = ftell (f);
+ fseek (f, 0, SEEK_SET);
+ buf = (unsigned char*) malloc (len);
+ n_read = fread (buf, 1, len, f);
+ assert (n_read == len);
+ LLVMFuzzerTestOneInput (buf, len);
+
+ free (buf);
+ printf ("Done!\n");
+ return 0;
+}
diff --git a/fuzzing/fuzz.h b/fuzzing/fuzz.h
new file mode 100644
index 000000000..4a879984c
--- /dev/null
+++ b/fuzzing/fuzz.h
@@ -0,0 +1,22 @@
+#include "gio/gio.h"
+#include "glib/glib.h"
+
+int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+static GLogWriterOutput
+empty_logging_func (GLogLevelFlags log_level, const GLogField *fields,
+ gsize n_fields, gpointer user_data)
+{
+ return G_LOG_WRITER_HANDLED;
+}
+#endif
+
+/* Disables logging for oss-fuzz. Must be used with each target. */
+static void
+fuzz_set_logging_func (void)
+{
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ g_log_set_writer_func (empty_logging_func, NULL, NULL);
+#endif
+}
diff --git a/fuzzing/fuzz_bookmark.c b/fuzzing/fuzz_bookmark.c
new file mode 100644
index 000000000..4f257fd0c
--- /dev/null
+++ b/fuzzing/fuzz_bookmark.c
@@ -0,0 +1,15 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ GBookmarkFile *bookmark = NULL;
+
+ fuzz_set_logging_func ();
+
+ bookmark = g_bookmark_file_new ();
+ g_bookmark_file_load_from_data (bookmark, (const gchar*) data, size, NULL);
+
+ g_bookmark_file_free (bookmark);
+ return 0;
+}
diff --git a/fuzzing/fuzz_bookmark.corpus b/fuzzing/fuzz_bookmark.corpus
new file mode 100644
index 000000000..5c78bc930
--- /dev/null
+++ b/fuzzing/fuzz_bookmark.corpus
@@ -0,0 +1 @@
+glib/tests/**.xbel
diff --git a/fuzzing/fuzz_dbus_message.c b/fuzzing/fuzz_dbus_message.c
new file mode 100644
index 000000000..bccb2ba3e
--- /dev/null
+++ b/fuzzing/fuzz_dbus_message.c
@@ -0,0 +1,28 @@
+#include "fuzz.h"
+
+const static GDBusCapabilityFlags flags = G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ gssize bytes;
+ GDBusMessage *msg = NULL;
+ guchar *blob = NULL;
+ gsize msg_size;
+
+ fuzz_set_logging_func ();
+
+ bytes = g_dbus_message_bytes_needed ((guchar*) data, size, NULL);
+ if (bytes <= 0)
+ return 0;
+
+ msg = g_dbus_message_new_from_blob ((guchar*) data, size, flags, NULL);
+ if (msg == NULL)
+ return 0;
+
+ blob = g_dbus_message_to_blob (msg, &msg_size, flags, NULL);
+
+ g_free (blob);
+ g_object_unref (msg);
+ return 0;
+}
diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c
new file mode 100644
index 000000000..8d0edc5fa
--- /dev/null
+++ b/fuzzing/fuzz_key.c
@@ -0,0 +1,16 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ GKeyFile *key = NULL;
+
+ fuzz_set_logging_func ();
+
+ key = g_key_file_new ();
+ g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE,
+ NULL);
+
+ g_key_file_free (key);
+ return 0;
+}
diff --git a/fuzzing/fuzz_key.corpus b/fuzzing/fuzz_key.corpus
new file mode 100644
index 000000000..5a1cb4166
--- /dev/null
+++ b/fuzzing/fuzz_key.corpus
@@ -0,0 +1,2 @@
+glib/tests/**.ini
+gio/tests/**.desktop
diff --git a/fuzzing/fuzz_variant_binary.c b/fuzzing/fuzz_variant_binary.c
new file mode 100644
index 000000000..995718c23
--- /dev/null
+++ b/fuzzing/fuzz_variant_binary.c
@@ -0,0 +1,21 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ GVariant *variant = NULL, *normal_variant = NULL;
+
+ fuzz_set_logging_func ();
+
+ variant = g_variant_new_from_data (G_VARIANT_TYPE_VARIANT, data, size, FALSE,
+ NULL, NULL);
+ if (variant == NULL)
+ return 0;
+
+ normal_variant = g_variant_take_ref (g_variant_get_normal_form (variant));
+ g_variant_get_data (variant);
+
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+ return 0;
+}
diff --git a/fuzzing/fuzz_variant_text.c b/fuzzing/fuzz_variant_text.c
new file mode 100644
index 000000000..a79790949
--- /dev/null
+++ b/fuzzing/fuzz_variant_text.c
@@ -0,0 +1,21 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ const gchar *gdata = (const gchar*) data;
+ GVariant *variant = NULL;
+ gchar *text = NULL;
+
+ fuzz_set_logging_func ();
+
+ variant = g_variant_parse (NULL, gdata, gdata + size, NULL, NULL);
+ if (variant == NULL)
+ return 0;
+
+ text = g_variant_print (variant, TRUE);
+
+ g_free (text);
+ g_variant_unref (variant);
+ return 0;
+}
diff --git a/fuzzing/fuzz_variant_text.dict b/fuzzing/fuzz_variant_text.dict
new file mode 100644
index 000000000..a0e528400
--- /dev/null
+++ b/fuzzing/fuzz_variant_text.dict
@@ -0,0 +1,32 @@
+"'"
+"\""
+"("
+")"
+"<"
+">"
+"["
+"]"
+"{"
+"}"
+"*"
+"?"
+"@"
+"b'"
+"b\""
+"boolean"
+"byte"
+"double"
+"false"
+"handle"
+"int16"
+"int32"
+"int64"
+"just"
+"nothing"
+"objectpath"
+"signature"
+"string"
+"true"
+"uint16"
+"uint32"
+"uint64"
diff --git a/fuzzing/meson.build b/fuzzing/meson.build
new file mode 100644
index 000000000..16878fedf
--- /dev/null
+++ b/fuzzing/meson.build
@@ -0,0 +1,28 @@
+fuzz_targets = [
+ 'fuzz_bookmark',
+ 'fuzz_dbus_message',
+ 'fuzz_key',
+ 'fuzz_variant_binary',
+ 'fuzz_variant_text',
+]
+
+deps = [libgmodule_dep, libgio_dep, libglib_dep, libgobject_dep]
+
+extra_sources = []
+extra_c_args = cc.get_supported_arguments('-Werror=unused-function')
+
+# Links in a static library provided by oss-fuzz, else a standalone driver.
+# https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md#buildsh-script-environment
+fuzzing_engine = cxx.find_library('FuzzingEngine', required : false)
+if fuzzing_engine.found()
+ deps += fuzzing_engine
+else
+ extra_sources += 'driver.c'
+endif
+
+foreach target_name : fuzz_targets
+ exe = executable(target_name, [extra_sources, target_name + '.c'],
+ c_args : extra_c_args,
+ dependencies : deps,
+ )
+endforeach
diff --git a/meson.build b/meson.build
index dd5bd8f3f..d562e8e87 100644
--- a/meson.build
+++ b/meson.build
@@ -1980,6 +1980,7 @@ subdir('gio')
if xgettext.found()
subdir('po')
endif
+subdir('fuzzing')
subdir('tests')
# Install glib-gettextize executable, if a UNIX-style shell is found
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]