oss-fuzz: Add fuzzing targets
authorErik de Castro Lopo <erikd@mega-nerd.com>
Sun, 17 Nov 2019 05:15:51 +0000 (16:15 +1100)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Sun, 17 Nov 2019 19:29:10 +0000 (06:29 +1100)
These fuzzing targets were originally from:

    https://github.com/guidovranken/flac-fuzzers.git

but having them in a separate repo was a huge pain in the neck when
working on fixing any problems found.

.gitignore
Makefile.am
configure.ac
oss-fuzz/Makefile.am [new file with mode: 0644]
oss-fuzz/fuzz-decoder.cc [new file with mode: 0644]
oss-fuzz/fuzz-encoder.cc [new file with mode: 0644]
oss-fuzz/fuzz-encoder.dict [new file with mode: 0644]

index 6e9ffce..c38747c 100644 (file)
@@ -75,3 +75,5 @@ test/picture.diff
 test/picture.log
 .dirstamp
 microbench/benchmark_residual
+oss-fuzz/fuzz-decoder
+oss-fuzz/fuzz-encoder
index 83e0140..ce4519f 100644 (file)
@@ -31,7 +31,7 @@
 
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = doc include m4 man src test build microbench
+SUBDIRS = doc include m4 man src test build microbench oss-fuzz
 
 if EXAMPLES
 SUBDIRS += examples
index 88f89a9..5dd4e3a 100644 (file)
@@ -374,6 +374,32 @@ AC_HELP_STRING([--disable-cpplibs], [Do not build libFLAC++]),
 esac], [disable_cpplibs=false])
 AM_CONDITIONAL(FLaC__WITH_CPPLIBS, [test "x$disable_cpplibs" != xtrue])
 
+AC_ARG_ENABLE([oss-fuzzers],
+  [AS_HELP_STRING([--enable-oss-fuzzers],
+    [Whether to generate the fuzzers for OSS-Fuzz (Clang only)])],
+  [have_oss_fuzzers=yes], [have_oss_fuzzers=no])
+
+if test "x$have_oss_fuzzers" = "xyes"; then
+  if test "x$xiph_cv_c_compiler_clang" = "xyes" ; then
+    AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_oss_fuzzers" = "xyes"])
+    if test "x$LIB_FUZZING_ENGINE" = "x" ; then
+      # Only set this if it is empty.
+         LIB_FUZZING_ENGINE=-fsanitize=fuzzer
+    fi
+  else
+    AM_CONDITIONAL([USE_OSSFUZZERS], [test "false" = "true"])
+    # Disable fuzzer if the compiler is not Clang.
+    AC_MSG_WARN([*** Ozz-Fuzz is disabled because that requres the  Clang compiler.])
+    have_oss_fuzzers="no (compiler is GCC)"
+  fi
+else
+  AM_CONDITIONAL([USE_OSSFUZZERS], [test "false" = "true"])
+fi
+
+AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
+AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"])
+AC_SUBST([LIB_FUZZING_ENGINE])
+
 dnl check for ogg library
 AC_ARG_ENABLE([ogg],
        AC_HELP_STRING([--disable-ogg], [Disable ogg support (default: test for libogg)]),
@@ -576,7 +602,8 @@ AC_CONFIG_FILES([ \
        test/metaflac-test-files/Makefile \
        test/pictures/Makefile \
        build/Makefile \
-       microbench/Makefile
+       microbench/Makefile \
+       oss-fuzz/Makefile
 ])
 AC_OUTPUT
 
@@ -585,19 +612,20 @@ AC_MSG_RESULT([
 
   Configuration summary :
 
-    FLAC version : ........................ ${VERSION}
+    FLAC version : ............................ ${VERSION}
 
-    Host CPU : ............................ ${host_cpu}
-    Host Vendor : ......................... ${host_vendor}
-    Host OS : ............................. ${host_os}
+    Host CPU : ................................ ${host_cpu}
+    Host Vendor : ............................. ${host_vendor}
+    Host OS : ................................. ${host_os}
 ])
 
-       echo "    Compiler is GCC : ..................... ${ac_cv_c_compiler_gnu}"
+       echo "    Compiler is GCC : ......................... ${ac_cv_c_compiler_gnu}"
 if test x$ac_cv_c_compiler_gnu = xyes ; then
-       echo "    GCC version : ......................... ${GCC_VERSION}"
+       echo "    GCC version : ............................. ${GCC_VERSION}"
 fi
-       echo "    Compiler is Clang : ................... ${xiph_cv_c_compiler_clang}"
-       echo "    SSE optimizations : ................... ${sse_os}"
-       echo "    Asm optimizations : ................... ${asm_optimisation}"
-       echo "    Ogg/FLAC support : .................... ${have_ogg}"
+       echo "    Compiler is Clang : ....................... ${xiph_cv_c_compiler_clang}"
+       echo "    SSE optimizations : ....................... ${sse_os}"
+       echo "    Asm optimizations : ....................... ${asm_optimisation}"
+       echo "    Ogg/FLAC support : ........................ ${have_ogg}"
+       echo "    Fuzzing support (Clang only) : ............ ${have_oss_fuzzers}"
 echo
diff --git a/oss-fuzz/Makefile.am b/oss-fuzz/Makefile.am
new file mode 100644 (file)
index 0000000..7c4e2f6
--- /dev/null
@@ -0,0 +1,62 @@
+#  FLAC - Free Lossless Audio Codec
+#  Copyright (C) 2019  Xiph.Org Foundation
+#
+#  This file is part the FLAC project.  FLAC is comprised of several
+#  components distributed under different licenses.  The codec libraries
+#  are distributed under Xiph.Org's BSD-like license (see the file
+#  COPYING.Xiph in this distribution).  All other programs, libraries, and
+#  plugins are distributed under the GPL (see COPYING.GPL).  The documentation
+#  is distributed under the Gnu FDL (see COPYING.FDL).  Each file in the
+#  FLAC distribution contains at the top the terms under which it may be
+#  distributed.
+#
+#  Since this particular file is relevant to all components of FLAC,
+#  it may be distributed under the Xiph.Org license, which is the least
+#  restrictive of those mentioned above.  See the file COPYING.Xiph in this
+#  distribution.
+
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/oss-fuzz
+
+AM_CXXFLAGS = -std=c++11
+
+EXTRA_DIST = \
+       fuzz-encoder.dict \
+       fuzzing/Readme.md \
+       fuzzing/datasource/datasource.hpp \
+       fuzzing/datasource/id.hpp \
+       fuzzing/exception.hpp \
+       fuzzing/memory.hpp \
+       fuzzing/types.hpp
+
+if USE_OSSFUZZ_FLAG
+FUZZ_FLAG = $(LIB_FUZZING_ENGINE)
+FUZZ_LDADD = -lFuzzer
+else
+if USE_OSSFUZZ_STATIC
+FUZZ_LDADD = $(LIB_FUZZING_ENGINE)
+FUZZ_FLAG = -lFuzzer
+endif
+endif
+
+noinst_PROGRAMS =
+
+if USE_OSSFUZZERS
+noinst_PROGRAMS += fuzz-decoder fuzz-encoder
+endif
+
+fuzz_decoder_SOURCES = fuzz-decoder.cc
+fuzz_decoder_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
+fuzz_decoder_LDFLAGS = $(AM_LDFLAGS) -static
+fuzz_decoder_LDADD = $(flac_libs) $(FUZZ_LDADD)
+
+fuzz_encoder_SOURCES = fuzz-encoder.cc
+fuzz_encoder_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
+fuzz_encoder_LDFLAGS = $(AM_LDFLAGS) -static
+fuzz_encoder_LDADD = $(flac_libs) $(FUZZ_LDADD)
+
+flac_libs = \
+       $(top_builddir)/src/libFLAC/libFLAC-static.la \
+       $(top_builddir)/src/libFLAC++/libFLAC++-static.la \
+       @OGG_LIBS@ \
+       -lm
+
diff --git a/oss-fuzz/fuzz-decoder.cc b/oss-fuzz/fuzz-decoder.cc
new file mode 100644 (file)
index 0000000..b273387
--- /dev/null
@@ -0,0 +1,355 @@
+#include <cstddef>
+#include <cstdint>
+
+#include <fuzzing/datasource/datasource.hpp>
+#include <fuzzing/memory.hpp>
+
+#include "FLAC++/decoder.h"
+
+template <> FLAC__MetadataType fuzzing::datasource::Base::Get<FLAC__MetadataType>(const uint64_t id) {
+    (void)id;
+    switch ( Get<uint8_t>() ) {
+        case 0:
+            return FLAC__METADATA_TYPE_STREAMINFO;
+        case 1:
+            return FLAC__METADATA_TYPE_PADDING;
+        case 2:
+            return FLAC__METADATA_TYPE_APPLICATION;
+        case 3:
+            return FLAC__METADATA_TYPE_SEEKTABLE;
+        case 4:
+            return FLAC__METADATA_TYPE_VORBIS_COMMENT;
+        case 5:
+            return FLAC__METADATA_TYPE_CUESHEET;
+        case 6:
+            return FLAC__METADATA_TYPE_PICTURE;
+        case 7:
+            return FLAC__METADATA_TYPE_UNDEFINED;
+        case 8:
+            return FLAC__MAX_METADATA_TYPE;
+        default:
+            return FLAC__METADATA_TYPE_STREAMINFO;
+    }
+}
+
+namespace FLAC {
+       namespace Decoder {
+        class FuzzerStream : public Stream {
+            private:
+                fuzzing::datasource::Datasource& ds;
+            public:
+                FuzzerStream(fuzzing::datasource::Datasource& dsrc) :
+                    Stream(), ds(dsrc) { }
+
+                ::FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes)  override {
+                    try {
+                        const size_t maxCopySize = *bytes;
+
+                        if ( maxCopySize > 0 ) {
+                            /* memset just to test if this overwrites anything, and triggers ASAN */
+                            memset(buffer, 0, maxCopySize);
+                        }
+
+                        const auto data = ds.GetData(0);
+                        const auto dataSize = data.size();
+                        const auto copySize = std::min(maxCopySize, dataSize);
+
+                        if ( copySize > 0 ) {
+                            memcpy(buffer, data.data(), copySize);
+                        }
+
+                        *bytes = copySize;
+
+                        return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+                    } catch ( ... ) {
+                           return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+                    }
+                }
+
+                ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])  override {
+                    {
+                        fuzzing::memory::memory_test(&(frame->header), sizeof(frame->header));
+                        fuzzing::memory::memory_test(&(frame->footer), sizeof(frame->footer));
+                    }
+
+                    {
+                        const auto numChannels = get_channels();
+                        const size_t bytesPerChannel = frame->header.blocksize * sizeof(FLAC__int32);
+                        for (size_t i = 0; i < numChannels; i++) {
+                            fuzzing::memory::memory_test(buffer[i], bytesPerChannel);
+                        }
+                    }
+
+                    try {
+                        if ( ds.Get<bool>() == true ) {
+                               return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+                        }
+                    } catch ( ... ) { }
+                    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+                }
+
+                void error_callback(::FLAC__StreamDecoderErrorStatus status)  override {
+                    fuzzing::memory::memory_test(status);
+                }
+
+                void metadata_callback(const ::FLAC__StreamMetadata *metadata) override {
+                    fuzzing::memory::memory_test(metadata->type);
+                    fuzzing::memory::memory_test(metadata->is_last);
+                    fuzzing::memory::memory_test(metadata->length);
+                    fuzzing::memory::memory_test(metadata->data);
+                }
+
+                ::FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) override {
+                    fuzzing::memory::memory_test(absolute_byte_offset);
+
+                    try {
+                        if ( ds.Get<bool>() == true ) {
+                            return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+                        } else {
+                            return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
+                        }
+                    } catch ( ... ) {
+                        return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+                    }
+                }
+#if 0
+                ::FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) override {
+                    fuzzing::memory::memory_test(*absolute_byte_offset);
+
+                    try {
+                        if ( ds.Get<bool>() == true ) {
+                            return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+                        } else {
+                            return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
+                        }
+                    } catch ( ... ) {
+                        return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+                    }
+                }
+
+                ::FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) override {
+                    fuzzing::memory::memory_test(*stream_length);
+
+                    try {
+                        if ( ds.Get<bool>() == true ) {
+                            return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+                        } else {
+                            return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
+                        }
+                    } catch ( ... ) {
+                        return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+                    }
+                }
+#endif
+        };
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    fuzzing::datasource::Datasource ds(data, size);
+    FLAC::Decoder::FuzzerStream decoder(ds);
+
+    try {
+        {
+            ::FLAC__StreamDecoderInitStatus ret;
+
+            if ( ds.Get<bool>() ) {
+                ret = decoder.init();
+            } else {
+                ret = decoder.init_ogg();
+            }
+
+            if ( ret != FLAC__STREAM_DECODER_INIT_STATUS_OK ) {
+                goto end;
+            }
+        }
+
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_ogg_serial_number\n");
+#endif
+            decoder.set_ogg_serial_number(ds.Get<long>());
+        }
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_md5_checking\n");
+#endif
+            decoder.set_md5_checking(ds.Get<bool>());
+        }
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_metadata_respond\n");
+#endif
+            decoder.set_metadata_respond(ds.Get<::FLAC__MetadataType>());
+        }
+        if ( ds.Get<bool>() ) {
+            const auto idVector = ds.GetData(0);
+            unsigned char id[4];
+            if ( idVector.size() >= sizeof(id) ) {
+                memcpy(id, idVector.data(), sizeof(id));
+#ifdef FUZZER_DEBUG
+                printf("set_metadata_respond_application\n");
+#endif
+                decoder.set_metadata_respond_application(id);
+            }
+        }
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_metadata_respond_all\n");
+#endif
+            decoder.set_metadata_respond_all();
+        }
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_metadata_ignore\n");
+#endif
+            decoder.set_metadata_ignore(ds.Get<::FLAC__MetadataType>());
+        }
+        if ( ds.Get<bool>() ) {
+            const auto idVector = ds.GetData(0);
+            unsigned char id[4];
+            if ( idVector.size() >= sizeof(id) ) {
+                memcpy(id, idVector.data(), sizeof(id));
+#ifdef FUZZER_DEBUG
+                printf("set_metadata_ignore_application\n");
+#endif
+                decoder.set_metadata_ignore_application(id);
+            }
+        }
+        if ( ds.Get<bool>() ) {
+#ifdef FUZZER_DEBUG
+            printf("set_metadata_ignore_all\n");
+#endif
+            decoder.set_metadata_ignore_all();
+        }
+
+        while ( ds.Get<bool>() ) {
+            switch ( ds.Get<uint8_t>() ) {
+                case    0:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("flush\n");
+#endif
+                        const bool res = decoder.flush();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    1:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("reset\n");
+#endif
+                        const bool res = decoder.reset();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    2:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("process_single\n");
+#endif
+                        const bool res = decoder.process_single();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    3:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("process_until_end_of_metadata\n");
+#endif
+                        const bool res = decoder.process_until_end_of_metadata();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    4:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("process_until_end_of_stream\n");
+#endif
+                        const bool res = decoder.process_until_end_of_stream();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    5:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("skip_single_frame\n");
+#endif
+                        const bool res = decoder.skip_single_frame();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    6:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("seek_absolute\n");
+#endif
+                        const bool res = decoder.seek_absolute(ds.Get<uint64_t>());
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    7:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_md5_checking\n");
+#endif
+                        const bool res = decoder.get_md5_checking();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    8:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_total_samples\n");
+#endif
+                        const bool res = decoder.get_total_samples();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    9:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_channels\n");
+#endif
+                        const bool res = decoder.get_channels();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    10:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_bits_per_sample\n");
+#endif
+                        const bool res = decoder.get_bits_per_sample();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    11:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_sample_rate\n");
+#endif
+                        const bool res = decoder.get_sample_rate();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+                case    12:
+                    {
+#ifdef FUZZER_DEBUG
+                        printf("get_blocksize\n");
+#endif
+                        const bool res = decoder.get_blocksize();
+                        fuzzing::memory::memory_test(res);
+                    }
+                    break;
+            }
+        }
+    } catch ( ... ) { }
+
+end:
+    {
+        const bool res = decoder.finish();
+        fuzzing::memory::memory_test(res);
+    }
+    return 0;
+}
diff --git a/oss-fuzz/fuzz-encoder.cc b/oss-fuzz/fuzz-encoder.cc
new file mode 100644 (file)
index 0000000..067af05
--- /dev/null
@@ -0,0 +1,154 @@
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include <fuzzing/datasource/datasource.hpp>
+#include <fuzzing/memory.hpp>
+
+#include "FLAC++/encoder.h"
+
+#define SAMPLE_VALUE_LIMIT (1024*1024*10)
+
+static_assert(SAMPLE_VALUE_LIMIT <= std::numeric_limits<FLAC__int32>::max(), "Invalid SAMPLE_VALUE_LIMIT");
+static_assert(-SAMPLE_VALUE_LIMIT >= std::numeric_limits<FLAC__int32>::min(), "Invalid SAMPLE_VALUE_LIMIT");
+
+namespace FLAC {
+       namespace Encoder {
+        class FuzzerStream : public Stream {
+            private:
+                // fuzzing::datasource::Datasource& ds;
+            public:
+                FuzzerStream(fuzzing::datasource::Datasource&) :
+                    Stream() { }
+
+                ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, uint32_t /* samples */, uint32_t /* current_frame */) override {
+                    fuzzing::memory::memory_test(buffer, bytes);
+#if 0
+                    try {
+                        if ( ds.Get<bool>() == true ) {
+                               return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
+                        }
+                    } catch ( ... ) { }
+#endif
+                    return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
+                }
+        };
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    fuzzing::datasource::Datasource ds(data, size);
+    FLAC::Encoder::FuzzerStream encoder(ds);
+
+    const int channels = 2;
+       encoder.set_channels(channels);
+       encoder.set_bits_per_sample(16);
+
+    try {
+        ::FLAC__StreamEncoderInitStatus ret;
+
+        if ( ds.Get<bool>() ) {
+            ret = encoder.init();
+        } else {
+            ret = encoder.init_ogg();
+        }
+
+        if ( ret != FLAC__STREAM_ENCODER_INIT_STATUS_OK ) {
+            goto end;
+        }
+
+        {
+            const bool res = encoder.set_streamable_subset(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_ogg_serial_number(ds.Get<long>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_verify(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_compression_level(ds.Get<uint8_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_do_exhaustive_model_search(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_do_mid_side_stereo(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_loose_mid_side_stereo(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const auto s = ds.Get<std::string>();
+            const bool res = encoder.set_apodization(s.data());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_max_lpc_order(ds.Get<uint8_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_qlp_coeff_precision(ds.Get<uint32_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_do_qlp_coeff_prec_search(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_do_escape_coding(ds.Get<bool>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_min_residual_partition_order(ds.Get<uint32_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_max_residual_partition_order(ds.Get<uint32_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_rice_parameter_search_dist(ds.Get<uint32_t>());
+            fuzzing::memory::memory_test(res);
+        }
+        {
+            const bool res = encoder.set_total_samples_estimate(ds.Get<uint64_t>());
+            fuzzing::memory::memory_test(res);
+        }
+
+        while ( ds.Get<bool>() ) {
+            {
+                auto dat = ds.GetVector<FLAC__int32>();
+                for (size_t i = 0; i < dat.size(); i++) {
+                    if ( SAMPLE_VALUE_LIMIT != 0 ) {
+                        if ( dat[i] < -SAMPLE_VALUE_LIMIT ) {
+                            dat[i] = -SAMPLE_VALUE_LIMIT;
+                        } else if ( dat[i] > SAMPLE_VALUE_LIMIT ) {
+                            dat[i] = SAMPLE_VALUE_LIMIT;
+                        }
+                    }
+                }
+                const uint32_t samples = dat.size() / 2;
+                if ( samples > 0 ) {
+                    const int32_t* ptr = dat.data();
+                    const bool res = encoder.process_interleaved(ptr, samples);
+                    fuzzing::memory::memory_test(res);
+                }
+            }
+        }
+    } catch ( ... ) { }
+
+end:
+    {
+        const bool res = encoder.finish();
+        fuzzing::memory::memory_test(res);
+    }
+    return 0;
+}
diff --git a/oss-fuzz/fuzz-encoder.dict b/oss-fuzz/fuzz-encoder.dict
new file mode 100644 (file)
index 0000000..fe5b77f
--- /dev/null
@@ -0,0 +1,17 @@
+"bartlett"
+"bartlett_hann"
+"blackman"
+"blackman_harris_4term_92db"
+"connes"
+"flattop"
+"gauss()"
+"hamming"
+"hann"
+"kaiser_bessel"
+"nuttall"
+"rectangle"
+"triangle"
+"tukey(0)"
+"partial_tukey(0)"
+"punchout_tukey(0)"
+"welch"