Commit a2c09f57 authored by pdknsk's avatar pdknsk Committed by Philip Withnall

Integrate oss-fuzz targets

parent 6c8b9f31
Fuzz targets used by [oss-fuzz](
## How to add new targets
Add **fuzz_target_name.c** and edit `` 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.
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](, [Dictionaries](, [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]( is recommended.
$ CC=clang CXX=clang++ meson DIR -Db_sanitize=<address|undefined> -Db_lundef=false
Afterwards run the affected target against the provided test case.
$ DIR/fuzzing/fuzz_target_name FILE
#### FAQs
###### What about Memory Sanitizer (MSAN)?
Correct MSAN instrumentation is [difficult to achieve]( locally, so false positives are very likely to mask the actual bug.
If need be, [you can still reproduce]( 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.
/* 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);
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;
#include "gio/gio.h"
#include "glib/glib.h"
int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
static GLogWriterOutput
empty_logging_func (GLogLevelFlags log_level, const GLogField *fields,
gsize n_fields, gpointer user_data)
/* Disables logging for oss-fuzz. Must be used with each target. */
static void
fuzz_set_logging_func (void)
g_log_set_writer_func (empty_logging_func, NULL, NULL);
#include "fuzz.h"
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;
#include "fuzz.h"
const static GDBusCapabilityFlags flags = G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
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;
#include "fuzz.h"
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,
g_key_file_free (key);
return 0;
#include "fuzz.h"
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,
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;
#include "fuzz.h"
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;
fuzz_targets = [
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.
fuzzing_engine = cxx.find_library('FuzzingEngine', required : false)
if fuzzing_engine.found()
deps += fuzzing_engine
extra_sources += 'driver.c'
foreach target_name : fuzz_targets
exe = executable(target_name, [extra_sources, target_name + '.c'],
c_args : extra_c_args,
dependencies : deps,
......@@ -1980,6 +1980,7 @@ subdir('gio')
if xgettext.found()
# Install glib-gettextize executable, if a UNIX-style shell is found
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment