summaryrefslogtreecommitdiff
path: root/fuzzing
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-12-15 17:42:40 -0600
committerPatrick Griffis <pgriffis@igalia.com>2020-12-16 13:36:06 -0600
commit46969e196a1b29120c5ae1fefa83df0152274e7b (patch)
treed885b0aaa5272225cba88727c194c76c0c803a5f /fuzzing
parent9eb8f2faa5b8657804175ef5a50cffbc3c602754 (diff)
downloadlibsoup-46969e196a1b29120c5ae1fefa83df0152274e7b.tar.gz
Add basic fuzzing support
Diffstat (limited to 'fuzzing')
-rw-r--r--fuzzing/fuzz.h21
-rw-r--r--fuzzing/fuzz_cookie_parse.c17
-rw-r--r--fuzzing/fuzz_cookie_parse.dict9
-rw-r--r--fuzzing/fuzz_decode_data_uri.c19
-rw-r--r--fuzzing/fuzz_decode_data_uri.dict5
-rw-r--r--fuzzing/meson.build46
6 files changed, 117 insertions, 0 deletions
diff --git a/fuzzing/fuzz.h b/fuzzing/fuzz.h
new file mode 100644
index 00000000..0d380285
--- /dev/null
+++ b/fuzzing/fuzz.h
@@ -0,0 +1,21 @@
+#include "libsoup/soup.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_cookie_parse.c b/fuzzing/fuzz_cookie_parse.c
new file mode 100644
index 00000000..296b8d75
--- /dev/null
+++ b/fuzzing/fuzz_cookie_parse.c
@@ -0,0 +1,17 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ // We only accept NUL terminated strings
+ if (!size || data[size - 1] != '\0')
+ return 0;
+
+ fuzz_set_logging_func ();
+
+ SoupCookie *cookie = soup_cookie_parse ((char*)data, NULL);
+
+ g_clear_pointer (&cookie, soup_cookie_free);
+
+ return 0;
+} \ No newline at end of file
diff --git a/fuzzing/fuzz_cookie_parse.dict b/fuzzing/fuzz_cookie_parse.dict
new file mode 100644
index 00000000..bed45447
--- /dev/null
+++ b/fuzzing/fuzz_cookie_parse.dict
@@ -0,0 +1,9 @@
+"domain="
+"expires="
+"httponly"
+"max-age="
+"secure"
+"samesite="
+"path="
+"="
+";" \ No newline at end of file
diff --git a/fuzzing/fuzz_decode_data_uri.c b/fuzzing/fuzz_decode_data_uri.c
new file mode 100644
index 00000000..97e0369f
--- /dev/null
+++ b/fuzzing/fuzz_decode_data_uri.c
@@ -0,0 +1,19 @@
+#include "fuzz.h"
+
+int
+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+{
+ GBytes *bytes;
+ char *data_uri;
+
+ fuzz_set_logging_func ();
+
+ data_uri = g_strdup_printf ("data:%.*s", (int)size, data);
+ // g_print("%s", data_uri);
+ bytes = soup_uri_decode_data_uri (data_uri, NULL);
+
+ g_clear_pointer (&bytes, g_bytes_unref);
+ g_free (data_uri);
+
+ return 0;
+} \ No newline at end of file
diff --git a/fuzzing/fuzz_decode_data_uri.dict b/fuzzing/fuzz_decode_data_uri.dict
new file mode 100644
index 00000000..25fff80b
--- /dev/null
+++ b/fuzzing/fuzz_decode_data_uri.dict
@@ -0,0 +1,5 @@
+";base64,"
+","
+";"
+"text/plain"
+"text/plain;base64," \ No newline at end of file
diff --git a/fuzzing/meson.build b/fuzzing/meson.build
new file mode 100644
index 00000000..865bfcd3
--- /dev/null
+++ b/fuzzing/meson.build
@@ -0,0 +1,46 @@
+fs = import('fs')
+
+fuzz_targets = [
+ 'fuzz_decode_data_uri',
+ 'fuzz_cookie_parse',
+]
+
+fuzzing_args = '-fsanitize=fuzzer,address,undefined'
+have_fuzzing = cc.has_argument(fuzzing_args)
+fuzzing_feature = get_option('fuzzing')
+
+if not have_fuzzing and fuzzing_feature.enabled()
+ error('clang and libfuzzer are required for fuzzing')
+endif
+
+if have_fuzzing and (fuzzing_feature.enabled() or fuzzing_feature.auto())
+ foreach target : fuzz_targets
+ exe = executable(target, [target + '.c'],
+ c_args : [fuzzing_args, '-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION'],
+ link_args : fuzzing_args,
+ dependencies : libsoup_dep,
+ )
+
+ extra_args = []
+ dict_file = join_paths(meson.current_source_dir(), target + '.dict')
+ if fs.exists(dict_file)
+ extra_args += '-dict=' + dict_file
+ endif
+
+ test(target, exe,
+ args: [
+ '-runs=500000',
+ '-jobs=16', # This will automatically limit itself to half your systems threads
+ '-artifact_prefix=meson-logs/' + target + '-',
+ '-print_final_stats=1',
+ ] + extra_args,
+ env: [
+ 'ASAN_OPTIONS=fast_unwind_on_malloc=0',
+ 'UBSAN_OPTIONS=print_stacktrace=1',
+ ],
+ suite: 'fuzzing',
+ timeout: 240,
+ priority: -1,
+ )
+ endforeach
+endif \ No newline at end of file