Move av1 decoder fuzzer from OSS directory into libaom BUG=aomedia:2257 Change-Id: I3f9c1a407e4c9500752c09e76004101eb302db25
diff --git a/examples/av1_dec_fuzzer.cc b/examples/av1_dec_fuzzer.cc new file mode 100644 index 0000000..96d16a8 --- /dev/null +++ b/examples/av1_dec_fuzzer.cc
@@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019, Alliance for Open Media. All rights reserved + * + * This source code is subject to the terms of the BSD 2 Clause License and + * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License + * was not distributed with this source code in the LICENSE file, you can + * obtain it at www.aomedia.org/license/software. If the Alliance for Open + * Media Patent License 1.0 was not distributed with this source code in the + * PATENTS file, you can obtain it at www.aomedia.org/license/patent. + */ + +/* + * See build_av1_dec_fuzzer.sh for building instructions. + */ + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <memory> + +#include "config/aom_config.h" +#include "aom/aom_decoder.h" +#include "aom/aomdx.h" +#include "aom_ports/mem_ops.h" +#include "common/ivfdec.h" + +static void close_file(FILE *file) { fclose(file); } + +extern "C" void usage_exit(void) { exit(EXIT_FAILURE); } + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + std::unique_ptr<FILE, decltype(&close_file)> file( + fmemopen((void *)data, size, "rb"), &close_file); + if (file == nullptr) { + return 0; + } + + char header[32]; + if (fread(header, 1, 32, file.get()) != 32) { + return 0; + } + const AvxInterface *decoder = get_aom_decoder_by_name("av1"); + if (decoder == nullptr) { + return 0; + } + + aom_codec_ctx_t codec; + // Set thread count in the range [1, 64]. + const unsigned int threads = (header[0] & 0x3f) + 1; + aom_codec_dec_cfg_t cfg = { threads, 0, 0, CONFIG_LOWBITDEPTH }; + if (aom_codec_dec_init(&codec, decoder->codec_interface(), &cfg, 0)) { + return 0; + } + + uint8_t *buffer = nullptr; + size_t buffer_size = 0; + size_t frame_size = 0; + while (!ivf_read_frame(file.get(), &buffer, &frame_size, &buffer_size, + nullptr)) { + const aom_codec_err_t err = + aom_codec_decode(&codec, buffer, frame_size, nullptr); + static_cast<void>(err); + aom_codec_iter_t iter = nullptr; + aom_image_t *img = nullptr; + while ((img = aom_codec_get_frame(&codec, &iter)) != nullptr) { + } + } + aom_codec_destroy(&codec); + free(buffer); + return 0; +}
diff --git a/examples/build_av1_dec_fuzzer.sh b/examples/build_av1_dec_fuzzer.sh new file mode 100755 index 0000000..86992a0 --- /dev/null +++ b/examples/build_av1_dec_fuzzer.sh
@@ -0,0 +1,78 @@ +#!/bin/bash +# +# Copyright (c) 2019, Alliance for Open Media. All rights reserved +# +# This source code is subject to the terms of the BSD 2 Clause License and +# the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License +# was not distributed with this source code in the LICENSE file, you can +# obtain it at www.aomedia.org/license/software. If the Alliance for Open +# Media Patent License 1.0 was not distributed with this source code in the +# PATENTS file, you can obtain it at www.aomedia.org/license/patent. +# +############################################################################### +# Fuzzer for libaom decoder. +# ========================== +# Requirements +# --------------------- +# Clang6.0 or above (must support -fsanitize=fuzzer) +# +# References: +# --------------------- +# http://llvm.org/docs/LibFuzzer.html +# https://github.com/google/oss-fuzz +# +# Steps to build / run +# --------------------- + +set -eu + +# Have a copy of AOM and a build directory ready. +if [[ $# -ne 2 ]]; then + echo "Pass in the AOM source tree as first argument, and a build directory " + echo "as the second argument. The AOM source tree can be obtained via: " + echo " git clone https://aomedia.googlesource.com/aom" + exit 2 +fi +if [[ -z "$CC" ]]; then + echo "Set the CC environment variable to point to your C compiler." + exit 2 +fi +if [[ -z "$CXX" ]]; then + echo "Set the CXX environment variable to point to your C++ compiler." + exit 2 +fi + +AOM_DIR=$1 +BUILD_DIR=$2 +# Run CMake with address sanitizer enabled and build the codec. +# Enable DO_RANGE_CHECK_CLAMP to suppress the noise of integer overflows +# in the transform functions. Also set memory limits. +EXTRA_C_FLAGS='-DDO_RANGE_CHECK_CLAMP=1 -DAOM_MAX_ALLOCABLE_MEMORY=1073741824' +cd "${BUILD_DIR}" +cmake "${AOM_DIR}" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONFIG_PIC=1 \ + -DCONFIG_SCALABILITY=0 -DCONFIG_LOWBITDEPTH=1 -DCONFIG_AV1_ENCODER=0 \ + -DENABLE_EXAMPLES=0 -DENABLE_DOCS=0 -DENABLE_TESTS=0 -DCONFIG_SIZE_LIMIT=1 \ + -DDECODE_HEIGHT_LIMIT=12288 -DDECODE_WIDTH_LIMIT=12288 \ + -DAOM_EXTRA_C_FLAGS="${EXTRA_C_FLAGS}" \ + -DAOM_EXTRA_CXX_FLAGS="${EXTRA_C_FLAGS}" -DSANITIZE=address + +# Build the codec. +make -j$(nproc) + +# Build some libaom utils that are not part of the core lib. +$CC -std=c99 -c -I${AOM_DIR} -I${BUILD_DIR} \ + ${AOM_DIR}/common/ivfdec.c -o ${BUILD_DIR}/ivfdec.o + +$CC -std=c99 -c -I${AOM_DIR} -I${BUILD_DIR} \ + ${AOM_DIR}/common/tools_common.c -o ${BUILD_DIR}/tools_common.o + +# Build the av1 fuzzer +$CXX -std=c++11 -DDECODER=av1 -I${AOM_DIR} -I${BUILD_DIR} \ + -fsanitize=fuzzer -Wl,--start-group \ + ${AOM_DIR}/examples/av1_dec_fuzzer.cc -o ${BUILD_DIR}/av1_dec_fuzzer \ + ${BUILD_DIR}/libaom.a ${BUILD_DIR}/ivfdec.o ${BUILD_DIR}/tools_common.o \ + -Wl,--end-group + +echo "Fuzzer built at ${BUILD_DIR}/av1_dec_fuzzer." +echo "Create a corpus directory, copy IVF files in there, and run:" +echo " av1_dec_fuzzer CORPUS_DIR"