mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-05 17:06:18 +01:00
Integrate oss-fuzz targets
This commit is contained in:
parent
6c8b9f31b1
commit
a2c09f57f6
49
fuzzing/README.md
Normal file
49
fuzzing/README.md
Normal file
@ -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.
|
32
fuzzing/driver.c
Normal file
32
fuzzing/driver.c
Normal file
@ -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;
|
||||
}
|
22
fuzzing/fuzz.h
Normal file
22
fuzzing/fuzz.h
Normal file
@ -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
|
||||
}
|
15
fuzzing/fuzz_bookmark.c
Normal file
15
fuzzing/fuzz_bookmark.c
Normal file
@ -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;
|
||||
}
|
1
fuzzing/fuzz_bookmark.corpus
Normal file
1
fuzzing/fuzz_bookmark.corpus
Normal file
@ -0,0 +1 @@
|
||||
glib/tests/**.xbel
|
28
fuzzing/fuzz_dbus_message.c
Normal file
28
fuzzing/fuzz_dbus_message.c
Normal file
@ -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;
|
||||
}
|
16
fuzzing/fuzz_key.c
Normal file
16
fuzzing/fuzz_key.c
Normal file
@ -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;
|
||||
}
|
2
fuzzing/fuzz_key.corpus
Normal file
2
fuzzing/fuzz_key.corpus
Normal file
@ -0,0 +1,2 @@
|
||||
glib/tests/**.ini
|
||||
gio/tests/**.desktop
|
21
fuzzing/fuzz_variant_binary.c
Normal file
21
fuzzing/fuzz_variant_binary.c
Normal file
@ -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;
|
||||
}
|
21
fuzzing/fuzz_variant_text.c
Normal file
21
fuzzing/fuzz_variant_text.c
Normal file
@ -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;
|
||||
}
|
32
fuzzing/fuzz_variant_text.dict
Normal file
32
fuzzing/fuzz_variant_text.dict
Normal file
@ -0,0 +1,32 @@
|
||||
"'"
|
||||
"\""
|
||||
"("
|
||||
")"
|
||||
"<"
|
||||
">"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
"*"
|
||||
"?"
|
||||
"@"
|
||||
"b'"
|
||||
"b\""
|
||||
"boolean"
|
||||
"byte"
|
||||
"double"
|
||||
"false"
|
||||
"handle"
|
||||
"int16"
|
||||
"int32"
|
||||
"int64"
|
||||
"just"
|
||||
"nothing"
|
||||
"objectpath"
|
||||
"signature"
|
||||
"string"
|
||||
"true"
|
||||
"uint16"
|
||||
"uint32"
|
||||
"uint64"
|
28
fuzzing/meson.build
Normal file
28
fuzzing/meson.build
Normal file
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user