ref: 858689e1dfb0f910834bd19bcf3e5270482fc8f8
parent: 47886aed9f041eaa484460893ba6bdd77f270ee7
author: Janne Grunau <[email protected]>
date: Tue Oct 2 15:20:52 EDT 2018
tests: add libfuzzer test target Disabled by default, enabble with `meson -Dbuild_libfuzzer=true -Db_lundef=false ...`. Fuzz target improved by the paralell work by Thierry Foucu in !138.
--- a/meson.build
+++ b/meson.build
@@ -64,8 +64,11 @@
host_machine.cpu_family().startswith('arm'))
cdata.set10('HAVE_ASM', is_asm_enabled)
+# libFuzzer target
+is_libfuzzer_enabled = (get_option('build_libfuzzer'))
+
#
# OS/Compiler checks and defines
#
@@ -156,6 +159,14 @@
add_project_arguments(cc.get_supported_arguments(optional_arguments), language : 'c')
+# libFuzzer related things
+if is_libfuzzer_enabled
+ if not cc.has_argument('-fsanitize=fuzzer')
+ error('build_libfuzzer requires "-fsanitize=fuzzer"')
+ endif
+ fuzzer_args = ['-fsanitize=fuzzer-no-link', '-fsanitize=fuzzer']
+ add_project_arguments(cc.first_supported_argument(fuzzer_args), language : 'c')
+endif
# Stack alignments flags
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -19,3 +19,8 @@
type: 'boolean',
value: true,
description: 'Build dav1d tests')
+
+option('build_libfuzzer',
+ type: 'boolean',
+ value: false,
+ description: 'Build dav1d libFuzzer target')
--- /dev/null
+++ b/tests/libfuzzer/dav1d_fuzzer.c
@@ -1,0 +1,98 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Janne Grunau
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <dav1d.h>
+
+#include "common/intops.h"
+
+// expects ivf input
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ Dav1dSettings settings = { 0 };
+ Dav1dContext * ctx = NULL;
+ Dav1dPicture pic;
+ const uint8_t *ptr = data;
+ int err;
+
+ if (size < 32) goto end;
+ ptr += 32; // skip ivf header
+
+ dav1d_default_settings(&settings);
+
+ err = dav1d_open(&ctx, &settings);
+ if (err < 0) goto end;
+
+ while (ptr <= data + size - 4) {
+ Dav1dData buf;
+
+ size_t frame_size = rl32(ptr);
+ ptr += 4;
+
+ if (frame_size > size || ptr > data + size - frame_size)
+ break;
+
+ // copy frame data to a new buffer to catch reads past the end of input
+ err = dav1d_data_create(&buf, frame_size);
+ if (err) goto cleanup;
+ memcpy(buf.data, ptr, frame_size);
+ ptr += frame_size;
+
+ do {
+ memset(&pic, 0, sizeof(pic));
+ err = dav1d_decode(ctx, &buf, &pic);
+ if (err == 0) {
+ dav1d_picture_unref(&pic);
+ } else {
+ if (!buf.sz) dav1d_data_unref(&buf);
+ if (err != -EAGAIN) {
+ break;
+ }
+ }
+ } while (buf.sz > 0);
+
+ if (buf.sz > 0 || frame_size == 0)
+ dav1d_data_unref(&buf);
+ }
+
+ do {
+ memset(&pic, 0, sizeof(pic));
+ err = dav1d_decode(ctx, NULL, &pic);
+ if (err == 0)
+ dav1d_picture_unref(&pic);
+ } while (err == 0);
+
+cleanup:
+ dav1d_close(&ctx);
+end:
+ return 0;
+}
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -81,3 +81,17 @@
test('checkasm test', checkasm)
endif
+
+if is_libfuzzer_enabled
+ dav1d_fuzzer_sources = files('libfuzzer/dav1d_fuzzer.c')
+
+ dav1d_fuzzer = executable('dav1d_fuzzer',
+ dav1d_fuzzer_sources,
+ include_directories: dav1d_inc_dirs,
+ c_args: [stackalign_flag, stackrealign_flag, '-fsanitize=fuzzer'],
+ link_args: ['-fsanitize=fuzzer'],
+ link_with : libdav1d,
+ build_by_default: true,
+ dependencies : [thread_dependency],
+ )
+endif