shithub: dav1d

Download patch

ref: 858689e1dfb0f910834bd19bcf3e5270482fc8f8
parent: 47886aed9f041eaa484460893ba6bdd77f270ee7
author: Janne Grunau <janne-vlc@jannau.net>
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.

diff: cannot open b/tests/libfuzzer//null: file does not exist: 'b/tests/libfuzzer//null'
--- 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