diff options
author | Patrick Griffis <pgriffis@igalia.com> | 2020-12-15 17:42:40 -0600 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2020-12-16 13:36:06 -0600 |
commit | 46969e196a1b29120c5ae1fefa83df0152274e7b (patch) | |
tree | d885b0aaa5272225cba88727c194c76c0c803a5f | |
parent | 9eb8f2faa5b8657804175ef5a50cffbc3c602754 (diff) | |
download | libsoup-46969e196a1b29120c5ae1fefa83df0152274e7b.tar.gz |
Add basic fuzzing support
-rw-r--r-- | .gitlab-ci.yml | 13 | ||||
-rw-r--r-- | fuzzing/fuzz.h | 21 | ||||
-rw-r--r-- | fuzzing/fuzz_cookie_parse.c | 17 | ||||
-rw-r--r-- | fuzzing/fuzz_cookie_parse.dict | 9 | ||||
-rw-r--r-- | fuzzing/fuzz_decode_data_uri.c | 19 | ||||
-rw-r--r-- | fuzzing/fuzz_decode_data_uri.dict | 5 | ||||
-rw-r--r-- | fuzzing/meson.build | 46 | ||||
-rw-r--r-- | meson.build | 7 | ||||
-rw-r--r-- | meson_options.txt | 6 |
9 files changed, 140 insertions, 3 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5f73e929..17d33977 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -58,6 +58,19 @@ fedora-asan: paths: - "_build/meson-logs/testlog.txt" +fedora-fuzzing: + stage: build + allow_failure: true + variables: + CC: clang + script: + - meson _build -Dauto-features=enabled -Dfuzzing=enabled -Dintrospection=disabled -Dvapi=disabled + - meson test -C _build --suite=fuzzing --timeout-multiplier=10 + artifacts: + when: on_failure + paths: + - _build/meson-logs/ + reference: stage: docs variables: 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 diff --git a/meson.build b/meson.build index 6564856c..a120a362 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project('libsoup', 'c', version: '2.91.0', - meson_version : '>=0.50', + meson_version : '>= 0.53', license : 'LGPL2', default_options : 'c_std=c99') @@ -66,8 +66,9 @@ else '-Wno-missing-include-dirs', ] - if get_option('b_sanitize') == 'address' - test_cflags += '-fno-omit-frame-pointer' + if get_option('b_sanitize') == 'address' or get_option('b_sanitize') == 'address,undefined' or \ + get_option('fuzzing').enabled() + test_cflags += ['-fno-omit-frame-pointer', '-fno-optimize-sibling-calls'] endif common_flags += cc.get_supported_arguments(test_cflags) diff --git a/meson_options.txt b/meson_options.txt index 6eab71ac..3a7bae5c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -70,3 +70,9 @@ option('sysprof', value: 'auto', description: 'enable sysprof-capture support for profiling' ) + +option('fuzzing', + type: 'feature', + value: 'disabled', + description: 'enable fuzzing support' +)
\ No newline at end of file |